@aurea-uds/react 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/actions.d.ts +33 -6
- package/dist/actions.js +38 -26
- 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 +11 -5
- package/dist/feedback-client.js +26 -15
- 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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/inputs-client.d.ts +215 -2
- package/dist/inputs-client.js +504 -8
- package/dist/inputs.d.ts +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +4 -0
- package/dist/layout-client.d.ts +14 -2
- package/dist/layout-client.js +2 -2
- package/dist/markup.d.ts +89 -9
- package/dist/markup.js +48 -11
- package/dist/navigation-client.d.ts +31 -7
- package/dist/navigation-client.js +60 -16
- package/dist/overlays.d.ts +20 -6
- package/dist/overlays.js +65 -10
- package/dist/pure.d.ts +20 -0
- package/dist/pure.js +2 -2
- package/dist/system.d.ts +5 -2
- package/dist/system.js +17 -9
- 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,7 +1,7 @@
|
|
|
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
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";
|
|
4
|
+
export type ButtonVariant = "primary" | "secondary" | "tertiary" | "outline" | "ghost" | "primary-outline" | "primary-ghost" | "danger" | "danger-outline" | "danger-ghost" | "link" | "link-primary" | "link-danger" | "nav";
|
|
5
5
|
export type ButtonAppearance = "solid" | "outline" | "ghost" | "link" | "nav";
|
|
6
6
|
export type ButtonTone = "neutral" | "brand" | "danger" | "success" | "warning" | "info";
|
|
7
7
|
export type ComponentSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
@@ -80,7 +80,11 @@ interface ToggleBase {
|
|
|
80
80
|
disabled?: boolean;
|
|
81
81
|
id?: string;
|
|
82
82
|
className?: string;
|
|
83
|
+
/** 0.32.0, o `ToggleButton` da referência: `default` com o fundo neutro (o padrão), `ghost` sem fundo
|
|
84
|
+
* (o desenho de até a 0.31.0). O ligado é o idioma "selecionado" da Aurea nos dois. */
|
|
85
|
+
variant?: ToggleVariant;
|
|
83
86
|
}
|
|
87
|
+
export type ToggleVariant = "default" | "ghost";
|
|
84
88
|
type ToggleChildren = Exclude<React.ReactNode, boolean | null | undefined>;
|
|
85
89
|
export type ToggleProps = ToggleBase & ({
|
|
86
90
|
children: ToggleChildren;
|
|
@@ -89,19 +93,35 @@ export type ToggleProps = ToggleBase & ({
|
|
|
89
93
|
children?: never;
|
|
90
94
|
label: string;
|
|
91
95
|
});
|
|
92
|
-
export declare function Toggle({ pressed, defaultPressed, onPressedChange, value, icon, label, size, disabled, id, className, children }: ToggleProps): React.JSX.Element;
|
|
96
|
+
export declare function Toggle({ pressed, defaultPressed, onPressedChange, value, icon, label, size: sizePedido, disabled, id, className, children, variant }: ToggleProps): React.JSX.Element;
|
|
93
97
|
export interface IconButtonProps extends Omit<ButtonProps, "children"> {
|
|
94
98
|
label: string;
|
|
95
99
|
icon: IconName;
|
|
96
100
|
}
|
|
97
101
|
export declare const IconButton: React.ForwardRefExoticComponent<Omit<IconButtonProps, "ref"> & RefAttributes<HTMLButtonElement>>;
|
|
102
|
+
export interface CloseButtonProps extends Omit<ButtonProps, "variant" | "appearance" | "tone" | "size" | "loading" | "leadingIcon" | "trailingIcon" | "href" | "target" | "rel" | "download" | "render" | "kbd" | "fullWidth" | "grow" | "pressed" | "share"> {
|
|
103
|
+
/** O nome que o leitor de tela anuncia. Padrão: a frase `close` ("Close"/"Fechar"). */
|
|
104
|
+
label?: string;
|
|
105
|
+
}
|
|
106
|
+
export declare const CloseButton: React.ForwardRefExoticComponent<Omit<CloseButtonProps, "ref"> & RefAttributes<HTMLButtonElement>>;
|
|
98
107
|
export interface ThemeToggleProps extends Omit<IconButtonProps, "icon" | "label" | "onClick" | "variant" | "appearance" | "tone" | "href" | "target" | "rel" | "download" | "render" | "kbd" | "loading" | "leadingIcon" | "trailingIcon" | "fullWidth" | "share"> {
|
|
99
108
|
}
|
|
100
109
|
export declare const ThemeToggle: React.ForwardRefExoticComponent<Omit<ThemeToggleProps, "ref"> & RefAttributes<HTMLButtonElement>>;
|
|
101
|
-
export
|
|
110
|
+
export interface ButtonGroupProps extends HTMLAttributes<HTMLDivElement>, RefAttributes<HTMLDivElement> {
|
|
102
111
|
label?: string;
|
|
103
112
|
orientation?: Responsive<Orientation>;
|
|
104
|
-
|
|
113
|
+
/** O desenho de todos os botões de dentro; cada um pode trocar o seu. */
|
|
114
|
+
variant?: ButtonVariant;
|
|
115
|
+
/** O tamanho de todos os botões de dentro; cada um pode trocar o seu. */
|
|
116
|
+
size?: Responsive<ComponentSize>;
|
|
117
|
+
/** Ocupa a largura do pai, e os botões repartem em partes iguais. */
|
|
118
|
+
fullWidth?: boolean;
|
|
119
|
+
/** Desliga todos os botões de dentro. */
|
|
120
|
+
disabled?: boolean;
|
|
121
|
+
/** Botões soltos (cápsulas com vão de 4), em vez de colados. */
|
|
122
|
+
detached?: boolean;
|
|
123
|
+
}
|
|
124
|
+
export declare function ButtonGroup({ label, orientation, variant, size, fullWidth, disabled, detached, className, ...props }: ButtonGroupProps): React.JSX.Element;
|
|
105
125
|
export declare function Toolbar({ orientation, label, className, ...props }: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement> & {
|
|
106
126
|
orientation?: Responsive<Orientation>;
|
|
107
127
|
label?: string;
|
|
@@ -113,7 +133,7 @@ export declare function ToolbarSeparator({ className, ...props }: HTMLAttributes
|
|
|
113
133
|
export interface ToolbarButtonProps extends Omit<ButtonProps, "share"> {
|
|
114
134
|
}
|
|
115
135
|
export declare const ToolbarButton: React.ForwardRefExoticComponent<Omit<ToolbarButtonProps, "ref"> & RefAttributes<HTMLButtonElement>>;
|
|
116
|
-
export
|
|
136
|
+
export interface ToggleGroupProps {
|
|
117
137
|
value?: string[];
|
|
118
138
|
defaultValue?: string[];
|
|
119
139
|
onValueChange?: (value: string[]) => void;
|
|
@@ -123,5 +143,12 @@ export declare function ToggleGroup({ value, defaultValue, onValueChange, multip
|
|
|
123
143
|
label?: string;
|
|
124
144
|
className?: string;
|
|
125
145
|
children: React.ReactNode;
|
|
126
|
-
|
|
146
|
+
/** O tamanho de todos os botões de dentro; cada um pode trocar o seu (valor simples, como o dela). */
|
|
147
|
+
size?: Extract<ComponentSize, "sm" | "md" | "lg">;
|
|
148
|
+
/** Ocupa a largura do pai, e os botões repartem em partes iguais. */
|
|
149
|
+
fullWidth?: boolean;
|
|
150
|
+
/** Botões soltos (vão de 4), em vez de colados. */
|
|
151
|
+
detached?: boolean;
|
|
152
|
+
}
|
|
153
|
+
export declare function ToggleGroup({ value, defaultValue, onValueChange, multiple, orientation, disabled, label, className, children, size, fullWidth, detached }: ToggleGroupProps): React.JSX.Element;
|
|
127
154
|
export {};
|
package/dist/actions.js
CHANGED
|
@@ -15,8 +15,11 @@ 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"],
|
|
@@ -27,7 +30,7 @@ const EIXOS = {
|
|
|
27
30
|
// uma classe própria", e é o que garante que NENHUMA baseline se mexe: `appearance="outline"`
|
|
28
31
|
// + `tone="danger"` emite `.btn-danger-outline`, o mesmo DOM de sempre.
|
|
29
32
|
const CLASSE_ANTIGA = new Map(Object.entries(EIXOS)
|
|
30
|
-
.map(([v, [a, t]]) => [`${a}/${t}`, v]));
|
|
33
|
+
.filter(([v]) => v !== "secondary").map(([v, [a, t]]) => [`${a}/${t}`, v]));
|
|
31
34
|
/** Resolve os dois eixos (ou o atalho) na classe que o core pinta. Exportada porque o teste
|
|
32
35
|
* cobra a matriz inteira, e porque quem monta um botão à mão precisa da mesma conta.
|
|
33
36
|
*
|
|
@@ -37,7 +40,10 @@ const CLASSE_ANTIGA = new Map(Object.entries(EIXOS)
|
|
|
37
40
|
* `--success`/`--success-foreground` e os irmãos são. `outline` voltou a ser só uma aparência
|
|
38
41
|
* que se pede, nunca o que sobra quando a nossa paleta não dá conta. */
|
|
39
42
|
export function buttonSkin(variant, appearance, tone) {
|
|
40
|
-
|
|
43
|
+
// A variação sem eixo pedido é a própria classe — é o caminho do `secondary`, que não tem célula.
|
|
44
|
+
if (appearance === undefined && tone === undefined)
|
|
45
|
+
return `btn-${variant ?? "tertiary"}`;
|
|
46
|
+
const [a0, t0] = EIXOS[variant ?? "tertiary"];
|
|
41
47
|
const a = appearance ?? a0, t = tone ?? t0;
|
|
42
48
|
const antiga = CLASSE_ANTIGA.get(`${a}/${t}`);
|
|
43
49
|
return antiga ? `btn-${antiga}` : cx(`btn-${a}`, `btn-tone-${t}`);
|
|
@@ -90,10 +96,15 @@ async function compartilhar(botao, dados, s, dentroDoProvider) {
|
|
|
90
96
|
avisar(true);
|
|
91
97
|
}
|
|
92
98
|
}
|
|
99
|
+
const GrupoDeBotoesContext = React.createContext(null);
|
|
93
100
|
// type="button" por default: o default do HTML é submit, e um "Cancelar"/"Remover"
|
|
94
101
|
// dentro de <form> dispararia a ação principal (auditoria 18/07/2026, ALTO 1).
|
|
95
102
|
// Quem quer submeter passa type="submit" explícito (como o MessageComposer faz).
|
|
96
|
-
export const Button = forwardRef(function Button({ variant, appearance, tone, size
|
|
103
|
+
export const Button = forwardRef(function Button({ variant: variantPedida, appearance, tone, size: sizePedido, 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) {
|
|
104
|
+
const grupo = React.useContext(GrupoDeBotoesContext);
|
|
105
|
+
const variant = variantPedida ?? grupo?.variant;
|
|
106
|
+
const size = sizePedido ?? grupo?.size ?? "md";
|
|
107
|
+
const disabled = disabledPedido ?? grupo?.disabled;
|
|
97
108
|
// G-AXIS-04 — `size` aceita valor simples, responsivo por viewport ou adaptativo por container.
|
|
98
109
|
// SOMATIVO por construção: valor simples continua emitindo `btn-sm`, byte por byte a mesma classe
|
|
99
110
|
// de antes, e por isso nenhuma baseline se mexe. Só o valor responsivo entra pela camada genérica
|
|
@@ -111,7 +122,7 @@ export const Button = forwardRef(function Button({ variant, appearance, tone, si
|
|
|
111
122
|
// da frente; e sem conteúdo (o `IconButton` ocupado) o invólucro vazio some, senão o `gap` dele
|
|
112
123
|
// empurraria a rodinha para fora do centro. Fora do estado ocupado o HTML é o mesmo de antes.
|
|
113
124
|
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 })] });
|
|
125
|
+
const inner = _jsxs(_Fragment, { children: [loading ? _jsx("span", { className: "spinner" }) : leadingIcon && _jsx(Icon, { name: leadingIcon }), (temConteudo || !loading) && _jsx("span", { children: children }), kbd && _jsx(Kbd, { className: "btn-kbd", children: kbd }), trailingIcon && _jsx(Icon, { name: trailingIcon })] });
|
|
115
126
|
// INERTE ≠ DESABILITADO, e a diferença é medida (M4, 13/08/2026): `disabled` tira o botão da
|
|
116
127
|
// ordem de foco, então quem navega por teclado nunca alcança a explicação de POR QUE não dá — e
|
|
117
128
|
// "não dá porque você não tem permissão" é justamente o caso em que a explicação é tudo. O
|
|
@@ -185,7 +196,9 @@ function temConteudoVisivel(children) {
|
|
|
185
196
|
// entre os estados**. Se o texto vira "Mute"/"Unmute" ou "Play"/"Pause", não é toggle — é
|
|
186
197
|
// 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
198
|
// 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 }) {
|
|
199
|
+
export function Toggle({ pressed, defaultPressed, onPressedChange, value, icon, label, size: sizePedido, disabled, id, className, children, variant = "default" }) {
|
|
200
|
+
const grupo = React.useContext(GrupoDeBotoesContext);
|
|
201
|
+
const size = sizePedido ?? grupo?.size;
|
|
189
202
|
// O tipo barra o consumidor TypeScript; este aviso barra o de JavaScript, que não tem tipo nenhum.
|
|
190
203
|
// Sem gate por NODE_ENV de propósito: o `dist` é saída de `tsc`, então `process` não existe no
|
|
191
204
|
// navegador e a referência quebraria o render — e um controle sem nome merece aparecer em produção
|
|
@@ -196,13 +209,22 @@ export function Toggle({ pressed, defaultPressed, onPressedChange, value, icon,
|
|
|
196
209
|
const rotuloVisivel = typeof label === "string" && label.trim().length > 0;
|
|
197
210
|
if (!textoVisivel && !rotuloVisivel)
|
|
198
211
|
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
|
-
|
|
212
|
+
// O tamanho pela MESMA conta do `Button` (0.32.0): até a 0.31.0 era `size!=="md"&&\`btn-${size}\``, e
|
|
213
|
+
// sem `size` saía a classe `btn-undefined` (medido no catálogo, nos três botões do `ToggleGroup`); com
|
|
214
|
+
// valor responsivo sairia `btn-[object Object]`.
|
|
215
|
+
const tamanho = ehResponsivo(size) ? classesResponsivas("size", size) : ((valorBase(size) ?? "md") !== "md" && `btn-${valorBase(size)}`);
|
|
216
|
+
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
217
|
}
|
|
201
218
|
// default ghost (não secondary): um ícone-ação solto — hambúrguer, tema, fechar — é sem
|
|
202
219
|
// caixa por convenção (pedido do Victor: hambúrguer sem borda). Quem quer a caixa passa
|
|
203
220
|
// variant. Alinha o React ao HTML dos docs, onde .btn-icon já é transparente.
|
|
204
221
|
// Ocupado, o glifo SAI e a rodinha fica sozinha no centro — ver o `inner` do `Button`.
|
|
205
|
-
|
|
222
|
+
// Dentro de um grupo com `variant`, o do grupo vale (0.32.0); solto, o padrão continua o fantasma.
|
|
223
|
+
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 }) }); });
|
|
224
|
+
export const CloseButton = forwardRef(function CloseButton({ label, className, children, ...props }, ref) {
|
|
225
|
+
const s = useAureaStrings();
|
|
226
|
+
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" }) });
|
|
227
|
+
});
|
|
206
228
|
export const ThemeToggle = forwardRef(function ThemeToggle({ className, ...props }, ref) {
|
|
207
229
|
const { theme, toggleTheme } = useAureaTheme();
|
|
208
230
|
const s = useAureaStrings();
|
|
@@ -212,12 +234,11 @@ export const ThemeToggle = forwardRef(function ThemeToggle({ className, ...props
|
|
|
212
234
|
// tem peso de ícone.
|
|
213
235
|
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
236
|
});
|
|
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 }); }
|
|
237
|
+
export function ButtonGroup({ label, orientation, variant, size, fullWidth, disabled, detached, className, ...props }) {
|
|
238
|
+
const s = useAureaStrings();
|
|
239
|
+
const grupo = React.useMemo(() => ({ variant, size, disabled }), [variant, size, disabled]);
|
|
240
|
+
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 }) });
|
|
241
|
+
}
|
|
221
242
|
// Toolbar: roving tabindex (setas navegam, Tab entra/sai) via Base UI.
|
|
222
243
|
// G-AXIS-06 — o valor responsivo RESOLVIDO é a única fonte de verdade: ele vai para o motor, o
|
|
223
244
|
// motor publica `data-orientation`/`aria-orientation` e ajusta o teclado, e a pele reage ao
|
|
@@ -233,18 +254,9 @@ export function Toolbar({ orientation, label, className, ...props }) {
|
|
|
233
254
|
export function ToolbarGroup({ label, className, ...props }) { return _jsx(BaseToolbar.Group, { "aria-label": label, className: cx("toolbar-group", className), ...props }); }
|
|
234
255
|
export function ToolbarSeparator({ className, ...props }) { return _jsx(BaseToolbar.Separator, { className: cx("toolbar-sep", className), ...props }); }
|
|
235
256
|
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 }) {
|
|
257
|
+
export function ToggleGroup({ value, defaultValue, onValueChange, multiple, orientation, disabled, label, className, children, size, fullWidth, detached }) {
|
|
247
258
|
const ancora = useRef(null);
|
|
248
259
|
const resolvida = useValorResponsivo(orientation, "horizontal", ancora);
|
|
249
|
-
|
|
260
|
+
const grupo = React.useMemo(() => ({ size }), [size]);
|
|
261
|
+
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
262
|
}
|
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, { 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
|
package/dist/color.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { AureaStrings } from "./pure.js";
|
|
2
|
+
/** Os três canais de 0 a 255. */
|
|
3
|
+
export interface Rgb {
|
|
4
|
+
r: number;
|
|
5
|
+
g: number;
|
|
6
|
+
b: number;
|
|
7
|
+
}
|
|
8
|
+
/** Matiz de 0 a 360; saturação e brilho de 0 a 1 (o HSV). */
|
|
9
|
+
export interface Hsb {
|
|
10
|
+
h: number;
|
|
11
|
+
s: number;
|
|
12
|
+
b: number;
|
|
13
|
+
}
|
|
14
|
+
/** Matiz de 0 a 360; saturação e luminosidade de 0 a 1. */
|
|
15
|
+
export interface Hsl {
|
|
16
|
+
h: number;
|
|
17
|
+
s: number;
|
|
18
|
+
l: number;
|
|
19
|
+
}
|
|
20
|
+
/** A cor de dentro das peças: HSB com o alfa (0 = transparente, 1 = opaca). */
|
|
21
|
+
export interface Cor extends Hsb {
|
|
22
|
+
a: number;
|
|
23
|
+
}
|
|
24
|
+
export type ColorSpace = "rgb" | "hsl" | "hsb";
|
|
25
|
+
export type ColorChannel = "hue" | "saturation" | "brightness" | "lightness" | "red" | "green" | "blue" | "alpha";
|
|
26
|
+
/** Os três canais de cada espaço, na ordem dele. */
|
|
27
|
+
export declare const COLOR_CHANNELS: Readonly<Record<ColorSpace, readonly [ColorChannel, ColorChannel, ColorChannel]>>;
|
|
28
|
+
/** `#rgb`, `#rgba`, `#rrggbb` ou `#rrggbbaa` (com ou sem `#`) → os canais e o alfa; o resto → `null`. */
|
|
29
|
+
export declare function parseHex(texto: string): (Rgb & {
|
|
30
|
+
a: number;
|
|
31
|
+
}) | null;
|
|
32
|
+
/** Os canais → `#rrggbb` (minúscula, como o `<input type="color">`); com alfa abaixo de 1, `#rrggbbaa`. */
|
|
33
|
+
export declare function toHex({ r, g, b, a }: Rgb & {
|
|
34
|
+
a?: number;
|
|
35
|
+
}): string;
|
|
36
|
+
/** Normaliza o texto hex; texto inválido → `null`. */
|
|
37
|
+
export declare const normalizeHex: (texto: string) => string | null;
|
|
38
|
+
/** Texto de cor → a cor de dentro: hex (3, 4, 6 ou 8 dígitos), `rgb()`, `hsl()` ou `hsb()`, com alfa. O resto →
|
|
39
|
+
* `null`. O matiz de `hsl()`/`hsb()` cinza é guardado (o hex o perderia). */
|
|
40
|
+
export declare function parseColor(texto: string): Cor | null;
|
|
41
|
+
/** A cor de dentro → hex (`#rrggbb`, ou `#rrggbbaa` com transparência). */
|
|
42
|
+
export declare const corToHex: (c: Cor) => string;
|
|
43
|
+
export declare function rgbToHsb({ r, g, b }: Rgb): Hsb;
|
|
44
|
+
export declare function hsbToRgb({ h, s, b }: Hsb): Rgb;
|
|
45
|
+
export declare function rgbToHsl({ r, g, b }: Rgb): Hsl;
|
|
46
|
+
export declare function hslToRgb({ h, s, l }: Hsl): Rgb;
|
|
47
|
+
/** A faixa de cada canal, a mesma da referência: matiz 0–360 (passo 1, salto 15); saturação, brilho e luminosidade
|
|
48
|
+
* 0–100 (passo 1, salto 10); vermelho, verde e azul 0–255 (passo 1, salto 17); alfa 0–1 (passo 0,01, salto 0,1). */
|
|
49
|
+
export declare function channelRange(ch: ColorChannel): {
|
|
50
|
+
min: number;
|
|
51
|
+
max: number;
|
|
52
|
+
step: number;
|
|
53
|
+
page: number;
|
|
54
|
+
};
|
|
55
|
+
/** O espaço em que um canal vive: luminosidade só no HSL, brilho só no HSB, vermelho/verde/azul só no RGB; matiz,
|
|
56
|
+
* saturação e alfa no espaço pedido (sem pedido, HSB). */
|
|
57
|
+
export declare function spaceOf(ch: ColorChannel, pedido?: ColorSpace): ColorSpace;
|
|
58
|
+
/** O valor de um canal, na faixa dele. */
|
|
59
|
+
export declare function getChannel(c: Cor, ch: ColorChannel, space?: ColorSpace): number;
|
|
60
|
+
/** A cor com um canal trocado (o valor é limitado à faixa). O matiz e a saturação de antes ficam quando a cor nova
|
|
61
|
+
* vira cinza ou preta. */
|
|
62
|
+
export declare function setChannel(c: Cor, ch: ColorChannel, v: number, space?: ColorSpace): Cor;
|
|
63
|
+
/** A luminância relativa da WCAG 2 (0 = preto, 1 = branco), a conta do contraste. */
|
|
64
|
+
export declare function relativeLuminance({ r, g, b }: Rgb): number;
|
|
65
|
+
/** A tinta que contrasta MAIS sobre a cor: `"dark"` (preto) ou `"light"` (branco), pela razão de contraste da WCAG
|
|
66
|
+
* — e não por um palpite de "cor clara". O amarelo da Aurea pede preto; um azul médio também. */
|
|
67
|
+
export declare function contrastingInk(rgb: Rgb): "dark" | "light";
|
|
68
|
+
type Direcao = "to right" | "to left" | "to top";
|
|
69
|
+
/** A cor pura de um matiz, em hex — a cor do pino da trilha de matiz. */
|
|
70
|
+
export declare const pureHue: (h: number) => string;
|
|
71
|
+
/** O FUNDO da trilha de um canal, para o `background` do trilho do `Slider`. O gradiente vai de ponta a ponta do
|
|
72
|
+
* trilho, mas as paradas começam e terminam na FOLGA (`--slider-cap`, o recuo que o pino respeita): antes da
|
|
73
|
+
* primeira e depois da última, a cor chapada da ponta. Assim o pino no mínimo fica sobre a cor do mínimo, em
|
|
74
|
+
* qualquer canal. O alfa vai do transparente à cor opaca (o xadrez embaixo é a pele, e não gradiente). */
|
|
75
|
+
export declare function trackBackground(c: Cor, ch: ColorChannel, space?: ColorSpace, direcao?: Direcao): string;
|
|
76
|
+
/** O fundo da área de cor para um par de canais, com o terceiro fixo no valor da cor de agora. A técnica é a da
|
|
77
|
+
* biblioteca da referência (escrita aqui por nós): no RGB, uma camada por canal somadas pelo modo de mistura
|
|
78
|
+
* `screen`; no HSL e no HSB, uma camada por canal com a receita de paradas dele, e a cor pura embaixo quando o
|
|
79
|
+
* fixo é o matiz. `x` anda do começo ao fim da linha (na escrita da direita para a esquerda, o começo é a direita);
|
|
80
|
+
* `y`, de baixo para cima. */
|
|
81
|
+
export declare function areaBackground(c: Cor, space: ColorSpace, x: ColorChannel, y: ColorChannel, rtl?: boolean): {
|
|
82
|
+
background: string;
|
|
83
|
+
blend?: string;
|
|
84
|
+
};
|
|
85
|
+
export type ColorNameStrings = Pick<AureaStrings, "colorHue" | "colorTone" | "colorNameFormat">;
|
|
86
|
+
export type ColorHueName = keyof AureaStrings["colorHue"];
|
|
87
|
+
export type ColorToneName = keyof AureaStrings["colorTone"];
|
|
88
|
+
/** O nome da cor na língua das frases: "vivid blue", "dark red", "rosa pálido". */
|
|
89
|
+
export declare function colorName(rgb: Rgb, s: ColorNameStrings): string;
|
|
90
|
+
/** O valor de um canal escrito para o leitor de tela e a saída: "210°", "80%", "128", alfa "50%". */
|
|
91
|
+
export declare function formatChannel(ch: ColorChannel, v: number): string;
|
|
92
|
+
export {};
|