@aurea-uds/native 0.30.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/dist/actions.d.ts +15 -1
- package/dist/actions.js +40 -17
- package/dist/busca.js +16 -14
- package/dist/display.js +17 -3
- package/dist/escolha.d.ts +121 -0
- package/dist/escolha.js +466 -0
- package/dist/exibicao.d.ts +188 -0
- package/dist/exibicao.js +457 -0
- package/dist/feedback.d.ts +48 -4
- package/dist/feedback.js +92 -28
- package/dist/icon-names.d.ts +7 -1
- package/dist/icon-names.js +2 -0
- package/dist/icon.d.ts +6 -4
- package/dist/icon.js +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.js +10 -1
- package/dist/inputs.d.ts +12 -3
- package/dist/inputs.js +71 -25
- package/dist/layout.d.ts +1 -1
- package/dist/layout.js +3 -0
- package/dist/menu.d.ts +99 -0
- package/dist/menu.js +452 -0
- package/dist/navigation.d.ts +1 -1
- package/dist/navigation.js +35 -18
- package/dist/numero.d.ts +2 -2
- package/dist/numero.js +6 -2
- package/dist/overlays.js +35 -9
- package/dist/sistema.js +15 -10
- package/dist/strings.d.ts +4 -0
- package/dist/strings.js +4 -0
- package/dist/text.js +7 -1
- package/dist/toast.js +9 -12
- package/icons/index.d.ts +1 -0
- package/icons/index.js +2 -1
- package/icons/x-bold.d.ts +6 -0
- package/icons/x-bold.js +10 -0
- package/package.json +2 -2
package/dist/actions.d.ts
CHANGED
|
@@ -87,11 +87,25 @@ export declare function IconButton(props: IconButtonProps): React.JSX.Element;
|
|
|
87
87
|
/**
|
|
88
88
|
* Quanto a ÁREA DE TOQUE do `IconButton` passa do círculo desenhado, de cada lado — R-24
|
|
89
89
|
* (08/10/2026). O alvo é o maior entre o desenho e o `targetMin` (44), centrado; o círculo de
|
|
90
|
-
* `md`
|
|
90
|
+
* `md` tinha 36, e sobravam 4 de cada lado. O `Badge` preso usa isto para se prender ao CÍRCULO,
|
|
91
91
|
* e não ao canto da área de toque — medido: preso à área de toque, o selo ficava 4 para fora.
|
|
92
|
+
* 0.32.0: com a escala de toque o `md` tem 48 e a folga é 0; sobra no `sm` (40: 2) e no `xs`.
|
|
92
93
|
*/
|
|
93
94
|
export declare function folgaDoToque(t: AureaTokens, size?: AureaButtonSize): number;
|
|
94
95
|
/** Fechado: sem `appearance` e sem `tone`, porque a cor é a do glifo. */
|
|
95
96
|
export interface ThemeToggleProps extends Omit<IconButtonProps, "name" | "label" | "onPress" | "appearance" | "tone" | "share"> {
|
|
96
97
|
}
|
|
97
98
|
export declare function ThemeToggle(props: ThemeToggleProps): React.JSX.Element;
|
|
99
|
+
export interface CloseButtonProps {
|
|
100
|
+
/** O nome que o leitor de tela anuncia. Padrão: a frase `close` ("Close"/"Fechar"). */
|
|
101
|
+
label?: string;
|
|
102
|
+
onPress?: PressableProps["onPress"];
|
|
103
|
+
disabled?: boolean;
|
|
104
|
+
/** Registro local de ícones, quando não há um em contexto. */
|
|
105
|
+
icons?: AureaIconRegistry;
|
|
106
|
+
/** Troca o X. */
|
|
107
|
+
children?: React.ReactNode;
|
|
108
|
+
testID?: string;
|
|
109
|
+
}
|
|
110
|
+
/** O botão de fechar: círculo neutro com o X, que já se chama "Close"/"Fechar". */
|
|
111
|
+
export declare function CloseButton({ label, onPress, disabled, icons, children, testID }: CloseButtonProps): React.JSX.Element;
|
package/dist/actions.js
CHANGED
|
@@ -26,17 +26,22 @@ import { canto, criarFolha, REACAO_AO_TOQUE, estadoAcessivel } from "./estilos.j
|
|
|
26
26
|
import { Icon } from "./icon.js";
|
|
27
27
|
import { Text } from "./text.js";
|
|
28
28
|
import { AvisosContext, useAureaStrings, useAureaTheme, useAureaTokens, useSobreAMarca } from "./theme.js";
|
|
29
|
-
const
|
|
30
|
-
xs:
|
|
29
|
+
const MEDIDA = {
|
|
30
|
+
xs: (s) => ({ altura: s.controlHSm, recheio: s.space3, vao: s.space1 + s.space05 }),
|
|
31
|
+
sm: (s) => ({ altura: s.touchControlHSm, recheio: s.space3 + s.space05, vao: s.space1 + s.space05 }),
|
|
32
|
+
md: (s) => ({ altura: s.touchControlHMd, recheio: s.space4, vao: s.space2 }),
|
|
33
|
+
lg: (s) => ({ altura: s.touchControlHLg, recheio: s.space5, vao: s.space2 + s.space05 }),
|
|
34
|
+
xl: (s) => ({ altura: s.touchControlHLg + s.space2, recheio: s.space6, vao: s.space2 + s.space05 }),
|
|
31
35
|
};
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
const GAP = { xs: 6, sm: 8, md: 8, lg: 8, xl: 10 };
|
|
36
|
+
// O degrau do `Text` do nativo, que sobe um em relação à web (ADR-0050): `xs` é 14, `base` é 16 e
|
|
37
|
+
// `lg` é 18.
|
|
35
38
|
const FONTE = {
|
|
36
|
-
xs: "xs", sm: "xs", md: "
|
|
39
|
+
xs: "xs", sm: "xs", md: "base", lg: "lg", xl: "lg",
|
|
37
40
|
};
|
|
41
|
+
// O ícone acompanha a altura nova: 16 até o `sm` (40), 20 no `md` (48), 24 do `lg` (56) para cima.
|
|
42
|
+
// Era 16 até o `md` e 20 no `lg` e no `xl`, quando o `md` tinha 36.
|
|
38
43
|
const ICONE = {
|
|
39
|
-
xs: "sm", sm: "sm", md: "
|
|
44
|
+
xs: "sm", sm: "sm", md: "md", lg: "lg", xl: "lg",
|
|
40
45
|
};
|
|
41
46
|
/** Par (fundo, texto, borda) por tom, para cada aparência. Tudo de token, nada cru. */
|
|
42
47
|
function pintar(t, tone) {
|
|
@@ -121,6 +126,8 @@ const folha = criarFolha((t) => ({
|
|
|
121
126
|
// pinta fundo, borda e raio é a `caixa` interna, com a altura do token. O botão continua com
|
|
122
127
|
// 36 dp de desenho e passa a ter 44 de alvo — e o leitor de tela enxerga os 44, porque o
|
|
123
128
|
// elemento acessível é o `Pressable`, não um retângulo invisível ao lado dele.
|
|
129
|
+
// 0.32.0: com a escala de toque, o `md` (48) e o `lg` (56) já passam do alvo sozinhos; o `sm`
|
|
130
|
+
// (40) e o `xs` (32) continuam ganhando os 44 por aqui.
|
|
124
131
|
// E2 (25/09/2026): SEM `alignSelf`. O botão obedece o pai, como na referência (a folha do botão dela
|
|
125
132
|
// não fixa alinhamento) e como o `.btn` da web num `.stack`. Era `alignSelf: "flex-start"`, e ele
|
|
126
133
|
// vencia o `alignItems: "center"` do pai: o botão do `EmptyState` ficava à esquerda com o resto
|
|
@@ -209,17 +216,18 @@ function CorpoDoBotao({ children, appearance = "solid", tone = "neutral", size =
|
|
|
209
216
|
const marca = useSobreAMarca();
|
|
210
217
|
const cor = pintarSobreAMarca(pintar(t, tone), marca, tone, appearance);
|
|
211
218
|
const corDaBorda = marca?.tinta ?? t.color.border;
|
|
219
|
+
const medida = MEDIDA[size](t.size);
|
|
212
220
|
const caixa = React.useMemo(() => ({
|
|
213
|
-
height:
|
|
214
|
-
paddingHorizontal:
|
|
215
|
-
gap:
|
|
221
|
+
height: medida.altura,
|
|
222
|
+
paddingHorizontal: medida.recheio,
|
|
223
|
+
gap: medida.vao,
|
|
216
224
|
backgroundColor: appearance === "solid" ? cor.solido : "transparent",
|
|
217
225
|
borderColor: cor.contorno ?? (appearance === "outline" ? corDaBorda : "transparent"),
|
|
218
226
|
...(fullWidth ? { flex: 1 } : null),
|
|
219
227
|
// A regra do botão-link da referência: `height: auto; padding: 0`, e a do botão dela já
|
|
220
228
|
// tem `border-width: 0`. A borda transparente de 1 empurraria o texto 1 para dentro.
|
|
221
229
|
...(semRecuo ? { height: undefined, paddingHorizontal: 0, borderWidth: 0 } : null),
|
|
222
|
-
}), [
|
|
230
|
+
}), [medida.altura, medida.recheio, medida.vao, appearance, cor.solido, cor.contorno, corDaBorda, fullWidth, semRecuo]);
|
|
223
231
|
const corDoTexto = appearance === "solid" ? cor.texto : cor.sobre;
|
|
224
232
|
return (_jsx(Pressable, { disabled: disabled, onPress: aoTocar, accessibilityRole: "button", accessibilityLabel: accessibilityLabel, ...estadoAcessivel({ disabled: !!disabled, pressed }), style: ({ pressed: tocando }) => [
|
|
225
233
|
s.alvo, fullWidth && s.alvoLargura,
|
|
@@ -231,8 +239,8 @@ function CorpoDoBotao({ children, appearance = "solid", tone = "neutral", size =
|
|
|
231
239
|
// Atkinson Hyperlegible (ADR-0053) sobe 0,984 e desce 0,316, o mesmo 1,3 (medido na
|
|
232
240
|
// tabela `hhea` dos dois arquivos, 01/10/2026): no Android o RN
|
|
233
241
|
// corta o que passa da linha, e a perna do g, do p e do ç sumia. Cabe em todo tamanho e
|
|
234
|
-
// densidade (
|
|
235
|
-
//
|
|
242
|
+
// densidade (conta da 0.32.0): `xs`/`sm` têm linha de 21 e o menor botão mede 28 (`xs`
|
|
243
|
+
// no compacto); o `md` tem linha de 24 e mede 44 ou mais; `lg`/`xl`, 27 e 52 ou mais.
|
|
236
244
|
? _jsx(Text, { size: FONTE[size], weight: 500, leading: "normal", style: { color: corDoTexto }, children: children })
|
|
237
245
|
: children, trailingIcon ? _jsx(Icon, { name: trailingIcon, size: ICONE[size], color: corDoTexto, icons: icons }) : null, trailing ?? null] }) }));
|
|
238
246
|
}
|
|
@@ -256,11 +264,12 @@ export function IconButton(props) {
|
|
|
256
264
|
/**
|
|
257
265
|
* Quanto a ÁREA DE TOQUE do `IconButton` passa do círculo desenhado, de cada lado — R-24
|
|
258
266
|
* (08/10/2026). O alvo é o maior entre o desenho e o `targetMin` (44), centrado; o círculo de
|
|
259
|
-
* `md`
|
|
267
|
+
* `md` tinha 36, e sobravam 4 de cada lado. O `Badge` preso usa isto para se prender ao CÍRCULO,
|
|
260
268
|
* e não ao canto da área de toque — medido: preso à área de toque, o selo ficava 4 para fora.
|
|
269
|
+
* 0.32.0: com a escala de toque o `md` tem 48 e a folga é 0; sobra no `sm` (40: 2) e no `xs`.
|
|
261
270
|
*/
|
|
262
271
|
export function folgaDoToque(t, size = "md") {
|
|
263
|
-
const lado = t.size
|
|
272
|
+
const lado = MEDIDA[size](t.size).altura;
|
|
264
273
|
return Math.max(0, (Math.max(lado, t.size.targetMin) - lado) / 2);
|
|
265
274
|
}
|
|
266
275
|
/** O corpo do `IconButton`. A cor própria do ícone (`corDoIcone`) é só do `ThemeToggle`: o
|
|
@@ -272,13 +281,14 @@ function BotaoDeIcone({ name, label, appearance = "ghost", tone = "neutral", siz
|
|
|
272
281
|
const marca = useSobreAMarca();
|
|
273
282
|
const cor = pintarSobreAMarca(pintar(t, tone), marca, tone, appearance);
|
|
274
283
|
const corDaBorda = marca?.tinta ?? t.color.border;
|
|
275
|
-
|
|
284
|
+
// O círculo tem a altura do botão do mesmo tamanho (o só-ícone da referência: `aspect-ratio: 1`).
|
|
285
|
+
const lado = MEDIDA[size](t.size).altura;
|
|
276
286
|
const caixa = React.useMemo(() => ({
|
|
277
287
|
height: lado, width: lado, paddingHorizontal: 0,
|
|
278
288
|
...canto(t.size.radiusControl),
|
|
279
289
|
backgroundColor: appearance === "solid" ? cor.solido : "transparent",
|
|
280
290
|
borderColor: cor.contorno ?? (appearance === "outline" ? corDaBorda : "transparent"),
|
|
281
|
-
}), [t, lado,
|
|
291
|
+
}), [t, lado, appearance, cor.solido, cor.contorno, corDaBorda]);
|
|
282
292
|
return (_jsx(Pressable, { disabled: disabled, onPress: aoTocar, accessibilityRole: "button", accessibilityLabel: label, ...estadoAcessivel({ disabled: !!disabled, pressed }), style: ({ pressed: tocando }) => [
|
|
283
293
|
// Largura FIXA, como o só-ícone da referência: ele nunca estica,
|
|
284
294
|
// nem numa coluna sem alinhamento. O alvo é o maior entre o desenho e o `targetMin`.
|
|
@@ -293,3 +303,16 @@ export function ThemeToggle(props) {
|
|
|
293
303
|
const escuro = theme === "dark";
|
|
294
304
|
return (_jsx(BotaoDeIcone, { ...props, name: escuro ? "sun" : "moon", label: escuro ? s.themeToLight : s.themeToDark, corDoIcone: escuro ? t.color.primary : t.color.foreground, pesoDoIcone: "fill", onPress: toggleTheme }));
|
|
295
305
|
}
|
|
306
|
+
/** O botão de fechar: círculo neutro com o X, que já se chama "Close"/"Fechar". */
|
|
307
|
+
export function CloseButton({ label, onPress, disabled, icons, children, testID }) {
|
|
308
|
+
const t = useAureaTokens();
|
|
309
|
+
const s = useAureaStrings();
|
|
310
|
+
const lado = t.size.touchControlHSm;
|
|
311
|
+
return (_jsx(Pressable, { disabled: disabled, onPress: onPress, accessibilityRole: "button", accessibilityLabel: label ?? s.close, ...estadoAcessivel({ disabled: !!disabled }), hitSlop: t.size.space3, testID: testID, style: ({ pressed: tocando }) => [
|
|
312
|
+
{ width: lado, height: lado, alignItems: "center", justifyContent: "center",
|
|
313
|
+
...canto(t.size.radiusFull), backgroundColor: t.color.secondary },
|
|
314
|
+
// Encolhe a 93%, como o da referência (o botão comum da Aurea vai a 97%).
|
|
315
|
+
tocando && { opacity: REACAO_AO_TOQUE.pressionado.opacity, transform: [{ scale: 0.93 }] },
|
|
316
|
+
disabled && REACAO_AO_TOQUE.inerte,
|
|
317
|
+
], children: children ?? _jsx(Icon, { name: "x", weight: "bold", size: "md", icons: icons, color: t.color.mutedForeground }) }));
|
|
318
|
+
}
|
package/dist/busca.js
CHANGED
|
@@ -72,20 +72,16 @@ import { IconButton } from "./actions.js";
|
|
|
72
72
|
import { canto, cantosDeCima, criarFolha, estadoAcessivel } from "./estilos.js";
|
|
73
73
|
import { Spinner } from "./feedback.js";
|
|
74
74
|
import { Icon } from "./icon.js";
|
|
75
|
-
import { KeyboardAvoiding, useCampo } from "./inputs.js";
|
|
75
|
+
import { KeyboardAvoiding, alturaDoTamanho, indicadorDaEscolhida, respiroDoGatilho, respiroDoTamanho, useCampo, } from "./inputs.js";
|
|
76
76
|
import { useReduceMotion, driverNativo } from "./movimento.js";
|
|
77
77
|
import { RecuoDaFolha } from "./screen.js";
|
|
78
78
|
import { Text } from "./text.js";
|
|
79
79
|
import { useAureaStrings, useAureaTokens, useTokensDoApp, ForaDaMarca, usePeleSobreAMarca } from "./theme.js";
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
|
|
80
|
+
// A altura e o respiro do campo vêm do `inputs.tsx` (0.32.0). Eram repetidos aqui, de propósito,
|
|
81
|
+
// para não tornar pública uma conta interna de lá — mas desde 02/10/2026 o `inputs.tsx` já os
|
|
82
|
+
// exporta ao `FileInput`, e a escala de toque mostrou o custo da cópia: duas contas para mudar
|
|
83
|
+
// juntas. Saem do arquivo, não do pacote.
|
|
84
84
|
const fonteDoTamanho = (t, s) => s === "sm" ? t.size.textSm : s === "lg" ? t.size.textLg : t.size.textBase; // ADR-0050: um degrau acima da web
|
|
85
|
-
// ⚠ O `13` do tamanho `md` NÃO é número inventado: é o `padding-inline` literal do `.input`
|
|
86
|
-
// (`aurea.css:685`), e é o mesmo valor que o `inputs.tsx:60` usa. Não há token de 13 — a escala
|
|
87
|
-
// tem `space3`=12 e `space4`=16 —, e é por isso que o CSS o escreve cru dos dois lados.
|
|
88
|
-
const respiroDoTamanho = (t, s) => s === "sm" ? t.size.space3 : s === "lg" ? t.size.space4 : 13;
|
|
89
85
|
// ── AS DUAS CONSTANTES DE INTERAÇÃO, e elas NÃO são geometria ────────────────────────────────
|
|
90
86
|
// Ficam nomeadas e no topo porque número solto no meio do componente é o que o `CLAUDE.md`
|
|
91
87
|
// passou a proibir em 12/09/2026. **Nenhuma das duas tem linha de `aurea.css` atrás, e não
|
|
@@ -175,10 +171,14 @@ const folha = criarFolha((t) => ({
|
|
|
175
171
|
// `CLAUDE.md` ("correção local é proibida sem responder quem mais tem esse problema") é o que
|
|
176
172
|
// traz as duas linhas para cá, e este campo é exatamente "quem mais".
|
|
177
173
|
campoDeTexto: { flex: 1, minWidth: 0, paddingVertical: 0, textAlignVertical: "center" },
|
|
174
|
+
// 0.32.0: a opção da lista do `Select` (`inputs.tsx`), que é a da referência — 12 em cima e
|
|
175
|
+
// embaixo, 8 dos lados, 8 até o indicador, 48 de toque no mínimo. Era `controlHLg` (40), 16 dos
|
|
176
|
+
// lados e 8 em cima e embaixo. As duas folhas continuam iguais, que é o combinado acima.
|
|
178
177
|
opcao: {
|
|
179
|
-
minHeight: t.size.
|
|
180
|
-
paddingHorizontal: t.size.
|
|
178
|
+
minHeight: t.size.touchControlHMd, flexDirection: "row", alignItems: "center", gap: t.size.space2,
|
|
179
|
+
paddingHorizontal: t.size.space2, paddingVertical: t.size.space3,
|
|
181
180
|
},
|
|
181
|
+
textoDaOpcao: { flex: 1, minWidth: 0 },
|
|
182
182
|
opcaoEscolhida: { backgroundColor: t.color.surface3 ?? t.color.muted },
|
|
183
183
|
vazio: { paddingHorizontal: t.size.space4, paddingVertical: t.size.space5, alignItems: "center" },
|
|
184
184
|
carregando: { paddingVertical: t.size.space4, alignItems: "center" },
|
|
@@ -304,7 +304,9 @@ export function Combobox({ items, value, onValueChange, onSearchChange, searchDe
|
|
|
304
304
|
const nada = !loading && filtrados.length === 0;
|
|
305
305
|
return (_jsxs(_Fragment, { children: [_jsxs(View, { style: [
|
|
306
306
|
s.caixa,
|
|
307
|
-
|
|
307
|
+
// 0.32.0: o gatilho do `Select` — altura de toque, 16 dos lados no `md` e 12 entre o
|
|
308
|
+
// texto e as ações (era 13 e nada).
|
|
309
|
+
{ height: alturaDoTamanho(t, tam), paddingHorizontal: respiroDoGatilho(t, tam), gap: t.size.space3 },
|
|
308
310
|
campo?.invalido && s.invalido,
|
|
309
311
|
// Sobre a marca a tinta vence inválido — ver `usePeleSobreAMarca`.
|
|
310
312
|
peleDaMarca,
|
|
@@ -324,7 +326,7 @@ export function Combobox({ items, value, onValueChange, onSearchChange, searchDe
|
|
|
324
326
|
sf.campoDeTexto,
|
|
325
327
|
{ fontSize: fonteDoTamanho(t, tam), fontFamily: tf.font.ui[400],
|
|
326
328
|
color: tf.color.foreground },
|
|
327
|
-
] }), texto.length > 0 && (_jsx(IconButton, { name: "x", label: strings.searchClear, appearance: "ghost", size: "sm", onPress: () => digitar(""), testID: testID ? `${testID}-busca-limpar` : undefined }))] }), loading && (_jsx(View, { style: sf.carregando, children: _jsx(Spinner, { label: strings.comboboxLoading }) })), nada && (_jsx(View, { style: sf.vazio, children: typeof empty === "string" || empty == null
|
|
329
|
+
] }), texto.length > 0 && (_jsx(IconButton, { name: "x", label: strings.searchClear, appearance: "ghost", size: "sm", onPress: () => digitar(""), testID: testID ? `${testID}-busca-limpar` : undefined }))] }), loading && (_jsx(View, { style: sf.carregando, children: _jsx(Spinner, { size: "sm", label: strings.comboboxLoading }) })), nada && (_jsx(View, { style: sf.vazio, children: typeof empty === "string" || empty == null
|
|
328
330
|
? _jsx(Text, { size: "sm", tone: "muted", children: empty ?? strings.comboboxEmpty })
|
|
329
331
|
: empty })), _jsx(FlatList, { data: filtrados, keyExtractor: (i) => i.value, keyboardShouldPersistTaps: "handled", onEndReached: onEndReached, onEndReachedThreshold: ANTECEDENCIA_DE_PAGINA, renderItem: ({ item }) => (_jsxs(Pressable, { disabled: item.disabled, onPress: () => { onValueChange?.(item); fechar(); }, accessibilityRole: "menuitem", ...estadoAcessivel({
|
|
330
332
|
selected: item.value === value?.value, disabled: !!item.disabled,
|
|
@@ -332,7 +334,7 @@ export function Combobox({ items, value, onValueChange, onSearchChange, searchDe
|
|
|
332
334
|
sf.opcao,
|
|
333
335
|
item.value === value?.value && sf.opcaoEscolhida,
|
|
334
336
|
item.disabled && sf.desabilitado,
|
|
335
|
-
], children: [_jsx(Text, { size: "md", weight:
|
|
337
|
+
], children: [_jsxs(View, { style: sf.textoDaOpcao, children: [_jsx(Text, { size: "md", weight: 500, children: item.label }), item.description != null && (_jsx(Text, { size: "xs", tone: "muted", children: item.description }))] }), item.value === value?.value && indicadorDaEscolhida(tf)] })) }), _jsx(RecuoDaFolha, { comTeclado: true })] })] }) }) })] }));
|
|
336
338
|
}
|
|
337
339
|
// ── A DOBRA DE ACENTO, e por que ela é sondada em vez de presumida ───────────────────────────
|
|
338
340
|
// Buscar "acucar" tem de achar "açúcar" — num catálogo em português, exigir o acento certo é
|
package/dist/display.js
CHANGED
|
@@ -15,7 +15,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
15
15
|
// .badge-solid/outline :1053-4 as duas ênfases além do `soft`
|
|
16
16
|
// .status aurea.css:1060 linha, gap space-2, mutedForeground, textSm
|
|
17
17
|
// .status-dot aurea.css:1055 8 quadrado, redondo, halo de 3 na cor corrente a 14%
|
|
18
|
-
// .avatar aurea.css:1196 quadrado da altura de controle
|
|
18
|
+
// .avatar aurea.css:1196 ~~quadrado da altura de controle~~, redondo, borda borderStrong
|
|
19
|
+
// (0.32.0: o lado e a letra são os do avatar nativo da referência)
|
|
19
20
|
// .kpi aurea.css:1207 coluna com gap 5 — **dentro de um Card**
|
|
20
21
|
//
|
|
21
22
|
// ⚠ **O `.kpi` do CSS mente sozinho, e o fonte corrige:** `markup.tsx:105` mostra que o `KPI` é
|
|
@@ -73,6 +74,8 @@ const folha = criarFolha((t) => ({
|
|
|
73
74
|
// RN, o mesmo efeito sai com opacidade no próprio anel.
|
|
74
75
|
pontoDeEstado: { width: 8, height: 8, ...canto(t.size.radiusFull) },
|
|
75
76
|
// ── Avatar ─────────────────────────────────────────────────────────────────────────────────
|
|
77
|
+
// 0.32.0 (ADR-0066): as medidas do avatar NATIVO da referência, lidas no pacote dela — 40 · 48 · 64,
|
|
78
|
+
// com as iniciais em 12 · 14 · 16 e peso médio. O lado sai no componente (`LADO_DO_AVATAR`).
|
|
76
79
|
avatar: {
|
|
77
80
|
alignItems: "center", justifyContent: "center", overflow: "hidden",
|
|
78
81
|
...canto(t.size.radiusFull), backgroundColor: t.color.surface3,
|
|
@@ -242,6 +245,14 @@ export function Status({ variant, state, children, style, ...rest }) {
|
|
|
242
245
|
? _jsx(Text, { size: "sm", children: rotulo })
|
|
243
246
|
: rotulo] }));
|
|
244
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* O lado do avatar, do pacote nativo da referência: 40 · 48 · 64 (0.32.0). Até a 0.31.0 era a altura
|
|
250
|
+
* de controle da WEB (`controlHSm/Md/Lg`, 32 · 36 · 40 no confortável), pequena para o polegar.
|
|
251
|
+
* Na escala de ESPAÇO, e não na de toque: o avatar não é controle e não anda com a densidade — é o
|
|
252
|
+
* que o `.avatar` da web já faz (`--space-8/10/12`). O 64 é o mesmo `space16` das molduras de 64
|
|
253
|
+
* da casa (a tela vazia, a miniatura do `PhotoInput`).
|
|
254
|
+
*/
|
|
255
|
+
const LADO_DO_AVATAR = (t, size) => size === "sm" ? t.size.space10 : size === "lg" ? t.size.space16 : t.size.space12;
|
|
245
256
|
/**
|
|
246
257
|
* O retrato redondo.
|
|
247
258
|
*
|
|
@@ -255,12 +266,15 @@ export function Avatar({ source, alt, fallback, size = "md", style, testID }) {
|
|
|
255
266
|
const [falhou, setFalhou] = React.useState(false);
|
|
256
267
|
// A `source` nova merece uma tentativa nova — é o `useEffect([src])` do `identity-client.tsx`.
|
|
257
268
|
React.useEffect(() => { setFalhou(false); }, [source]);
|
|
258
|
-
const lado =
|
|
269
|
+
const lado = LADO_DO_AVATAR(t, size);
|
|
259
270
|
const fonte = typeof source === "string" ? { uri: source } : source;
|
|
260
271
|
return (_jsx(View, { testID: testID, accessible: !!alt, accessibilityRole: alt ? "image" : undefined, accessibilityLabel: alt || undefined, style: [s.avatar, { width: lado, height: lado }, style], children: fonte && !falhou
|
|
261
272
|
? _jsx(Image, { source: fonte, style: s.imagem, onError: () => setFalhou(true) })
|
|
262
273
|
: typeof fallback === "string"
|
|
263
|
-
|
|
274
|
+
// As iniciais da referência: 12 · 14 · 16 em peso médio (eram 14 ou 16, em negrito), com
|
|
275
|
+
// as linhas de 16 · 20 · 24 — a mesma escada da letra do selo, e pela mesma razão: o token
|
|
276
|
+
// direto, porque o `size` do `Text` sobe um degrau no telefone (ADR-0050) e a referência não.
|
|
277
|
+
? _jsx(Text, { weight: 500, style: LETRA_DO_SELO(t, size), children: fallback })
|
|
264
278
|
: fallback }));
|
|
265
279
|
}
|
|
266
280
|
const TOM_DA_DIRECAO = { up: "success", down: "danger", flat: "neutral" };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type StyleProp, type ViewStyle } from "react-native";
|
|
3
|
+
import { type AureaIcon, type AureaIconRegistry } from "./icon.js";
|
|
4
|
+
export type AureaSliderOrientation = "horizontal" | "vertical";
|
|
5
|
+
export interface SliderProps<V extends number | readonly number[] = number | readonly number[]> {
|
|
6
|
+
/** O rótulo. Obrigatório: é o nome das alças. `labelHidden` o tira da tela e deixa para o leitor de tela. */
|
|
7
|
+
label: React.ReactNode;
|
|
8
|
+
labelHidden?: boolean;
|
|
9
|
+
/** Um número, ou uma lista de dois para a faixa (duas alças). */
|
|
10
|
+
value?: V;
|
|
11
|
+
defaultValue?: V;
|
|
12
|
+
/** Chamado a cada passo, com o número (ou a lista, na faixa). */
|
|
13
|
+
onValueChange?: (value: V) => void;
|
|
14
|
+
/** Chamado ao soltar a alça, ao tocar no trilho e a cada passo do leitor de tela — o momento de salvar. */
|
|
15
|
+
onValueCommitted?: (value: V) => void;
|
|
16
|
+
/** Padrões da web: 0, 100 e 1. */
|
|
17
|
+
min?: number;
|
|
18
|
+
max?: number;
|
|
19
|
+
step?: number;
|
|
20
|
+
orientation?: AureaSliderOrientation;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/** As opções do `Intl.NumberFormat` do valor. Mesma prop da web e do `NumberField`. */
|
|
23
|
+
format?: Intl.NumberFormatOptions;
|
|
24
|
+
/** O locale do `Intl`. Sem ele, o do aparelho. */
|
|
25
|
+
locale?: string;
|
|
26
|
+
/** Mostrar o valor ao lado do rótulo. Padrão: sim. */
|
|
27
|
+
showValue?: boolean;
|
|
28
|
+
/** Com dois valores, o nome de cada alça, na ordem ("Mínimo", "Máximo"). */
|
|
29
|
+
thumbLabels?: readonly string[];
|
|
30
|
+
style?: StyleProp<ViewStyle>;
|
|
31
|
+
testID?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* O controle deslizante da referência: o trilho, o preenchimento e a alça em cápsula, com o rótulo
|
|
35
|
+
* e o valor na linha de cima.
|
|
36
|
+
*
|
|
37
|
+
* <Slider label="Volume" defaultValue={30} />
|
|
38
|
+
* <Slider label="Preço" value={faixa} onValueChange={setFaixa} min={0} max={1000} step={10}
|
|
39
|
+
* format={{style: "currency", currency: "BRL"}} locale="pt-BR" thumbLabels={["Mínimo", "Máximo"]} />
|
|
40
|
+
*
|
|
41
|
+
* Arrastar a alça move a partir de onde ela está; tocar no trilho leva a alça mais perto até ali (e
|
|
42
|
+
* continua arrastando, como na web). Na faixa, uma alça não passa da outra — para nela, como na
|
|
43
|
+
* referência. Cada alça é um elemento `adjustable`: o leitor de tela anuncia o valor formatado e
|
|
44
|
+
* desliza um passo para cima ou para baixo (`increment`/`decrement`).
|
|
45
|
+
*/
|
|
46
|
+
export declare function Slider<V extends number | readonly number[]>({ label, labelHidden, value, defaultValue, onValueChange, onValueCommitted, min, max, step, orientation, disabled, format, locale, showValue, thumbLabels, style, testID, }: SliderProps<V>): React.JSX.Element;
|
|
47
|
+
export interface OTPFieldProps {
|
|
48
|
+
/** Quantas casas. Obrigatório, como na web: sem ele o campo não sabe quando está completo. */
|
|
49
|
+
length: number;
|
|
50
|
+
value?: string;
|
|
51
|
+
defaultValue?: string;
|
|
52
|
+
onValueChange?: (value: string) => void;
|
|
53
|
+
/** Esconde os dígitos atrás de um ponto. */
|
|
54
|
+
mask?: boolean;
|
|
55
|
+
disabled?: boolean;
|
|
56
|
+
/** O nome do campo para o leitor de tela. Dentro de um `Field`, vale o rótulo dele. */
|
|
57
|
+
label?: string;
|
|
58
|
+
style?: StyleProp<ViewStyle>;
|
|
59
|
+
testID?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* O campo de código de uso único — a anatomia da referência: UM campo de texto invisível por cima
|
|
63
|
+
* das casas, que só desenham. É ele que recebe o teclado, o colar e o código do SMS
|
|
64
|
+
* (`textContentType="oneTimeCode"` no iPhone, `autoComplete="sms-otp"` no Android).
|
|
65
|
+
*
|
|
66
|
+
* <Field label="Código enviado por SMS"><OTPField length={6} value={codigo} onValueChange={setCodigo} /></Field>
|
|
67
|
+
*
|
|
68
|
+
* A casa da vez ganha a borda do foco e o cursor que pisca (parado com "menos movimento"). Só
|
|
69
|
+
* dígitos entram, como na web. Para o leitor de tela é um campo só, com o nome do `label` (ou do
|
|
70
|
+
* `Field`); as casas ficam fora da árvore, para ele não ler cada dígito duas vezes.
|
|
71
|
+
*/
|
|
72
|
+
export declare function OTPField({ length, value, defaultValue, onValueChange, mask, disabled, label, style, testID }: OTPFieldProps): React.JSX.Element;
|
|
73
|
+
export type AureaTagGroupSelectionMode = "none" | "single" | "multiple";
|
|
74
|
+
export type AureaTagSize = "sm" | "md" | "lg";
|
|
75
|
+
export type AureaTagVariant = "default" | "surface";
|
|
76
|
+
export interface AureaTagItem {
|
|
77
|
+
id: string;
|
|
78
|
+
label: React.ReactNode;
|
|
79
|
+
/** O texto do nome do X ("Remover Design"), quando o `label` não é texto. */
|
|
80
|
+
textValue?: string;
|
|
81
|
+
/** O nome de um glifo do registro, ou o próprio desenho (R-11). */
|
|
82
|
+
icon?: AureaIcon;
|
|
83
|
+
disabled?: boolean;
|
|
84
|
+
}
|
|
85
|
+
export interface TagGroupProps {
|
|
86
|
+
/** O nome do grupo. `labelHidden` o tira da tela e deixa para o leitor de tela. */
|
|
87
|
+
label: React.ReactNode;
|
|
88
|
+
labelHidden?: boolean;
|
|
89
|
+
description?: React.ReactNode;
|
|
90
|
+
errorMessage?: React.ReactNode;
|
|
91
|
+
items: readonly AureaTagItem[];
|
|
92
|
+
selectionMode?: AureaTagGroupSelectionMode;
|
|
93
|
+
selectedKeys?: readonly string[];
|
|
94
|
+
defaultSelectedKeys?: readonly string[];
|
|
95
|
+
onSelectionChange?: (keys: string[]) => void;
|
|
96
|
+
/** Com ele, cada etiqueta ganha o X. */
|
|
97
|
+
onRemove?: (ids: string[]) => void;
|
|
98
|
+
size?: AureaTagSize;
|
|
99
|
+
variant?: AureaTagVariant;
|
|
100
|
+
/** Registro local de ícones (o `x` e os das etiquetas), quando não há um em contexto. */
|
|
101
|
+
icons?: AureaIconRegistry;
|
|
102
|
+
style?: StyleProp<ViewStyle>;
|
|
103
|
+
testID?: string;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* O grupo de etiquetas da referência: as etiquetas numa fila que quebra, com rótulo, descrição e
|
|
107
|
+
* erro; escolha de nenhuma, uma ou várias; e o X de tirar.
|
|
108
|
+
*
|
|
109
|
+
* <TagGroup label="Assuntos" selectionMode="multiple" items={assuntos}
|
|
110
|
+
* selectedKeys={escolhidos} onSelectionChange={setEscolhidos} onRemove={tirar} />
|
|
111
|
+
*
|
|
112
|
+
* ⚠ **O X é IRMÃO da etiqueta, e não filho**, ao contrário da referência (lá o botão de tirar mora
|
|
113
|
+
* dentro do item tocável). No iPhone, um tocável dentro de outro some para o VoiceOver (`check
|
|
114
|
+
* 43`); aqui a etiqueta é uma moldura com duas partes lado a lado — a que escolhe e a que tira —,
|
|
115
|
+
* como o `.tag-main` e o `.tag-remove` da web.
|
|
116
|
+
*
|
|
117
|
+
* Com escolha, cada etiqueta é um botão com o estado `selected`; sem escolha, é só texto. A
|
|
118
|
+
* escolhida ganha o fundo com 10% da marca e a letra no destaque (`primaryEmphasis`), a pintura
|
|
119
|
+
* da web.
|
|
120
|
+
*/
|
|
121
|
+
export declare function TagGroup({ label, labelHidden, description, errorMessage, items, selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange, onRemove, size, variant, icons, style, testID, }: TagGroupProps): React.JSX.Element;
|