@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
package/README.md
CHANGED
|
@@ -60,12 +60,14 @@ segue sem a função — não quebra a tela.
|
|
|
60
60
|
|
|
61
61
|
**O arrumador fora da tela principal (`layoutWorker`).** Num mapa grande, a arrumação pode prender a
|
|
62
62
|
tela por alguns segundos. O mapa aceita um trabalhador (Web Worker) que o app cria — cada empacotador
|
|
63
|
-
cria trabalhador do seu jeito, e por isso quem entrega é o app.
|
|
63
|
+
cria trabalhador do seu jeito, e por isso quem entrega é o app. A Aurea publica o trabalhador por um
|
|
64
|
+
caminho dela, `@aurea-uds/react/graph-worker`, que traz o do `elkjs` (o peer opcional) junto — o app
|
|
65
|
+
não importa o motor por fora. No Vite:
|
|
64
66
|
|
|
65
67
|
```js
|
|
66
|
-
import
|
|
68
|
+
import TrabalhadorDoMapa from "@aurea-uds/react/graph-worker?worker";
|
|
67
69
|
|
|
68
|
-
<DependencyGraph layout="layered" layoutWorker={() => new
|
|
70
|
+
<DependencyGraph layout="layered" layoutWorker={() => new TrabalhadorDoMapa()} … />
|
|
69
71
|
```
|
|
70
72
|
|
|
71
73
|
Em qualquer outro empacotador, o jeito que sempre funciona: copie `node_modules/elkjs/lib/elk-worker.min.js`
|
package/dist/actions.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { type ButtonHTMLAttributes, type HTMLAttributes, type ReactElement, type RefAttributes } from "react";
|
|
2
2
|
import { type Orientation, type Responsive } from "./pure.js";
|
|
3
|
-
import { type IconName } from "./system.js";
|
|
4
|
-
export type ButtonVariant = "primary" | "secondary" | "outline" | "ghost" | "primary-outline" | "primary-ghost" | "danger" | "danger-outline" | "danger-ghost" | "link" | "link-primary" | "link-danger" | "nav";
|
|
5
|
-
export type ButtonAppearance = "solid" | "outline" | "ghost" | "link" | "nav";
|
|
3
|
+
import { type IconName, type AureaIcon } from "./system.js";
|
|
4
|
+
export type ButtonVariant = "primary" | "secondary" | "tertiary" | "outline" | "ghost" | "primary-outline" | "primary-ghost" | "danger" | "danger-outline" | "danger-ghost" | "link" | "link-primary" | "link-danger" | "nav" | "danger-soft";
|
|
5
|
+
export type ButtonAppearance = "solid" | "outline" | "ghost" | "link" | "nav" | "soft";
|
|
6
6
|
export type ButtonTone = "neutral" | "brand" | "danger" | "success" | "warning" | "info";
|
|
7
7
|
export type ComponentSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
8
8
|
/** Resolve os dois eixos (ou o atalho) na classe que o core pinta. Exportada porque o teste
|
|
@@ -20,10 +20,13 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, Re
|
|
|
20
20
|
tone?: ButtonTone;
|
|
21
21
|
size?: Responsive<ComponentSize>;
|
|
22
22
|
loading?: boolean;
|
|
23
|
-
leadingIcon?:
|
|
24
|
-
trailingIcon?:
|
|
23
|
+
leadingIcon?: AureaIcon;
|
|
24
|
+
trailingIcon?: AureaIcon;
|
|
25
25
|
href?: string;
|
|
26
26
|
fullWidth?: boolean;
|
|
27
|
+
/** Menos peso (15/10/2026): a letra apagada e um degrau menor (12 no `sm`) — o botão de ferramenta de um topo de
|
|
28
|
+
* site, como o "Theme" da referência. A caixa e o fundo são os da aparência escolhida. */
|
|
29
|
+
quiet?: boolean;
|
|
27
30
|
/** C-03 (24/09/2026): numa fila (`Cluster`), divide o espaço em partes iguais com os outros botões
|
|
28
31
|
* que também têm `grow`. O `fullWidth` não serve ali: ele pede a linha inteira. */
|
|
29
32
|
grow?: boolean;
|
|
@@ -50,7 +53,9 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, Re
|
|
|
50
53
|
* quebrar, e por isso este é o momento mais barato que vai existir.
|
|
51
54
|
*/
|
|
52
55
|
pressed?: boolean;
|
|
53
|
-
|
|
56
|
+
/** O atalho, à mostra e anunciado. Texto: uma caixinha só ("⌘K"). LISTA (15/10/2026): uma caixinha por tecla, como
|
|
57
|
+
* a busca da referência (`["Ctrl", "K"]`), e o leitor de tela recebe a combinação (`Control+K`). */
|
|
58
|
+
kbd?: string | readonly string[];
|
|
54
59
|
/**
|
|
55
60
|
* GAR-14 (0.28.0): o botão COMPARTILHA. Ele pergunta ao navegador se sabe compartilhar este link
|
|
56
61
|
* (`navigator.canShare`) — detectar o recurso, e não adivinhar o aparelho, é o padrão da web. Sabe
|
|
@@ -80,7 +85,11 @@ interface ToggleBase {
|
|
|
80
85
|
disabled?: boolean;
|
|
81
86
|
id?: string;
|
|
82
87
|
className?: string;
|
|
88
|
+
/** 0.32.0, o `ToggleButton` da referência: `default` com o fundo neutro (o padrão), `ghost` sem fundo
|
|
89
|
+
* (o desenho de até a 0.31.0). O ligado é o idioma "selecionado" da Aurea nos dois. */
|
|
90
|
+
variant?: ToggleVariant;
|
|
83
91
|
}
|
|
92
|
+
export type ToggleVariant = "default" | "ghost";
|
|
84
93
|
type ToggleChildren = Exclude<React.ReactNode, boolean | null | undefined>;
|
|
85
94
|
export type ToggleProps = ToggleBase & ({
|
|
86
95
|
children: ToggleChildren;
|
|
@@ -89,19 +98,38 @@ export type ToggleProps = ToggleBase & ({
|
|
|
89
98
|
children?: never;
|
|
90
99
|
label: string;
|
|
91
100
|
});
|
|
92
|
-
export declare function Toggle({ pressed, defaultPressed, onPressedChange, value, icon, label, size, disabled, id, className, children }: ToggleProps): React.JSX.Element;
|
|
101
|
+
export declare function Toggle({ pressed, defaultPressed, onPressedChange, value, icon, label, size: sizePedido, disabled, id, className, children, variant }: ToggleProps): React.JSX.Element;
|
|
93
102
|
export interface IconButtonProps extends Omit<ButtonProps, "children"> {
|
|
94
103
|
label: string;
|
|
95
|
-
icon:
|
|
104
|
+
icon: AureaIcon;
|
|
96
105
|
}
|
|
97
106
|
export declare const IconButton: React.ForwardRefExoticComponent<Omit<IconButtonProps, "ref"> & RefAttributes<HTMLButtonElement>>;
|
|
98
|
-
export interface
|
|
107
|
+
export interface CloseButtonProps extends Omit<ButtonProps, "quiet" | "variant" | "appearance" | "tone" | "size" | "loading" | "leadingIcon" | "trailingIcon" | "href" | "target" | "rel" | "download" | "render" | "kbd" | "fullWidth" | "grow" | "pressed" | "share"> {
|
|
108
|
+
/** O nome que o leitor de tela anuncia. Padrão: a frase `close` ("Close"/"Fechar"). */
|
|
109
|
+
label?: string;
|
|
110
|
+
}
|
|
111
|
+
export declare const CloseButton: React.ForwardRefExoticComponent<Omit<CloseButtonProps, "ref"> & RefAttributes<HTMLButtonElement>>;
|
|
112
|
+
export interface ThemeToggleProps extends Omit<IconButtonProps, "quiet" | "icon" | "label" | "onClick" | "variant" | "appearance" | "tone" | "href" | "target" | "rel" | "download" | "render" | "kbd" | "loading" | "leadingIcon" | "trailingIcon" | "fullWidth" | "share"> {
|
|
113
|
+
/** `"light-dark"` (o padrão): o botão que alterna. `"light-dark-system"` (15/10/2026): a chave de três posições do
|
|
114
|
+
* topo da referência — claro, escuro e sistema (seguir o do computador, e mudar junto). */
|
|
115
|
+
mode?: "light-dark" | "light-dark-system";
|
|
99
116
|
}
|
|
100
117
|
export declare const ThemeToggle: React.ForwardRefExoticComponent<Omit<ThemeToggleProps, "ref"> & RefAttributes<HTMLButtonElement>>;
|
|
101
|
-
export
|
|
118
|
+
export interface ButtonGroupProps extends HTMLAttributes<HTMLDivElement>, RefAttributes<HTMLDivElement> {
|
|
102
119
|
label?: string;
|
|
103
120
|
orientation?: Responsive<Orientation>;
|
|
104
|
-
|
|
121
|
+
/** O desenho de todos os botões de dentro; cada um pode trocar o seu. */
|
|
122
|
+
variant?: ButtonVariant;
|
|
123
|
+
/** O tamanho de todos os botões de dentro; cada um pode trocar o seu. */
|
|
124
|
+
size?: Responsive<ComponentSize>;
|
|
125
|
+
/** Ocupa a largura do pai, e os botões repartem em partes iguais. */
|
|
126
|
+
fullWidth?: boolean;
|
|
127
|
+
/** Desliga todos os botões de dentro. */
|
|
128
|
+
disabled?: boolean;
|
|
129
|
+
/** Botões soltos (cápsulas com vão de 4), em vez de colados. */
|
|
130
|
+
detached?: boolean;
|
|
131
|
+
}
|
|
132
|
+
export declare function ButtonGroup({ label, orientation, variant, size, fullWidth, disabled, detached, className, ...props }: ButtonGroupProps): React.JSX.Element;
|
|
105
133
|
export declare function Toolbar({ orientation, label, className, ...props }: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement> & {
|
|
106
134
|
orientation?: Responsive<Orientation>;
|
|
107
135
|
label?: string;
|
|
@@ -113,7 +141,7 @@ export declare function ToolbarSeparator({ className, ...props }: HTMLAttributes
|
|
|
113
141
|
export interface ToolbarButtonProps extends Omit<ButtonProps, "share"> {
|
|
114
142
|
}
|
|
115
143
|
export declare const ToolbarButton: React.ForwardRefExoticComponent<Omit<ToolbarButtonProps, "ref"> & RefAttributes<HTMLButtonElement>>;
|
|
116
|
-
export
|
|
144
|
+
export interface ToggleGroupProps {
|
|
117
145
|
value?: string[];
|
|
118
146
|
defaultValue?: string[];
|
|
119
147
|
onValueChange?: (value: string[]) => void;
|
|
@@ -123,5 +151,12 @@ export declare function ToggleGroup({ value, defaultValue, onValueChange, multip
|
|
|
123
151
|
label?: string;
|
|
124
152
|
className?: string;
|
|
125
153
|
children: React.ReactNode;
|
|
126
|
-
|
|
154
|
+
/** O tamanho de todos os botões de dentro; cada um pode trocar o seu (valor simples, como o dela). */
|
|
155
|
+
size?: Extract<ComponentSize, "sm" | "md" | "lg">;
|
|
156
|
+
/** Ocupa a largura do pai, e os botões repartem em partes iguais. */
|
|
157
|
+
fullWidth?: boolean;
|
|
158
|
+
/** Botões soltos (vão de 4), em vez de colados. */
|
|
159
|
+
detached?: boolean;
|
|
160
|
+
}
|
|
161
|
+
export declare function ToggleGroup({ value, defaultValue, onValueChange, multiple, orientation, disabled, label, className, children, size, fullWidth, detached }: ToggleGroupProps): React.JSX.Element;
|
|
127
162
|
export {};
|
package/dist/actions.js
CHANGED
|
@@ -15,19 +15,25 @@ import { Icon, useAureaTheme } from "./system.js";
|
|
|
15
15
|
// O dicionário que desachata o enum. É a ÚNICA fonte da correspondência: o gate do
|
|
16
16
|
// `validate.py` lê daqui para provar que todo par ou tem regra no core ou está declarado
|
|
17
17
|
// ausente com motivo, e a ficha do registry declara os mesmos dois eixos.
|
|
18
|
+
// O `secondary` não tem célula própria nos dois eixos (a letra da marca no fundo neutro não é nenhum
|
|
19
|
+
// par aparência × tom): os eixos dele são os do `tertiary`, que valem só quando quem chama troca a
|
|
20
|
+
// aparência ou o tom — aí sai a célula pedida, como em todo atalho.
|
|
18
21
|
const EIXOS = {
|
|
19
|
-
primary: ["solid", "brand"], secondary: ["solid", "neutral"],
|
|
22
|
+
primary: ["solid", "brand"], secondary: ["solid", "neutral"], tertiary: ["solid", "neutral"],
|
|
20
23
|
outline: ["outline", "neutral"], ghost: ["ghost", "neutral"],
|
|
21
24
|
"primary-outline": ["outline", "brand"], "primary-ghost": ["ghost", "brand"],
|
|
22
25
|
danger: ["solid", "danger"], "danger-outline": ["outline", "danger"], "danger-ghost": ["ghost", "danger"],
|
|
23
26
|
link: ["link", "neutral"], "link-primary": ["link", "brand"], "link-danger": ["link", "danger"],
|
|
24
|
-
nav: ["nav", "neutral"]
|
|
27
|
+
nav: ["nav", "neutral"], "danger-soft": ["soft", "danger"]
|
|
25
28
|
};
|
|
29
|
+
// Atalhos que NÃO têm classe própria (15/10/2026): saem como os dois eixos (`btn-soft btn-tone-danger`), e herdam as
|
|
30
|
+
// regras de cor do tom nos dois temas em vez de repeti-las numa classe nova.
|
|
31
|
+
const SO_EIXOS = new Set(["danger-soft"]);
|
|
26
32
|
// caminho de volta: par → nome antigo. Existir aqui significa "o core já pinta esta célula com
|
|
27
33
|
// uma classe própria", e é o que garante que NENHUMA baseline se mexe: `appearance="outline"`
|
|
28
34
|
// + `tone="danger"` emite `.btn-danger-outline`, o mesmo DOM de sempre.
|
|
29
35
|
const CLASSE_ANTIGA = new Map(Object.entries(EIXOS)
|
|
30
|
-
.map(([v, [a, t]]) => [`${a}/${t}`, v]));
|
|
36
|
+
.filter(([v]) => v !== "secondary" && !SO_EIXOS.has(v)).map(([v, [a, t]]) => [`${a}/${t}`, v]));
|
|
31
37
|
/** Resolve os dois eixos (ou o atalho) na classe que o core pinta. Exportada porque o teste
|
|
32
38
|
* cobra a matriz inteira, e porque quem monta um botão à mão precisa da mesma conta.
|
|
33
39
|
*
|
|
@@ -37,7 +43,10 @@ const CLASSE_ANTIGA = new Map(Object.entries(EIXOS)
|
|
|
37
43
|
* `--success`/`--success-foreground` e os irmãos são. `outline` voltou a ser só uma aparência
|
|
38
44
|
* que se pede, nunca o que sobra quando a nossa paleta não dá conta. */
|
|
39
45
|
export function buttonSkin(variant, appearance, tone) {
|
|
40
|
-
|
|
46
|
+
// A variação sem eixo pedido é a própria classe — é o caminho do `secondary`, que não tem célula.
|
|
47
|
+
if (appearance === undefined && tone === undefined && !(variant && SO_EIXOS.has(variant)))
|
|
48
|
+
return `btn-${variant ?? "tertiary"}`;
|
|
49
|
+
const [a0, t0] = EIXOS[variant ?? "tertiary"];
|
|
41
50
|
const a = appearance ?? a0, t = tone ?? t0;
|
|
42
51
|
const antiga = CLASSE_ANTIGA.get(`${a}/${t}`);
|
|
43
52
|
return antiga ? `btn-${antiga}` : cx(`btn-${a}`, `btn-tone-${t}`);
|
|
@@ -90,10 +99,21 @@ async function compartilhar(botao, dados, s, dentroDoProvider) {
|
|
|
90
99
|
avisar(true);
|
|
91
100
|
}
|
|
92
101
|
}
|
|
102
|
+
const GrupoDeBotoesContext = React.createContext(null);
|
|
93
103
|
// type="button" por default: o default do HTML é submit, e um "Cancelar"/"Remover"
|
|
94
104
|
// dentro de <form> dispararia a ação principal (auditoria 18/07/2026, ALTO 1).
|
|
95
105
|
// Quem quer submeter passa type="submit" explícito (como o MessageComposer faz).
|
|
96
|
-
|
|
106
|
+
// O nome da combinação para o `aria-keyshortcuts`: as teclas juntas por "+", com os nomes da especificação (o ESPAÇO
|
|
107
|
+
// separa atalhos ALTERNATIVOS — "Ctrl K" quer dizer "Ctrl" ou "K"). O texto solto passa como veio, como antes.
|
|
108
|
+
const NOME_DA_TECLA = { ctrl: "Control", control: "Control", "⌃": "Control", cmd: "Meta", command: "Meta", "⌘": "Meta", meta: "Meta",
|
|
109
|
+
shift: "Shift", "⇧": "Shift", alt: "Alt", option: "Alt", "⌥": "Alt", enter: "Enter", "↵": "Enter", esc: "Escape", escape: "Escape" };
|
|
110
|
+
const atalhoAnunciado = (kbd) => typeof kbd === "string" ? (kbd || undefined)
|
|
111
|
+
: kbd && kbd.length > 0 ? kbd.map(k => NOME_DA_TECLA[k.toLowerCase()] ?? k).join("+") : undefined;
|
|
112
|
+
export const Button = forwardRef(function Button({ variant: variantPedida, appearance, tone, size: sizePedido, quiet, loading, leadingIcon, trailingIcon, className, children, disabled: disabledPedido, type = "button", href, fullWidth, grow, target, rel, download, pressed, kbd, onClick, onClickCapture, "aria-disabled": ariaDisabled, render, share, ...props }, ref) {
|
|
113
|
+
const grupo = React.useContext(GrupoDeBotoesContext);
|
|
114
|
+
const variant = variantPedida ?? grupo?.variant;
|
|
115
|
+
const size = sizePedido ?? grupo?.size ?? "md";
|
|
116
|
+
const disabled = disabledPedido ?? grupo?.disabled;
|
|
97
117
|
// G-AXIS-04 — `size` aceita valor simples, responsivo por viewport ou adaptativo por container.
|
|
98
118
|
// SOMATIVO por construção: valor simples continua emitindo `btn-sm`, byte por byte a mesma classe
|
|
99
119
|
// de antes, e por isso nenhuma baseline se mexe. Só o valor responsivo entra pela camada genérica
|
|
@@ -101,7 +121,7 @@ export const Button = forwardRef(function Button({ variant, appearance, tone, si
|
|
|
101
121
|
// Quem decide é o CSS: nada aqui observa largura, e o HTML do servidor já sai correto.
|
|
102
122
|
const responsivo = ehResponsivo(size);
|
|
103
123
|
const base = valorBase(size) ?? "md";
|
|
104
|
-
const cls = cx("btn", buttonSkin(variant, appearance, tone), responsivo ? classesResponsivas("size", size) : (base !== "md" && `btn-${base}`), fullWidth && "btn-block", grow && "btn-grow", className);
|
|
124
|
+
const cls = cx("btn", buttonSkin(variant, appearance, tone), responsivo ? classesResponsivas("size", size) : (base !== "md" && `btn-${base}`), fullWidth && "btn-block", grow && "btn-grow", quiet && "btn-quiet", className);
|
|
105
125
|
// kbd dentro do botão: mostra o atalho E o anuncia (aria-keyshortcuts), senão é enfeite.
|
|
106
126
|
// 🔴 OCUPADO TROCA, NÃO ACRESCENTA (01/10/2026, achado pelo Victor no aureauds.dev): a rodinha
|
|
107
127
|
// entrava ANTES do ícone, e no `IconButton` — 36 de largura fixa — rodinha e glifo não cabiam:
|
|
@@ -111,7 +131,7 @@ export const Button = forwardRef(function Button({ variant, appearance, tone, si
|
|
|
111
131
|
// da frente; e sem conteúdo (o `IconButton` ocupado) o invólucro vazio some, senão o `gap` dele
|
|
112
132
|
// empurraria a rodinha para fora do centro. Fora do estado ocupado o HTML é o mesmo de antes.
|
|
113
133
|
const temConteudo = children != null && children !== false;
|
|
114
|
-
const inner = _jsxs(_Fragment, { children: [loading ? _jsx("span", { className: "spinner" }) : leadingIcon && _jsx(Icon, { name: leadingIcon }), (temConteudo || !loading) && _jsx("span", { children: children }), kbd && _jsx(Kbd, { children: kbd }), trailingIcon && _jsx(Icon, { name: trailingIcon })] });
|
|
134
|
+
const inner = _jsxs(_Fragment, { children: [loading ? _jsx("span", { className: "spinner" }) : leadingIcon && _jsx(Icon, { name: leadingIcon }), (temConteudo || !loading) && _jsx("span", { children: children }), typeof kbd === "string" ? (kbd && _jsx(Kbd, { className: "btn-kbd", children: kbd })) : kbd && kbd.length > 0 && _jsx("span", { className: "btn-kbds", children: kbd.map((k, i) => _jsx(Kbd, { className: "btn-kbd", children: k }, i)) }), trailingIcon && _jsx(Icon, { name: trailingIcon })] });
|
|
115
135
|
// INERTE ≠ DESABILITADO, e a diferença é medida (M4, 13/08/2026): `disabled` tira o botão da
|
|
116
136
|
// ordem de foco, então quem navega por teclado nunca alcança a explicação de POR QUE não dá — e
|
|
117
137
|
// "não dá porque você não tem permissão" é justamente o caso em que a explicação é tudo. O
|
|
@@ -121,7 +141,7 @@ export const Button = forwardRef(function Button({ variant, appearance, tone, si
|
|
|
121
141
|
// Mesmo remendo do AUD-0004, que já barrava o link desabilitado; aqui ele alcança o <button>.
|
|
122
142
|
const inerte = ariaDisabled === true || ariaDisabled === "true";
|
|
123
143
|
const off = disabled || loading;
|
|
124
|
-
const shared = { "aria-keyshortcuts": kbd
|
|
144
|
+
const shared = { "aria-keyshortcuts": atalhoAnunciado(kbd), "aria-busy": loading || undefined };
|
|
125
145
|
// GAR-14: o `share` emite a mesma marcação que o `aurea.js` lê ([data-aurea-share]) — o catálogo
|
|
126
146
|
// estático não hidrata, e é ela que faz o botão funcionar lá. Os textos vão junto, na língua do app.
|
|
127
147
|
const s = useAureaStrings();
|
|
@@ -185,7 +205,9 @@ function temConteudoVisivel(children) {
|
|
|
185
205
|
// entre os estados**. Se o texto vira "Mute"/"Unmute" ou "Play"/"Pause", não é toggle — é
|
|
186
206
|
// botão de ação, porque quem lê tela ouve o rótulo NOVO e o estado ao mesmo tempo e não sabe
|
|
187
207
|
// se o botão descreve o que é ou o que fará.
|
|
188
|
-
export function Toggle({ pressed, defaultPressed, onPressedChange, value, icon, label, size, disabled, id, className, children }) {
|
|
208
|
+
export function Toggle({ pressed, defaultPressed, onPressedChange, value, icon, label, size: sizePedido, disabled, id, className, children, variant = "default" }) {
|
|
209
|
+
const grupo = React.useContext(GrupoDeBotoesContext);
|
|
210
|
+
const size = sizePedido ?? grupo?.size;
|
|
189
211
|
// O tipo barra o consumidor TypeScript; este aviso barra o de JavaScript, que não tem tipo nenhum.
|
|
190
212
|
// Sem gate por NODE_ENV de propósito: o `dist` é saída de `tsc`, então `process` não existe no
|
|
191
213
|
// navegador e a referência quebraria o render — e um controle sem nome merece aparecer em produção
|
|
@@ -196,28 +218,48 @@ export function Toggle({ pressed, defaultPressed, onPressedChange, value, icon,
|
|
|
196
218
|
const rotuloVisivel = typeof label === "string" && label.trim().length > 0;
|
|
197
219
|
if (!textoVisivel && !rotuloVisivel)
|
|
198
220
|
console.error("Aurea: <Toggle> sem `children` visível e sem `label` não tem nome acessível — quem usa leitor de tela encontra um botão anônimo. Passe `label` quando o toggle for só ícone.");
|
|
199
|
-
|
|
221
|
+
// O tamanho pela MESMA conta do `Button` (0.32.0): até a 0.31.0 era `size!=="md"&&\`btn-${size}\``, e
|
|
222
|
+
// sem `size` saía a classe `btn-undefined` (medido no catálogo, nos três botões do `ToggleGroup`); com
|
|
223
|
+
// valor responsivo sairia `btn-[object Object]`.
|
|
224
|
+
const tamanho = ehResponsivo(size) ? classesResponsivas("size", size) : ((valorBase(size) ?? "md") !== "md" && `btn-${valorBase(size)}`);
|
|
225
|
+
return _jsxs(BaseToggle, { id: id, value: value, disabled: disabled, pressed: pressed, defaultPressed: defaultPressed, onPressedChange: soOValor(onPressedChange), "aria-label": textoVisivel ? undefined : (rotuloVisivel ? label : undefined), className: cx("btn", variant === "ghost" ? "btn-ghost" : "btn-tertiary", tamanho, !textoVisivel && "btn-icon", "toggle", className), children: [icon && _jsx(Icon, { name: icon }), children] });
|
|
200
226
|
}
|
|
201
227
|
// default ghost (não secondary): um ícone-ação solto — hambúrguer, tema, fechar — é sem
|
|
202
228
|
// caixa por convenção (pedido do Victor: hambúrguer sem borda). Quem quer a caixa passa
|
|
203
229
|
// variant. Alinha o React ao HTML dos docs, onde .btn-icon já é transparente.
|
|
204
230
|
// Ocupado, o glifo SAI e a rodinha fica sozinha no centro — ver o `inner` do `Button`.
|
|
205
|
-
|
|
206
|
-
export const
|
|
207
|
-
|
|
231
|
+
// Dentro de um grupo com `variant`, o do grupo vale (0.32.0); solto, o padrão continua o fantasma.
|
|
232
|
+
export const IconButton = forwardRef(function IconButton({ label, icon, variant, className, loading, ...props }, ref) { const grupo = React.useContext(GrupoDeBotoesContext); return _jsx(Button, { ref: ref, variant: variant ?? (grupo?.variant ? undefined : "ghost"), className: cx("btn-icon", className), "aria-label": label, loading: loading, ...props, children: loading ? null : _jsx(Icon, { name: icon }) }); });
|
|
233
|
+
export const CloseButton = forwardRef(function CloseButton({ label, className, children, ...props }, ref) {
|
|
234
|
+
const s = useAureaStrings();
|
|
235
|
+
return _jsx(Button, { ref: ref, variant: "tertiary", className: cx("close-button", className), "aria-label": label ?? s.close, ...props, children: children ?? _jsx(Icon, { name: "x", weight: "bold" }) });
|
|
236
|
+
});
|
|
237
|
+
export const ThemeToggle = forwardRef(function ThemeToggle({ className, mode = "light-dark", ...props }, ref) {
|
|
238
|
+
const { theme, preference, toggleTheme, setTheme } = useAureaTheme();
|
|
208
239
|
const s = useAureaStrings();
|
|
209
240
|
const escuro = theme === "dark";
|
|
241
|
+
const nome = React.useId();
|
|
242
|
+
// A CHAVE DE TRÊS POSIÇÕES (15/10/2026, o Victor: "A, B, C, pode"): a do topo da referência, medida nela — a
|
|
243
|
+
// cápsula de 34 com as três opções de 26 e o glifo de 16. São botões de opção NATIVOS, como as amostras do
|
|
244
|
+
// `ColorSwatch`: a escolha única e as setas são do navegador. A escolhida tem o glifo cheio (ADR-0053) e a pele da
|
|
245
|
+
// aba escolhida (ADR-0059). Quem escolhe é o provider (`"system"` segue o sistema).
|
|
246
|
+
if (mode === "light-dark-system") {
|
|
247
|
+
const opcoes = [["light", "sun", s.themeLight], ["dark", "moon", s.themeDark], ["system", "monitor", s.themeSystem]];
|
|
248
|
+
return _jsx("div", { role: "radiogroup", "aria-label": s.themeChoice, className: cx("theme-switch", className), children: opcoes.map(([v, icone, rotulo]) => {
|
|
249
|
+
const marcada = preference === v;
|
|
250
|
+
return _jsxs("label", { className: "theme-switch-option", children: [_jsx("input", { type: "radio", className: "theme-switch-input", name: nome, value: v, checked: marcada, disabled: props.disabled, "aria-label": rotulo, onChange: () => setTheme(v) }), _jsx(Icon, { name: icone, size: "sm", weight: marcada ? "fill" : "regular" })] }, v);
|
|
251
|
+
}) });
|
|
252
|
+
}
|
|
210
253
|
// O corpo do `IconButton`, escrito aqui só para o glifo sair na forma CHEIA (ADR-0053: a lua e o
|
|
211
254
|
// sol cheios, como os do conjunto de ícones anterior, aprovados pela imagem em 25/09/2026). O `IconButton` público não
|
|
212
255
|
// tem peso de ícone.
|
|
213
256
|
return _jsx(Button, { ref: ref, variant: "ghost", className: cx("btn-icon", escuro ? "theme-toggle-sun" : "theme-toggle-moon", className), "aria-label": escuro ? s.themeToLight : s.themeToDark, onClick: toggleTheme, ...props, children: _jsx(Icon, { name: escuro ? "sun" : "moon", weight: "fill" }) });
|
|
214
257
|
});
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
export function ButtonGroup({ label, orientation, className, ...props }) { const s = useAureaStrings(); return _jsx("div", { role: "group", "aria-label": label ?? s.optionsLabel, className: cx("btn-group", peleDoEixo("btn-group", orientation, "horizontal", "btn-group"), className), ...props }); }
|
|
258
|
+
export function ButtonGroup({ label, orientation, variant, size, fullWidth, disabled, detached, className, ...props }) {
|
|
259
|
+
const s = useAureaStrings();
|
|
260
|
+
const grupo = React.useMemo(() => ({ variant, size, disabled }), [variant, size, disabled]);
|
|
261
|
+
return _jsx(GrupoDeBotoesContext.Provider, { value: grupo, children: _jsx("div", { role: "group", "aria-label": label ?? s.optionsLabel, className: cx("btn-group", peleDoEixo("btn-group", orientation, "horizontal", "btn-group"), detached && "btn-group-detached", fullWidth && "btn-group-full", className), ...props }) });
|
|
262
|
+
}
|
|
221
263
|
// Toolbar: roving tabindex (setas navegam, Tab entra/sai) via Base UI.
|
|
222
264
|
// G-AXIS-06 — o valor responsivo RESOLVIDO é a única fonte de verdade: ele vai para o motor, o
|
|
223
265
|
// motor publica `data-orientation`/`aria-orientation` e ajusta o teclado, e a pele reage ao
|
|
@@ -233,18 +275,9 @@ export function Toolbar({ orientation, label, className, ...props }) {
|
|
|
233
275
|
export function ToolbarGroup({ label, className, ...props }) { return _jsx(BaseToolbar.Group, { "aria-label": label, className: cx("toolbar-group", className), ...props }); }
|
|
234
276
|
export function ToolbarSeparator({ className, ...props }) { return _jsx(BaseToolbar.Separator, { className: cx("toolbar-sep", className), ...props }); }
|
|
235
277
|
export const ToolbarButton = forwardRef(function ToolbarButton({ variant = "ghost", ...props }, ref) { return _jsx(BaseToolbar.Button, { ref: ref, disabled: props.disabled, render: _jsx(Button, { variant: variant, ...props }) }); });
|
|
236
|
-
|
|
237
|
-
//
|
|
238
|
-
// Não é o SegmentedControl, e confundir os dois constrói a coisa errada com o nome certo: o
|
|
239
|
-
// `SegmentedControl` é escolha ÚNICA e obrigatória entre alternativas de uma mesma dimensão
|
|
240
|
-
// ("dia / semana / mês") e se parece com uma cápsula; aqui cada botão liga e desliga por conta
|
|
241
|
-
// própria, `multiple` permite vários ao mesmo tempo, e zero selecionado é estado legítimo. É a
|
|
242
|
-
// barra de formatação de um editor, não um filtro de período.
|
|
243
|
-
//
|
|
244
|
-
// O motor dá o roving tabindex, o `loopFocus` e o contrato de pressionado; a pele é a do
|
|
245
|
-
// `.btn-group`, porque um grupo de botões é o que isto é.
|
|
246
|
-
export function ToggleGroup({ value, defaultValue, onValueChange, multiple, orientation, disabled, label, className, children }) {
|
|
278
|
+
export function ToggleGroup({ value, defaultValue, onValueChange, multiple, orientation, disabled, label, className, children, size, fullWidth, detached }) {
|
|
247
279
|
const ancora = useRef(null);
|
|
248
280
|
const resolvida = useValorResponsivo(orientation, "horizontal", ancora);
|
|
249
|
-
|
|
281
|
+
const grupo = React.useMemo(() => ({ size }), [size]);
|
|
282
|
+
return _jsx(GrupoDeBotoesContext.Provider, { value: grupo, children: _jsx(BaseToggleGroup, { ref: ancora, value: value, defaultValue: defaultValue, onValueChange: soOValor(onValueChange), multiple: multiple, orientation: resolvida, disabled: disabled, "aria-label": label, className: cx("toggle-group", detached && "toggle-group-detached", fullWidth && "toggle-group-full", className), children: children }) });
|
|
250
283
|
}
|
package/dist/agents.js
CHANGED
|
@@ -100,7 +100,7 @@ export function HumanApproval({ title, description, details, risk, reasoning, de
|
|
|
100
100
|
const s = useAureaStrings();
|
|
101
101
|
return _jsxs("section", { className: cx("card", "approval", className), "aria-label": typeof title === "string" ? title : s.approvalLabel, ...props, children: [_jsxs("header", { className: "approval-head", children: [_jsx("strong", { children: title }), risk && _jsx(Badge, { variant: risk === "high" ? "danger" : risk === "medium" ? "warning" : "neutral", children: s.approvalRisk[risk] })] }), description && _jsx("p", { className: "approval-desc", children: description }), !!details?.length && _jsx(DataList, { items: details }), reasoning && _jsx("p", { className: "approval-reason", children: reasoning }), deadline && _jsxs("p", { className: "hint", children: [s.approvalDeadline, ": ", deadline] }), decision
|
|
102
102
|
? _jsx(Alert, { variant: decision === "approved" ? "success" : "warning", children: decision === "approved" ? s.approvalApproved : s.approvalDenied })
|
|
103
|
-
: _jsxs("footer", { className: "approval-actions", children: [_jsx(Button, { variant: "
|
|
103
|
+
: _jsxs("footer", { className: "approval-actions", children: [_jsx(Button, { variant: "tertiary", onClick: onDeny, children: s.approvalDeny }), _jsx(Button, { variant: "primary", onClick: onApprove, children: s.approvalApprove })] })] });
|
|
104
104
|
}
|
|
105
105
|
// ToolPermission — o que cada ferramenta pode, sem perguntar de novo.
|
|
106
106
|
//
|
package/dist/calendar.d.ts
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { DayPicker } from "react-day-picker";
|
|
2
|
+
import { DayPicker, type DateRange, type DayPickerLocale } from "react-day-picker";
|
|
3
|
+
import { type Responsive } from "./pure.js";
|
|
4
|
+
import { type IconName } from "./system.js";
|
|
5
|
+
import type { FieldSize } from "./markup.js";
|
|
3
6
|
export type CalendarProps = React.ComponentProps<typeof DayPicker> & {
|
|
4
7
|
label?: string;
|
|
5
8
|
};
|
|
6
9
|
export declare function Calendar({ label, className, classNames, ...props }: CalendarProps): React.JSX.Element;
|
|
10
|
+
export interface DatePickerBase {
|
|
11
|
+
minimumDate?: Date;
|
|
12
|
+
maximumDate?: Date;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
size?: Responsive<FieldSize>;
|
|
15
|
+
/** A língua do campo E do calendário: o objeto de `react-day-picker/locale` (`import {ptBR} from
|
|
16
|
+
* "react-day-picker/locale"`), o mesmo que o `Calendar` recebe. Padrão: inglês, o padrão do motor. */
|
|
17
|
+
locale?: DayPickerLocale;
|
|
18
|
+
/** Como a data vira texto no gatilho. Padrão: dia, mês curto e ano na língua do `locale` (sem ele, inglês). */
|
|
19
|
+
format?: (d: Date) => string;
|
|
20
|
+
/** O texto do gatilho vazio. Padrão: a frase `datePlaceholder` (ou `dateRangePlaceholder` no intervalo). */
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
/** O ícone no fim do gatilho. Padrão: `calendar`; `false` tira. */
|
|
23
|
+
icon?: IconName | false;
|
|
24
|
+
/** Vai no formulário como `aaaa-mm-dd`; no intervalo, `aaaa-mm-dd/aaaa-mm-dd` (o intervalo da ISO 8601). */
|
|
25
|
+
name?: string;
|
|
26
|
+
id?: string;
|
|
27
|
+
className?: string;
|
|
28
|
+
"aria-label"?: string;
|
|
29
|
+
"aria-labelledby"?: string;
|
|
30
|
+
"aria-describedby"?: string;
|
|
31
|
+
}
|
|
32
|
+
export type DatePickerProps = DatePickerBase & ({
|
|
33
|
+
range?: false;
|
|
34
|
+
value?: Date;
|
|
35
|
+
defaultValue?: Date;
|
|
36
|
+
onChange?: (d: Date) => void;
|
|
37
|
+
} | {
|
|
38
|
+
range: true;
|
|
39
|
+
value?: DateRange;
|
|
40
|
+
defaultValue?: DateRange;
|
|
41
|
+
onChange?: (r: DateRange) => void;
|
|
42
|
+
});
|
|
43
|
+
export declare function DatePicker(props: DatePickerProps): React.JSX.Element;
|
package/dist/calendar.js
CHANGED
|
@@ -1,7 +1,44 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// A diretiva aqui NÃO vem de um hook nosso — este arquivo não chama nenhum. Vem do motor: o
|
|
4
|
+
// `react-day-picker` usa estado e NÃO publica `"use client"` no dist dele (medido em
|
|
5
|
+
// 06/08/2026, junto com `recharts` e `@tanstack/react-table`, que também não publicam; o
|
|
6
|
+
// `@base-ui/react` publica). Sem a diretiva, o módulo seria de servidor e o motor quebraria
|
|
7
|
+
// dentro dele. É o caso que a regra "tem hook? leva diretiva" não enxerga, e por isso o
|
|
8
|
+
// check 26 do validate.py também olha para essas três importações.
|
|
9
|
+
//
|
|
10
|
+
// Lote 4 do BUILDING.md (01/08/2026). SUBPATH PRÓPRIO, como ./chart, ./data-grid e ./qrcode: o
|
|
11
|
+
// único componente que precisa do `react-day-picker`, que é peer OPCIONAL.
|
|
12
|
+
//
|
|
13
|
+
// O MOTOR, e por que este: o Base UI — que já é dependência dura daqui — **não tem** calendário
|
|
14
|
+
// nem campo de data. Medido em 01/08/2026 na lista de exports do 1.6.0, que é a versão mais
|
|
15
|
+
// recente. Então o motor era decisão aberta, e a resposta é a mesma de uma das referências: react-day-picker.
|
|
16
|
+
//
|
|
17
|
+
// O que foi medido antes de escolher (o registro completo está no REFERENCES.md):
|
|
18
|
+
// • renderiza no SERVIDOR — 8618 bytes, <table> de verdade, 42 células. Ao contrário do
|
|
19
|
+
// Recharts, então o catálogo não precisa de prerender nenhum;
|
|
20
|
+
// • a semântica já vem certa: role="grid"/"gridcell", aria-selected, <button> por dia,
|
|
21
|
+
// o mês em role="status" aria-live, e <thead aria-hidden> com <th scope="col">;
|
|
22
|
+
// • tem API de tema PRÓPRIA (`classNames`), que é o que permite manter todo nome `rdp-*`
|
|
23
|
+
// fora do nosso CSS — mesma saída da pele do CodeEditor, que vem pelo EditorView.theme.
|
|
24
|
+
//
|
|
25
|
+
// O que NÃO entrou: o motor headless que outra das referências escolheu. Trazer um segundo motor
|
|
26
|
+
// headless para conviver com o Base UI é criar padrão paralelo, que o protocolo proíbe.
|
|
27
|
+
//
|
|
28
|
+
// ~~E o que NÃO se constrói aqui: um `DatePicker`. Aquela mesma referência não tem componente-raiz para isso e
|
|
29
|
+
// diz por quê — seletor de data é composição de Popover com calendário, e a Aurea já tem os
|
|
30
|
+
// dois. A composição está registrada como PATTERN, que é o veículo da casa para isso.~~
|
|
31
|
+
// 13/10/2026 (ADR-0068): o `DatePicker` ENTRA, e mora aqui. A referência principal tem a peça (a frase
|
|
32
|
+
// acima falava de outra referência), o nativo da Aurea já tem um `DatePicker`, e quase todo sistema do
|
|
33
|
+
// mercado entrega o seletor de data como componente — deixado como padrão, cada app refazia o foco, a
|
|
34
|
+
// janela e a leitura da data, e cada um saía diferente. Escolha do Victor: *"data B"*. Mora neste arquivo
|
|
35
|
+
// pelo mesmo motivo do `Calendar`: o motor de calendário é dependência OPCIONAL, e só este caminho o puxa.
|
|
36
|
+
import React from "react";
|
|
3
37
|
import { DayPicker } from "react-day-picker";
|
|
4
|
-
import {
|
|
38
|
+
import { Popover as BasePopover } from "@base-ui/react/popover";
|
|
39
|
+
import { cx, useAureaStrings, usePortalContainer, controlesRotulaveis } from "./internal.js";
|
|
40
|
+
import { peleDoEixo } from "./pure.js";
|
|
41
|
+
import { Icon } from "./system.js";
|
|
5
42
|
// Só TRÊS nomes são renomeados, e é de propósito. Todo o resto da pele é escrito contra ELEMENTO
|
|
6
43
|
// (`.calendar table`, `.calendar th`, `.calendar td button`) e contra os `data-*` que o motor já
|
|
7
44
|
// emite (`data-selected`, `data-today`, `data-outside`, `data-disabled`, `data-hidden`) — e
|
|
@@ -25,3 +62,79 @@ export function Calendar({ label, className, classNames, ...props }) {
|
|
|
25
62
|
// motor não deixa a raiz dele ser um `group`, e nenhum dos dois papéis dele serve aqui.
|
|
26
63
|
return label ? _jsx("div", { role: "group", "aria-label": label, children: grade }) : grade;
|
|
27
64
|
}
|
|
65
|
+
// A data do formulário pela data LOCAL: `toISOString` passa por UTC e, à noite no Brasil, daria o dia seguinte.
|
|
66
|
+
const dataIso = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
67
|
+
// A língua vem do `locale`, a MESMA que o calendário usa, e nunca do ambiente: com a língua do ambiente, o
|
|
68
|
+
// servidor escrevia "12 de ago. de 2026" e o navegador "Aug 12, 2026" — medido em 13/10/2026, erro de
|
|
69
|
+
// hidratação 418 no catálogo. Sem `locale`, inglês, como o motor (a regra da casa do `agents.tsx`: padrão fixo).
|
|
70
|
+
const formatoPadrao = (d, locale) => d.toLocaleDateString(locale?.code ?? "en-US", { day: "numeric", month: "short", year: "numeric" });
|
|
71
|
+
export function DatePicker(props) {
|
|
72
|
+
const { minimumDate, maximumDate, disabled, size, locale, format, placeholder, icon = "calendar", name, id, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby } = props;
|
|
73
|
+
const s = useAureaStrings();
|
|
74
|
+
const portal = usePortalContainer();
|
|
75
|
+
const [aberta, setAberta] = React.useState(false);
|
|
76
|
+
const cliques = React.useRef(0);
|
|
77
|
+
const gatilho = React.useRef(null);
|
|
78
|
+
const [idDoRotulo, setIdDoRotulo] = React.useState();
|
|
79
|
+
const [interno, setInterno] = React.useState(props.defaultValue);
|
|
80
|
+
const valor = props.value !== undefined ? props.value : interno;
|
|
81
|
+
const formatar = format ?? ((d) => formatoPadrao(d, locale));
|
|
82
|
+
let texto;
|
|
83
|
+
let campo;
|
|
84
|
+
if (props.range) {
|
|
85
|
+
const r = valor;
|
|
86
|
+
if (r?.from)
|
|
87
|
+
texto = r.to && r.to.getTime() !== r.from.getTime() ? `${formatar(r.from)} – ${formatar(r.to)}` : formatar(r.from);
|
|
88
|
+
if (r?.from)
|
|
89
|
+
campo = `${dataIso(r.from)}/${dataIso(r.to ?? r.from)}`;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
const d = valor;
|
|
93
|
+
if (d) {
|
|
94
|
+
texto = formatar(d);
|
|
95
|
+
campo = dataIso(d);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const vazio = texto === undefined;
|
|
99
|
+
const limites = [minimumDate && { before: minimumDate }, maximumDate && { after: maximumDate }].filter(Boolean);
|
|
100
|
+
const comum = {
|
|
101
|
+
disabled: limites.length ? limites : undefined,
|
|
102
|
+
startMonth: minimumDate, endMonth: maximumDate, locale,
|
|
103
|
+
defaultMonth: props.range ? valor?.from : valor,
|
|
104
|
+
autoFocus: true,
|
|
105
|
+
};
|
|
106
|
+
// O intervalo é NOSSO, pelo dia clicado (o 2º argumento do motor), e não o que o motor calcula: o dele
|
|
107
|
+
// ESTENDE o intervalo que já existe — com 1 a 3 escolhido, clicar 15 e 20 dava 1 a 20. Aqui, cada
|
|
108
|
+
// abertura começa um intervalo novo: o 1º clique é uma ponta, o 2º a outra, em qualquer ordem.
|
|
109
|
+
const calendario = props.range
|
|
110
|
+
? _jsx(Calendar, { ...comum, mode: "range", selected: valor, onSelect: (_, dia) => {
|
|
111
|
+
cliques.current += 1;
|
|
112
|
+
const inicio = valor?.from;
|
|
113
|
+
const r = cliques.current === 1 || !inicio ? { from: dia, to: undefined }
|
|
114
|
+
: dia < inicio ? { from: dia, to: inicio } : { from: inicio, to: dia };
|
|
115
|
+
if (props.value === undefined)
|
|
116
|
+
setInterno(r);
|
|
117
|
+
props.onChange?.(r);
|
|
118
|
+
if (cliques.current >= 2)
|
|
119
|
+
setAberta(false);
|
|
120
|
+
} })
|
|
121
|
+
: _jsx(Calendar, { ...comum, mode: "single", selected: valor, onSelect: (d) => {
|
|
122
|
+
if (!d)
|
|
123
|
+
return;
|
|
124
|
+
if (props.value === undefined)
|
|
125
|
+
setInterno(d);
|
|
126
|
+
props.onChange?.(d);
|
|
127
|
+
setAberta(false);
|
|
128
|
+
} });
|
|
129
|
+
return _jsxs(BasePopover.Root, { open: aberta, onOpenChange: (o) => {
|
|
130
|
+
// O `<label for>` que nomeia o gatilho (o do `Field` tem `id`), pela ligação do próprio navegador.
|
|
131
|
+
if (o) {
|
|
132
|
+
cliques.current = 0;
|
|
133
|
+
setIdDoRotulo(gatilho.current?.labels?.[0]?.id || undefined);
|
|
134
|
+
}
|
|
135
|
+
setAberta(o);
|
|
136
|
+
}, children: [_jsxs(BasePopover.Trigger, { ref: gatilho, disabled: disabled, id: id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, className: cx("select", "select-trigger", "date-picker-trigger", peleDoEixo("select", size), className), children: [_jsx("span", { className: "select-value", "data-placeholder": vazio ? "" : undefined, lang: vazio ? undefined : locale?.code, children: texto ?? placeholder ?? (props.range ? s.dateRangePlaceholder : s.datePlaceholder) }), icon !== false && _jsx(Icon, { name: icon })] }), name && _jsx("input", { type: "hidden", name: name, value: campo ?? "" }), _jsx(BasePopover.Portal, { container: portal, children: _jsx(BasePopover.Positioner, { className: "positioner", side: "bottom", align: "start", sideOffset: 6, children: _jsx(BasePopover.Popup, { className: "popover date-picker-popover", "aria-labelledby": ariaLabelledby ?? idDoRotulo, "aria-label": (ariaLabelledby ?? idDoRotulo) ? undefined
|
|
137
|
+
: ariaLabel ?? (props.range ? s.dateRangePlaceholder : s.datePlaceholder), children: calendario }) }) })] });
|
|
138
|
+
}
|
|
139
|
+
// O `Field` nomeia o gatilho com `<label for>`: o `id` que ele injeta vai para o botão (ver `internal.tsx`).
|
|
140
|
+
controlesRotulaveis.add(DatePicker);
|
package/dist/code-client.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare function CodeBlock({ children, language, copyable, className }: {
|
|
2
|
+
export declare function CodeBlock({ children, language, copyable, preview, className }: {
|
|
3
3
|
children: string;
|
|
4
4
|
language?: string;
|
|
5
5
|
copyable?: boolean;
|
|
6
|
+
/** A prévia viva do código: com ela, o bloco vira a caixa de exemplo, com as abas Prévia | Código. */
|
|
7
|
+
preview?: React.ReactNode;
|
|
6
8
|
className?: string;
|
|
7
9
|
}): React.JSX.Element;
|
package/dist/code-client.js
CHANGED
|
@@ -9,7 +9,29 @@ import { Icon } from "./system.js";
|
|
|
9
9
|
// copyable: o gatilho é marcado com data-aurea-copy e o COMPORTAMENTO mora no aurea.js do
|
|
10
10
|
// core (uma implementação para React e para HTML puro). O onClick daqui atende quem só
|
|
11
11
|
// carrega o pacote React; ele para a propagação pro core não copiar duas vezes.
|
|
12
|
-
|
|
12
|
+
// DOC-02 (0.32.0): a CAIXA DE EXEMPLO do site da Aurea virou o `preview` do `CodeBlock` — as abas
|
|
13
|
+
// Prévia | Código (o controle segmentado ocupando a largura), a prévia no fundo afundado e o código sem
|
|
14
|
+
// moldura. É a caixa do site de hoje (decisão do Victor, 06/10/2026: a da Aurea, não a da referência),
|
|
15
|
+
// agora no pacote, para o site usar só peças da Aurea. O teclado é o das abas do APG: setas, Home e End.
|
|
16
|
+
// Sem o `aurea.js` na página — quem troca a aba é o React.
|
|
17
|
+
function CaixaDeExemplo({ preview, codigo, className }) {
|
|
18
|
+
const s = useAureaStrings();
|
|
19
|
+
const id = React.useId();
|
|
20
|
+
const [aba, setAba] = React.useState("preview");
|
|
21
|
+
const refPrevia = React.useRef(null), refCodigo = React.useRef(null);
|
|
22
|
+
const ir = (a) => { setAba(a); (a === "preview" ? refPrevia : refCodigo).current?.focus(); };
|
|
23
|
+
const tecla = (e) => {
|
|
24
|
+
if (!["ArrowRight", "ArrowLeft", "Home", "End"].includes(e.key))
|
|
25
|
+
return;
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
ir(e.key === "Home" ? "preview" : e.key === "End" ? "code" : aba === "preview" ? "code" : "preview");
|
|
28
|
+
};
|
|
29
|
+
const botao = (a, rotulo) => _jsx("button", { type: "button", role: "tab", id: `${id}-${a}`, ref: a === "preview" ? refPrevia : refCodigo, className: aba === a ? "active" : undefined, "aria-selected": aba === a, "aria-controls": `${id}-${a}-panel`, tabIndex: aba === a ? 0 : -1, onClick: () => setAba(a), onKeyDown: tecla, children: rotulo });
|
|
30
|
+
return _jsxs("div", { className: cx("demo code-preview", className), children: [_jsx("div", { className: "demo-tabs", children: _jsxs("div", { className: "segmented", role: "tablist", children: [botao("preview", s.codeBlockPreview), botao("code", s.codeBlockCode)] }) }), _jsx("div", { className: "demo-panel", "data-panel": "preview", role: "tabpanel", id: `${id}-preview-panel`, "aria-labelledby": `${id}-preview`, tabIndex: 0, hidden: aba !== "preview", children: preview }), _jsx("div", { className: "demo-panel demo-code", "data-panel": "code", role: "tabpanel", id: `${id}-code-panel`, "aria-labelledby": `${id}-code`, tabIndex: 0, hidden: aba !== "code", children: codigo })] });
|
|
31
|
+
}
|
|
32
|
+
export function CodeBlock({ children, language = "text", copyable, preview, className }) {
|
|
33
|
+
if (preview !== undefined)
|
|
34
|
+
return _jsx(CaixaDeExemplo, { preview: preview, className: className, codigo: _jsx(CodeBlock, { language: language, copyable: copyable, children: children }) });
|
|
13
35
|
const s = useAureaStrings();
|
|
14
36
|
// tabIndex no <pre>: `.code-block` é `overflow:auto` por construção, então é REGIÃO ROLÁVEL
|
|
15
37
|
// e não tem nada focável dentro — quem navega por teclado não alcança o código que passa da
|