@aurea-uds/native 0.12.2 → 0.12.4

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.js CHANGED
@@ -22,7 +22,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
22
  // do Lote 3. Aparência sem consumidor é a ADR-0034 ("ter a variante não é usar").
23
23
  import * as React from "react";
24
24
  import { Pressable, View } from "react-native";
25
- import { criarFolha, REACAO_AO_TOQUE } from "./estilos.js";
25
+ import { criarFolha, REACAO_AO_TOQUE, estadoAcessivel } from "./estilos.js";
26
26
  import { Icon } from "./icon.js";
27
27
  import { Text } from "./text.js";
28
28
  import { useAureaStrings, useAureaTheme, useAureaTokens, useSobreAMarca } from "./theme.js";
@@ -166,7 +166,7 @@ function CorpoDoBotao({ children, appearance = "solid", tone = "neutral", size =
166
166
  ...(semRecuo ? { height: undefined, paddingHorizontal: 0, borderWidth: 0 } : null),
167
167
  }), [t, size, appearance, cor.solido, cor.contorno, corDaBorda, fullWidth, semRecuo]);
168
168
  const corDoTexto = appearance === "solid" ? cor.texto : cor.sobre;
169
- return (_jsx(Pressable, { disabled: disabled, accessibilityRole: "button", accessibilityLabel: accessibilityLabel, accessibilityState: { disabled: !!disabled, ...(pressed === undefined ? null : { checked: pressed }) }, style: ({ pressed: tocando }) => [
169
+ return (_jsx(Pressable, { disabled: disabled, accessibilityRole: "button", accessibilityLabel: accessibilityLabel, ...estadoAcessivel({ disabled: !!disabled, pressed }), style: ({ pressed: tocando }) => [
170
170
  s.alvo, fullWidth && s.alvoLargura,
171
171
  tocando && s.pressionado, disabled && s.inerte,
172
172
  ], ...rest, children: _jsxs(View, { style: [s.caixa, caixa], children: [leading ?? null, leadingIcon ? _jsx(Icon, { name: leadingIcon, size: ICONE[size], color: corDoTexto, icons: icons }) : null, typeof children === "string"
@@ -211,7 +211,7 @@ function BotaoDeIcone({ name, label, appearance = "ghost", tone = "neutral", siz
211
211
  backgroundColor: appearance === "solid" ? cor.solido : "transparent",
212
212
  borderColor: cor.contorno ?? (appearance === "outline" ? corDaBorda : "transparent"),
213
213
  }), [t, lado, size, appearance, cor.solido, cor.contorno, corDaBorda]);
214
- return (_jsx(Pressable, { disabled: disabled, accessibilityRole: "button", accessibilityLabel: label, accessibilityState: { disabled: !!disabled, ...(pressed === undefined ? null : { checked: pressed }) }, style: ({ pressed: tocando }) => [
214
+ return (_jsx(Pressable, { disabled: disabled, accessibilityRole: "button", accessibilityLabel: label, ...estadoAcessivel({ disabled: !!disabled, pressed }), style: ({ pressed: tocando }) => [
215
215
  // Largura FIXA, como o só-ícone do HeroUI (`.button--icon-only`: `w-10`): ele nunca estica,
216
216
  // nem numa coluna sem alinhamento. O alvo é o maior entre o desenho e o `targetMin`.
217
217
  s.alvo, { width: Math.max(lado, t.size.targetMin), alignItems: "center" },
package/dist/busca.js CHANGED
@@ -69,7 +69,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
69
69
  import * as React from "react";
70
70
  import { Animated, Easing, FlatList, Modal, PanResponder, Pressable, TextInput, View, } from "react-native";
71
71
  import { IconButton } from "./actions.js";
72
- import { criarFolha } from "./estilos.js";
72
+ import { criarFolha, estadoAcessivel } from "./estilos.js";
73
73
  import { Spinner } from "./feedback.js";
74
74
  import { Icon } from "./icon.js";
75
75
  import { KeyboardAvoiding, useCampo } from "./inputs.js";
@@ -306,7 +306,7 @@ export function Combobox({ items, value, onValueChange, onSearchChange, searchDe
306
306
  peleDaMarca,
307
307
  inativo && s.desabilitado,
308
308
  style,
309
- ], children: [_jsx(Pressable, { testID: testID, onPress: inativo ? undefined : () => setAberto(true), disabled: inativo, accessibilityRole: "button", accessibilityLabel: campo?.label, accessibilityHint: campo?.hint, accessibilityValue: { text: value?.label }, accessibilityState: { disabled: !!inativo, expanded: aberto }, style: s.gatilho, children: _jsx(Text, { size: tam === "sm" ? "xs" : tam === "lg" ? "base" : "md", tone: value ? "default" : "subtle", numberOfLines: 1, style: { flex: 1, minWidth: 0 }, children: value?.label ?? placeholder ?? "" }) }), _jsxs(View, { style: s.acoes, children: [clearable && value != null && !inativo && (_jsx(IconButton, { name: "close", label: strings.comboboxClear, appearance: "ghost", size: "sm", onPress: () => onValueChange?.(null), testID: testID ? `${testID}-limpar` : undefined })), chevron && (_jsx(Pressable, { accessible: false, disabled: inativo, style: s.setaToque, onPress: inativo ? undefined : () => setAberto(true), testID: testID ? `${testID}-seta` : undefined, children: _jsx(Icon, { name: chevron, size: "sm", color: t.color.subtleForeground }) }))] })] }), _jsx(ForaDaMarca, { children: _jsx(Modal, { visible: aberto, transparent: true, animationType: reduzir !== false ? "none" : "slide", statusBarTranslucent: true, navigationBarTranslucent: true, onRequestClose: fechar, children: _jsxs(KeyboardAvoiding, { style: s.fundoDaLista, children: [_jsx(Pressable, { style: s.fundoDeToque, onPress: fechar, accessible: false, testID: testID ? `${testID}-fundo` : undefined }), _jsxs(Animated.View, { style: [s.lista, { transform: [{ translateY: arrasto }] }], onLayout: (e) => { altura.current = e.nativeEvent.layout.height; }, children: [_jsx(View, { style: s.puxadorArea, ...(draggable ? gestos.panHandlers : null), accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", children: _jsx(View, { style: s.puxador }) }), _jsxs(View, { style: [s.grupo, { height: alturaDoTamanho(t, tam) }], ...(draggable ? gestos.panHandlers : null), children: [searchIcon && _jsx(Icon, { name: searchIcon, size: "sm", color: t.color.subtleForeground }), _jsx(TextInput, { testID: testID ? `${testID}-busca` : undefined, value: texto, onChangeText: digitar, placeholder: searchPlaceholder ?? strings.comboboxSearch, placeholderTextColor: t.color.subtleForeground,
309
+ ], children: [_jsx(Pressable, { testID: testID, onPress: inativo ? undefined : () => setAberto(true), disabled: inativo, accessibilityRole: "button", accessibilityLabel: campo?.label, accessibilityHint: campo?.hint, accessibilityValue: { text: value?.label }, ...estadoAcessivel({ disabled: !!inativo, expanded: aberto }), style: s.gatilho, children: _jsx(Text, { size: tam === "sm" ? "xs" : tam === "lg" ? "base" : "md", tone: value ? "default" : "subtle", numberOfLines: 1, style: { flex: 1, minWidth: 0 }, children: value?.label ?? placeholder ?? "" }) }), _jsxs(View, { style: s.acoes, children: [clearable && value != null && !inativo && (_jsx(IconButton, { name: "close", label: strings.comboboxClear, appearance: "ghost", size: "sm", onPress: () => onValueChange?.(null), testID: testID ? `${testID}-limpar` : undefined })), chevron && (_jsx(Pressable, { accessible: false, disabled: inativo, style: s.setaToque, onPress: inativo ? undefined : () => setAberto(true), testID: testID ? `${testID}-seta` : undefined, children: _jsx(Icon, { name: chevron, size: "sm", color: t.color.subtleForeground }) }))] })] }), _jsx(ForaDaMarca, { children: _jsx(Modal, { visible: aberto, transparent: true, animationType: reduzir !== false ? "none" : "slide", statusBarTranslucent: true, navigationBarTranslucent: true, onRequestClose: fechar, children: _jsxs(KeyboardAvoiding, { style: s.fundoDaLista, children: [_jsx(Pressable, { style: s.fundoDeToque, onPress: fechar, accessible: false, testID: testID ? `${testID}-fundo` : undefined }), _jsxs(Animated.View, { style: [s.lista, { transform: [{ translateY: arrasto }] }], onLayout: (e) => { altura.current = e.nativeEvent.layout.height; }, children: [_jsx(View, { style: s.puxadorArea, ...(draggable ? gestos.panHandlers : null), accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", children: _jsx(View, { style: s.puxador }) }), _jsxs(View, { style: [s.grupo, { height: alturaDoTamanho(t, tam) }], ...(draggable ? gestos.panHandlers : null), children: [searchIcon && _jsx(Icon, { name: searchIcon, size: "sm", color: t.color.subtleForeground }), _jsx(TextInput, { testID: testID ? `${testID}-busca` : undefined, value: texto, onChangeText: digitar, placeholder: searchPlaceholder ?? strings.comboboxSearch, placeholderTextColor: t.color.subtleForeground,
310
310
  // ⚠ `autoFocus` é o que faz a folha valer a pena: abrir um campo de busca e
311
311
  // exigir um segundo toque para o teclado subir é um toque a mais em cada
312
312
  // cadastro. O foco entra com a folha; o teclado vem junto.
@@ -322,9 +322,9 @@ export function Combobox({ items, value, onValueChange, onSearchChange, searchDe
322
322
  color: t.color.foreground },
323
323
  ] }), texto.length > 0 && (_jsx(IconButton, { name: "close", label: strings.searchClear, appearance: "ghost", size: "sm", onPress: () => digitar(""), testID: testID ? `${testID}-busca-limpar` : undefined }))] }), loading && (_jsx(View, { style: s.carregando, children: _jsx(Spinner, { label: strings.comboboxLoading }) })), nada && (_jsx(View, { style: s.vazio, children: typeof empty === "string" || empty == null
324
324
  ? _jsx(Text, { size: "sm", tone: "muted", children: empty ?? strings.comboboxEmpty })
325
- : empty })), _jsx(FlatList, { data: filtrados, keyExtractor: (i) => i.value, keyboardShouldPersistTaps: "handled", onEndReached: onEndReached, onEndReachedThreshold: ANTECEDENCIA_DE_PAGINA, renderItem: ({ item }) => (_jsx(Pressable, { disabled: item.disabled, onPress: () => { onValueChange?.(item); fechar(); }, accessibilityRole: "menuitem", accessibilityState: {
325
+ : empty })), _jsx(FlatList, { data: filtrados, keyExtractor: (i) => i.value, keyboardShouldPersistTaps: "handled", onEndReached: onEndReached, onEndReachedThreshold: ANTECEDENCIA_DE_PAGINA, renderItem: ({ item }) => (_jsx(Pressable, { disabled: item.disabled, onPress: () => { onValueChange?.(item); fechar(); }, accessibilityRole: "menuitem", ...estadoAcessivel({
326
326
  selected: item.value === value?.value, disabled: !!item.disabled,
327
- }, style: [
327
+ }), style: [
328
328
  s.opcao,
329
329
  item.value === value?.value && s.opcaoEscolhida,
330
330
  item.disabled && s.desabilitado,
@@ -418,7 +418,7 @@ export function SearchField({ value, onChangeText, onSearchChange, searchDelay =
418
418
  peleDaMarca && focado && { borderWidth: t.size.borderWidth * 2 },
419
419
  inativo && s.desabilitado,
420
420
  style,
421
- ], children: [icon && _jsx(Icon, { name: icon, size: "sm", color: peleDaMarca?.color ?? t.color.subtleForeground }), _jsx(TextInput, { testID: testID ? `${testID}-campo` : undefined, value: value, onChangeText: digitar, placeholder: placeholder, placeholderTextColor: peleDaMarca?.color ?? t.color.subtleForeground, editable: !inativo, autoCorrect: false, autoCapitalize: "none", returnKeyType: "search", onSubmitEditing: onSubmit, onFocus: () => setFocado(true), onBlur: () => setFocado(false), accessibilityRole: "search", accessibilityLabel: campo?.label ?? placeholder, accessibilityHint: campo?.hint, accessibilityState: { disabled: !!inativo }, style: [
421
+ ], children: [icon && _jsx(Icon, { name: icon, size: "sm", color: peleDaMarca?.color ?? t.color.subtleForeground }), _jsx(TextInput, { testID: testID ? `${testID}-campo` : undefined, value: value, onChangeText: digitar, placeholder: placeholder, placeholderTextColor: peleDaMarca?.color ?? t.color.subtleForeground, editable: !inativo, autoCorrect: false, autoCapitalize: "none", returnKeyType: "search", onSubmitEditing: onSubmit, onFocus: () => setFocado(true), onBlur: () => setFocado(false), accessibilityRole: "search", accessibilityLabel: campo?.label ?? placeholder, accessibilityHint: campo?.hint, ...estadoAcessivel({ disabled: !!inativo }), style: [
422
422
  s.campoDeTexto,
423
423
  { fontSize: fonteDoTamanho(t, tam), fontFamily: t.font.ui[400],
424
424
  color: t.color.foreground },
package/dist/chart.js CHANGED
@@ -54,7 +54,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
54
54
  import * as React from "react";
55
55
  import { Pressable, View } from "react-native";
56
56
  import Svg, { Circle, G, Line, Path, Rect, Text as SvgText } from "react-native-svg";
57
- import { criarFolha } from "./estilos.js";
57
+ import { criarFolha, estadoAcessivel } from "./estilos.js";
58
58
  import { Text } from "./text.js";
59
59
  import { useAureaStrings, useAureaTokens } from "./theme.js";
60
60
  /** A altura padrão, igual ao `--chart-h,220px` do `aurea.css:1329`. */
@@ -187,7 +187,7 @@ export function Chart({ labels, series, label, mark = "line", height = ALTURA, y
187
187
  const v = serie.data[selecionado];
188
188
  return v == null ? null : (_jsx(Circle, { cx: x(selecionado), cy: y(v), r: 4, fill: cores[n], stroke: t.color.card, strokeWidth: 2 }, n));
189
189
  })] })) : null] }) })) : null, largura > 0 ? (_jsx(View, { style: { position: "absolute", left: CALHA.esquerda, top: CALHA.topo,
190
- width: areaL, height: areaA, flexDirection: "row" }, children: labels.map((rotulo, i) => (_jsx(Pressable, { onPress: () => tocar(i), accessibilityRole: "button", accessibilityState: { selected: selecionado === i }, accessibilityLabel: [
190
+ width: areaL, height: areaA, flexDirection: "row" }, children: labels.map((rotulo, i) => (_jsx(Pressable, { onPress: () => tocar(i), accessibilityRole: "button", ...estadoAcessivel({ selected: selecionado === i }), accessibilityLabel: [
191
191
  rotulo,
192
192
  ...series.map((serie) => {
193
193
  const v = serie.data[i];
package/dist/estilos.d.ts CHANGED
@@ -58,4 +58,57 @@ export declare const REACAO_AO_TOQUE: {
58
58
  readonly opacity: 0.45;
59
59
  };
60
60
  };
61
+ /** O estado que o leitor de tela anuncia. Mesmas chaves do `accessibilityState` do React Native. */
62
+ export type EstadoAcessivel = {
63
+ checked?: boolean | "mixed";
64
+ selected?: boolean;
65
+ disabled?: boolean;
66
+ expanded?: boolean;
67
+ busy?: boolean;
68
+ /** O botão que liga e desliga. No aparelho vira `checked`; na web vira `aria-pressed`. */
69
+ pressed?: boolean;
70
+ };
71
+ /**
72
+ * O estado para o leitor de tela, dito **duas vezes**: em `accessibilityState` (o aparelho) e em
73
+ * `aria-*` (a web).
74
+ *
75
+ * EXISTE POR UMA MEDIÇÃO (R-20, 01/10/2026). O `react-native-web` 0.21.3 **não lê**
76
+ * `accessibilityState`: o `createDOMProps` dele só conhece `aria-checked`, `aria-selected`,
77
+ * `aria-disabled`, `aria-expanded` e `aria-busy` (e os `accessibilityChecked` e afins, que estão
78
+ * para sair). Com só o `accessibilityState`, o `RadioGroup` aberto no navegador saía sem
79
+ * `aria-checked`, e o leitor de tela não dizia qual opção estava marcada.
80
+ *
81
+ * O React Native 0.87 aceita as mesmas `aria-*` e as junta ao `accessibilityState` com o mesmo
82
+ * valor, então o aparelho não muda.
83
+ *
84
+ * ⚠ `pressed` (o botão de ligar e desligar) é a exceção: no aparelho continua `checked`, como
85
+ * sempre foi; na web vira `aria-pressed`, porque `aria-checked` num `button` o leitor ignora. Os
86
+ * tipos do React Native não têm `aria-pressed`; o aparelho descarta a propriedade que não conhece.
87
+ *
88
+ * Uso: `<Pressable {...estadoAcessivel({checked, disabled})} />`. Ferramenta de dentro: **não
89
+ * sai pela porta da frente do pacote.**
90
+ */
91
+ export declare function estadoAcessivel(estado: EstadoAcessivel | undefined): {
92
+ accessibilityState: undefined;
93
+ "aria-checked"?: undefined;
94
+ "aria-selected"?: undefined;
95
+ "aria-disabled"?: undefined;
96
+ "aria-expanded"?: undefined;
97
+ "aria-busy"?: undefined;
98
+ "aria-pressed"?: undefined;
99
+ } | {
100
+ accessibilityState: {
101
+ checked?: boolean | "mixed";
102
+ selected?: boolean;
103
+ disabled?: boolean;
104
+ expanded?: boolean;
105
+ busy?: boolean;
106
+ };
107
+ "aria-checked": "mixed" | boolean | undefined;
108
+ "aria-selected": boolean | undefined;
109
+ "aria-disabled": boolean | undefined;
110
+ "aria-expanded": boolean | undefined;
111
+ "aria-busy": boolean | undefined;
112
+ "aria-pressed": boolean | undefined;
113
+ };
61
114
  export {};
package/dist/estilos.js CHANGED
@@ -67,3 +67,38 @@ export const REACAO_AO_TOQUE = {
67
67
  pressionado: { opacity: 0.9, transform: [{ scale: 0.97 }] },
68
68
  inerte: { opacity: 0.45 },
69
69
  };
70
+ /**
71
+ * O estado para o leitor de tela, dito **duas vezes**: em `accessibilityState` (o aparelho) e em
72
+ * `aria-*` (a web).
73
+ *
74
+ * EXISTE POR UMA MEDIÇÃO (R-20, 01/10/2026). O `react-native-web` 0.21.3 **não lê**
75
+ * `accessibilityState`: o `createDOMProps` dele só conhece `aria-checked`, `aria-selected`,
76
+ * `aria-disabled`, `aria-expanded` e `aria-busy` (e os `accessibilityChecked` e afins, que estão
77
+ * para sair). Com só o `accessibilityState`, o `RadioGroup` aberto no navegador saía sem
78
+ * `aria-checked`, e o leitor de tela não dizia qual opção estava marcada.
79
+ *
80
+ * O React Native 0.87 aceita as mesmas `aria-*` e as junta ao `accessibilityState` com o mesmo
81
+ * valor, então o aparelho não muda.
82
+ *
83
+ * ⚠ `pressed` (o botão de ligar e desligar) é a exceção: no aparelho continua `checked`, como
84
+ * sempre foi; na web vira `aria-pressed`, porque `aria-checked` num `button` o leitor ignora. Os
85
+ * tipos do React Native não têm `aria-pressed`; o aparelho descarta a propriedade que não conhece.
86
+ *
87
+ * Uso: `<Pressable {...estadoAcessivel({checked, disabled})} />`. Ferramenta de dentro: **não
88
+ * sai pela porta da frente do pacote.**
89
+ */
90
+ export function estadoAcessivel(estado) {
91
+ if (!estado)
92
+ return { accessibilityState: undefined };
93
+ const { pressed, ...resto } = estado;
94
+ const doAparelho = pressed === undefined ? resto : { ...resto, checked: pressed };
95
+ return {
96
+ accessibilityState: doAparelho,
97
+ "aria-checked": resto.checked,
98
+ "aria-selected": resto.selected,
99
+ "aria-disabled": resto.disabled,
100
+ "aria-expanded": resto.expanded,
101
+ "aria-busy": resto.busy,
102
+ "aria-pressed": pressed,
103
+ };
104
+ }
package/dist/feedback.js CHANGED
@@ -22,7 +22,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
22
22
  import * as React from "react";
23
23
  import { Animated, Easing, View } from "react-native";
24
24
  import { IconButton } from "./actions.js";
25
- import { criarFolha } from "./estilos.js";
25
+ import { criarFolha, estadoAcessivel } from "./estilos.js";
26
26
  import { Icon } from "./icon.js";
27
27
  import { useReduceMotion } from "./movimento.js";
28
28
  import { gravidadeDoEstado } from "./strings.js";
@@ -239,7 +239,7 @@ export function DataState({ state, message, skeleton, emptyTitle, emptyIcon, act
239
239
  const s = folha(t);
240
240
  const strings = useAureaStrings();
241
241
  const conteudo = () => (typeof children === "function" ? children() : children);
242
- const caixa = (dentro, ocupado) => (_jsx(View, { accessibilityState: ocupado ? { busy: true } : undefined, style: [s.regiao, style], ...rest, children: dentro }));
242
+ const caixa = (dentro, ocupado) => (_jsx(View, { ...estadoAcessivel(ocupado ? { busy: true } : undefined), style: [s.regiao, style], ...rest, children: dentro }));
243
243
  if (state === "loading")
244
244
  return caixa(skeleton ?? _jsx(Skeleton, { height: t.size.space8 }), true);
245
245
  if (state === "error") {
package/dist/index.d.ts CHANGED
@@ -24,8 +24,8 @@ export type { AureaStrings, AureaUniversalState } from "./strings.js";
24
24
  export { useReduceMotion } from "./movimento.js";
25
25
  export { BottomNav, Topbar, NavList, Stepper, Tabs } from "./navigation.js";
26
26
  export type { BottomNavProps, TopbarProps, NavListProps, StepperProps, AureaNavItem, AureaNavListItem, AureaStepItem, AureaStepState, AureaBottomNavVariant, AureaBottomNavIndicator, AureaBottomNavWidth, AureaTopbarVariant, AureaTopbarInset, TabsProps, AureaTabItem, } from "./navigation.js";
27
- export { Field, Label, Input, Textarea, Select, Switch, Checkbox, Radio, SegmentedControl, Form, KeyboardAvoiding, useCampo, } from "./inputs.js";
28
- export type { FieldProps, LabelProps, InputProps, TextareaProps, SelectProps, SwitchProps, CheckboxProps, RadioProps, SegmentedControlProps, FormProps, KeyboardAvoidingProps, AureaFieldSize, } from "./inputs.js";
27
+ export { Field, Label, Input, Textarea, Select, Switch, Checkbox, Radio, RadioGroup, SegmentedControl, Form, KeyboardAvoiding, useCampo, } from "./inputs.js";
28
+ export type { FieldProps, LabelProps, InputProps, TextareaProps, SelectProps, SwitchProps, CheckboxProps, RadioProps, RadioGroupProps, RadioGroupItemProps, AureaRadioIndicatorPlacement, SegmentedControlProps, FormProps, KeyboardAvoidingProps, AureaFieldSize, } from "./inputs.js";
29
29
  export { InputGroup, InputGroupAddon, PasswordField, useGrupoDeCampo } from "./inputs.js";
30
30
  export type { InputGroupProps, InputGroupAddonProps, PasswordFieldProps } from "./inputs.js";
31
31
  export { Dialog, ConfirmDialog, Drawer, BottomSheet } from "./overlays.js";
package/dist/index.js CHANGED
@@ -59,7 +59,7 @@ export { BottomNav, Topbar, NavList, Stepper, Tabs } from "./navigation.js";
59
59
  // ⚠ O `Field` NÃO nomeia o controle por referência, como o `<label for>` da web: ele empurra o
60
60
  // nome, a dica e o estado de inválido para o controle por CONTEXTO. É a tradução que decidiu o
61
61
  // lote — o RN não tem `id` nem `htmlFor`.
62
- export { Field, Label, Input, Textarea, Select, Switch, Checkbox, Radio, SegmentedControl, Form, KeyboardAvoiding, useCampo, } from "./inputs.js";
62
+ export { Field, Label, Input, Textarea, Select, Switch, Checkbox, Radio, RadioGroup, SegmentedControl, Form, KeyboardAvoiding, useCampo, } from "./inputs.js";
63
63
  // ⚠ O GRUPO e o campo de SENHA entraram depois do Lote 4, medidos pelo app na tela de entrar
64
64
  // (15/09/2026): o campo não tinha onde encaixar glifo, e `secureTextEntry` esconde a senha sem
65
65
  // dar botão para mostrá-la. **Os dois já existiam na web desde 29/08/2026** — a falta era só
package/dist/inputs.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { TextInput, type KeyboardTypeOptions, type StyleProp, type TextInputProps, type TextStyle, type ViewProps, type ViewStyle } from "react-native";
2
+ import { TextInput, type KeyboardTypeOptions, type PressableProps, type StyleProp, type TextInputProps, type TextStyle, type ViewProps, type ViewStyle } from "react-native";
3
3
  import { type AureaFilaJustify } from "./rolagem.js";
4
4
  import { type AureaIconRegistry, type IconName } from "./icon.js";
5
5
  export type AureaFieldSize = "sm" | "md" | "lg";
@@ -249,6 +249,59 @@ export declare function Checkbox(p: CheckboxProps): React.JSX.Element;
249
249
  * estado do app — quem sabe qual está escolhido é o `useState` da tela, e `checked` sai dele.
250
250
  */
251
251
  export declare function Radio(p: RadioProps): React.JSX.Element;
252
+ /** De que lado da linha a marca fica: `end` (padrão, como o exemplo do HeroUI) ou `start`. */
253
+ export type AureaRadioIndicatorPlacement = "start" | "end";
254
+ export interface RadioGroupProps extends ViewProps {
255
+ /** O valor do item escolhido. Controlado: quem guarda é a tela. */
256
+ value?: string;
257
+ onValueChange?: (value: string) => void;
258
+ /** Desliga o grupo inteiro. */
259
+ disabled?: boolean;
260
+ /** Pinta o grupo de erro (marca e rótulo na cor de perigo), como o `isInvalid` do HeroUI. */
261
+ invalid?: boolean;
262
+ /** O nome do grupo para quem usa leitor de tela ("Forma de entrega"). */
263
+ label?: string;
264
+ /** `vertical` (padrão) ou `horizontal`, como o HeroUI. */
265
+ orientation?: "vertical" | "horizontal";
266
+ /**
267
+ * De que lado fica a marca, em todos os itens: `end` (padrão) ou `start`. O HeroUI decide isso
268
+ * pela ORDEM dos filhos do item (`<Radio />` antes ou depois do texto); aqui o texto é prop, então
269
+ * o lado vira uma lista fechada de duas opções, com o nome que o HeroUI usa para posição.
270
+ */
271
+ indicatorPlacement?: AureaRadioIndicatorPlacement;
272
+ children?: React.ReactNode;
273
+ }
274
+ export interface RadioGroupItemProps extends Omit<PressableProps, "children" | "style" | "disabled"> {
275
+ /** O valor que este item escreve no grupo quando é tocado. */
276
+ value: string;
277
+ label?: React.ReactNode;
278
+ description?: React.ReactNode;
279
+ /** Desliga só este item. */
280
+ disabled?: boolean;
281
+ /** Erro só neste item. */
282
+ invalid?: boolean;
283
+ /** O lado da marca só neste item; sem ele, vale o do grupo. */
284
+ indicatorPlacement?: AureaRadioIndicatorPlacement;
285
+ style?: StyleProp<ViewStyle>;
286
+ }
287
+ declare function RaizDoGrupoDeRadio({ value, onValueChange, disabled, invalid, label, orientation, indicatorPlacement, style, children, ...rest }: RadioGroupProps): React.JSX.Element;
288
+ declare function ItemDoGrupoDeRadio({ value, label, description, disabled, invalid, indicatorPlacement, style, accessibilityLabel, ...rest }: RadioGroupItemProps): React.JSX.Element;
289
+ /**
290
+ * Um conjunto de opções em que só uma fica escolhida — o `RadioGroup` do HeroUI Native.
291
+ *
292
+ * <RadioGroup label="Forma de entrega" value={entrega} onValueChange={setEntrega}>
293
+ * <RadioGroup.Item value="normal" label="Normal" description="Em 5 a 7 dias úteis" />
294
+ * <Separator />
295
+ * <RadioGroup.Item value="expressa" label="Expressa" description="Em 2 a 3 dias úteis" />
296
+ * </RadioGroup>
297
+ *
298
+ * Os filhos são livres: entre os itens cabe um `Separator`, e o grupo inteiro cabe num `Card`,
299
+ * como no exemplo do HeroUI. Tocar no item já escolhido não muda nada. Com
300
+ * `indicatorPlacement="start"` a marca vai para o início da linha.
301
+ */
302
+ export declare const RadioGroup: typeof RaizDoGrupoDeRadio & {
303
+ Item: typeof ItemDoGrupoDeRadio;
304
+ };
252
305
  /**
253
306
  * ⚠ **Ele TIRAVA a `description`, e passou a aceitá-la em 17/09/2026** — pedido do consumidor
254
307
  * (uma linha de explicação embaixo de "Desbloqueio por digital", no Perfil).
package/dist/inputs.js CHANGED
@@ -39,7 +39,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
39
39
  // .segmented :922 linha, gap 3, padding 3, minH controlHMd, fundo muted
40
40
  import * as React from "react";
41
41
  import { Animated, KeyboardAvoidingView as KeyboardAvoidingViewRN, Modal, Platform, Pressable, ScrollView, TextInput, View, } from "react-native";
42
- import { comOpacidade, criarFolha } from "./estilos.js";
42
+ import { comOpacidade, criarFolha, estadoAcessivel } from "./estilos.js";
43
43
  import { FilaRolante } from "./rolagem.js";
44
44
  import { IconButton } from "./actions.js";
45
45
  import { Icon } from "./icon.js";
@@ -219,7 +219,7 @@ export function Input({ value, defaultValue, onChangeText, placeholder, disabled
219
219
  },
220
220
  // O nome e a dica vêm do `Field` — ver o bloco acima sobre por que a ligação da web não
221
221
  // atravessa. Sem isto, o campo é um nó anônimo para o leitor de tela.
222
- accessibilityLabel: campo?.label, accessibilityHint: campo?.hint, accessibilityState: { disabled: !!inativo }, "aria-invalid": campo?.invalido, style: [
222
+ accessibilityLabel: campo?.label, accessibilityHint: campo?.hint, ...estadoAcessivel({ disabled: !!inativo }), "aria-invalid": campo?.invalido, style: [
223
223
  // DENTRO DE UM GRUPO o campo não desenha caixa nenhuma: borda, fundo, altura, respiro,
224
224
  // inválido, foco e desabilitado passam a ser do grupo. Manter qualquer um dos dois
225
225
  // desenhando daria borda dentro de borda — que é exatamente o defeito que o `.input-group
@@ -347,7 +347,7 @@ function ControleMarcado({ papel, label, description, checked, onChange, disable
347
347
  // do rótulo (entrelinha normal), então a conta sai dos mesmos tokens que desenham o texto.
348
348
  const linha = t.size.textBase * t.size.leadingNormal;
349
349
  const noTopo = align === "start" ? { marginTop: Math.max(0, (linha - lado) / 2) } : null;
350
- return (_jsxs(Pressable, { testID: testID, onPress: inativo ? undefined : () => onChange?.(!checked), disabled: inativo, accessibilityRole: papel, accessibilityState: { checked: !!checked, disabled: !!inativo },
350
+ return (_jsxs(Pressable, { testID: testID, onPress: inativo ? undefined : () => onChange?.(!checked), disabled: inativo, accessibilityRole: papel, ...estadoAcessivel({ checked: !!checked, disabled: !!inativo }),
351
351
  // ⚠ O `accessibilityLabel` de fora vence o `label` escrito, e existe para o caso em que o
352
352
  // nome JÁ está na tela ao lado — uma linha de `NavList`, por exemplo. Sem ele, ou o nome
353
353
  // aparece escrito duas vezes, ou o controle sobe MUDO para quem usa leitor de tela.
@@ -382,6 +382,56 @@ export function Checkbox(p) { return _jsx(ControleMarcado, { ...p, papel: "check
382
382
  * estado do app — quem sabe qual está escolhido é o `useState` da tela, e `checked` sai dele.
383
383
  */
384
384
  export function Radio(p) { return _jsx(ControleMarcado, { ...p, papel: "radio" }); }
385
+ const GrupoDeRadio = React.createContext(null);
386
+ function RaizDoGrupoDeRadio({ value, onValueChange, disabled, invalid, label, orientation = "vertical", indicatorPlacement, style, children, ...rest }) {
387
+ const t = useAureaTokens();
388
+ const contexto = React.useMemo(() => ({ value, onValueChange, disabled, invalid, indicatorPlacement }), [value, onValueChange, disabled, invalid, indicatorPlacement]);
389
+ return (_jsx(GrupoDeRadio.Provider, { value: contexto, children: _jsx(View, { accessibilityRole: "radiogroup", accessibilityLabel: label, ...estadoAcessivel({ disabled: !!disabled }), style: [{ gap: t.size.space3, flexDirection: orientation === "horizontal" ? "row" : "column" }, style], ...rest, children: children }) }));
390
+ }
391
+ function ItemDoGrupoDeRadio({ value, label, description, disabled, invalid, indicatorPlacement, style, accessibilityLabel, ...rest }) {
392
+ const t = useAureaTokens();
393
+ const s = folha(t);
394
+ const grupo = React.useContext(GrupoDeRadio);
395
+ if (__DEV__ && !grupo)
396
+ console.warn("Aurea: RadioGroup.Item fora de um RadioGroup não escolhe nada.");
397
+ const escolhido = grupo?.value === value;
398
+ const inativo = disabled ?? grupo?.disabled;
399
+ const erro = invalid ?? grupo?.invalid;
400
+ const perigo = t.color.danger400 ?? t.color.destructive;
401
+ const marca = t.size.space6;
402
+ const ponto = t.size.space2 + t.size.space05;
403
+ const noInicio = (indicatorPlacement ?? grupo?.indicatorPlacement ?? "end") === "start";
404
+ const texto = (label != null || description != null) && (_jsxs(View, { style: { flex: 1, minWidth: 0 }, children: [typeof label === "string"
405
+ ? _jsx(Text, { size: "base", weight: 500, tone: erro ? "danger" : "default", children: label }) : label, description != null && (typeof description === "string"
406
+ ? _jsx(Text, { size: "sm", tone: "muted", children: description }) : description)] }, "texto"));
407
+ const marcaDesenhada = (_jsx(View, { style: [
408
+ s.marcaBase,
409
+ { width: marca, height: marca, borderRadius: t.size.radiusFull },
410
+ erro && { borderColor: perigo, backgroundColor: "transparent" },
411
+ escolhido && { backgroundColor: erro ? perigo : t.color.controlSelected,
412
+ borderColor: erro ? perigo : t.color.controlSelected },
413
+ ], children: escolhido && _jsx(View, { style: { width: ponto, height: ponto, borderRadius: t.size.radiusFull,
414
+ backgroundColor: t.color.controlSelectedForeground } }) }, "marca"));
415
+ return (_jsx(Pressable, { onPress: inativo || escolhido ? undefined : () => grupo?.onValueChange?.(value), disabled: inativo, accessibilityRole: "radio", ...estadoAcessivel({ checked: escolhido, disabled: !!inativo }), accessibilityLabel: accessibilityLabel ?? (typeof label === "string" ? label : undefined), accessibilityHint: typeof description === "string" ? description : undefined, style: [
416
+ { flexDirection: "row", alignItems: "center", justifyContent: "space-between",
417
+ gap: t.size.space3, minHeight: t.size.targetMin },
418
+ inativo && s.desabilitado, style,
419
+ ], ...rest, children: noInicio ? [marcaDesenhada, texto] : [texto, marcaDesenhada] }));
420
+ }
421
+ /**
422
+ * Um conjunto de opções em que só uma fica escolhida — o `RadioGroup` do HeroUI Native.
423
+ *
424
+ * <RadioGroup label="Forma de entrega" value={entrega} onValueChange={setEntrega}>
425
+ * <RadioGroup.Item value="normal" label="Normal" description="Em 5 a 7 dias úteis" />
426
+ * <Separator />
427
+ * <RadioGroup.Item value="expressa" label="Expressa" description="Em 2 a 3 dias úteis" />
428
+ * </RadioGroup>
429
+ *
430
+ * Os filhos são livres: entre os itens cabe um `Separator`, e o grupo inteiro cabe num `Card`,
431
+ * como no exemplo do HeroUI. Tocar no item já escolhido não muda nada. Com
432
+ * `indicatorPlacement="start"` a marca vai para o início da linha.
433
+ */
434
+ export const RadioGroup = Object.assign(RaizDoGrupoDeRadio, { Item: ItemDoGrupoDeRadio });
385
435
  /**
386
436
  * O interruptor.
387
437
  *
@@ -419,7 +469,7 @@ export function Switch({ label, description, checked, onChange, disabled, size,
419
469
  a.start();
420
470
  return () => a.stop();
421
471
  }, [checked, pos, reduzir]);
422
- return (_jsxs(Pressable, { testID: testID, onPress: inativo ? undefined : () => onChange?.(!checked), disabled: inativo, accessibilityRole: "switch", accessibilityState: { checked: !!checked, disabled: !!inativo },
472
+ return (_jsxs(Pressable, { testID: testID, onPress: inativo ? undefined : () => onChange?.(!checked), disabled: inativo, accessibilityRole: "switch", ...estadoAcessivel({ checked: !!checked, disabled: !!inativo }),
423
473
  // O `accessibilityLabel` de fora vence o `label` escrito — ver a prop, em `ControleProps`.
424
474
  accessibilityLabel: accessibilityLabel ?? (typeof label === "string" ? label : campo?.label),
425
475
  // Mesma regra do `ControleMarcado`: a descrição vira DICA quando é texto. Sem isto ela
@@ -467,7 +517,7 @@ export function SegmentedControl({ items, value, onChange, label, disabled, just
467
517
  const inativo = disabled ?? campo?.disabled;
468
518
  return (_jsx(FilaRolante, { justify: justify, children: _jsx(View, { accessibilityRole: "radiogroup", accessibilityLabel: label ?? campo?.label, style: [s.segmentada, inativo && s.desabilitado, style], ...rest, children: items.map((it) => {
469
519
  const ativo = it.value === value;
470
- return (_jsxs(Pressable, { onPress: inativo ? undefined : () => onChange?.(it.value), disabled: inativo, accessibilityRole: "radio", accessibilityState: { checked: ativo, disabled: !!inativo }, accessibilityLabel: typeof it.label === "string" ? it.label : undefined, style: [s.segmento, ativo && s.segmentoAtivo], children: [typeof it.label === "string"
520
+ return (_jsxs(Pressable, { onPress: inativo ? undefined : () => onChange?.(it.value), disabled: inativo, accessibilityRole: "radio", ...estadoAcessivel({ checked: ativo, disabled: !!inativo }), accessibilityLabel: typeof it.label === "string" ? it.label : undefined, style: [s.segmento, ativo && s.segmentoAtivo], children: [typeof it.label === "string"
471
521
  ? _jsx(Text, { size: "sm", weight: ativo ? 600 : 400,
472
522
  // 🔴 ERA `foreground`, E ISSO QUEBRAVA A LINGUAGEM DE SELECIONADO.
473
523
  // Achado pelo consumidor em 17/09/2026. A web pinta o escolhido com a
@@ -518,7 +568,7 @@ export function Select({ items, value, onChange, placeholder, disabled, size, ch
518
568
  const inativo = disabled ?? campo?.disabled;
519
569
  const [aberto, setAberto] = React.useState(false);
520
570
  const escolhido = items.find((i) => i.value === value);
521
- return (_jsxs(_Fragment, { children: [_jsxs(Pressable, { testID: testID, onPress: inativo ? undefined : () => setAberto(true), disabled: inativo, accessibilityRole: "button", accessibilityLabel: campo?.label, accessibilityHint: campo?.hint, accessibilityValue: { text: escolhido?.label }, accessibilityState: { disabled: !!inativo, expanded: aberto }, style: [
571
+ return (_jsxs(_Fragment, { children: [_jsxs(Pressable, { testID: testID, onPress: inativo ? undefined : () => setAberto(true), disabled: inativo, accessibilityRole: "button", accessibilityLabel: campo?.label, accessibilityHint: campo?.hint, accessibilityValue: { text: escolhido?.label }, ...estadoAcessivel({ disabled: !!inativo, expanded: aberto }), style: [
522
572
  s.caixa,
523
573
  { flexDirection: "row", alignItems: "center", justifyContent: "space-between",
524
574
  height: alturaDoTamanho(t, tam), paddingHorizontal: respiroDoTamanho(t, tam) },
@@ -527,7 +577,7 @@ export function Select({ items, value, onChange, placeholder, disabled, size, ch
527
577
  peleDaMarca,
528
578
  inativo && s.desabilitado,
529
579
  style,
530
- ], children: [_jsx(Text, { size: tam === "sm" ? "xs" : tam === "lg" ? "base" : "md", tone: escolhido ? "default" : "subtle", numberOfLines: 1, children: escolhido?.label ?? placeholder ?? "" }), chevron && _jsx(Icon, { name: chevron, size: "sm", color: peleDaMarca?.color ?? t.color.subtleForeground })] }), _jsx(ForaDaMarca, { children: _jsx(Modal, { visible: aberto, transparent: true, animationType: "slide", statusBarTranslucent: true, navigationBarTranslucent: true, onRequestClose: () => setAberto(false), children: _jsxs(View, { style: s.fundoDaLista, children: [_jsx(Pressable, { style: s.fundoDeToque, onPress: () => setAberto(false), accessible: false }), _jsxs(View, { style: s.lista, children: [_jsx(ScrollView, { children: items.map((it) => (_jsx(Pressable, { disabled: it.disabled, onPress: () => { onChange?.(it.value); setAberto(false); }, accessibilityRole: "menuitem", accessibilityState: { selected: it.value === value, disabled: !!it.disabled }, style: [s.opcao, it.disabled && s.desabilitado], children: _jsx(Text, { size: "md", weight: it.value === value ? 600 : 400, children: it.label }) }, it.value))) }), _jsx(RecuoDaFolha, {})] })] }) }) })] }));
580
+ ], children: [_jsx(Text, { size: tam === "sm" ? "xs" : tam === "lg" ? "base" : "md", tone: escolhido ? "default" : "subtle", numberOfLines: 1, children: escolhido?.label ?? placeholder ?? "" }), chevron && _jsx(Icon, { name: chevron, size: "sm", color: peleDaMarca?.color ?? t.color.subtleForeground })] }), _jsx(ForaDaMarca, { children: _jsx(Modal, { visible: aberto, transparent: true, animationType: "slide", statusBarTranslucent: true, navigationBarTranslucent: true, onRequestClose: () => setAberto(false), children: _jsxs(View, { style: s.fundoDaLista, children: [_jsx(Pressable, { style: s.fundoDeToque, onPress: () => setAberto(false), accessible: false }), _jsxs(View, { style: s.lista, children: [_jsx(ScrollView, { children: items.map((it) => (_jsx(Pressable, { disabled: it.disabled, onPress: () => { onChange?.(it.value); setAberto(false); }, accessibilityRole: "menuitem", ...estadoAcessivel({ selected: it.value === value, disabled: !!it.disabled }), style: [s.opcao, it.disabled && s.desabilitado], children: _jsx(Text, { size: "md", weight: it.value === value ? 600 : 400, children: it.label }) }, it.value))) }), _jsx(RecuoDaFolha, {})] })] }) }) })] }));
531
581
  }
532
582
  /**
533
583
  * A pilha de campos, com o respiro do `--space-5`.
package/dist/layout.js CHANGED
@@ -17,7 +17,7 @@ import { Pressable, StyleSheet, View } from "react-native";
17
17
  // `@aurea-uds/react` ja' faz (o `Stack` da web e' `HTMLAttributes & RefAttributes`, sem
18
18
  // envelope). O `ViewProps`/`TextProps` do RN 0.87 ja' declaram `ref`, entao ele viaja no
19
19
  // `...rest` sem nada a mais.
20
- import { criarFolha, REACAO_AO_TOQUE } from "./estilos.js";
20
+ import { criarFolha, REACAO_AO_TOQUE, estadoAcessivel } from "./estilos.js";
21
21
  import { Text } from "./text.js";
22
22
  import { useAureaTokens, SobreAMarca } from "./theme.js";
23
23
  const folha = criarFolha((t) => ({
@@ -203,7 +203,7 @@ export function Card({ variant, style, ...rest }) {
203
203
  const { action, children, onPress, disabled, ...resto } = rest;
204
204
  if (onPress != null) {
205
205
  const pele = variant ?? "interactive";
206
- return (_jsx(Pressable, { onPress: onPress, disabled: disabled, accessibilityRole: "button", accessibilityState: { disabled: !!disabled }, style: ({ pressed: tocando }) => [
206
+ return (_jsx(Pressable, { onPress: onPress, disabled: disabled, accessibilityRole: "button", ...estadoAcessivel({ disabled: !!disabled }), style: ({ pressed: tocando }) => [
207
207
  s.cardBase, s[`card_${pele}`],
208
208
  tocando && REACAO_AO_TOQUE.pressionado, disabled && REACAO_AO_TOQUE.inerte,
209
209
  style,
package/dist/midia.js CHANGED
@@ -38,7 +38,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
38
38
  // e serve ao mesmo caso real: o consumidor que já usa `expo-image`.
39
39
  import * as React from "react";
40
40
  import { Image as ImageRN, Pressable, View, } from "react-native";
41
- import { criarFolha } from "./estilos.js";
41
+ import { criarFolha, estadoAcessivel } from "./estilos.js";
42
42
  import { Icon } from "./icon.js";
43
43
  import { Grid } from "./layout.js";
44
44
  import { Dialog } from "./overlays.js";
@@ -176,6 +176,6 @@ export function Gallery({ items, label, selected, onSelect, zoom, ratio = 1, min
176
176
  // Com legenda, o nome do ladrilho é a legenda e a imagem já saiu da árvore (o
177
177
  // `alt=""` acima). Sem legenda, o nome é o `alt`.
178
178
  accessibilityLabel: temLegenda && typeof item.caption === "string"
179
- ? item.caption : item.alt, accessibilityState: { selected: item.id === selected }, style: [s.ladrilho, item.id === selected && s.ladrilhoEscolhido], children: miolo }, item.id));
179
+ ? item.caption : item.alt, ...estadoAcessivel({ selected: item.id === selected }), style: [s.ladrilho, item.id === selected && s.ladrilhoEscolhido], children: miolo }, item.id));
180
180
  }) }), zoom && (_jsx(Dialog, { open: aberto != null, title: aberto ? (typeof aberto.caption === "string" ? aberto.caption : aberto.alt) : "", onClose: () => setAmpliado(null), testID: testID ? `${testID}-ampliada` : undefined, children: aberto && _jsx(Image, { source: aberto.source, alt: aberto.alt, fit: "contain", ratio: ratio }) }))] }));
181
181
  }
@@ -3,7 +3,7 @@ import { Pressable, View } from "react-native";
3
3
  import { useSafeAreaInsets } from "react-native-safe-area-context";
4
4
  import { useAnotarBottomNav } from "./barranav.js";
5
5
  import { Badge } from "./display.js";
6
- import { comOpacidade, criarFolha } from "./estilos.js";
6
+ import { comOpacidade, criarFolha, estadoAcessivel } from "./estilos.js";
7
7
  import { Icon } from "./icon.js";
8
8
  import { Card } from "./layout.js";
9
9
  import { FilaRolante } from "./rolagem.js";
@@ -258,7 +258,7 @@ export function BottomNav({ items, current, variant = "floating", indicator = "n
258
258
  : t.color.foreground;
259
259
  return (_jsxs(Pressable, { onPress: it.onPress, disabled: it.disabled,
260
260
  // `link` e não `tab`: uma aba troca um painel DESTA tela; isto troca de tela.
261
- accessibilityRole: "link", accessibilityState: { selected: ativo, disabled: !!it.disabled }, style: [
261
+ accessibilityRole: "link", ...estadoAcessivel({ selected: ativo, disabled: !!it.disabled }), style: [
262
262
  s.aba, justa && s.aba_content,
263
263
  indicator === "subtle" && { borderRadius: t.size.radiusCard - t.size.space1 },
264
264
  ativo && (indicator === "subtle" || indicator === "pill")
@@ -350,7 +350,7 @@ export function NavList({ items, chevron = "chevron--right", style, ...rest }) {
350
350
  ? _jsx(Text, { size: "xs", tone: "muted", numberOfLines: 1, children: it.description })
351
351
  : it.description)] }), valorEhTexto && _jsx(Text, { size: "sm", tone: "muted", children: it.value }), temAcao && chevron
352
352
  && _jsx(Icon, { name: chevron, size: "sm", color: t.color.mutedForeground })] }));
353
- return (_jsxs(View, { style: [s.linha, it.disabled && { opacity: t.size.opacityDisabled }], children: [temAcao ? (_jsx(Pressable, { onPress: it.onPress, disabled: it.disabled, accessibilityRole: "link", accessibilityState: { disabled: !!it.disabled }, style: s.linhaMiolo, children: miolo })) : (_jsx(View, { accessible: true, accessibilityState: { disabled: !!it.disabled }, style: s.linhaMiolo, children: miolo })), !valorEhTexto && it.value != null ? it.value : null] }, it.id));
353
+ return (_jsxs(View, { style: [s.linha, it.disabled && { opacity: t.size.opacityDisabled }], children: [temAcao ? (_jsx(Pressable, { onPress: it.onPress, disabled: it.disabled, accessibilityRole: "link", ...estadoAcessivel({ disabled: !!it.disabled }), style: s.linhaMiolo, children: miolo })) : (_jsx(View, { accessible: true, ...estadoAcessivel({ disabled: !!it.disabled }), style: s.linhaMiolo, children: miolo })), !valorEhTexto && it.value != null ? it.value : null] }, it.id));
354
354
  }) }));
355
355
  }
356
356
  /**
@@ -382,7 +382,7 @@ export function Stepper({ items, label, doneIcon = "checkmark", errorIcon = "err
382
382
  : it.label, it.optional != null && (typeof it.optional === "string"
383
383
  ? _jsx(Text, { size: "xs", tone: "muted", align: "center", children: it.optional })
384
384
  : it.optional)] }));
385
- return it.onPress ? (_jsx(Pressable, { onPress: it.onPress, accessibilityRole: "button", accessibilityState: { selected: st === "active" }, style: s.passo, children: miolo }, n)) : (_jsx(View, { accessible: true, accessibilityState: { selected: st === "active" }, style: s.passo, children: miolo }, n));
385
+ return it.onPress ? (_jsx(Pressable, { onPress: it.onPress, accessibilityRole: "button", ...estadoAcessivel({ selected: st === "active" }), style: s.passo, children: miolo }, n)) : (_jsx(View, { accessible: true, ...estadoAcessivel({ selected: st === "active" }), style: s.passo, children: miolo }, n));
386
386
  }) }));
387
387
  }
388
388
  /**
@@ -425,7 +425,7 @@ export function Tabs({ tabs, value, onChange, label, justify, style, ...rest })
425
425
  const aberta = tabs.find((it) => it.id === value);
426
426
  return (_jsxs(View, { style: style, ...rest, children: [_jsx(FilaRolante, { justify: justify, children: _jsx(View, { accessibilityRole: "tablist", accessibilityLabel: label ?? strings.tabsLabel, style: s.abas, children: tabs.map((it) => {
427
427
  const ativa = it.id === value;
428
- return (_jsx(Pressable, { onPress: it.disabled ? undefined : () => onChange?.(it.id), disabled: it.disabled, accessibilityRole: "tab", accessibilityState: { selected: ativa, disabled: !!it.disabled }, accessibilityLabel: typeof it.label === "string" ? it.label : undefined, style: [s.abaDeTab, ativa && s.abaDeTabAtiva, it.disabled && { opacity: t.size.opacityDisabled }], children: typeof it.label === "string"
428
+ return (_jsx(Pressable, { onPress: it.disabled ? undefined : () => onChange?.(it.id), disabled: it.disabled, accessibilityRole: "tab", ...estadoAcessivel({ selected: ativa, disabled: !!it.disabled }), accessibilityLabel: typeof it.label === "string" ? it.label : undefined, style: [s.abaDeTab, ativa && s.abaDeTabAtiva, it.disabled && { opacity: t.size.opacityDisabled }], children: typeof it.label === "string"
429
429
  ? _jsx(Text, { size: "sm", weight: ativa ? 600 : 400, style: { color: ativa ? t.color.foreground : t.color.mutedForeground }, children: it.label })
430
430
  : it.label }, it.id));
431
431
  }) }) }), aberta
package/dist/numero.js CHANGED
@@ -47,7 +47,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
47
47
  import * as React from "react";
48
48
  import { Platform, TextInput, View } from "react-native";
49
49
  import { IconButton } from "./actions.js";
50
- import { criarFolha } from "./estilos.js";
50
+ import { criarFolha, estadoAcessivel } from "./estilos.js";
51
51
  import { useCampo } from "./inputs.js";
52
52
  import { useAureaStrings, useAureaTokens, usePeleSobreAMarca } from "./theme.js";
53
53
  const alturaDoTamanho = (t, s) => s === "sm" ? t.size.controlHSm : s === "lg" ? t.size.controlHLg : t.size.controlHMd;
@@ -358,7 +358,7 @@ export function NumberField({ value, defaultValue, onValueChange, min, max, step
358
358
  return (_jsxs(View, { testID: testID, style: [s.grupo, fullWidth && s.grupoLargo, inativo && s.desabilitado, style], children: [mostrarBotoes && (_jsx(IconButton, { name: icons.decrement, label: strings.decrement, appearance: "ghost", size: tam, disabled: inativo || noLimite(-1), onPress: () => empurrar(-1), testID: testID ? `${testID}-menos` : undefined })), _jsx(TextInput, { testID: testID ? `${testID}-campo` : undefined, value: mostrar, onChangeText: digitar, onFocus: () => { setFocado(true); setEmEdicao(paraEdicao(numero, locale)); }, onBlur: () => { setFocado(false); confirmar(); }, editable: !inativo && !readOnly, placeholder: placeholder, placeholderTextColor: peleDaMarca?.color ?? t.color.subtleForeground, keyboardType: keyboardType ?? tecladoPadrao,
359
359
  // O nome vem do `Field`, como em todo controle deste pacote — e `label` cobre quem usa o
360
360
  // campo solto. Sem um dos dois, é um nó anônimo para o leitor de tela.
361
- accessibilityLabel: label ?? campo?.label, accessibilityHint: campo?.hint, accessibilityState: { disabled: !!inativo }, "aria-invalid": campo?.invalido, style: [
361
+ accessibilityLabel: label ?? campo?.label, accessibilityHint: campo?.hint, ...estadoAcessivel({ disabled: !!inativo }), "aria-invalid": campo?.invalido, style: [
362
362
  s.campo,
363
363
  fullWidth && s.campoLargo,
364
364
  { height: alturaDoTamanho(t, tam), fontSize: fonteDoTamanho(t, tam),
package/dist/sistema.js CHANGED
@@ -36,7 +36,7 @@ import RNDateTimePicker, { DateTimePickerAndroid } from "@react-native-community
36
36
  import * as ImagePicker from "expo-image-picker";
37
37
  import { IconButton } from "./actions.js";
38
38
  import { Avatar } from "./display.js";
39
- import { criarFolha } from "./estilos.js";
39
+ import { criarFolha, estadoAcessivel } from "./estilos.js";
40
40
  import { Alert } from "./feedback.js";
41
41
  import { Icon } from "./icon.js";
42
42
  import { useCampo } from "./inputs.js";
@@ -107,7 +107,7 @@ export function DatePicker({ value, onChange, mode = "date", minimumDate, maximu
107
107
  setAbertoNoIOS(true);
108
108
  }, [value, mode, minimumDate, maximumDate, receber]);
109
109
  const mostrarSeletorIOS = abertoNoIOS && Platform.OS !== "android";
110
- return (_jsxs(_Fragment, { children: [_jsxs(Pressable, { testID: testID, onPress: inativo ? undefined : abrir, disabled: inativo, accessibilityRole: "button", accessibilityLabel: campo?.label, accessibilityHint: campo?.hint, accessibilityValue: { text: value ? texto : undefined }, accessibilityState: { disabled: !!inativo }, style: [
110
+ return (_jsxs(_Fragment, { children: [_jsxs(Pressable, { testID: testID, onPress: inativo ? undefined : abrir, disabled: inativo, accessibilityRole: "button", accessibilityLabel: campo?.label, accessibilityHint: campo?.hint, accessibilityValue: { text: value ? texto : undefined }, ...estadoAcessivel({ disabled: !!inativo }), style: [
111
111
  s.gatilho,
112
112
  { height: alturaDoTamanho(t, tam),
113
113
  paddingHorizontal: tam === "sm" ? t.size.space3 : tam === "lg" ? t.size.space4 : 13 },
@@ -166,5 +166,5 @@ export function PhotoInput({ value = [], onChange, max = 1, source = "camera", d
166
166
  .map((a) => ({ uri: a.uri, width: a.width, height: a.height }));
167
167
  onChange?.([...value, ...novas]);
168
168
  }, [source, max, value, onChange, onPermissionDenied]);
169
- return (_jsxs(View, { testID: testID, style: style, children: [negadoDeVez && (_jsx(Alert, { variant: "warning", children: _jsxs(View, { style: { gap: t.size.space2 }, children: [_jsx(Text, { size: "sm", tone: "muted", children: strings.cameraDenied }), offerSettings && (_jsx(Pressable, { onPress: () => Linking.openSettings(), accessibilityRole: "button", accessibilityLabel: strings.openSettings, children: _jsx(Text, { size: "sm", weight: 600, tone: "primary", children: strings.openSettings }) }))] }) })), _jsxs(View, { style: s.galeria, children: [value.map((foto, n) => (_jsxs(View, { style: s.miniatura, children: [_jsx(Avatar, { source: foto.uri, size: "lg", alt: "" }), _jsx(View, { style: s.remover, children: _jsx(IconButton, { appearance: "ghost", size: "sm", name: removeIcon, label: strings.photoRemove, onPress: () => onChange?.(value.filter((_, i) => i !== n)) }) })] }, foto.uri))), !cheio && (_jsx(Pressable, { onPress: inativo ? undefined : escolher, disabled: inativo, accessibilityRole: "button", accessibilityLabel: campo?.label, accessibilityState: { disabled: !!inativo }, style: [s.adicionar, inativo && s.desabilitado], children: addIcon && _jsx(Icon, { name: addIcon, size: "lg", color: t.color.subtleForeground }) }))] })] }));
169
+ return (_jsxs(View, { testID: testID, style: style, children: [negadoDeVez && (_jsx(Alert, { variant: "warning", children: _jsxs(View, { style: { gap: t.size.space2 }, children: [_jsx(Text, { size: "sm", tone: "muted", children: strings.cameraDenied }), offerSettings && (_jsx(Pressable, { onPress: () => Linking.openSettings(), accessibilityRole: "button", accessibilityLabel: strings.openSettings, children: _jsx(Text, { size: "sm", weight: 600, tone: "primary", children: strings.openSettings }) }))] }) })), _jsxs(View, { style: s.galeria, children: [value.map((foto, n) => (_jsxs(View, { style: s.miniatura, children: [_jsx(Avatar, { source: foto.uri, size: "lg", alt: "" }), _jsx(View, { style: s.remover, children: _jsx(IconButton, { appearance: "ghost", size: "sm", name: removeIcon, label: strings.photoRemove, onPress: () => onChange?.(value.filter((_, i) => i !== n)) }) })] }, foto.uri))), !cheio && (_jsx(Pressable, { onPress: inativo ? undefined : escolher, disabled: inativo, accessibilityRole: "button", accessibilityLabel: campo?.label, ...estadoAcessivel({ disabled: !!inativo }), style: [s.adicionar, inativo && s.desabilitado], children: addIcon && _jsx(Icon, { name: addIcon, size: "lg", color: t.color.subtleForeground }) }))] })] }));
170
170
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurea-uds/native",
3
- "version": "0.12.2",
3
+ "version": "0.12.4",
4
4
  "description": "A Aurea UDS para React Native: o provider de tema e densidade, os componentes e os ícones do Carbon sobre react-native-svg.",
5
5
  "keywords": [
6
6
  "aurea",
@@ -51,7 +51,7 @@
51
51
  "NOTICE"
52
52
  ],
53
53
  "dependencies": {
54
- "@aurea-uds/tokens": "^0.12.2"
54
+ "@aurea-uds/tokens": "^0.12.4"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "@react-native-community/datetimepicker": ">=8",