@aurea-uds/native 0.8.2 → 0.8.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
@@ -42,8 +42,25 @@ const ICONE = {
42
42
  function pintar(t, tone) {
43
43
  const m = {
44
44
  neutral: { solido: t.color.secondary, texto: t.color.secondaryForeground, sobre: t.color.foreground },
45
- brand: { solido: t.color.primary, texto: t.color.primaryForeground, sobre: t.color.primary },
46
- danger: { solido: t.color.destructive, texto: t.color.destructiveForeground, sobre: t.color.destructive },
45
+ // ⚠ O TOM DA MARCA TEM DUAS CORES, e confundi-las foi defeito publicado na `0.8.2`.
46
+ //
47
+ // `solido` é o amarelo da marca, que é FUNDO: o texto por cima é escuro e lê bem.
48
+ // `sobre` é o mesmo amarelo virando TEXTO — e aí ele some. Medido sobre o fundo do tema
49
+ // claro: **1,73:1**, contra os 4,5:1 que a WCAG exige para texto normal. No escuro dá 10,34.
50
+ //
51
+ // O token certo existe desde sempre e é o `link`: mesmo matiz (86.047), mais escuro,
52
+ // **5,02:1** no claro — e no escuro ele É o amarelo da marca, então nada muda lá. A
53
+ // identidade não foi tocada: o amarelo de preencher continua invariável, como manda o
54
+ // `CLAUDE.md`. O que mudou é qual dos dois se usa para ESCREVER.
55
+ //
56
+ // ⚠ Achado pelo app na tela de entrar, não por teste nosso — os 1430 passavam por cima.
57
+ brand: { solido: t.color.primary, texto: t.color.primaryForeground, sobre: t.color.link },
58
+ // ⚠ MESMO DEFEITO DO TOM DA MARCA, achado por medir os outros tons em vez de parar no
59
+ // primeiro: `destructive` escrito sobre o tema claro dá **4,30:1** — reprova por pouco, mas
60
+ // reprova. O `danger400` passa nos DOIS temas (6,86 no claro, 7,47 no escuro), e não é
61
+ // invenção: o `Input` já usa esse token para a borda de inválido.
62
+ // O `solido` continua no `destructive`, porque ali ele é FUNDO e o texto por cima é claro.
63
+ danger: { solido: t.color.destructive, texto: t.color.destructiveForeground, sobre: t.color.danger400 ?? t.color.destructive },
47
64
  success: { solido: t.color.success, texto: t.color.successForeground, sobre: t.color.success },
48
65
  warning: { solido: t.color.warning, texto: t.color.warningForeground, sobre: t.color.warning },
49
66
  info: { solido: t.color.info, texto: t.color.infoForeground, sobre: t.color.info },
package/dist/busca.js CHANGED
@@ -114,6 +114,23 @@ const folha = criarFolha((t) => ({
114
114
  // `space05` mede 2 — o mesmo valor, agora com nome. O `.combobox-actions` da web
115
115
  // (`aurea.css:1673`) usa `gap:2px` literal; aqui o token existe, então é ele que entra.
116
116
  acoes: { flexDirection: "row", alignItems: "center", gap: t.size.space05 },
117
+ // 🔴 O GATILHO É IRMÃO DO X, NÃO ANCESTRAL — defeito achado pelo consumidor em 16/09/2026.
118
+ // O `IconButton` de limpar vivia DENTRO deste `Pressable`, e um `Pressable` nasce `accessible`
119
+ // (`Pressable.js:274`). No iOS esse `accessible` vira `isAccessibilityElement`
120
+ // (`RCTViewComponentView.mm:398`), e quem é elemento de acessibilidade NÃO expõe os filhos —
121
+ // então o X existia na tela e não existia para o VoiceOver.
122
+ // ⚠ **No Android não sumia**, e é por isso que o defeito atravessou o smoke inteiro: lá
123
+ // `accessible` só liga `isFocusable` (`ReactViewManager.kt:96`) e o `ReactViewGroup.kt:1048`
124
+ // continua entregando os filhos à árvore. Um aparelho só nunca responderia esta pergunta.
125
+ // ⚠ É a MESMA forma dos dois consertos que este pacote já carrega (`busca.tsx` fundo da folha,
126
+ // `inputs.tsx:909`): **num sistema de toque, o irmão resolve o que o ancestral quebra.**
127
+ // Nenhuma distância nova: `flex`, `minWidth` e `100%` são relações, não medidas.
128
+ gatilho: { flex: 1, minWidth: 0, height: "100%", flexDirection: "row", alignItems: "center" },
129
+ // A seta deixou de ser enfeite dentro do gatilho e virou toque próprio — é onde a pessoa toca
130
+ // para abrir. `accessible={false}` no JSX porque o gatilho JÁ anuncia tudo: um segundo botão
131
+ // aqui seria a mesma informação duas vezes. O `Icon` sem rótulo já se esconde sozinho
132
+ // (`icon.tsx:104`), então não sobra nada para o leitor de tela tropeçar.
133
+ setaToque: { height: "100%", justifyContent: "center" },
117
134
  // A folha, com a mesma anatomia da do `Select` (`inputs.tsx:98-113`) — e é de propósito que
118
135
  // sejam iguais: são o mesmo gesto, e duas folhas diferentes para o mesmo gesto é como uma
119
136
  // biblioteca deixa de ter linguagem.
@@ -271,13 +288,13 @@ export function Combobox({ items, value, onValueChange, onSearchChange, searchDe
271
288
  return items.filter((i) => dobrar(i.label).includes(alvo));
272
289
  }, [items, texto, onSearchChange]);
273
290
  const nada = !loading && filtrados.length === 0;
274
- 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: value?.label }, accessibilityState: { disabled: !!inativo, expanded: aberto }, style: [
291
+ return (_jsxs(_Fragment, { children: [_jsxs(View, { style: [
275
292
  s.caixa,
276
293
  { height: alturaDoTamanho(t, tam), paddingHorizontal: respiroDoTamanho(t, tam) },
277
294
  campo?.invalido && s.invalido,
278
295
  inativo && s.desabilitado,
279
296
  style,
280
- ], 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(Icon, { name: chevron, size: "sm", color: t.color.subtleForeground })] })] }), _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; }, onStartShouldSetResponder: () => true, 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,
297
+ ], 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(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; }, onStartShouldSetResponder: () => true, 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,
281
298
  // ⚠ `autoFocus` é o que faz a folha valer a pena: abrir um campo de busca e
282
299
  // exigir um segundo toque para o teclado subir é um toque a mais em cada
283
300
  // cadastro. O foco entra com a folha; o teclado vem junto.
package/dist/index.d.ts CHANGED
@@ -9,8 +9,8 @@ export { Icon, IconRegistryProvider, criarRegistroDeIcones } from "./icon.js";
9
9
  export type { IconProps, IconName, AureaIconComponent, AureaIconRegistry, AureaIconSize, } from "./icon.js";
10
10
  export { Screen } from "./screen.js";
11
11
  export type { ScreenProps, AureaScreenBackground, AureaScreenEdge } from "./screen.js";
12
- export { Stack, Cluster, Grid, Card } from "./layout.js";
13
- export type { StackProps, GridProps, CardProps, AureaCardVariant } from "./layout.js";
12
+ export { Stack, Cluster, Grid, Card, Separator } from "./layout.js";
13
+ export type { StackProps, GridProps, CardProps, SeparatorProps, AureaCardVariant } from "./layout.js";
14
14
  export { Button, IconButton } from "./actions.js";
15
15
  export type { ButtonProps, IconButtonProps, AureaButtonAppearance, AureaButtonSize, AureaButtonTone, } from "./actions.js";
16
16
  export { Spinner, Skeleton, Progress, Alert, EmptyState, DataState, ICONE_DA_VARIANTE } from "./feedback.js";
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ export { Icon, IconRegistryProvider, criarRegistroDeIcones } from "./icon.js";
33
33
  // A ÚNICA peça do Lote 1 com dependência de terceiro — `react-native-safe-area-context`,
34
34
  // autorizada pelo Victor em 03/09/2026 depois de o lote parar por ela (`BUILDING.md` §3).
35
35
  export { Screen } from "./screen.js";
36
- export { Stack, Cluster, Grid, Card } from "./layout.js";
36
+ export { Stack, Cluster, Grid, Card, Separator } from "./layout.js";
37
37
  export { Button, IconButton } from "./actions.js";
38
38
  // ── Lote 2 — o painel, que é só leitura ────────────────────────────────────────────────────
39
39
  export { Spinner, Skeleton, Progress, Alert, EmptyState, DataState, ICONE_DA_VARIANTE } from "./feedback.js";
package/dist/inputs.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
- import { type KeyboardTypeOptions, type StyleProp, type TextStyle, type ViewProps, type ViewStyle } from "react-native";
3
- import { type IconName } from "./icon.js";
2
+ import { TextInput, type KeyboardTypeOptions, type StyleProp, type TextInputProps, type TextStyle, type ViewProps, type ViewStyle } from "react-native";
3
+ import { type AureaIconRegistry, type IconName } from "./icon.js";
4
4
  export type AureaFieldSize = "sm" | "md" | "lg";
5
5
  type ContextoDeCampo = {
6
6
  label?: string;
@@ -59,7 +59,30 @@ export interface LabelProps extends ViewProps {
59
59
  * entrega. Um `Label` solto é decoração; use-o dentro de um `Field`.
60
60
  */
61
61
  export declare function Label({ children, trailing, style, ...rest }: LabelProps): React.JSX.Element;
62
- export interface InputProps {
62
+ /**
63
+ * ⚠ **O `Input` HERDA do `TextInput`, e isso é conserto de defeito publicado na `0.8.2`.**
64
+ *
65
+ * Até ali a interface listava catorze props e o componente desestruturava as catorze **sem
66
+ * `...rest`**: tudo o que não estivesse na lista era **descartado em silêncio**. O app achou na
67
+ * tela de entrar, e o efeito não aparece na tela — aparece no uso: sem `autoComplete` e
68
+ * `textContentType` o gerenciador de senhas não reconhece os campos; sem `autoCorrect` o teclado
69
+ * "corrige" o e-mail; sem `returnKeyType`/`onSubmitEditing` o botão "próximo" não pula para a
70
+ * senha; e sem `ref` não há como focar o campo por código.
71
+ *
72
+ * ⚠ **Era pior do que parece:** o `PasswordField` repassa `...rest` ao `Input` — e o `Input`
73
+ * jogava fora. Duas camadas concordando em perder a prop.
74
+ *
75
+ * O que continua sendo da Aurea está no `Omit` abaixo, e a razão de cada um está ao lado.
76
+ */
77
+ export interface InputProps extends Omit<TextInputProps, "style" | "editable" | "placeholderTextColor" | "onBlur" | "onFocus" | "accessibilityLabel" | "accessibilityHint" | "accessibilityState"> {
78
+ /**
79
+ * O nó do `TextInput` lá dentro — para focar por código (`ref.current?.focus()`), que é como
80
+ * o "próximo" do teclado pula de um campo para o outro.
81
+ *
82
+ * Chega por PROPS e atravessa no `...rest`: é o padrão do React 19, sem `forwardRef`, o mesmo
83
+ * que o `layout.tsx` já documenta. **Faltava na `0.8.2`** — não havia como focar campo nenhum.
84
+ */
85
+ ref?: React.Ref<React.ComponentRef<typeof TextInput>>;
63
86
  value?: string;
64
87
  defaultValue?: string;
65
88
  onChangeText?: (v: string) => void;
@@ -111,7 +134,7 @@ export interface InputProps {
111
134
  * (`aurea.css:686`); **não há ponteiro no telefone**. O foco continua existindo e é o que marca o
112
135
  * campo ativo.
113
136
  */
114
- export declare function Input({ value, defaultValue, onChangeText, placeholder, disabled, size, keyboardType, secureTextEntry, autoCapitalize, formatOnBlur, onBlur, onFocus, multiline, style, testID, }: InputProps): React.JSX.Element;
137
+ export declare function Input({ value, defaultValue, onChangeText, placeholder, disabled, size, keyboardType, secureTextEntry, autoCapitalize, formatOnBlur, onBlur, onFocus, multiline, style, testID, ...rest }: InputProps): React.JSX.Element;
115
138
  export interface TextareaProps extends InputProps {
116
139
  /** Linhas visíveis. Vira altura mínima, porque no RN não há `rows`. */
117
140
  rows?: number;
@@ -173,8 +196,33 @@ export declare function InputGroupAddon({ children, style, testID, ...rest }: In
173
196
  export interface PasswordFieldProps extends Omit<InputProps, "secureTextEntry" | "multiline" | "keyboardType"> {
174
197
  /** Começa visível. Padrão: escondida. */
175
198
  defaultVisible?: boolean;
199
+ /**
200
+ * Um desenho na FRENTE do campo — o cadeado, quase sempre.
201
+ *
202
+ * ⚠ **Faltava na `0.8.2`, e a falta era de desenho meu:** o `PasswordField` monta o grupo por
203
+ * dentro, então não havia onde encaixar nada antes do campo. Quem quisesse um cadeado teria de
204
+ * desmontar a peça e remontar à mão, perdendo o olho, o rótulo que anuncia o estado e o
205
+ * `autoCapitalize` que nasce em `none`.
206
+ *
207
+ * <PasswordField leading={<Icon name="locked" size="sm" />} … />
208
+ */
209
+ leading?: React.ReactNode;
210
+ /**
211
+ * O registro de glifos, quando o do `AureaProvider` não tem os dois que este componente usa.
212
+ *
213
+ * 🔴 **ELE PRECISA DE DOIS ÍCONES, e isto não estava escrito em lugar nenhum — defeito da
214
+ * `0.8.2`:** o olho é `view` e `view--off`. Se faltarem no registro, **o botão fica invisível**
215
+ * e o aviso sai só em desenvolvimento: em produção a pessoa simplesmente não consegue ver a
216
+ * senha que digitou, sem nada na tela explicando.
217
+ *
218
+ * import Olho from "@aurea-uds/native/icons/view";
219
+ * import OlhoOff from "@aurea-uds/native/icons/view--off";
220
+ * const ICONES = criarRegistroDeIcones({view: Olho, "view--off": OlhoOff});
221
+ * // no provider, junto dos outros — ou aqui: <PasswordField icons={ICONES} />
222
+ */
223
+ icons?: AureaIconRegistry;
176
224
  }
177
- export declare function PasswordField({ defaultVisible, size, disabled, autoCapitalize, testID, style, ...rest }: PasswordFieldProps): React.JSX.Element;
225
+ export declare function PasswordField({ defaultVisible, size, disabled, autoCapitalize, leading, icons, testID, style, ...rest }: PasswordFieldProps): React.JSX.Element;
178
226
  export type CheckboxProps = ControleProps;
179
227
  export type RadioProps = ControleProps;
180
228
  /** A caixa que marca. `accessibilityRole="checkbox"` + `state.checked`. */
package/dist/inputs.js CHANGED
@@ -168,7 +168,11 @@ export function Label({ children, trailing, style, ...rest }) {
168
168
  * (`aurea.css:686`); **não há ponteiro no telefone**. O foco continua existindo e é o que marca o
169
169
  * campo ativo.
170
170
  */
171
- export function Input({ value, defaultValue, onChangeText, placeholder, disabled, size, keyboardType, secureTextEntry, autoCapitalize, formatOnBlur, onBlur, onFocus, multiline, style, testID, }) {
171
+ export function Input({ value, defaultValue, onChangeText, placeholder, disabled, size, keyboardType, secureTextEntry, autoCapitalize, formatOnBlur, onBlur, onFocus, multiline, style, testID,
172
+ // ⚠ O `...rest` NÃO é enfeite: sem ele, toda prop do `TextInput` que a lista acima não nomeia
173
+ // era descartada em silêncio — `autoComplete`, `textContentType`, `autoCorrect`,
174
+ // `returnKeyType`, `onSubmitEditing`, `maxLength`. Defeito publicado na `0.8.2`.
175
+ ...rest }) {
172
176
  const t = useAureaTokens();
173
177
  const s = folha(t);
174
178
  const campo = useCampo();
@@ -176,7 +180,11 @@ export function Input({ value, defaultValue, onChangeText, placeholder, disabled
176
180
  const tam = size ?? grupo?.size ?? campo?.size ?? "md";
177
181
  const inativo = disabled ?? grupo?.disabled ?? campo?.disabled;
178
182
  const [focado, setFocado] = React.useState(false);
179
- return (_jsx(TextInput, { testID: testID, value: value, defaultValue: defaultValue, onChangeText: onChangeText, placeholder: placeholder, placeholderTextColor: t.color.subtleForeground, editable: !inativo, keyboardType: keyboardType, secureTextEntry: secureTextEntry, autoCapitalize: autoCapitalize, multiline: multiline, onFocus: () => { setFocado(true); grupo?.aoFocar(true); onFocus?.(); }, onBlur: () => {
183
+ return (_jsx(TextInput
184
+ // O resto vem PRIMEIRO de propósito: o que a Aurea calcula (respiro, cor, nome do `Field`,
185
+ // `editable`) tem de vencer, e as props que ela redefine estão no `Omit` da interface —
186
+ // então não chegam por aqui e não há o que sobrescrever por acidente.
187
+ , { ...rest, testID: testID, value: value, defaultValue: defaultValue, onChangeText: onChangeText, placeholder: placeholder, placeholderTextColor: t.color.subtleForeground, editable: !inativo, keyboardType: keyboardType, secureTextEntry: secureTextEntry, autoCapitalize: autoCapitalize, multiline: multiline, onFocus: () => { setFocado(true); grupo?.aoFocar(true); onFocus?.(); }, onBlur: () => {
180
188
  setFocado(false);
181
189
  grupo?.aoFocar(false);
182
190
  // Só avisa quando o texto MUDOU: emitir o mesmo valor a cada saída de foco faria o app
@@ -281,13 +289,13 @@ export function InputGroupAddon({ children, style, testID, ...rest }) {
281
289
  const s = folha(t);
282
290
  return _jsx(View, { testID: testID, style: [s.encaixe, style], ...rest, children: children });
283
291
  }
284
- export function PasswordField({ defaultVisible = false, size, disabled, autoCapitalize = "none", testID, style, ...rest }) {
292
+ export function PasswordField({ defaultVisible = false, size, disabled, autoCapitalize = "none", leading, icons, testID, style, ...rest }) {
285
293
  const strings = useAureaStrings();
286
294
  const campo = useCampo();
287
295
  const [visivel, setVisivel] = React.useState(defaultVisible);
288
296
  const tam = size ?? campo?.size ?? "md";
289
297
  const inativo = disabled ?? campo?.disabled;
290
- return (_jsxs(InputGroup, { size: tam, disabled: inativo, testID: testID, children: [_jsx(Input, { ...rest, size: tam, disabled: inativo, autoCapitalize: autoCapitalize, secureTextEntry: !visivel, style: style, testID: testID ? `${testID}-campo` : undefined }), _jsx(InputGroupAddon, { children: _jsx(IconButton, { name: visivel ? "view--off" : "view", label: visivel ? strings.passwordHide : strings.passwordShow, appearance: "ghost", size: tam === "lg" ? "md" : "sm", disabled: inativo, onPress: () => setVisivel(v => !v), testID: testID ? `${testID}-olho` : undefined }) })] }));
298
+ return (_jsxs(InputGroup, { size: tam, disabled: inativo, testID: testID, children: [leading ? _jsx(InputGroupAddon, { children: leading }) : null, _jsx(Input, { ...rest, size: tam, disabled: inativo, autoCapitalize: autoCapitalize, secureTextEntry: !visivel, style: style, testID: testID ? `${testID}-campo` : undefined }), _jsx(InputGroupAddon, { children: _jsx(IconButton, { name: visivel ? "view--off" : "view", label: visivel ? strings.passwordHide : strings.passwordShow, appearance: "ghost", size: tam === "lg" ? "md" : "sm", disabled: inativo, icons: icons, onPress: () => setVisivel(v => !v), testID: testID ? `${testID}-olho` : undefined }) })] }));
291
299
  }
292
300
  function ControleMarcado({ papel, label, description, checked, onChange, disabled, size, style, testID, }) {
293
301
  const t = useAureaTokens();
package/dist/layout.d.ts CHANGED
@@ -33,6 +33,28 @@ export interface GridProps extends ViewProps {
33
33
  */
34
34
  export declare function Grid({ minColumnWidth, style, children, ...rest }: GridProps): React.JSX.Element;
35
35
  /** Qual superfície o cartão é. Mesmos seis nomes da ficha da web. */
36
+ export interface SeparatorProps extends ViewProps {
37
+ orientation?: "horizontal" | "vertical";
38
+ /**
39
+ * Um texto NO MEIO da linha — "ou entre com", numa tela de entrar.
40
+ *
41
+ * ⚠ **Isto NÃO existe na web, e a divergência fica declarada em vez de escondida.** Lá o
42
+ * `.separator` é só a linha, e um rótulo no meio nunca foi pedido. Aqui foi: o app mediu essa
43
+ * lacuna na tela de entrar, e a demanda manda no nativo desde o Lote 7. **Com `label`, a
44
+ * orientação é sempre horizontal** — texto no meio de uma linha vertical não é a mesma peça.
45
+ */
46
+ label?: React.ReactNode;
47
+ }
48
+ /**
49
+ * A linha de divisão do sistema. Mesma cor e mesma espessura do `.separator` da web.
50
+ *
51
+ * ⚠ **Ela NÃO recebe papel de acessibilidade, e isso é escolha medida, não esquecimento.** O
52
+ * `<hr>` da web traz o papel `separator` de graça; no React Native esse papel **não existe na
53
+ * lista** — inventar o mais parecido diria uma coisa errada ao leitor de tela, que é exatamente
54
+ * a armadilha que o Lote 5 e a `Table` do Lote 6 já pagaram. Uma linha decorativa calada é o
55
+ * comportamento certo.
56
+ */
57
+ export declare function Separator({ orientation, label, style, ...rest }: SeparatorProps): React.JSX.Element;
36
58
  export type AureaCardVariant = "base" | "raised" | "interactive" | "inset" | "selected" | "danger";
37
59
  export interface CardProps extends ViewProps {
38
60
  variant?: AureaCardVariant;
package/dist/layout.js CHANGED
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // Aurea nativo — os primitivos de layout: `Stack`, `Cluster`, `Grid`, `Card`.
3
3
  //
4
4
  // Medidos no core da web antes de escrever (passo 1 do BUILDING.md), e o que eles são lá:
@@ -18,8 +18,18 @@ import { View } from "react-native";
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
20
  import { criarFolha } from "./estilos.js";
21
+ import { Text } from "./text.js";
21
22
  import { useAureaTokens } from "./theme.js";
22
23
  const folha = criarFolha((t) => ({
24
+ // A LINHA DO SISTEMA, e os números são os mesmos do `.separator` da web (`aurea.css`): cor de
25
+ // `border` e espessura de UM pixel. ⚠ Um pixel não sai de `--space-*` de propósito — a linha
26
+ // do sistema é de um pixel, e um pixel não é espaçamento. A mesma frase está no CSS.
27
+ separador: { backgroundColor: t.color.border },
28
+ separadorH: { height: t.size.borderWidth, width: "100%" },
29
+ separadorV: { width: t.size.borderWidth, alignSelf: "stretch", minHeight: t.size.space5 },
30
+ // A linha COM texto no meio: duas linhas que esticam e o rótulo entre elas, sem encolher.
31
+ separadorRotulado: { flexDirection: "row", alignItems: "center", gap: t.size.space3, width: "100%" },
32
+ separadorPedaco: { flex: 1, height: t.size.borderWidth, backgroundColor: t.color.border },
23
33
  // `gap` no RN existe desde a 0.71 e é o mesmo conceito do flex gap do CSS — medido no contrato
24
34
  // do `react-native` 0.86/0.87 que o pacote declara como peer (>=0.76).
25
35
  stack: { flexDirection: "column", gap: t.size.space4 },
@@ -74,6 +84,25 @@ export function Grid({ minColumnWidth = 240, style, children, ...rest }) {
74
84
  const celula = React.useMemo(() => ({ flexGrow: 0, flexShrink: 1, flexBasis: minColumnWidth, minWidth: minColumnWidth, maxWidth: "100%" }), [minColumnWidth]);
75
85
  return (_jsx(View, { style: [s.grid, style], ...rest, children: React.Children.map(children, (filho) => React.isValidElement(filho) ? _jsx(View, { style: celula, children: filho }) : filho) }));
76
86
  }
87
+ /**
88
+ * A linha de divisão do sistema. Mesma cor e mesma espessura do `.separator` da web.
89
+ *
90
+ * ⚠ **Ela NÃO recebe papel de acessibilidade, e isso é escolha medida, não esquecimento.** O
91
+ * `<hr>` da web traz o papel `separator` de graça; no React Native esse papel **não existe na
92
+ * lista** — inventar o mais parecido diria uma coisa errada ao leitor de tela, que é exatamente
93
+ * a armadilha que o Lote 5 e a `Table` do Lote 6 já pagaram. Uma linha decorativa calada é o
94
+ * comportamento certo.
95
+ */
96
+ export function Separator({ orientation = "horizontal", label, style, ...rest }) {
97
+ const t = useAureaTokens();
98
+ const s = folha(t);
99
+ if (label != null) {
100
+ return (_jsxs(View, { style: [s.separadorRotulado, style], ...rest, children: [_jsx(View, { style: s.separadorPedaco }), typeof label === "string"
101
+ ? _jsx(Text, { size: "sm", tone: "muted", children: label })
102
+ : label, _jsx(View, { style: s.separadorPedaco })] }));
103
+ }
104
+ return (_jsx(View, { style: [s.separador, orientation === "vertical" ? s.separadorV : s.separadorH, style], ...rest }));
105
+ }
77
106
  /**
78
107
  * Superfície flutuante, raio 22 (`--radius-card`) — identidade declarada INTOCÁVEL.
79
108
  *
package/dist/text.d.ts CHANGED
@@ -7,7 +7,7 @@ export type AureaTextWeight = 400 | 500 | 600 | 700;
7
7
  /** Papel de tipografia — os três `--font-*` da Aurea. */
8
8
  export type AureaTextFont = "ui" | "editorial" | "code";
9
9
  /** O que a cor SIGNIFICA. Mesmo vocabulário do `tone` do Button (ADR-0044). */
10
- export type AureaTextTone = "default" | "muted" | "subtle" | "primary" | "danger" | "success" | "warning" | "info";
10
+ export type AureaTextTone = "default" | "muted" | "subtle" | "primary" | "link" | "danger" | "success" | "warning" | "info";
11
11
  export type AureaTextLeading = "none" | "tight" | "normal" | "relaxed";
12
12
  export interface TextProps extends TextPropsRN {
13
13
  size?: AureaTextSize;
package/dist/text.js CHANGED
@@ -32,7 +32,11 @@ const ENTRELINHA = {
32
32
  };
33
33
  const COR = {
34
34
  default: "foreground", muted: "mutedForeground", subtle: "subtleForeground",
35
- primary: "primary", danger: "destructive", success: "success",
35
+ // ⚠ `primary` e `link` são o MESMO amarelo em matiz, e NÃO são intercambiáveis.
36
+ // `primary` é o amarelo de PREENCHER, e escrito sobre o tema claro ele mede 1,73:1 — some.
37
+ // `link` é o de ESCREVER: mesmo matiz, mais escuro, 5,02:1 no claro, e no escuro é o próprio
38
+ // amarelo da marca. Quem quer texto amarelo legível nos dois temas usa `link`.
39
+ primary: "primary", link: "link", danger: "destructive", success: "success",
36
40
  warning: "warning", info: "info",
37
41
  };
38
42
  // A folha cobre só o que NÃO depende das props — a cor por tom. O resto (tamanho, peso, família)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurea-uds/native",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "description": "React Native target for Aurea UDS: the theme x density provider, the first components and the Carbon icons, drawn on react-native-svg.",
5
5
  "keywords": [
6
6
  "aurea",
@@ -47,7 +47,7 @@
47
47
  "NOTICE"
48
48
  ],
49
49
  "dependencies": {
50
- "@aurea-uds/tokens": "^0.8.2"
50
+ "@aurea-uds/tokens": "^0.8.4"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@react-native-community/datetimepicker": ">=8",