@aurea-uds/react 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -2
- package/dist/actions.d.ts +20 -0
- package/dist/actions.js +59 -5
- package/dist/agents.d.ts +209 -0
- package/dist/agents.js +302 -0
- package/dist/calendar.d.ts +6 -0
- package/dist/calendar.js +27 -0
- package/dist/chart.d.ts +10 -0
- package/dist/chart.js +53 -0
- package/dist/code-client.d.ts +6 -0
- package/dist/code-client.js +24 -0
- package/dist/code-editor.js +1 -0
- package/dist/code.d.ts +2 -13
- package/dist/code.js +5 -18
- package/dist/communication.js +1 -0
- package/dist/data-display-client.d.ts +14 -0
- package/dist/data-display-client.js +22 -0
- package/dist/data-display.d.ts +2 -23
- package/dist/data-display.js +5 -13
- package/dist/data-grid.d.ts +52 -3
- package/dist/data-grid.js +205 -25
- package/dist/feedback-client.d.ts +64 -0
- package/dist/feedback-client.js +110 -0
- package/dist/feedback.d.ts +2 -53
- package/dist/feedback.js +5 -71
- package/dist/file-input.d.ts +21 -2
- package/dist/file-input.js +202 -21
- package/dist/graph.d.ts +33 -0
- package/dist/graph.js +178 -0
- package/dist/identity-client.d.ts +9 -0
- package/dist/identity-client.js +12 -0
- package/dist/identity.d.ts +2 -8
- package/dist/identity.js +5 -3
- package/dist/index.d.ts +4 -1
- package/dist/index.js +33 -3
- package/dist/inputs-client.d.ts +105 -0
- package/dist/inputs-client.js +264 -0
- package/dist/inputs.d.ts +2 -65
- package/dist/inputs.js +9 -61
- package/dist/internal.d.ts +23 -70
- package/dist/internal.js +115 -23
- package/dist/layout-client.d.ts +9 -0
- package/dist/layout-client.js +72 -0
- package/dist/layout.d.ts +2 -14
- package/dist/layout.js +5 -22
- package/dist/markup.d.ts +72 -0
- package/dist/markup.js +87 -0
- package/dist/media-client.d.ts +36 -0
- package/dist/media-client.js +239 -0
- package/dist/media.d.ts +2 -9
- package/dist/media.js +5 -98
- package/dist/navigation-client.d.ts +94 -0
- package/dist/navigation-client.js +154 -0
- package/dist/navigation.d.ts +2 -59
- package/dist/navigation.js +5 -113
- package/dist/overlays.d.ts +28 -0
- package/dist/overlays.js +66 -10
- package/dist/pure.d.ts +196 -0
- package/dist/pure.js +111 -0
- package/dist/qrcode.d.ts +2 -1
- package/dist/qrcode.js +3 -2
- package/dist/system.d.ts +11 -1
- package/dist/system.js +59 -4
- package/package.json +40 -4
package/dist/navigation.d.ts
CHANGED
|
@@ -1,59 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export declare function Breadcrumb({ items, label }: {
|
|
4
|
-
items: Array<{
|
|
5
|
-
label: ReactNode;
|
|
6
|
-
href?: string;
|
|
7
|
-
}>;
|
|
8
|
-
label?: string;
|
|
9
|
-
}): React.JSX.Element;
|
|
10
|
-
export declare function Tabs({ tabs, value, onChange, label }: {
|
|
11
|
-
tabs: Array<{
|
|
12
|
-
id: string;
|
|
13
|
-
label: ReactNode;
|
|
14
|
-
content: ReactNode;
|
|
15
|
-
}>;
|
|
16
|
-
value: string;
|
|
17
|
-
onChange: (id: string) => void;
|
|
18
|
-
label?: string;
|
|
19
|
-
}): React.JSX.Element;
|
|
20
|
-
export declare function Pagination({ page, total, onPageChange }: {
|
|
21
|
-
page: number;
|
|
22
|
-
total: number;
|
|
23
|
-
onPageChange: (p: number) => void;
|
|
24
|
-
}): React.JSX.Element;
|
|
25
|
-
export interface TocItem {
|
|
26
|
-
id: string;
|
|
27
|
-
label: string;
|
|
28
|
-
sub?: boolean;
|
|
29
|
-
}
|
|
30
|
-
export declare function TableOfContents({ items, current, label, className, ...props }: HTMLAttributes<HTMLElement> & RefAttributes<HTMLElement> & {
|
|
31
|
-
items: TocItem[];
|
|
32
|
-
current?: string;
|
|
33
|
-
label?: string;
|
|
34
|
-
}): React.JSX.Element;
|
|
35
|
-
export interface TreeNode {
|
|
36
|
-
id: string;
|
|
37
|
-
label: ReactNode;
|
|
38
|
-
icon?: IconName;
|
|
39
|
-
children?: TreeNode[];
|
|
40
|
-
}
|
|
41
|
-
export declare function TreeView({ items, defaultExpandedIds, onSelect, label, className }: {
|
|
42
|
-
items: TreeNode[];
|
|
43
|
-
defaultExpandedIds?: string[];
|
|
44
|
-
onSelect?: (node: TreeNode) => void;
|
|
45
|
-
label?: string;
|
|
46
|
-
className?: string;
|
|
47
|
-
}): ReactElement<unknown, string | React.JSXElementConstructor<any>>;
|
|
48
|
-
export declare function Sidebar({ children, className, ...props }: HTMLAttributes<HTMLElement> & RefAttributes<HTMLElement>): React.JSX.Element;
|
|
49
|
-
export type TopbarVariant = "floating" | "flush" | "pill";
|
|
50
|
-
export declare function Topbar({ variant, brand, children, className, ...props }: HTMLAttributes<HTMLElement> & RefAttributes<HTMLElement> & {
|
|
51
|
-
variant?: TopbarVariant;
|
|
52
|
-
brand?: ReactNode;
|
|
53
|
-
}): React.JSX.Element;
|
|
54
|
-
export declare function CommandPaletteShell({ open, query, onQueryChange, children }: {
|
|
55
|
-
open: boolean;
|
|
56
|
-
query: string;
|
|
57
|
-
onQueryChange: (v: string) => void;
|
|
58
|
-
children?: ReactNode;
|
|
59
|
-
}): React.JSX.Element | null;
|
|
1
|
+
export * from "./navigation-client.js";
|
|
2
|
+
export { Topbar, type TopbarVariant } from "./markup.js";
|
package/dist/navigation.js
CHANGED
|
@@ -1,113 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
7
|
-
import { cx, useAureaStrings } from "./internal.js";
|
|
8
|
-
import { Icon } from "./system.js";
|
|
9
|
-
import { Button } from "./actions.js";
|
|
10
|
-
import { Badge } from "./feedback.js";
|
|
11
|
-
import { SearchField } from "./inputs.js";
|
|
12
|
-
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: "chevron--right", size: "sm" }), " ", i.href ? _jsx("a", { href: i.href, children: i.label }) : _jsx("strong", { "aria-current": "page", children: i.label })] }, n)) }); }
|
|
13
|
-
export function Tabs({ tabs, value, onChange, label }) { const s = useAureaStrings(); return _jsxs(BaseTabs.Root, { value: value, onValueChange: v => onChange(String(v)), children: [_jsx(BaseTabs.List, { className: "tabs", "aria-label": label ?? s.tabsLabel, activateOnFocus: true, 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: "card card-inset", tabIndex: 0, children: t.content }, t.id))] }); }
|
|
14
|
-
export function Pagination({ page, total, onPageChange }) { const s = useAureaStrings(); return _jsxs("nav", { className: "pagination", "aria-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 })] }); }
|
|
15
|
-
export function TableOfContents({ items, current, label, className, ...props }) {
|
|
16
|
-
const s = useAureaStrings();
|
|
17
|
-
return _jsxs("nav", { className: cx("toc", className), "aria-label": label ?? s.tocLabel, ...props, children: [_jsx("p", { className: "toc-label", children: label ?? s.tocLabel }), items.map(i => _jsx("a", { href: `#${i.id}`, className: cx(i.sub && "toc-sub"), ...(i.id === current ? { "aria-current": "true" } : {}), children: i.label }, i.id))] });
|
|
18
|
-
}
|
|
19
|
-
function flattenVisible(nodes, expanded, level = 1, parentId, acc = []) {
|
|
20
|
-
for (const node of nodes) {
|
|
21
|
-
acc.push({ node, level, parentId });
|
|
22
|
-
if (node.children?.length && expanded.has(node.id))
|
|
23
|
-
flattenVisible(node.children, expanded, level + 1, node.id, acc);
|
|
24
|
-
}
|
|
25
|
-
return acc;
|
|
26
|
-
}
|
|
27
|
-
export function TreeView({ items, defaultExpandedIds, onSelect, label, className }) {
|
|
28
|
-
const s = useAureaStrings();
|
|
29
|
-
const baseId = React.useId();
|
|
30
|
-
const [expanded, setExpanded] = React.useState(() => new Set(defaultExpandedIds));
|
|
31
|
-
const [selected, setSelected] = React.useState();
|
|
32
|
-
const [active, setActive] = React.useState(() => items[0]?.id);
|
|
33
|
-
const rootRef = React.useRef(null);
|
|
34
|
-
const visible = flattenVisible(items, expanded);
|
|
35
|
-
// Roving tab stop derivado: se o nó ativo saiu do conjunto visível (dados
|
|
36
|
-
// trocados, nó removido), o primeiro visível volta a ser tabulável — senão a
|
|
37
|
-
// árvore inteira fica tabIndex=-1 e some da ordem do Tab (auditoria, MÉDIO 1).
|
|
38
|
-
const effectiveActive = active !== undefined && visible.some(v => v.node.id === active) ? active : visible[0]?.node.id;
|
|
39
|
-
const focusId = (id) => { setActive(id); rootRef.current?.querySelector(`[data-tree-id="${CSS.escape(id)}"]`)?.focus(); };
|
|
40
|
-
const toggle = (id, open) => setExpanded(prev => { const n = new Set(prev); if (open)
|
|
41
|
-
n.add(id);
|
|
42
|
-
else
|
|
43
|
-
n.delete(id); return n; });
|
|
44
|
-
const select = (node) => { setSelected(node.id); onSelect?.(node); };
|
|
45
|
-
const onKeyDown = (e) => {
|
|
46
|
-
const idx = visible.findIndex(v => v.node.id === effectiveActive);
|
|
47
|
-
if (idx < 0)
|
|
48
|
-
return;
|
|
49
|
-
const cur = visible[idx], hasChildren = !!cur.node.children?.length, isOpen = expanded.has(cur.node.id);
|
|
50
|
-
const rtl = getComputedStyle(e.currentTarget).direction === "rtl";
|
|
51
|
-
const expandKey = rtl ? "ArrowLeft" : "ArrowRight", collapseKey = rtl ? "ArrowRight" : "ArrowLeft";
|
|
52
|
-
switch (e.key) {
|
|
53
|
-
case "ArrowDown":
|
|
54
|
-
e.preventDefault();
|
|
55
|
-
if (idx < visible.length - 1)
|
|
56
|
-
focusId(visible[idx + 1].node.id);
|
|
57
|
-
break;
|
|
58
|
-
case "ArrowUp":
|
|
59
|
-
e.preventDefault();
|
|
60
|
-
if (idx > 0)
|
|
61
|
-
focusId(visible[idx - 1].node.id);
|
|
62
|
-
break;
|
|
63
|
-
case expandKey:
|
|
64
|
-
e.preventDefault();
|
|
65
|
-
if (hasChildren && !isOpen)
|
|
66
|
-
toggle(cur.node.id, true);
|
|
67
|
-
else if (hasChildren && isOpen)
|
|
68
|
-
focusId(cur.node.children[0].id);
|
|
69
|
-
break;
|
|
70
|
-
case collapseKey:
|
|
71
|
-
e.preventDefault();
|
|
72
|
-
if (hasChildren && isOpen)
|
|
73
|
-
toggle(cur.node.id, false);
|
|
74
|
-
else if (cur.parentId)
|
|
75
|
-
focusId(cur.parentId);
|
|
76
|
-
break;
|
|
77
|
-
case "Home":
|
|
78
|
-
e.preventDefault();
|
|
79
|
-
focusId(visible[0].node.id);
|
|
80
|
-
break;
|
|
81
|
-
case "End":
|
|
82
|
-
e.preventDefault();
|
|
83
|
-
focusId(visible[visible.length - 1].node.id);
|
|
84
|
-
break;
|
|
85
|
-
case "Enter":
|
|
86
|
-
case " ":
|
|
87
|
-
e.preventDefault();
|
|
88
|
-
select(cur.node);
|
|
89
|
-
if (hasChildren)
|
|
90
|
-
toggle(cur.node.id, !isOpen);
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
const renderNodes = (nodes, level) => (_jsx("ul", { ref: level === 1 ? rootRef : undefined, className: cx(level === 1 ? "tree" : "tree-group", level === 1 && className), role: level === 1 ? "tree" : "group", "aria-label": level === 1 ? (label ?? s.treeLabel) : undefined, onKeyDown: level === 1 ? onKeyDown : undefined, children: nodes.map(node => {
|
|
95
|
-
const hasChildren = !!node.children?.length, isOpen = expanded.has(node.id), isSelected = selected === node.id, labelId = baseId + node.id;
|
|
96
|
-
return _jsxs("li", { className: "tree-item", role: "treeitem", "data-tree-id": node.id, "aria-level": level, "aria-expanded": hasChildren ? isOpen : undefined, "aria-selected": isSelected, "aria-labelledby": labelId, tabIndex: node.id === effectiveActive ? 0 : -1, children: [_jsxs("span", { className: "tree-node", "data-selected": isSelected || undefined, style: { paddingInlineStart: `calc(var(--space-3) + ${level - 1} * var(--space-4))` }, onClick: () => { focusId(node.id); select(node); if (hasChildren)
|
|
97
|
-
toggle(node.id, !isOpen); }, children: [hasChildren ? _jsx(Icon, { name: "chevron--right", size: "sm", className: "tree-twist" }) : _jsx("span", { className: "tree-indent", "aria-hidden": "true" }), node.icon && _jsx(Icon, { name: node.icon, size: "sm" }), _jsx("span", { id: labelId, className: "tree-label", children: node.label })] }), hasChildren && isOpen && renderNodes(node.children, level + 1)] }, node.id);
|
|
98
|
-
}) }));
|
|
99
|
-
return renderNodes(items, 1);
|
|
100
|
-
}
|
|
101
|
-
// Sidebar/Topbar: eram <aside>/<header> soltos DENTRO do AppShell; agora são componentes
|
|
102
|
-
// nomeados que o AppShell COMPÕE (dogfooding, AUREA.md §2.4 — "se o catálogo mostra uma
|
|
103
|
-
// Sidebar, a sidebar dele É a Sidebar da Aurea"). O landmark vem do elemento nativo
|
|
104
|
-
// (<aside>=complementary, <header>=banner); o <nav> de navegação é do consumidor, passado
|
|
105
|
-
// como children — por isso não embutimos <nav> aqui (aninharia landmark).
|
|
106
|
-
export function Sidebar({ children, className, ...props }) { return _jsx("aside", { className: cx("sidebar", className), ...props, children: children }); }
|
|
107
|
-
export function Topbar({ variant = "floating", brand, children, className, ...props }) { return _jsxs("header", { className: cx("topbar", `topbar-${variant}`, className), ...props, children: [brand != null && _jsx("div", { className: "brand", children: brand }), children] }); }
|
|
108
|
-
// Shell NÃO-modal de propósito: é presentational (o consumidor controla open) e não
|
|
109
|
-
// tem focus trap/inert/Escape — declarar aria-modal sem entregar a modalidade faria
|
|
110
|
-
// leitores ocultarem o resto da página com o teclado ainda alcançando tudo
|
|
111
|
-
// (auditoria 18/07/2026, ALTO 2; APG dialog-modal). Modal de verdade = BaseDialog.
|
|
112
|
-
export function CommandPaletteShell({ open, query, onQueryChange, children }) { const s = useAureaStrings(); if (!open)
|
|
113
|
-
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] }) }); }
|
|
1
|
+
// VITRINE da categoria — é este arquivo que `@aurea-uds/react/navigation` resolve. Sem
|
|
2
|
+
// `"use client"` de propósito: a diretiva contamina o módulo inteiro e faria a marcação pura
|
|
3
|
+
// chegar como cliente por vizinhança (ADR-0026; o check 26b reprova quem a puser de volta aqui).
|
|
4
|
+
export * from "./navigation-client.js";
|
|
5
|
+
export { Topbar } from "./markup.js";
|
package/dist/overlays.d.ts
CHANGED
|
@@ -7,6 +7,16 @@ export declare function Dialog({ open, title, children, footer, onClose }: {
|
|
|
7
7
|
footer?: ReactNode;
|
|
8
8
|
onClose: () => void;
|
|
9
9
|
}): React.JSX.Element;
|
|
10
|
+
export declare function ConfirmDialog({ open, title, description, confirmLabel, cancelLabel, destructive, onConfirm, onCancel }: {
|
|
11
|
+
open: boolean;
|
|
12
|
+
title: ReactNode;
|
|
13
|
+
description: ReactNode;
|
|
14
|
+
confirmLabel?: string;
|
|
15
|
+
cancelLabel?: string;
|
|
16
|
+
destructive?: boolean;
|
|
17
|
+
onConfirm: () => void;
|
|
18
|
+
onCancel: () => void;
|
|
19
|
+
}): React.JSX.Element;
|
|
10
20
|
export declare function Drawer({ open, title, children, onClose, side }: {
|
|
11
21
|
open: boolean;
|
|
12
22
|
title: ReactNode;
|
|
@@ -14,6 +24,19 @@ export declare function Drawer({ open, title, children, onClose, side }: {
|
|
|
14
24
|
onClose: () => void;
|
|
15
25
|
side?: "left" | "right";
|
|
16
26
|
}): React.JSX.Element;
|
|
27
|
+
export type AccessGateProps = {
|
|
28
|
+
allowed: boolean;
|
|
29
|
+
children: ReactElement;
|
|
30
|
+
} & ({
|
|
31
|
+
mode?: "hide";
|
|
32
|
+
fallback?: ReactNode;
|
|
33
|
+
reason?: never;
|
|
34
|
+
} | {
|
|
35
|
+
mode: "disable";
|
|
36
|
+
reason: ReactNode;
|
|
37
|
+
fallback?: never;
|
|
38
|
+
});
|
|
39
|
+
export declare function AccessGate({ allowed, children, ...resto }: AccessGateProps): React.JSX.Element;
|
|
17
40
|
export type OverlaySide = "top" | "right" | "bottom" | "left";
|
|
18
41
|
export declare function Tooltip({ children, content, side }: {
|
|
19
42
|
children: ReactElement;
|
|
@@ -26,6 +49,11 @@ export declare function Popover({ trigger, title, children, side }: {
|
|
|
26
49
|
children: ReactNode;
|
|
27
50
|
side?: OverlaySide;
|
|
28
51
|
}): React.JSX.Element;
|
|
52
|
+
export declare function HoverCard({ trigger, children, side }: {
|
|
53
|
+
trigger: ReactElement;
|
|
54
|
+
children: ReactNode;
|
|
55
|
+
side?: OverlaySide;
|
|
56
|
+
}): React.JSX.Element;
|
|
29
57
|
export interface MenuItemDef {
|
|
30
58
|
label: ReactNode;
|
|
31
59
|
onClick?: () => void;
|
package/dist/overlays.js
CHANGED
|
@@ -1,36 +1,92 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
3
|
// Fase 9 (achado A5): este arquivo saiu do index.tsx de 970 linhas. Um módulo por categoria
|
|
3
4
|
// do registry — a taxonomia já existia e é gateada. A ordem de import entre eles é um DAG:
|
|
4
5
|
// internal → system → actions → feedback → inputs → navigation → layout → data-display → resto.
|
|
5
6
|
import React from "react";
|
|
6
7
|
import { Dialog as BaseDialog } from "@base-ui/react/dialog";
|
|
8
|
+
import { AlertDialog as BaseAlertDialog } from "@base-ui/react/alert-dialog";
|
|
7
9
|
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
8
10
|
import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
|
|
9
11
|
import { Menu as BaseMenu } from "@base-ui/react/menu";
|
|
10
12
|
import { ContextMenu as BaseContextMenu } from "@base-ui/react/context-menu";
|
|
11
|
-
import {
|
|
13
|
+
import { PreviewCard as BasePreviewCard } from "@base-ui/react/preview-card";
|
|
14
|
+
import { cx, useAureaStrings, usePortalContainer } from "./internal.js";
|
|
12
15
|
import { Icon } from "./system.js";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
import { Button } from "./actions.js";
|
|
17
|
+
export function Dialog({ open, title, children, footer, onClose }) { const s = useAureaStrings(); const portal = usePortalContainer(); return _jsx(BaseDialog.Root, { open: open, onOpenChange: o => { if (!o)
|
|
18
|
+
onClose(); }, children: _jsxs(BaseDialog.Portal, { container: portal, children: [_jsx(BaseDialog.Backdrop, { className: "dialog-backdrop" }), _jsxs(BaseDialog.Popup, { className: "dialog", 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: "close" }) })] }), _jsx("div", { className: "dialog-body", children: children }), footer && _jsx("footer", { children: footer })] })] }) }); }
|
|
19
|
+
// ConfirmDialog (M5): a decisão que não se fecha por engano. NÃO é um Dialog com dois botões —
|
|
20
|
+
// é `role="alertdialog"`, e a diferença é de comportamento, não de aparência: o Base UI tira do
|
|
21
|
+
// AlertDialog.Root as props `modal` e `disablePointerDismissal` (medido no d.ts de 1.6.0), ou
|
|
22
|
+
// seja, clicar fora NÃO fecha. Num Dialog comum, clicar fora vira "cancelei" sem a pessoa ter
|
|
23
|
+
// decidido — que é exatamente o acidente que este componente existe para impedir.
|
|
24
|
+
//
|
|
25
|
+
// FOCO NO BOTÃO SEGURO: quem abre um "isto apaga" e aperta Enter por reflexo tem de cancelar,
|
|
26
|
+
// não apagar. As quatro referências convergem em cancelar-antes-de-agir na ORDEM visual, e
|
|
27
|
+
// nenhuma delas move o foco — este passo saiu de medir o teclado, não de ler.
|
|
28
|
+
//
|
|
29
|
+
// DUAS coisas garantem, e as duas foram medidas em 13/08/2026, uma de cada vez:
|
|
30
|
+
// • a ORDEM do DOM — o Cancelar vem primeiro, e o motor foca o primeiro focável. Sozinha, ela
|
|
31
|
+
// já faz o teste passar; tirar só o `initialFocus` NÃO reprova.
|
|
32
|
+
// • o `initialFocus`, que é o cinto: com a ordem dos dois botões INVERTIDA ele continua
|
|
33
|
+
// segurando o foco no Cancelar, e é aí que ele prova que não é enfeite. Sem ele e com a
|
|
34
|
+
// ordem invertida, o teste reprova — que é o defeito de verdade, porque inverter a ordem é
|
|
35
|
+
// uma mudança de aparência que alguém faz sem pensar no teclado.
|
|
36
|
+
// O teste cobra o EFEITO ("o foco nasce no seguro"), não o mecanismo. É por isso que ele
|
|
37
|
+
// sobrevive a trocar um dos dois — e reprova quando os dois somem.
|
|
38
|
+
//
|
|
39
|
+
// ESCOPO MENOR que a referência (BUILDING.md §5): lá são nove peças compostas
|
|
40
|
+
// (Root/Trigger/Content/Header/Title/Description/Footer/Cancel/Action). Aqui é uma prop `open`,
|
|
41
|
+
// como no `Dialog` e no `Drawer` — a composição não acrescenta escolha nenhuma num diálogo cujo
|
|
42
|
+
// corpo é uma frase e dois botões.
|
|
43
|
+
//
|
|
44
|
+
// `description` é prop e não `children` porque ela é o nó de `aria-describedby`: o AlertDialog
|
|
45
|
+
// só anuncia o que passa pelo `Description`. Como `children`, um consumidor poria um <div> no
|
|
46
|
+
// meio e o leitor de tela perderia a frase que diz o que se perde.
|
|
47
|
+
export function ConfirmDialog({ open, title, description, confirmLabel, cancelLabel, destructive, onConfirm, onCancel }) {
|
|
48
|
+
const s = useAureaStrings();
|
|
49
|
+
const portal = usePortalContainer();
|
|
50
|
+
const seguro = React.useRef(null);
|
|
51
|
+
return _jsx(BaseAlertDialog.Root, { open: open, onOpenChange: o => { if (!o)
|
|
52
|
+
onCancel(); }, children: _jsxs(BaseAlertDialog.Portal, { container: portal, children: [_jsx(BaseAlertDialog.Backdrop, { className: "dialog-backdrop" }), _jsxs(BaseAlertDialog.Popup, { className: "dialog dialog-confirm", initialFocus: seguro, children: [_jsx("header", { children: _jsx(BaseAlertDialog.Title, { render: _jsx("h2", {}), children: title }) }), _jsx(BaseAlertDialog.Description, { className: "dialog-body", children: description }), _jsxs("footer", { children: [_jsx(Button, { ref: seguro, variant: "secondary", onClick: onCancel, children: cancelLabel ?? s.confirmCancel }), _jsx(Button, { variant: destructive ? "danger" : "primary", onClick: onConfirm, children: confirmLabel ?? s.confirmProceed })] })] })] }) });
|
|
53
|
+
}
|
|
54
|
+
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)
|
|
55
|
+
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: "close" }) })] }), children] })] }) }); }
|
|
56
|
+
export function AccessGate({ allowed, children, ...resto }) {
|
|
57
|
+
if (allowed)
|
|
58
|
+
return children;
|
|
59
|
+
if (resto.mode === "disable")
|
|
60
|
+
return _jsx(Tooltip, { content: resto.reason, children: React.cloneElement(children, { "aria-disabled": true }) });
|
|
61
|
+
return _jsx(_Fragment, { children: resto.fallback ?? null });
|
|
62
|
+
}
|
|
17
63
|
// `role="tooltip"` + `aria-describedby` no disparador é o que faz a dica EXISTIR para leitor
|
|
18
64
|
// de tela. Medido em 30/07/2026: sem isso, o popup saía sem role e sem id, e o disparador sem
|
|
19
65
|
// aria-describedby — quem navega por leitor de tela ouvia só o rótulo do botão e nunca o
|
|
20
66
|
// conteúdo da dica. Era tooltip visual, não acessível (padrão APG Tooltip).
|
|
21
67
|
// O id aponta para um elemento que só existe quando aberto; referência pendente é ignorada
|
|
22
68
|
// pela tecnologia assistiva, então não precisa acompanhar o estado.
|
|
23
|
-
export function Tooltip({ children, content, side = "top" }) { const id = React.useId(); return _jsxs(BaseTooltip.Root, { children: [_jsx(BaseTooltip.Trigger, { render: children, "aria-describedby": id }), _jsx(BaseTooltip.Portal, { children: _jsx(BaseTooltip.Positioner, { side: side, sideOffset: 8, children: _jsx(BaseTooltip.Popup, { id: id, role: "tooltip", className: "tooltip", children: content }) }) })] }); }
|
|
24
|
-
export function Popover({ trigger, title, children, side = "bottom" }) { return _jsxs(BasePopover.Root, { children: [_jsx(BasePopover.Trigger, { render: trigger }), _jsx(BasePopover.Portal, { children: _jsx(BasePopover.Positioner, { side: side, sideOffset: 8, children: _jsxs(BasePopover.Popup, { className: "popover", children: [title && _jsx(BasePopover.Title, { render: _jsx("strong", {}), children: title }), children] }) }) })] }); }
|
|
69
|
+
export function Tooltip({ children, content, side = "top" }) { const id = React.useId(); const portal = usePortalContainer(); return _jsxs(BaseTooltip.Root, { children: [_jsx(BaseTooltip.Trigger, { render: children, "aria-describedby": id }), _jsx(BaseTooltip.Portal, { container: portal, children: _jsx(BaseTooltip.Positioner, { side: side, sideOffset: 8, children: _jsx(BaseTooltip.Popup, { id: id, role: "tooltip", className: "tooltip", children: content }) }) })] }); }
|
|
70
|
+
export function Popover({ trigger, title, children, side = "bottom" }) { const portal = usePortalContainer(); return _jsxs(BasePopover.Root, { children: [_jsx(BasePopover.Trigger, { render: trigger }), _jsx(BasePopover.Portal, { container: portal, children: _jsx(BasePopover.Positioner, { side: side, sideOffset: 8, children: _jsxs(BasePopover.Popup, { className: "popover", children: [title && _jsx(BasePopover.Title, { render: _jsx("strong", {}), children: title }), children] }) }) })] }); }
|
|
71
|
+
// HoverCard (Lote 1 do BUILDING.md). Não é Tooltip nem Popover, e a diferença é de propósito,
|
|
72
|
+
// não de aparência: a Tooltip é um RÓTULO curto (`role="tooltip"`, some ao mover o mouse); o
|
|
73
|
+
// Popover abre por CLIQUE e pode conter foco; este é uma PRÉVIA rica que aparece ao repousar o
|
|
74
|
+
// ponteiro sobre um link e cujo conteúdo é alcançável — o cartão de perfil ao passar sobre um
|
|
75
|
+
// nome. As três referências que o têm chamam de hover-card ou preview-card e concordam nisso.
|
|
76
|
+
// Superfície reusa `.popover` de propósito: é a mesma camada flutuante do sistema, e dar a ela
|
|
77
|
+
// um segundo nome criaria duas peles para a mesma coisa.
|
|
78
|
+
// Por depender de repouso do ponteiro, NÃO serve para informação essencial — quem navega só por
|
|
79
|
+
// teclado ou toque não abre um hover card. Conteúdo obrigatório vai em Popover.
|
|
80
|
+
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 }) }) })] }); }
|
|
25
81
|
// ContextMenu.Item/.Separator/.Popup são os MESMOS componentes de Menu.* no Base UI,
|
|
26
82
|
// então os itens renderizam igual nos dois menus.
|
|
27
83
|
const renderMenuItems = (items) => items.map((it, i) => it === "separator"
|
|
28
84
|
? _jsx(BaseMenu.Separator, { className: "menu-sep" }, i)
|
|
29
85
|
: _jsxs(BaseMenu.Item, { className: "menu-item", disabled: it.disabled, onClick: it.onClick, children: [it.leadingIcon && _jsx(Icon, { name: it.leadingIcon }), it.label] }, i));
|
|
30
|
-
export function DropdownMenu({ trigger, items, side = "bottom", label }) { return _jsxs(BaseMenu.Root, { children: [_jsx(BaseMenu.Trigger, { render: trigger }), _jsx(BaseMenu.Portal, { children: _jsx(BaseMenu.Positioner, { side: side, sideOffset: 6, children: _jsx(BaseMenu.Popup, { className: "menu", "aria-label": label, children: renderMenuItems(items) }) }) })] }); }
|
|
86
|
+
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) }) }) })] }); }
|
|
31
87
|
// ContextMenu: abre no botão direito e — por teclado — em Shift+F10 / tecla Menu,
|
|
32
88
|
// que o browser só dispara (como evento contextmenu) sobre um elemento FOCADO. Por
|
|
33
89
|
// isso o gatilho é focável (tabIndex 0) e tem nome acessível (auditoria 18/07/2026,
|
|
34
90
|
// MÉDIO 3); sem isso o teclado não alcança o menu. Consumidor pode sobrescrever
|
|
35
91
|
// tabIndex via children se o próprio já for focável.
|
|
36
|
-
export function ContextMenu({ children, items, label, className }) { return _jsxs(BaseContextMenu.Root, { children: [_jsx(BaseContextMenu.Trigger, { className: className, tabIndex: 0, "aria-label": label, "aria-haspopup": "menu", children: children }), _jsx(BaseContextMenu.Portal, { children: _jsx(BaseContextMenu.Positioner, { children: _jsx(BaseContextMenu.Popup, { className: "menu", "aria-label": label, children: renderMenuItems(items) }) }) })] }); }
|
|
92
|
+
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) }) }) })] }); }
|
package/dist/pure.d.ts
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
export declare const cx: (...v: Array<string | false | null | undefined>) => string;
|
|
2
|
+
export type UniversalState = "waiting_user" | "waiting_approval" | "waiting_dependency" | "offline" | "stale" | "partial" | "degraded";
|
|
3
|
+
export declare const universalStates: readonly UniversalState[];
|
|
4
|
+
export declare const stateSeverity: (state: UniversalState) => "info" | "warning";
|
|
5
|
+
export interface AureaStrings {
|
|
6
|
+
close: string;
|
|
7
|
+
confirmCancel: string;
|
|
8
|
+
dataError: string;
|
|
9
|
+
dataEmpty: string;
|
|
10
|
+
confirmProceed: string;
|
|
11
|
+
paginationLabel: string;
|
|
12
|
+
previous: string;
|
|
13
|
+
next: string;
|
|
14
|
+
breadcrumbLabel: string;
|
|
15
|
+
tabsLabel: string;
|
|
16
|
+
optionsLabel: string;
|
|
17
|
+
tableLabel: string;
|
|
18
|
+
commandLabel: string;
|
|
19
|
+
commandPlaceholder: string;
|
|
20
|
+
dismissNotification: string;
|
|
21
|
+
toolbarLabel: string;
|
|
22
|
+
loading: string;
|
|
23
|
+
otpDigit: string;
|
|
24
|
+
stepperLabel: string;
|
|
25
|
+
increment: string;
|
|
26
|
+
decrement: string;
|
|
27
|
+
comboboxEmpty: string;
|
|
28
|
+
comboboxClear: string;
|
|
29
|
+
comboboxOpen: string;
|
|
30
|
+
comboboxRemove: string;
|
|
31
|
+
comboboxLoading: string;
|
|
32
|
+
fileDropPrompt: string;
|
|
33
|
+
fileAdded: string;
|
|
34
|
+
fileRemoved: string;
|
|
35
|
+
fileRemove: string;
|
|
36
|
+
fileTooLarge: string;
|
|
37
|
+
fileWrongType: string;
|
|
38
|
+
treeLabel: string;
|
|
39
|
+
notificationsLabel: string;
|
|
40
|
+
notificationMarkAll: string;
|
|
41
|
+
notificationEmpty: string;
|
|
42
|
+
notificationUnread: string;
|
|
43
|
+
notificationNew: string;
|
|
44
|
+
dataGridFilter: string;
|
|
45
|
+
dataGridEmpty: string;
|
|
46
|
+
dataGridSelectAll: string;
|
|
47
|
+
dataGridSelectRow: string;
|
|
48
|
+
dataGridSelected: string;
|
|
49
|
+
dataGridClearSelection: string;
|
|
50
|
+
dataGridBulkLabel: string;
|
|
51
|
+
dataGridColumns: string;
|
|
52
|
+
dataGridResize: string;
|
|
53
|
+
dataGridStale: string;
|
|
54
|
+
dataGridPartial: string;
|
|
55
|
+
dataGridError: string;
|
|
56
|
+
dataGridDetails: string;
|
|
57
|
+
dataGridDetailPanel: string;
|
|
58
|
+
dataGridExport: string;
|
|
59
|
+
dataGridExportRows: string;
|
|
60
|
+
dataGridExportFiltered: string;
|
|
61
|
+
dataGridExportSelected: string;
|
|
62
|
+
mediaPlayer: string;
|
|
63
|
+
mediaPlay: string;
|
|
64
|
+
mediaPause: string;
|
|
65
|
+
mediaMute: string;
|
|
66
|
+
mediaUnmute: string;
|
|
67
|
+
mediaSeek: string;
|
|
68
|
+
mediaVolume: string;
|
|
69
|
+
mediaCaptionsShow: string;
|
|
70
|
+
mediaCaptionsHide: string;
|
|
71
|
+
mediaSkipBack: string;
|
|
72
|
+
mediaSkipForward: string;
|
|
73
|
+
mediaFullscreenEnter: string;
|
|
74
|
+
mediaFullscreenExit: string;
|
|
75
|
+
carouselLabel: string;
|
|
76
|
+
carouselSlide: string;
|
|
77
|
+
positionOf: string;
|
|
78
|
+
carouselPrev: string;
|
|
79
|
+
carouselNext: string;
|
|
80
|
+
galleryLabel: string;
|
|
81
|
+
sortableLabel: string;
|
|
82
|
+
sortableHandle: string;
|
|
83
|
+
sortableHelp: string;
|
|
84
|
+
sortableGrabbed: string;
|
|
85
|
+
sortableDropped: string;
|
|
86
|
+
sortableMoved: string;
|
|
87
|
+
sortableCanceled: string;
|
|
88
|
+
blockEditorLabel: string;
|
|
89
|
+
blockLabel: string;
|
|
90
|
+
blockRemove: string;
|
|
91
|
+
uploadSending: string;
|
|
92
|
+
uploadCancel: string;
|
|
93
|
+
uploadRetry: string;
|
|
94
|
+
uploadError: string;
|
|
95
|
+
uploadCanceled: string;
|
|
96
|
+
uploadComplete: string;
|
|
97
|
+
uploadPause: string;
|
|
98
|
+
uploadResume: string;
|
|
99
|
+
uploadPaused: string;
|
|
100
|
+
uploadPending: string;
|
|
101
|
+
uploadChecksum: string;
|
|
102
|
+
uploadChecksumBad: string;
|
|
103
|
+
fileConflict: string;
|
|
104
|
+
fileReplace: string;
|
|
105
|
+
fileKeepBoth: string;
|
|
106
|
+
fileSkip: string;
|
|
107
|
+
uploadReceipt: string;
|
|
108
|
+
uploadReceiptCopy: string;
|
|
109
|
+
agentInspector: string;
|
|
110
|
+
invocationLabel: string;
|
|
111
|
+
invocationInput: string;
|
|
112
|
+
invocationOutput: string;
|
|
113
|
+
taskQueueLabel: string;
|
|
114
|
+
taskState: Record<"queued" | "running" | "completed" | "failed" | "blocked" | "paused", string>;
|
|
115
|
+
taskPriority: Record<"low" | "medium" | "high", string>;
|
|
116
|
+
approvalLabel: string;
|
|
117
|
+
approvalApprove: string;
|
|
118
|
+
approvalDeny: string;
|
|
119
|
+
approvalApproved: string;
|
|
120
|
+
approvalDenied: string;
|
|
121
|
+
approvalDeadline: string;
|
|
122
|
+
approvalRisk: Record<"low" | "medium" | "high", string>;
|
|
123
|
+
permissionLabel: string;
|
|
124
|
+
permissionAsk: string;
|
|
125
|
+
permissionAlways: string;
|
|
126
|
+
permissionNever: string;
|
|
127
|
+
eventStreamLabel: string;
|
|
128
|
+
traceLabel: string;
|
|
129
|
+
healthLabel: string;
|
|
130
|
+
healthState: Record<"operational" | "degraded" | "down" | "maintenance" | "unknown", string>;
|
|
131
|
+
modelUsageLabel: string;
|
|
132
|
+
usageMetric: Record<"tokens" | "cost" | "requests", string>;
|
|
133
|
+
costMeterLabel: string;
|
|
134
|
+
costMeterSpent: string;
|
|
135
|
+
costMeterRemaining: string;
|
|
136
|
+
costMeterExceeded: string;
|
|
137
|
+
costMeterNear: string;
|
|
138
|
+
costMeterOver: string;
|
|
139
|
+
memoryLabel: string;
|
|
140
|
+
memoryProvenance: string;
|
|
141
|
+
memoryOperation: Record<"added" | "updated" | "recalled" | "forgotten", string>;
|
|
142
|
+
memoryScope: Record<"episodic" | "semantic" | "procedural", string>;
|
|
143
|
+
agentMessageLabel: string;
|
|
144
|
+
agentMessageTo: string;
|
|
145
|
+
agentMessageBroadcast: string;
|
|
146
|
+
agentMessageReason: string;
|
|
147
|
+
agentMessageKind: Record<"request" | "response" | "handoff" | "broadcast" | "error", string>;
|
|
148
|
+
automationWhen: string;
|
|
149
|
+
automationThen: string;
|
|
150
|
+
automationEnabled: string;
|
|
151
|
+
automationLastRun: string;
|
|
152
|
+
automationResult: Record<"success" | "failure", string>;
|
|
153
|
+
graphLabel: string;
|
|
154
|
+
agentState: Record<"idle" | "thinking" | "running" | "paused" | "error" | "completed", string>;
|
|
155
|
+
codeEditor: string;
|
|
156
|
+
chatLabel: string;
|
|
157
|
+
chatMessage: string;
|
|
158
|
+
chatSend: string;
|
|
159
|
+
qrCode: string;
|
|
160
|
+
chartLabel: string;
|
|
161
|
+
copyCode: string;
|
|
162
|
+
tocLabel: string;
|
|
163
|
+
navigationToggle: string;
|
|
164
|
+
sidebarLabel: string;
|
|
165
|
+
universalState: Record<UniversalState, string>;
|
|
166
|
+
}
|
|
167
|
+
export declare const defaultStrings: AureaStrings;
|
|
168
|
+
export declare const ptBR: AureaStrings;
|
|
169
|
+
export declare const defaultSpriteUrl = "/aurea-icons.svg";
|
|
170
|
+
export interface GridState {
|
|
171
|
+
sorting?: Array<{
|
|
172
|
+
id: string;
|
|
173
|
+
desc: boolean;
|
|
174
|
+
}>;
|
|
175
|
+
globalFilter?: string;
|
|
176
|
+
columnFilters?: Array<{
|
|
177
|
+
id: string;
|
|
178
|
+
value: unknown;
|
|
179
|
+
}>;
|
|
180
|
+
page?: number;
|
|
181
|
+
}
|
|
182
|
+
export declare function gridStateToParams(state: GridState, into?: URLSearchParams): URLSearchParams;
|
|
183
|
+
export declare function gridStateFromParams(params: URLSearchParams, filters?: Array<{
|
|
184
|
+
column: string;
|
|
185
|
+
facet?: boolean;
|
|
186
|
+
}>): GridState;
|
|
187
|
+
export interface ScreenState extends GridState {
|
|
188
|
+
tab?: string;
|
|
189
|
+
view?: string;
|
|
190
|
+
detail?: string;
|
|
191
|
+
}
|
|
192
|
+
export declare function screenStateToParams(state: ScreenState, into?: URLSearchParams): URLSearchParams;
|
|
193
|
+
export declare function screenStateFromParams(params: URLSearchParams, filters?: Array<{
|
|
194
|
+
column: string;
|
|
195
|
+
facet?: boolean;
|
|
196
|
+
}>): ScreenState;
|