@aurea-uds/react 0.31.0 → 0.33.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/README.md +5 -3
- package/dist/actions.d.ts +48 -13
- package/dist/actions.js +64 -31
- package/dist/agents.js +1 -1
- package/dist/calendar.d.ts +38 -1
- package/dist/calendar.js +115 -2
- package/dist/code-client.d.ts +3 -1
- package/dist/code-client.js +23 -1
- package/dist/color.d.ts +92 -0
- package/dist/color.js +293 -0
- package/dist/disclosure.d.ts +19 -9
- package/dist/disclosure.js +8 -1
- package/dist/feedback-client.d.ts +14 -6
- package/dist/feedback-client.js +29 -16
- package/dist/graph-worker.d.ts +1 -0
- package/dist/graph-worker.js +17 -0
- package/dist/graph.d.ts +11 -1
- package/dist/graph.js +214 -19
- package/dist/icon-names.d.ts +7 -1
- package/dist/icon-names.js +2 -0
- package/dist/identity-client.d.ts +6 -1
- package/dist/identity-client.js +2 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/inputs-client.d.ts +245 -3
- package/dist/inputs-client.js +541 -14
- package/dist/inputs.d.ts +1 -1
- package/dist/internal.d.ts +7 -4
- package/dist/internal.js +6 -1
- package/dist/layout-client.d.ts +14 -2
- package/dist/layout-client.js +2 -2
- package/dist/markup.d.ts +135 -15
- package/dist/markup.js +87 -17
- package/dist/navigation-client.d.ts +38 -10
- package/dist/navigation-client.js +77 -21
- package/dist/overlays.d.ts +20 -6
- package/dist/overlays.js +70 -15
- package/dist/pure.d.ts +27 -0
- package/dist/pure.js +2 -2
- package/dist/system.d.ts +12 -6
- package/dist/system.js +52 -13
- package/package.json +8 -2
|
@@ -24,7 +24,8 @@ export declare function Breadcrumb({ items, label }: {
|
|
|
24
24
|
}): React.JSX.Element;
|
|
25
25
|
export type TabsOrientation = "horizontal" | "vertical";
|
|
26
26
|
export type TabsPanel = "card" | "plain";
|
|
27
|
-
export
|
|
27
|
+
export type TabsVariant = "primary" | "secondary";
|
|
28
|
+
export declare function Tabs({ tabs, value, onChange, label, orientation, activateOnFocus, loopFocus, panel, variant }: {
|
|
28
29
|
tabs: Array<{
|
|
29
30
|
id: string;
|
|
30
31
|
label: ReactNode;
|
|
@@ -37,12 +38,26 @@ export declare function Tabs({ tabs, value, onChange, label, orientation, activa
|
|
|
37
38
|
activateOnFocus?: boolean;
|
|
38
39
|
loopFocus?: boolean;
|
|
39
40
|
panel?: TabsPanel;
|
|
41
|
+
variant?: TabsVariant;
|
|
40
42
|
}): React.JSX.Element;
|
|
41
|
-
export
|
|
43
|
+
export type PaginationVariant = "numbers" | "simple" | "compact";
|
|
44
|
+
export interface PaginationProps {
|
|
42
45
|
page: number;
|
|
43
46
|
total: number;
|
|
44
|
-
onPageChange
|
|
45
|
-
|
|
47
|
+
onPageChange?: (p: number) => void;
|
|
48
|
+
variant?: PaginationVariant;
|
|
49
|
+
/** O resumo à esquerda — "1 a 5 de 50 pedidos". */
|
|
50
|
+
summary?: ReactNode;
|
|
51
|
+
/** O endereço de cada página. Com ele, as páginas são links. */
|
|
52
|
+
href?: (page: number) => string;
|
|
53
|
+
/** Quantas páginas aparecem de cada lado da atual. Padrão: 1. */
|
|
54
|
+
siblings?: number;
|
|
55
|
+
/** O nome do marco de navegação. Padrão: a frase `paginationLabel`. Com duas paginações na mesma
|
|
56
|
+
* página, cada uma diz de quê ("Páginas dos pedidos"), senão o leitor de tela ouve dois marcos iguais. */
|
|
57
|
+
label?: string;
|
|
58
|
+
className?: string;
|
|
59
|
+
}
|
|
60
|
+
export declare function Pagination({ page, total, onPageChange, variant, summary, href, siblings, label, className }: PaginationProps): React.JSX.Element;
|
|
46
61
|
export interface TocItem {
|
|
47
62
|
id: string;
|
|
48
63
|
label: string;
|
|
@@ -80,12 +95,16 @@ export interface SidebarItem {
|
|
|
80
95
|
/** O link do roteador do app (M-01): `<Link href="/relatorios" />`. Recebe a pele, o estado de página atual e o conteúdo do item. */
|
|
81
96
|
render?: ReactElement;
|
|
82
97
|
}
|
|
83
|
-
export type SidebarVariant = "floating" | "flush";
|
|
84
|
-
export
|
|
98
|
+
export type SidebarVariant = "floating" | "flush" | "plain";
|
|
99
|
+
export type SidebarScrollbar = "hover" | "visible";
|
|
100
|
+
export type SidebarPlacement = "left" | "right";
|
|
101
|
+
export declare function Sidebar({ items, current, collapsed, variant, placement, scrollbar, label, children, className, onClick, ...props }: HTMLAttributes<HTMLElement> & RefAttributes<HTMLElement> & {
|
|
85
102
|
items?: SidebarItem[];
|
|
86
103
|
current?: string;
|
|
87
104
|
collapsed?: boolean;
|
|
88
105
|
variant?: SidebarVariant;
|
|
106
|
+
placement?: SidebarPlacement;
|
|
107
|
+
scrollbar?: SidebarScrollbar;
|
|
89
108
|
label?: string;
|
|
90
109
|
}): React.JSX.Element;
|
|
91
110
|
export type BottomNavVariant = "floating" | "edge";
|
|
@@ -135,17 +154,26 @@ export interface CommandItem {
|
|
|
135
154
|
icon?: IconName;
|
|
136
155
|
kbd?: string;
|
|
137
156
|
run: () => void;
|
|
157
|
+
/** 0.32.0 (DOC-06): o grupo do item ("Componentes", "Páginas"). Itens com o mesmo grupo saem juntos,
|
|
158
|
+
* sob o título dele, na ordem em que o grupo aparece primeiro. */
|
|
159
|
+
group?: string;
|
|
138
160
|
}
|
|
139
|
-
export declare function CommandPalette({ open, onClose, items, placeholder, label }: {
|
|
161
|
+
export declare function CommandPalette({ open, onClose, items, placeholder, label, shortcuts }: {
|
|
140
162
|
open: boolean;
|
|
141
163
|
onClose: () => void;
|
|
142
164
|
items: CommandItem[];
|
|
143
165
|
placeholder?: string;
|
|
144
166
|
label?: string;
|
|
145
|
-
|
|
146
|
-
|
|
167
|
+
/** 0.32.0 (DOC-07): a linha que ensina as teclas, embaixo — ↑ ↓ mover, Enter abrir, Esc fechar. */
|
|
168
|
+
shortcuts?: boolean;
|
|
169
|
+
}): React.JSX.Element;
|
|
170
|
+
export declare function CommandPaletteShell({ open, query, onQueryChange, onClose, label, children }: {
|
|
147
171
|
open: boolean;
|
|
148
172
|
query: string;
|
|
149
173
|
onQueryChange: (v: string) => void;
|
|
174
|
+
/** Quem fecha: a janela avisa pelo Esc e pelo clique fora. */
|
|
175
|
+
onClose?: () => void;
|
|
176
|
+
/** O nome da janela (o padrão é o da paleta, "Command palette"). */
|
|
177
|
+
label?: string;
|
|
150
178
|
children?: ReactNode;
|
|
151
|
-
}): React.JSX.Element
|
|
179
|
+
}): React.JSX.Element;
|
|
@@ -7,6 +7,7 @@ import React, { useRef } from "react";
|
|
|
7
7
|
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
8
8
|
import { useDirection } from "@base-ui/react/direction-provider";
|
|
9
9
|
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete";
|
|
10
|
+
import { Dialog as BaseDialog } from "@base-ui/react/dialog";
|
|
10
11
|
import { useValorResponsivo } from "./responsivo-runtime.js";
|
|
11
12
|
import { cx, fundirRender, useAureaStrings, usePortalContainer } from "./internal.js";
|
|
12
13
|
import { Kbd } from "./markup.js";
|
|
@@ -29,8 +30,37 @@ export function Stepper({ items, label, className }) {
|
|
|
29
30
|
}) });
|
|
30
31
|
}
|
|
31
32
|
export function Breadcrumb({ items, label }) { const s = useAureaStrings(); return _jsx("nav", { className: "breadcrumb", "aria-label": label ?? s.breadcrumbLabel, children: items.map((i, n) => _jsxs(React.Fragment, { children: [n > 0 && _jsx(Icon, { name: "caret-right", size: "sm" }), " ", i.render ? fundirRender(i.render, { children: i.label }, "a") : i.href ? _jsx("a", { href: i.href, children: i.label }) : _jsx("strong", { "aria-current": "page", children: i.label })] }, n)) }); }
|
|
32
|
-
export function Tabs({ tabs, value, onChange, label, orientation, activateOnFocus = true, loopFocus, panel = "card" }) { const s = useAureaStrings(); const ancora = useRef(null); const resolvida = useValorResponsivo(orientation, "horizontal", ancora); return _jsxs(BaseTabs.Root, { ref: ancora, value: value, onValueChange: v => onChange(String(v)), orientation: resolvida, className: "tabs-root", children: [_jsx(BaseTabs.List, { className: "tabs", "aria-label": label ?? s.tabsLabel, activateOnFocus: activateOnFocus, loopFocus: loopFocus, children: tabs.map(t => _jsx(BaseTabs.Tab, { value: t.id, className: "tab", children: t.label }, t.id)) }), tabs.map(t => _jsx(BaseTabs.Panel, { value: t.id, className: panel === "plain" ? "tabs-panel" : "card card-inset", tabIndex: 0, children: t.content }, t.id))] }); }
|
|
33
|
-
|
|
33
|
+
export function Tabs({ tabs, value, onChange, label, orientation, activateOnFocus = true, loopFocus, panel = "card", variant = "primary" }) { const s = useAureaStrings(); const ancora = useRef(null); const resolvida = useValorResponsivo(orientation, "horizontal", ancora); return _jsxs(BaseTabs.Root, { ref: ancora, value: value, onValueChange: v => onChange(String(v)), orientation: resolvida, className: "tabs-root", children: [_jsx(BaseTabs.List, { className: cx("tabs", variant === "secondary" && "tabs-secondary"), "aria-label": label ?? s.tabsLabel, activateOnFocus: activateOnFocus, loopFocus: loopFocus, children: tabs.map(t => _jsx(BaseTabs.Tab, { value: t.id, className: "tab", children: t.label }, t.id)) }), tabs.map(t => _jsx(BaseTabs.Panel, { value: t.id, className: panel === "plain" ? "tabs-panel" : "card card-inset", tabIndex: 0, children: t.content }, t.id))] }); }
|
|
34
|
+
function paginasVisiveis(page, total, siblings) {
|
|
35
|
+
if (total <= 5 + siblings * 2)
|
|
36
|
+
return Array.from({ length: total }, (_, i) => i + 1);
|
|
37
|
+
const ini = Math.max(2, page - siblings), fim = Math.min(total - 1, page + siblings);
|
|
38
|
+
const meio = Array.from({ length: fim - ini + 1 }, (_, i) => ini + i);
|
|
39
|
+
return [1, ...(ini > 2 ? ["..."] : []), ...meio, ...(fim < total - 1 ? ["..."] : []), total];
|
|
40
|
+
}
|
|
41
|
+
export function Pagination({ page, total, onPageChange, variant = "numbers", summary, href, siblings = 1, label, className }) {
|
|
42
|
+
const s = useAureaStrings();
|
|
43
|
+
if (variant === "compact")
|
|
44
|
+
return _jsxs("nav", { className: cx("pagination", className), "aria-label": label ?? s.paginationLabel, children: [_jsx(Button, { variant: "ghost", size: "sm", disabled: page <= 1, onClick: () => onPageChange?.(page - 1), children: s.previous }), _jsxs(Badge, { variant: "primary", children: [page, " / ", total] }), _jsx(Button, { variant: "ghost", size: "sm", disabled: page >= total, onClick: () => onPageChange?.(page + 1), children: s.next })] });
|
|
45
|
+
// Um item: link (com `href`) ou botão. Desligado (a primeira página no "anterior"), sem endereço.
|
|
46
|
+
const item = (alvo, conteudo, { atual = false, nav, rotulo } = {}) => {
|
|
47
|
+
const fora = alvo < 1 || alvo > total;
|
|
48
|
+
const cls = cx("pagination-link", nav && "pagination-link-nav", atual && "active");
|
|
49
|
+
const comuns = { className: cls, "aria-label": rotulo, "aria-current": atual ? "page" : undefined };
|
|
50
|
+
if (href)
|
|
51
|
+
return fora ? _jsx("a", { ...comuns, "aria-disabled": "true", children: conteudo })
|
|
52
|
+
: _jsx("a", { ...comuns, href: href(alvo), onClick: onPageChange ? (e) => { if (!e.metaKey && !e.ctrlKey && !e.shiftKey && e.button === 0) {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
onPageChange(alvo);
|
|
55
|
+
} } : undefined, children: conteudo });
|
|
56
|
+
return _jsx("button", { type: "button", ...comuns, disabled: fora, onClick: () => onPageChange?.(alvo), children: conteudo });
|
|
57
|
+
};
|
|
58
|
+
const anterior = item(page - 1, _jsxs(_Fragment, { children: [_jsx(Icon, { name: "caret-left", className: "pagination-nav-icon" }), _jsx("span", { children: s.previous })] }), { nav: "prev" });
|
|
59
|
+
const proxima = item(page + 1, _jsxs(_Fragment, { children: [_jsx("span", { children: s.next }), _jsx(Icon, { name: "caret-right", className: "pagination-nav-icon" })] }), { nav: "next" });
|
|
60
|
+
return _jsxs("nav", { className: cx("pagination", className), "aria-label": label ?? s.paginationLabel, children: [summary != null && _jsx("span", { className: "pagination-summary", children: summary }), _jsxs("ul", { className: "pagination-content", children: [_jsx("li", { children: anterior }), variant === "numbers" && paginasVisiveis(page, total, siblings).map((p, i) => p === "..."
|
|
61
|
+
? _jsx("li", { children: _jsx("span", { className: "pagination-ellipsis", "aria-hidden": "true", children: "\u2026" }) }, `e${i}`)
|
|
62
|
+
: _jsx("li", { children: item(p, p, { atual: p === page, rotulo: `${s.paginationPage} ${p}` }) }, p)), _jsx("li", { children: proxima })] })] });
|
|
63
|
+
}
|
|
34
64
|
export function TableOfContents({ items, current, label, className, ...props }) {
|
|
35
65
|
const s = useAureaStrings();
|
|
36
66
|
const meu = React.useRef(null);
|
|
@@ -43,7 +73,7 @@ export function TableOfContents({ items, current, label, className, ...props })
|
|
|
43
73
|
return _jsxs("nav", { ref: n => { meu.current = n; if (typeof refDele === "function")
|
|
44
74
|
refDele(n);
|
|
45
75
|
else if (refDele)
|
|
46
|
-
refDele.current = n; }, className: cx("toc", className), "aria-label": label ?? s.tocLabel, ...resto, children: [
|
|
76
|
+
refDele.current = n; }, className: cx("toc", className), "aria-label": label ?? s.tocLabel, ...resto, children: [_jsxs("p", { className: "toc-label", children: [_jsx("span", { className: "toc-label-icon", "aria-hidden": "true" }), label ?? s.tocLabel] }), items.map(i => _jsx("a", { href: `#${i.id}`, className: cx(i.sub && "toc-sub"), ...(i.id === atual ? { "aria-current": "true" } : {}), children: i.label }, i.id))] });
|
|
47
77
|
}
|
|
48
78
|
/** Qual dos `items` está na faixa de leitura, observando o documento. Devolve `undefined` até o
|
|
49
79
|
* primeiro cálculo — e em SSR, onde não há documento para observar.
|
|
@@ -235,10 +265,10 @@ function fecharGavetaAoEscolher(e) {
|
|
|
235
265
|
}
|
|
236
266
|
catch { /* motor sem popover: não há gaveta */ }
|
|
237
267
|
}
|
|
238
|
-
export function Sidebar({ items, current, collapsed, variant = "floating", label, children, className, onClick, ...props }) {
|
|
268
|
+
export function Sidebar({ items, current, collapsed, variant = "floating", placement = "left", scrollbar = "hover", label, children, className, onClick, ...props }) {
|
|
239
269
|
const s = useAureaStrings();
|
|
240
270
|
const baseId = React.useId();
|
|
241
|
-
return _jsxs("aside", { className: cx("sidebar", variant !== "floating" && `sidebar-${variant}`, collapsed && "sidebar-collapsed", className), onClick: e => { onClick?.(e); fecharGavetaAoEscolher(e); }, ...props, children: [items && items.length > 0 && _jsx("nav", { className: "sidebar-nav", "aria-label": label ?? s.sidebarLabel, children: sidebarList(items, { baseId, current, collapsed }) }), children] });
|
|
271
|
+
return _jsxs("aside", { className: cx("sidebar", variant !== "floating" && `sidebar-${variant}`, collapsed && "sidebar-collapsed", placement === "right" && "sidebar-right", scrollbar === "visible" && "sidebar-scrollbar-visible", className), "data-placement": placement, onClick: e => { onClick?.(e); fecharGavetaAoEscolher(e); }, ...props, children: [items && items.length > 0 && _jsx("nav", { className: "sidebar-nav", "aria-label": label ?? s.sidebarLabel, children: sidebarList(items, { baseId, current, collapsed }) }), children] });
|
|
242
272
|
}
|
|
243
273
|
const LEGADO = {
|
|
244
274
|
flat: ["edge", "none"], surface: ["floating", "circle"], pill: ["floating", "pill"], dock: ["floating", "circle"]
|
|
@@ -282,24 +312,50 @@ export function NavList({ items, className, ...props }) {
|
|
|
282
312
|
: _jsx("button", { type: "button", className: "nav-list-row", "aria-disabled": it.disabled || undefined, onClick: it.disabled ? undefined : it.onClick, children: miolo }) }, it.id);
|
|
283
313
|
}) });
|
|
284
314
|
}
|
|
285
|
-
export function CommandPalette({ open, onClose, items, placeholder, label }) {
|
|
315
|
+
export function CommandPalette({ open, onClose, items, placeholder, label, shortcuts = true }) {
|
|
286
316
|
const s = useAureaStrings();
|
|
317
|
+
const idAtalhos = React.useId();
|
|
318
|
+
// GRUPOS (0.32.0, DOC-06). Em 13/08/2026 a Aurea ficou SEM grupo, e a medição decidiu: dar a cada
|
|
319
|
+
// `Group` a sua fatia de itens passava POR CIMA do filtro do motor (digitar "the" devolvia os três).
|
|
320
|
+
// O caminho certo é o da documentação do motor (1.6.0, a paleta de exemplo dele): `items` agrupados
|
|
321
|
+
// (`{value, items}`), e a lista recebe os grupos JÁ FILTRADOS. Sem `group` em nenhum item, a lista é
|
|
322
|
+
// a de sempre.
|
|
323
|
+
const grupos = React.useMemo(() => {
|
|
324
|
+
if (!items.some(i => i.group))
|
|
325
|
+
return null;
|
|
326
|
+
const mapa = new Map();
|
|
327
|
+
for (const i of items) {
|
|
328
|
+
const g = i.group ?? "";
|
|
329
|
+
if (!mapa.has(g))
|
|
330
|
+
mapa.set(g, []);
|
|
331
|
+
mapa.get(g).push(i);
|
|
332
|
+
}
|
|
333
|
+
return [...mapa].map(([value, itens]) => ({ value, items: itens }));
|
|
334
|
+
}, [items]);
|
|
287
335
|
const portal = usePortalContainer();
|
|
288
|
-
|
|
289
|
-
return null;
|
|
290
|
-
// SEM AGRUPAMENTO na v1, e a medição é que decidiu (13/08/2026). O `Autocomplete.Root` não
|
|
291
|
-
// consome a estrutura agrupada como o `Combobox.Root` consome — e o caminho alternativo, dar a
|
|
292
|
-
// cada `Group` a sua fatia de itens, PASSA POR CIMA do filtro do motor: digitar "the" devolvia
|
|
293
|
-
// os três comandos. Entre agrupar e filtrar, filtrar é o ponto de uma paleta de comandos.
|
|
294
|
-
// Fica registrado como limite, não como esquecimento: quando alguém precisar de grupo aqui, o
|
|
295
|
-
// caminho é o `Combobox.Root`, e isso é troca de motor, não ajuste.
|
|
336
|
+
const campo = useRef(null);
|
|
296
337
|
const executa = (item) => { onClose(); item.run(); };
|
|
297
338
|
const linha = (item) => _jsxs(BaseAutocomplete.Item, { value: item, className: "menu-item command-item", onClick: () => executa(item), children: [item.icon && _jsx(Icon, { name: item.icon }), _jsx("span", { className: "command-item-label", children: item.label }), item.kbd && _jsx(Kbd, { children: item.kbd })] }, item.id);
|
|
298
|
-
//
|
|
299
|
-
//
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
339
|
+
// A JANELA É A DO MOTOR (14/10/2026), como na paleta de exemplo dele (1.6.0): `Dialog` por fora,
|
|
340
|
+
// `Autocomplete` `inline` por dentro. Até aqui a moldura era uma `div` feita à mão, e o Victor achou no site
|
|
341
|
+
// publicado: o clique no fundo não fechava, e depois dele o foco ia para a página — o Esc, que era escutado
|
|
342
|
+
// dentro da caixa, não chegava mais. A janela do motor fecha pelos dois caminhos, prende o Tab, trava a
|
|
343
|
+
// rolagem de trás e devolve o foco a quem abriu. O `open` continua do consumidor: o motor só AVISA
|
|
344
|
+
// (`onOpenChange`), e quem fecha é o `onClose` — mesma regra do Dialog e do Drawer daqui. Os nomes de classe
|
|
345
|
+
// ficaram: a moldura (`Viewport`) é a `.command-overlay`, a caixa (`Popup`) é a `.command-palette`.
|
|
346
|
+
return _jsx(BaseDialog.Root, { open: open, onOpenChange: o => { if (!o)
|
|
347
|
+
onClose(); }, children: _jsx(BaseDialog.Portal, { container: portal, children: _jsx(BaseDialog.Viewport, { className: "command-overlay", children: _jsxs(BaseDialog.Popup, { className: "command-palette", "aria-label": label ?? s.commandLabel, initialFocus: campo, children: [_jsxs(BaseAutocomplete.Root, { items: (grupos ?? items), itemToStringValue: (i) => i.label, mode: "list", open: true, inline: true, autoHighlight: "always", keepHighlight: true, children: [_jsx(BaseAutocomplete.Input, { ref: campo, className: "input", "aria-label": placeholder ?? s.commandPlaceholder, placeholder: placeholder ?? s.commandPlaceholder, "aria-expanded": true, "aria-describedby": shortcuts ? idAtalhos : undefined }), _jsxs("div", { className: "menu command-list", children: [_jsx(BaseAutocomplete.Empty, { className: "combobox-empty", children: s.comboboxEmpty }), _jsx(BaseAutocomplete.List, { children: grupos
|
|
348
|
+
? (g) => _jsxs(BaseAutocomplete.Group, { items: g.items, className: "command-group", children: [g.value && _jsx(BaseAutocomplete.GroupLabel, { className: "command-group-label", children: g.value }), _jsx(BaseAutocomplete.Collection, { children: linha })] }, g.value)
|
|
349
|
+
: _jsx(BaseAutocomplete.Collection, { children: linha }) })] })] }), shortcuts && _jsxs("p", { className: "command-shortcuts", id: idAtalhos, children: [_jsxs("span", { children: [_jsx(Kbd, { children: "\u2191" }), _jsx(Kbd, { children: "\u2193" }), " ", s.commandHintMove] }), _jsxs("span", { children: [_jsx(Kbd, { children: "Enter" }), " ", s.commandHintSelect] }), _jsxs("span", { children: [_jsx(Kbd, { children: "Esc" }), " ", s.commandHintClose] })] })] }) }) }) });
|
|
350
|
+
}
|
|
351
|
+
// A CASCA (15/10/2026, o Victor: "C sim"): a mesma janela do motor da `CommandPalette` acima. Até aqui era uma `div`
|
|
352
|
+
// feita à mão — o mesmo defeito que a busca do site teve: o clique fora e o Esc não fechavam, e o Tab saía da caixa.
|
|
353
|
+
// Agora o motor avisa pelos dois caminhos (`onClose`, novo), prende o Tab e devolve o foco a quem abriu. Sem `onClose`,
|
|
354
|
+
// a janela fica aberta até o `open` do consumidor mudar — como antes. O campo recebe o foco pelo `initialFocus`.
|
|
355
|
+
export function CommandPaletteShell({ open, query, onQueryChange, onClose, label, children }) {
|
|
356
|
+
const s = useAureaStrings();
|
|
357
|
+
const portal = usePortalContainer();
|
|
358
|
+
const campo = useRef(null);
|
|
359
|
+
return _jsx(BaseDialog.Root, { open: open, onOpenChange: o => { if (!o)
|
|
360
|
+
onClose?.(); }, children: _jsx(BaseDialog.Portal, { container: portal, children: _jsx(BaseDialog.Viewport, { className: "command-overlay", children: _jsxs(BaseDialog.Popup, { className: "command-palette", "aria-label": label ?? s.commandLabel, initialFocus: campo, children: [_jsx(SearchField, { ref: campo, "aria-label": s.commandPlaceholder, value: query, onChange: e => onQueryChange(e.target.value), placeholder: s.commandPlaceholder }), children] }) }) }) });
|
|
303
361
|
}
|
|
304
|
-
export function CommandPaletteShell({ open, query, onQueryChange, children }) { const s = useAureaStrings(); if (!open)
|
|
305
|
-
return null; return _jsx("div", { className: "command-overlay", children: _jsxs("div", { className: "command-palette", role: "dialog", "aria-label": s.commandLabel, children: [_jsx(SearchField, { autoFocus: true, "aria-label": s.commandPlaceholder, value: query, onChange: e => onQueryChange(e.target.value), placeholder: s.commandPlaceholder }), children] }) }); }
|
package/dist/overlays.d.ts
CHANGED
|
@@ -2,7 +2,9 @@ import React, { type ReactNode, type ReactElement } from "react";
|
|
|
2
2
|
import { type Responsive } from "./pure.js";
|
|
3
3
|
import { type IconName } from "./system.js";
|
|
4
4
|
export type DialogSize = "xs" | "sm" | "md" | "lg" | "xl" | "full";
|
|
5
|
-
export
|
|
5
|
+
export type DialogPlacement = "auto" | "center" | "top" | "bottom";
|
|
6
|
+
export type DialogIconTone = "neutral" | "brand" | "info" | "success" | "warning" | "danger";
|
|
7
|
+
export declare function Dialog({ open, title, children, footer, onClose, size, dismissible, icon, iconTone, placement }: {
|
|
6
8
|
open: boolean;
|
|
7
9
|
title: ReactNode;
|
|
8
10
|
children: ReactNode;
|
|
@@ -10,8 +12,11 @@ export declare function Dialog({ open, title, children, footer, onClose, size, d
|
|
|
10
12
|
onClose: () => void;
|
|
11
13
|
size?: DialogSize;
|
|
12
14
|
dismissible?: boolean;
|
|
15
|
+
icon?: IconName;
|
|
16
|
+
iconTone?: DialogIconTone;
|
|
17
|
+
placement?: DialogPlacement;
|
|
13
18
|
}): React.JSX.Element;
|
|
14
|
-
export declare function ConfirmDialog({ open, title, description, confirmLabel, cancelLabel, destructive, onConfirm, onCancel }: {
|
|
19
|
+
export declare function ConfirmDialog({ open, title, description, confirmLabel, cancelLabel, destructive, onConfirm, onCancel, icon, iconTone, placement }: {
|
|
15
20
|
open: boolean;
|
|
16
21
|
title: ReactNode;
|
|
17
22
|
description: ReactNode;
|
|
@@ -20,13 +25,18 @@ export declare function ConfirmDialog({ open, title, description, confirmLabel,
|
|
|
20
25
|
destructive?: boolean;
|
|
21
26
|
onConfirm: () => void;
|
|
22
27
|
onCancel: () => void;
|
|
28
|
+
icon?: IconName;
|
|
29
|
+
iconTone?: DialogIconTone;
|
|
30
|
+
placement?: DialogPlacement;
|
|
23
31
|
}): React.JSX.Element;
|
|
24
|
-
export
|
|
32
|
+
export type DrawerSide = "left" | "right" | "top" | "bottom";
|
|
33
|
+
export declare function Drawer({ open, title, children, footer, onClose, side }: {
|
|
25
34
|
open: boolean;
|
|
26
35
|
title: ReactNode;
|
|
27
36
|
children: ReactNode;
|
|
37
|
+
footer?: ReactNode;
|
|
28
38
|
onClose: () => void;
|
|
29
|
-
side?:
|
|
39
|
+
side?: DrawerSide;
|
|
30
40
|
}): React.JSX.Element;
|
|
31
41
|
export type AccessGateProps = {
|
|
32
42
|
allowed: boolean;
|
|
@@ -42,16 +52,20 @@ export type AccessGateProps = {
|
|
|
42
52
|
});
|
|
43
53
|
export declare function AccessGate({ allowed, children, ...resto }: AccessGateProps): React.JSX.Element;
|
|
44
54
|
export type OverlaySide = "top" | "right" | "bottom" | "left";
|
|
45
|
-
export declare function Tooltip({ children, content, side }: {
|
|
55
|
+
export declare function Tooltip({ children, content, side, arrow, delay, closeDelay }: {
|
|
46
56
|
children: ReactElement;
|
|
47
57
|
content: ReactNode;
|
|
48
58
|
side?: OverlaySide;
|
|
59
|
+
arrow?: boolean;
|
|
60
|
+
delay?: number;
|
|
61
|
+
closeDelay?: number;
|
|
49
62
|
}): React.JSX.Element;
|
|
50
|
-
export declare function Popover({ trigger, title, children, side }: {
|
|
63
|
+
export declare function Popover({ trigger, title, children, side, arrow }: {
|
|
51
64
|
trigger: ReactElement;
|
|
52
65
|
title?: ReactNode;
|
|
53
66
|
children: ReactNode;
|
|
54
67
|
side?: OverlaySide;
|
|
68
|
+
arrow?: boolean;
|
|
55
69
|
}): React.JSX.Element;
|
|
56
70
|
export declare function HoverCard({ trigger, children, side }: {
|
|
57
71
|
trigger: ReactElement;
|
package/dist/overlays.js
CHANGED
|
@@ -5,6 +5,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
5
5
|
// internal → system → actions → feedback → inputs → navigation → layout → data-display → resto.
|
|
6
6
|
import React, { useRef } from "react";
|
|
7
7
|
import { Dialog as BaseDialog } from "@base-ui/react/dialog";
|
|
8
|
+
import { Drawer as BaseDrawer } from "@base-ui/react/drawer";
|
|
8
9
|
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog";
|
|
9
10
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
10
11
|
import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
|
|
@@ -15,12 +16,17 @@ import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
|
|
|
15
16
|
import { cx, useAureaStrings, usePortalContainer } from "./internal.js";
|
|
16
17
|
import { useValorResponsivo } from "./responsivo-runtime.js";
|
|
17
18
|
import { Icon } from "./system.js";
|
|
18
|
-
import { Button } from "./actions.js";
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
import { Button, CloseButton } from "./actions.js";
|
|
20
|
+
function IconeDaJanela({ icon, tone }) {
|
|
21
|
+
return _jsx("span", { className: cx("dialog-icon", `dialog-icon-${tone}`), "aria-hidden": "true", children: _jsx(Icon, { name: icon }) });
|
|
22
|
+
}
|
|
23
|
+
export function Dialog({ open, title, children, footer, onClose, size = "md", dismissible = true, icon, iconTone = "neutral", placement = "auto" }) {
|
|
21
24
|
const portal = usePortalContainer();
|
|
25
|
+
// O X vem PRIMEIRO na ordem do documento, como o gatilho de fechar da referência: o motor foca o
|
|
26
|
+
// primeiro focável ao abrir, e era o X também quando ele morava no fim do cabeçalho (o título não é
|
|
27
|
+
// focável) — a ordem do Tab não muda.
|
|
22
28
|
return _jsx(BaseDialog.Root, { open: open, disablePointerDismissal: !dismissible, onOpenChange: o => { if (!o && dismissible)
|
|
23
|
-
onClose(); }, children: _jsxs(BaseDialog.Portal, { container: portal, children: [_jsx(BaseDialog.Backdrop, { className: "dialog-backdrop" }), _jsxs(BaseDialog.Popup, { className: cx("dialog", size !== "md" && `dialog-${size}`),
|
|
29
|
+
onClose(); }, children: _jsxs(BaseDialog.Portal, { container: portal, children: [_jsx(BaseDialog.Backdrop, { className: "dialog-backdrop" }), _jsxs(BaseDialog.Popup, { className: cx("dialog", size !== "md" && `dialog-${size}`), "data-placement": placement, children: [_jsx(BaseDialog.Close, { render: _jsx(CloseButton, { className: "dialog-close", disabled: !dismissible }) }), _jsxs("header", { className: "dialog-header", children: [icon && _jsx(IconeDaJanela, { icon: icon, tone: iconTone }), _jsx(BaseDialog.Title, { render: _jsx("h2", {}), className: "dialog-heading", children: title })] }), _jsx("div", { className: "dialog-body", children: children }), footer && _jsx("footer", { className: "dialog-footer", children: footer })] })] }) });
|
|
24
30
|
}
|
|
25
31
|
// ConfirmDialog (M5): a decisão que não se fecha por engano. NÃO é um Dialog com dois botões —
|
|
26
32
|
// é `role="alertdialog"`, e a diferença é de comportamento, não de aparência: o Base UI tira do
|
|
@@ -50,15 +56,23 @@ export function Dialog({ open, title, children, footer, onClose, size = "md", di
|
|
|
50
56
|
// `description` é prop e não `children` porque ela é o nó de `aria-describedby`: o AlertDialog
|
|
51
57
|
// só anuncia o que passa pelo `Description`. Como `children`, um consumidor poria um <div> no
|
|
52
58
|
// meio e o leitor de tela perderia a frase que diz o que se perde.
|
|
53
|
-
|
|
59
|
+
//
|
|
60
|
+
// 0.32.0: a anatomia do `Dialog` (a da referência), sem o X — a decisão não se fecha por engano. O
|
|
61
|
+
// ícone é o círculo de 40 de lá; a cor dele segue o `destructive` quando quem usa não escolhe.
|
|
62
|
+
export function ConfirmDialog({ open, title, description, confirmLabel, cancelLabel, destructive, onConfirm, onCancel, icon, iconTone, placement = "auto" }) {
|
|
54
63
|
const s = useAureaStrings();
|
|
55
64
|
const portal = usePortalContainer();
|
|
56
65
|
const seguro = React.useRef(null);
|
|
57
66
|
return _jsx(BaseAlertDialog.Root, { open: open, onOpenChange: o => { if (!o)
|
|
58
|
-
onCancel(); }, children: _jsxs(BaseAlertDialog.Portal, { container: portal, children: [_jsx(BaseAlertDialog.Backdrop, { className: "dialog-backdrop" }), _jsxs(BaseAlertDialog.Popup, { className: "dialog dialog-confirm", initialFocus: seguro, children: [
|
|
67
|
+
onCancel(); }, children: _jsxs(BaseAlertDialog.Portal, { container: portal, children: [_jsx(BaseAlertDialog.Backdrop, { className: "dialog-backdrop" }), _jsxs(BaseAlertDialog.Popup, { className: "dialog dialog-confirm", initialFocus: seguro, "data-placement": placement, children: [_jsxs("header", { className: "dialog-header", children: [icon && _jsx(IconeDaJanela, { icon: icon, tone: iconTone ?? (destructive ? "danger" : "neutral") }), _jsx(BaseAlertDialog.Title, { render: _jsx("h2", {}), className: "dialog-heading", children: title })] }), _jsx(BaseAlertDialog.Description, { className: "dialog-body", children: description }), _jsxs("footer", { className: "dialog-footer", children: [_jsx(Button, { ref: seguro, variant: "tertiary", onClick: onCancel, children: cancelLabel ?? s.confirmCancel }), _jsx(Button, { variant: destructive ? "danger" : "primary", onClick: onConfirm, children: confirmLabel ?? s.confirmProceed })] })] })] }) });
|
|
68
|
+
}
|
|
69
|
+
const ARRASTO_DO_LADO = { left: "left", right: "right", top: "up", bottom: "down" };
|
|
70
|
+
export function Drawer({ open, title, children, footer, onClose, side = "right" }) {
|
|
71
|
+
const portal = usePortalContainer();
|
|
72
|
+
const alca = _jsx("div", { className: "drawer-handle", "aria-hidden": "true" });
|
|
73
|
+
return _jsx(BaseDrawer.Root, { open: open, onOpenChange: o => { if (!o)
|
|
74
|
+
onClose(); }, swipeDirection: ARRASTO_DO_LADO[side], children: _jsxs(BaseDrawer.Portal, { container: portal, children: [_jsx(BaseDrawer.Backdrop, { className: "drawer-backdrop" }), _jsx(BaseDrawer.Viewport, { className: "drawer-viewport", children: _jsxs(BaseDrawer.Popup, { className: cx("drawer", `drawer-${side}`), children: [_jsx(BaseDrawer.Close, { render: _jsx(CloseButton, { className: "dialog-close" }) }), side === "bottom" && alca, _jsx("header", { className: "dialog-header", children: _jsx(BaseDrawer.Title, { render: _jsx("h2", {}), className: "dialog-heading", children: title }) }), _jsx(BaseDrawer.Content, { className: "dialog-body", children: children }), footer && _jsx("footer", { className: "dialog-footer", children: footer }), side === "top" && alca] }) })] }) });
|
|
59
75
|
}
|
|
60
|
-
export function Drawer({ open, title, children, onClose, side = "right" }) { const s = useAureaStrings(); const portal = usePortalContainer(); return _jsx(BaseDialog.Root, { open: open, onOpenChange: o => { if (!o)
|
|
61
|
-
onClose(); }, children: _jsxs(BaseDialog.Portal, { container: portal, children: [_jsx(BaseDialog.Backdrop, { className: "drawer-backdrop" }), _jsxs(BaseDialog.Popup, { className: cx("drawer", `drawer-${side}`), children: [_jsxs("header", { children: [_jsx(BaseDialog.Title, { render: _jsx("h2", {}), children: title }), _jsx(BaseDialog.Close, { className: "btn btn-ghost btn-icon", "aria-label": s.close, children: _jsx(Icon, { name: "x" }) })] }), children] })] }) }); }
|
|
62
76
|
export function AccessGate({ allowed, children, ...resto }) {
|
|
63
77
|
if (allowed)
|
|
64
78
|
return children;
|
|
@@ -72,8 +86,49 @@ export function AccessGate({ allowed, children, ...resto }) {
|
|
|
72
86
|
// conteúdo da dica. Era tooltip visual, não acessível (padrão APG Tooltip).
|
|
73
87
|
// O id aponta para um elemento que só existe quando aberto; referência pendente é ignorada
|
|
74
88
|
// pela tecnologia assistiva, então não precisa acompanhar o estado.
|
|
75
|
-
|
|
76
|
-
|
|
89
|
+
//
|
|
90
|
+
// 0.32.0, a dica e o popover da referência:
|
|
91
|
+
// • A SETA (`arrow`), desligada por padrão como lá. O desenho é nosso (uma curva de 12 × 6, sem a
|
|
92
|
+
// ponta afiada); ela tem o fundo da janela e a linha da borda, então a borda dá a volta nela.
|
|
93
|
+
// A dica com seta se afasta 8 do gatilho (`--space-2`: os 6 da seta e 2 de folga); sem
|
|
94
|
+
// seta, 4 (`--space-1`) — a referência usa 7 e 3, que não são da nossa escala. O popover fica
|
|
95
|
+
// sempre a 8, com ou sem seta, como o dela.
|
|
96
|
+
// • O ATRASO da dica é o dela: 1,5 s para abrir e 0,5 s para fechar (o motor abre em 0,6 s e
|
|
97
|
+
// fecha na hora). Pelo teclado ela abre já, e depois da primeira as vizinhas abrem sem esperar
|
|
98
|
+
// — é o grupo do `Tooltip.Provider` do `AureaProvider`.
|
|
99
|
+
// • O GATILHO FOCÁVEL (C-11): a dica em cima de um texto só abria pelo teclado se o app pusesse
|
|
100
|
+
// `tabIndex`. A referência resolve no gatilho, que sai focável como botão; aqui também — o que
|
|
101
|
+
// não é focável sozinho (um `<span>`, um selo) ganha `tabIndex=0` e `role="button"`. Na
|
|
102
|
+
// marcação, quando o filho é uma tag; e, quando é um componente, no nó de verdade, depois de
|
|
103
|
+
// montado, porque só o DOM sabe o que o componente desenhou.
|
|
104
|
+
const ATRASO_DA_DICA = 1500, ATRASO_PARA_FECHAR_A_DICA = 500;
|
|
105
|
+
function Seta() { return _jsxs("svg", { viewBox: "0 0 12 12", "aria-hidden": "true", children: [_jsx("path", { className: "overlay-arrow-fill", d: "M0 0Q6 12 12 0Z" }), _jsx("path", { className: "overlay-arrow-line", d: "M0 0Q6 12 12 0", fill: "none" })] }); }
|
|
106
|
+
const FOCAVEIS_POR_NATUREZA = new Set(["button", "input", "select", "textarea", "summary", "iframe", "audio", "video"]);
|
|
107
|
+
function focavelNaMarcacao(el) {
|
|
108
|
+
if (typeof el.type !== "string")
|
|
109
|
+
return undefined;
|
|
110
|
+
const p = el.props;
|
|
111
|
+
if (p.tabIndex !== undefined)
|
|
112
|
+
return true;
|
|
113
|
+
if (el.type === "a" || el.type === "area")
|
|
114
|
+
return p.href !== undefined;
|
|
115
|
+
return FOCAVEIS_POR_NATUREZA.has(el.type);
|
|
116
|
+
}
|
|
117
|
+
function garantirFoco(no) {
|
|
118
|
+
if (!no || no.tabIndex >= 0 || no.hasAttribute("tabindex"))
|
|
119
|
+
return;
|
|
120
|
+
no.tabIndex = 0;
|
|
121
|
+
if (!no.hasAttribute("role"))
|
|
122
|
+
no.setAttribute("role", "button");
|
|
123
|
+
}
|
|
124
|
+
export function Tooltip({ children, content, side = "top", arrow = false, delay = ATRASO_DA_DICA, closeDelay = ATRASO_PARA_FECHAR_A_DICA }) {
|
|
125
|
+
const id = React.useId();
|
|
126
|
+
const triggerId = children.props.id;
|
|
127
|
+
const portal = usePortalContainer();
|
|
128
|
+
const foco = focavelNaMarcacao(children) === false ? { tabIndex: 0, role: "button" } : {};
|
|
129
|
+
return _jsxs(BaseTooltip.Root, { children: [_jsx(BaseTooltip.Trigger, { ref: garantirFoco, id: triggerId, render: children, "aria-describedby": id, delay: delay, closeDelay: closeDelay, ...foco }), _jsx(BaseTooltip.Portal, { container: portal, children: _jsx(BaseTooltip.Positioner, { className: "positioner", side: side, sideOffset: arrow ? 8 : 4, children: _jsxs(BaseTooltip.Popup, { id: id, role: "tooltip", className: "tooltip", children: [arrow && _jsx(BaseTooltip.Arrow, { className: "overlay-arrow", children: _jsx(Seta, {}) }), content] }) }) })] });
|
|
130
|
+
}
|
|
131
|
+
export function Popover({ trigger, title, children, side = "bottom", arrow = false }) { const portal = usePortalContainer(); return _jsxs(BasePopover.Root, { children: [_jsx(BasePopover.Trigger, { render: trigger }), _jsx(BasePopover.Portal, { container: portal, children: _jsx(BasePopover.Positioner, { className: "positioner", side: side, sideOffset: 8, children: _jsxs(BasePopover.Popup, { className: "popover", children: [arrow && _jsx(BasePopover.Arrow, { className: "overlay-arrow", children: _jsx(Seta, {}) }), title && _jsx(BasePopover.Title, { render: _jsx("strong", {}), className: "popover-title", children: title }), children] }) }) })] }); }
|
|
77
132
|
// HoverCard (Lote 1 do BUILDING.md). Não é Tooltip nem Popover, e a diferença é de propósito,
|
|
78
133
|
// não de aparência: a Tooltip é um RÓTULO curto (`role="tooltip"`, some ao mover o mouse); o
|
|
79
134
|
// Popover abre por CLIQUE e pode conter foco; este é uma PRÉVIA rica que aparece ao repousar o
|
|
@@ -83,7 +138,7 @@ export function Popover({ trigger, title, children, side = "bottom" }) { const p
|
|
|
83
138
|
// um segundo nome criaria duas peles para a mesma coisa.
|
|
84
139
|
// Por depender de repouso do ponteiro, NÃO serve para informação essencial — quem navega só por
|
|
85
140
|
// teclado ou toque não abre um hover card. Conteúdo obrigatório vai em Popover.
|
|
86
|
-
export function HoverCard({ trigger, children, side = "bottom" }) { const portal = usePortalContainer(); return _jsxs(BasePreviewCard.Root, { children: [_jsx(BasePreviewCard.Trigger, { render: trigger }), _jsx(BasePreviewCard.Portal, { container: portal, children: _jsx(BasePreviewCard.Positioner, { side: side, sideOffset: 8, children: _jsx(BasePreviewCard.Popup, { className: "popover hover-card", children: children }) }) })] }); }
|
|
141
|
+
export function HoverCard({ trigger, children, side = "bottom" }) { const portal = usePortalContainer(); return _jsxs(BasePreviewCard.Root, { children: [_jsx(BasePreviewCard.Trigger, { render: trigger }), _jsx(BasePreviewCard.Portal, { container: portal, children: _jsx(BasePreviewCard.Positioner, { className: "positioner", side: side, sideOffset: 8, children: _jsx(BasePreviewCard.Popup, { className: "popover hover-card", children: children }) }) })] }); }
|
|
87
142
|
// A MARCA de um item que alterna fica num slot de largura FIXA, e não condicional: sem ele, um
|
|
88
143
|
// menu com um item marcado e outro não desalinharia os rótulos a cada clique — o texto andaria
|
|
89
144
|
// para o lado sozinho. É a mesma razão de o `leadingIcon` ter lugar próprio.
|
|
@@ -114,7 +169,7 @@ function renderMenuItems(items, portal) {
|
|
|
114
169
|
const sm = it;
|
|
115
170
|
// O submenu é uma RAIZ própria com gatilho próprio — não é um item que "abre outro menu".
|
|
116
171
|
// É o que dá `aria-haspopup`, a seta para a direita e o fechamento em cascata de graça.
|
|
117
|
-
return _jsxs(BaseMenu.SubmenuRoot, { children: [_jsxs(BaseMenu.SubmenuTrigger, { className: "menu-item", disabled: sm.disabled, children: [dentro(sm), _jsx(Icon, { name: "caret-right", size: "sm", className: "menu-seta" })] }), _jsx(BaseMenu.Portal, { container: portal, children: _jsx(BaseMenu.Positioner, { side: "inline-end", sideOffset: 4, children: _jsx(BaseMenu.Popup, { className: "menu", children: renderMenuItems(sm.items, portal) }) }) })] }, i);
|
|
172
|
+
return _jsxs(BaseMenu.SubmenuRoot, { children: [_jsxs(BaseMenu.SubmenuTrigger, { className: "menu-item", disabled: sm.disabled, children: [dentro(sm), _jsx(Icon, { name: "caret-right", size: "sm", className: "menu-seta" })] }), _jsx(BaseMenu.Portal, { container: portal, children: _jsx(BaseMenu.Positioner, { className: "positioner", side: "inline-end", sideOffset: 4, children: _jsx(BaseMenu.Popup, { className: "menu", children: renderMenuItems(sm.items, portal) }) }) })] }, i);
|
|
118
173
|
}
|
|
119
174
|
case "checkbox": {
|
|
120
175
|
const c = it;
|
|
@@ -136,13 +191,13 @@ function renderMenuItems(items, portal) {
|
|
|
136
191
|
}
|
|
137
192
|
});
|
|
138
193
|
}
|
|
139
|
-
export function DropdownMenu({ trigger, items, side = "bottom", label }) { const portal = usePortalContainer(); return _jsxs(BaseMenu.Root, { children: [_jsx(BaseMenu.Trigger, { render: trigger }), _jsx(BaseMenu.Portal, { container: portal, children: _jsx(BaseMenu.Positioner, { side: side, sideOffset: 6, children: _jsx(BaseMenu.Popup, { className: "menu", "aria-label": label, children: renderMenuItems(items, portal) }) }) })] }); }
|
|
194
|
+
export function DropdownMenu({ trigger, items, side = "bottom", label }) { const portal = usePortalContainer(); return _jsxs(BaseMenu.Root, { children: [_jsx(BaseMenu.Trigger, { render: trigger }), _jsx(BaseMenu.Portal, { container: portal, children: _jsx(BaseMenu.Positioner, { className: "positioner", side: side, sideOffset: 6, children: _jsx(BaseMenu.Popup, { className: "menu", "aria-label": label, children: renderMenuItems(items, portal) }) }) })] }); }
|
|
140
195
|
// ContextMenu: abre no botão direito e — por teclado — em Shift+F10 / tecla Menu,
|
|
141
196
|
// que o browser só dispara (como evento contextmenu) sobre um elemento FOCADO. Por
|
|
142
197
|
// isso o gatilho é focável (tabIndex 0) e tem nome acessível (auditoria 18/07/2026,
|
|
143
198
|
// MÉDIO 3); sem isso o teclado não alcança o menu. Consumidor pode sobrescrever
|
|
144
199
|
// tabIndex via children se o próprio já for focável.
|
|
145
|
-
export function ContextMenu({ children, items, label, className }) { const portal = usePortalContainer(); return _jsxs(BaseContextMenu.Root, { children: [_jsx(BaseContextMenu.Trigger, { className: className, tabIndex: 0, "aria-label": label, "aria-haspopup": "menu", children: children }), _jsx(BaseContextMenu.Portal, { container: portal, children: _jsx(BaseContextMenu.Positioner, { children: _jsx(BaseContextMenu.Popup, { className: "menu", "aria-label": label, children: renderMenuItems(items, portal) }) }) })] }); }
|
|
200
|
+
export function ContextMenu({ children, items, label, className }) { const portal = usePortalContainer(); return _jsxs(BaseContextMenu.Root, { children: [_jsx(BaseContextMenu.Trigger, { className: className, tabIndex: 0, "aria-label": label, "aria-haspopup": "menu", children: children }), _jsx(BaseContextMenu.Portal, { container: portal, children: _jsx(BaseContextMenu.Positioner, { className: "positioner", children: _jsx(BaseContextMenu.Popup, { className: "menu", "aria-label": label, children: renderMenuItems(items, portal) }) }) })] }); }
|
|
146
201
|
// G-AXIS-06 — o valor responsivo RESOLVIDO é a única fonte de verdade: ele vai para o motor, o
|
|
147
202
|
// motor publica `data-orientation`/`aria-orientation` e ajusta o teclado, e a pele reage ao
|
|
148
203
|
// atributo publicado. Ver `decisions/0047-css-first-para-apresentacao-runtime-para-semantica.md`.
|
|
@@ -151,5 +206,5 @@ export function Menubar({ menus, label, modal, disabled, loopFocus, orientation,
|
|
|
151
206
|
const ancora = useRef(null);
|
|
152
207
|
const resolvida = useValorResponsivo(orientation, "horizontal", ancora);
|
|
153
208
|
const vertical = resolvida === "vertical";
|
|
154
|
-
return _jsx(BaseMenubar, { ref: ancora, modal: modal, disabled: disabled, loopFocus: loopFocus, orientation: resolvida, "aria-label": label, className: cx("menubar", className), children: menus.map((m, i) => _jsxs(BaseMenu.Root, { disabled: m.disabled, children: [_jsx(BaseMenu.Trigger, { className: "menubar-trigger", children: m.label }), _jsx(BaseMenu.Portal, { container: portal, children: _jsx(BaseMenu.Positioner, { side: vertical ? "inline-end" : "bottom", align: "start", sideOffset: 4, children: _jsx(BaseMenu.Popup, { className: "menu", children: renderMenuItems(m.items) }) }) })] }, i)) });
|
|
209
|
+
return _jsx(BaseMenubar, { ref: ancora, modal: modal, disabled: disabled, loopFocus: loopFocus, orientation: resolvida, "aria-label": label, className: cx("menubar", className), children: menus.map((m, i) => _jsxs(BaseMenu.Root, { disabled: m.disabled, children: [_jsx(BaseMenu.Trigger, { className: "menubar-trigger", children: m.label }), _jsx(BaseMenu.Portal, { container: portal, children: _jsx(BaseMenu.Positioner, { className: "positioner", side: vertical ? "inline-end" : "bottom", align: "start", sideOffset: 4, children: _jsx(BaseMenu.Popup, { className: "menu", children: renderMenuItems(m.items) }) }) })] }, i)) });
|
|
155
210
|
}
|
package/dist/pure.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export declare function fundirRender(render: ReactElement | undefined, props: {
|
|
|
4
4
|
className?: string;
|
|
5
5
|
} & Record<string, unknown>, padrao?: string): ReactElement;
|
|
6
6
|
export type AureaTheme = "dark" | "light";
|
|
7
|
+
/** O que se ESCOLHE (15/10/2026): um tema, ou `"system"` — seguir o claro/escuro do sistema, e mudar junto com ele.
|
|
8
|
+
* O tema na tela continua sendo `AureaTheme`; a preferência é o que a chave de três posições guarda. */
|
|
9
|
+
export type AureaThemePreference = AureaTheme | "system";
|
|
7
10
|
export type AureaDensity = "compact" | "comfortable" | "spacious";
|
|
8
11
|
export type UniversalState = "waiting_user" | "waiting_approval" | "waiting_dependency" | "offline" | "stale" | "partial" | "degraded";
|
|
9
12
|
export declare const universalStates: readonly UniversalState[];
|
|
@@ -15,9 +18,12 @@ export interface AureaStrings {
|
|
|
15
18
|
close: string;
|
|
16
19
|
confirmCancel: string;
|
|
17
20
|
dataError: string;
|
|
21
|
+
dataCrashed: string;
|
|
22
|
+
dataRetry: string;
|
|
18
23
|
dataEmpty: string;
|
|
19
24
|
confirmProceed: string;
|
|
20
25
|
paginationLabel: string;
|
|
26
|
+
paginationPage: string;
|
|
21
27
|
previous: string;
|
|
22
28
|
next: string;
|
|
23
29
|
breadcrumbLabel: string;
|
|
@@ -26,6 +32,9 @@ export interface AureaStrings {
|
|
|
26
32
|
tableLabel: string;
|
|
27
33
|
commandLabel: string;
|
|
28
34
|
commandPlaceholder: string;
|
|
35
|
+
commandHintMove: string;
|
|
36
|
+
commandHintSelect: string;
|
|
37
|
+
commandHintClose: string;
|
|
29
38
|
dismissNotification: string;
|
|
30
39
|
toolbarLabel: string;
|
|
31
40
|
loading: string;
|
|
@@ -166,6 +175,8 @@ export interface AureaStrings {
|
|
|
166
175
|
graphZoomOut: string;
|
|
167
176
|
graphFit: string;
|
|
168
177
|
graphLegend: string;
|
|
178
|
+
graphLegendKind: string;
|
|
179
|
+
graphLegendStatus: string;
|
|
169
180
|
graphOverview: string;
|
|
170
181
|
graphConnections: string;
|
|
171
182
|
graphShow: string;
|
|
@@ -209,6 +220,8 @@ export interface AureaStrings {
|
|
|
209
220
|
qrCode: string;
|
|
210
221
|
chartLabel: string;
|
|
211
222
|
copyCode: string;
|
|
223
|
+
codeBlockPreview: string;
|
|
224
|
+
codeBlockCode: string;
|
|
212
225
|
copied: string;
|
|
213
226
|
linkCopied: string;
|
|
214
227
|
linkCopyFailed: string;
|
|
@@ -219,7 +232,21 @@ export interface AureaStrings {
|
|
|
219
232
|
sidebarExpand: string;
|
|
220
233
|
bottomNavLabel: string;
|
|
221
234
|
themeToDark: string;
|
|
235
|
+
themeChoice: string;
|
|
236
|
+
themeLight: string;
|
|
237
|
+
themeDark: string;
|
|
238
|
+
themeSystem: string;
|
|
222
239
|
themeToLight: string;
|
|
240
|
+
datePlaceholder: string;
|
|
241
|
+
dateRangePlaceholder: string;
|
|
242
|
+
colorPicker: string;
|
|
243
|
+
colorArea2D: string;
|
|
244
|
+
colorChannel: Record<"hue" | "saturation" | "brightness" | "lightness" | "red" | "green" | "blue" | "alpha", string>;
|
|
245
|
+
colorHue: Record<"red" | "orange" | "yellow" | "green" | "cyan" | "blue" | "purple" | "magenta" | "pink" | "brown" | "gray" | "white" | "black", string>;
|
|
246
|
+
colorTone: Record<"veryDark" | "dark" | "light" | "veryLight" | "vivid" | "pale" | "grayish", string>;
|
|
247
|
+
colorNameFormat: string;
|
|
248
|
+
colorHex: string;
|
|
249
|
+
colorSwatches: string;
|
|
223
250
|
universalState: Record<UniversalState, string>;
|
|
224
251
|
}
|
|
225
252
|
export declare const defaultStrings: AureaStrings;
|