@aurea-uds/native 0.8.11 → 0.8.13

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 } from "./estilos.js";
25
+ import { criarFolha, REACAO_AO_TOQUE } from "./estilos.js";
26
26
  import { Icon } from "./icon.js";
27
27
  import { Text } from "./text.js";
28
28
  import { useAureaTokens, useSobreAMarca } from "./theme.js";
@@ -114,10 +114,9 @@ const folha = criarFolha((t) => ({
114
114
  borderRadius: t.size.radiusControl, // 999 — pill, identidade INTOCÁVEL
115
115
  borderWidth: t.size.borderWidth,
116
116
  },
117
- // `.btn:active { transform:scale(.97); opacity:.9 }` no core — a mesma reação, medida lá.
118
- pressionado: { opacity: 0.9, transform: [{ scale: 0.97 }] },
119
- // `.btn:disabled { opacity:.45 }`
120
- inerte: { opacity: 0.45 },
117
+ // `.btn:active` e `.btn:disabled` do core — os números moram no `estilos.ts` desde que o
118
+ // `Card` com `onPress` passou a reagir igual (R-04, 24/09/2026).
119
+ ...REACAO_AO_TOQUE,
121
120
  }));
122
121
  /**
123
122
  * Botão. `Pressable` do RN, alvo ≥ `--target-min`, pele de token.
package/dist/busca.js CHANGED
@@ -80,7 +80,7 @@ import { useAureaStrings, useAureaTokens, ForaDaMarca, usePeleSobreAMarca } from
80
80
  // tornaria pública uma conta interna do outro módulo, e um `import` de função privada entre
81
81
  // módulos irmãos é o começo de um acoplamento que ninguém declara. São três linhas.
82
82
  const alturaDoTamanho = (t, s) => s === "sm" ? t.size.controlHSm : s === "lg" ? t.size.controlHLg : t.size.controlHMd;
83
- const fonteDoTamanho = (t, s) => s === "sm" ? t.size.textXs : s === "lg" ? t.size.textBase : t.size.textMd;
83
+ const fonteDoTamanho = (t, s) => s === "sm" ? t.size.textSm : s === "lg" ? t.size.textLg : t.size.textBase; // ADR-0050: um degrau acima da web
84
84
  // ⚠ O `13` do tamanho `md` NÃO é número inventado: é o `padding-inline` literal do `.input`
85
85
  // (`aurea.css:685`), e é o mesmo valor que o `inputs.tsx:60` usa. Não há token de 13 — a escala
86
86
  // tem `space3`=12 e `space4`=16 —, e é por isso que o CSS o escreve cru dos dois lados.
package/dist/chart.js CHANGED
@@ -169,7 +169,7 @@ export function Chart({ labels, series, label, mark = "line", height = ALTURA, y
169
169
  return d.trim();
170
170
  };
171
171
  const tocar = (i) => { setTocado(i); onSelect?.(i); };
172
- return (_jsxs(View, { style: [s.caixa, style], testID: testID, children: [_jsxs(View, { onLayout: (e) => setLargura(e.nativeEvent.layout.width), style: { height }, children: [largura > 0 ? (_jsx(View, { accessible: true, accessibilityLabel: nome, children: _jsxs(Svg, { width: largura, height: height, testID: testID ? `${testID}-svg` : undefined, children: [_jsx(G, { children: passos.map((v, i) => (_jsx(Line, { x1: CALHA.esquerda, y1: y(v), x2: largura - CALHA.direita, y2: y(v), stroke: t.color.border, strokeWidth: t.size.borderWidth }, `g${i}`))) }), _jsxs(G, { children: [passos.map((v, i) => (_jsx(SvgText, { x: CALHA.esquerda - 6, y: y(v) + 4, textAnchor: "end", fontSize: t.size.textXs, fontFamily: t.font.ui[400], fill: t.color.mutedForeground, children: formatValue(v) }, `ty${i}`))), labels.map((rotulo, i) => (_jsx(SvgText, { x: x(i), y: height - 6, textAnchor: "middle", fontSize: t.size.textXs, fontFamily: t.font.ui[400], fill: t.color.mutedForeground, children: rotulo }, `tx${i}`)))] }), series.map((serie, n) => {
172
+ return (_jsxs(View, { style: [s.caixa, style], testID: testID, children: [_jsxs(View, { onLayout: (e) => setLargura(e.nativeEvent.layout.width), style: { height }, children: [largura > 0 ? (_jsx(View, { accessible: true, accessibilityLabel: nome, children: _jsxs(Svg, { width: largura, height: height, testID: testID ? `${testID}-svg` : undefined, children: [_jsx(G, { children: passos.map((v, i) => (_jsx(Line, { x1: CALHA.esquerda, y1: y(v), x2: largura - CALHA.direita, y2: y(v), stroke: t.color.border, strokeWidth: t.size.borderWidth }, `g${i}`))) }), _jsxs(G, { children: [passos.map((v, i) => (_jsx(SvgText, { x: CALHA.esquerda - 6, y: y(v) + 4, textAnchor: "end", fontSize: t.size.textSm, fontFamily: t.font.ui[400], fill: t.color.mutedForeground, children: formatValue(v) }, `ty${i}`))), labels.map((rotulo, i) => (_jsx(SvgText, { x: x(i), y: height - 6, textAnchor: "middle", fontSize: t.size.textSm, fontFamily: t.font.ui[400], fill: t.color.mutedForeground, children: rotulo }, `tx${i}`)))] }), series.map((serie, n) => {
173
173
  const marca = serie.mark ?? mark;
174
174
  const cor = cores[n];
175
175
  if (marca === "bar") {
package/dist/estilos.d.ts CHANGED
@@ -30,4 +30,29 @@ export declare function criarFolha<T extends NamedStyles<T> | NamedStyles<Record
30
30
  * do pacote**: é ferramenta de dentro, e o `check 39` cobraria teste de tudo que sai por lá.
31
31
  */
32
32
  export declare const comOpacidade: (cor: string, pct: number) => string;
33
+ /**
34
+ * A reação ao TOQUE de tudo que é alvo inteiro — hoje o `Button`, o `IconButton` e o `Card` com
35
+ * `onPress`. Os números são os do core: `.btn:active { transform:scale(.97); opacity:.9 }` e
36
+ * `.btn:disabled { opacity:.45 }`.
37
+ *
38
+ * ⚠ **Mora aqui desde 24/09/2026 (R-04)**, quando o `Card` passou a responder ao toque e a
39
+ * decisão foi *"a mesma reação do `Button`"*. Copiar os três números para o `layout.tsx` faria
40
+ * duas peças dizerem a mesma coisa em dois lugares — e a primeira que mudasse deixaria a outra
41
+ * para trás. Mesma razão do `comOpacidade` acima, e pelo mesmo motivo **não sai pela porta da
42
+ * frente do pacote**.
43
+ *
44
+ * ⚠ **Não é animação:** não há transição, o alvo SALTA para 0,97 enquanto o dedo está em cima.
45
+ * Por isso ele não consulta `useReduceMotion` — não há movimento para parar.
46
+ */
47
+ export declare const REACAO_AO_TOQUE: {
48
+ readonly pressionado: {
49
+ readonly opacity: 0.9;
50
+ readonly transform: readonly [{
51
+ readonly scale: 0.97;
52
+ }];
53
+ };
54
+ readonly inerte: {
55
+ readonly opacity: 0.45;
56
+ };
57
+ };
33
58
  export {};
package/dist/estilos.js CHANGED
@@ -46,3 +46,21 @@ export function criarFolha(descrever) {
46
46
  export const comOpacidade = (cor, pct) => /^#[0-9a-fA-F]{6}$/.test(cor)
47
47
  ? cor + Math.round(Math.max(0, Math.min(1, pct)) * 255).toString(16).padStart(2, "0")
48
48
  : cor;
49
+ /**
50
+ * A reação ao TOQUE de tudo que é alvo inteiro — hoje o `Button`, o `IconButton` e o `Card` com
51
+ * `onPress`. Os números são os do core: `.btn:active { transform:scale(.97); opacity:.9 }` e
52
+ * `.btn:disabled { opacity:.45 }`.
53
+ *
54
+ * ⚠ **Mora aqui desde 24/09/2026 (R-04)**, quando o `Card` passou a responder ao toque e a
55
+ * decisão foi *"a mesma reação do `Button`"*. Copiar os três números para o `layout.tsx` faria
56
+ * duas peças dizerem a mesma coisa em dois lugares — e a primeira que mudasse deixaria a outra
57
+ * para trás. Mesma razão do `comOpacidade` acima, e pelo mesmo motivo **não sai pela porta da
58
+ * frente do pacote**.
59
+ *
60
+ * ⚠ **Não é animação:** não há transição, o alvo SALTA para 0,97 enquanto o dedo está em cima.
61
+ * Por isso ele não consulta `useReduceMotion` — não há movimento para parar.
62
+ */
63
+ export const REACAO_AO_TOQUE = {
64
+ pressionado: { opacity: 0.9, transform: [{ scale: 0.97 }] },
65
+ inerte: { opacity: 0.45 },
66
+ };
package/dist/index.d.ts CHANGED
@@ -23,7 +23,7 @@ export { defaultStrings, ptBR, gravidadeDoEstado, AUREA_UNIVERSAL_STATES } from
23
23
  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
- export type { BottomNavProps, TopbarProps, NavListProps, StepperProps, AureaNavItem, AureaNavListItem, AureaStepItem, AureaStepState, AureaBottomNavVariant, AureaBottomNavIndicator, AureaTopbarVariant, TabsProps, AureaTabItem, } from "./navigation.js";
26
+ export type { BottomNavProps, TopbarProps, NavListProps, StepperProps, AureaNavItem, AureaNavListItem, AureaStepItem, AureaStepState, AureaBottomNavVariant, AureaBottomNavIndicator, AureaBottomNavWidth, AureaTopbarVariant, TabsProps, AureaTabItem, } from "./navigation.js";
27
27
  export { Field, Label, Input, Textarea, Select, Switch, Checkbox, Radio, SegmentedControl, Form, KeyboardAvoiding, useCampo, } from "./inputs.js";
28
28
  export type { FieldProps, LabelProps, InputProps, TextareaProps, SelectProps, SwitchProps, CheckboxProps, RadioProps, SegmentedControlProps, FormProps, KeyboardAvoidingProps, AureaFieldSize, } from "./inputs.js";
29
29
  export { InputGroup, InputGroupAddon, PasswordField, useGrupoDeCampo } from "./inputs.js";
package/dist/inputs.js CHANGED
@@ -47,7 +47,7 @@ import { useReduceMotion } from "./movimento.js";
47
47
  import { Text } from "./text.js";
48
48
  import { useAureaStrings, useAureaTokens, usePeleSobreAMarca, ForaDaMarca } from "./theme.js";
49
49
  const alturaDoTamanho = (t, s) => s === "sm" ? t.size.controlHSm : s === "lg" ? t.size.controlHLg : t.size.controlHMd;
50
- const fonteDoTamanho = (t, s) => s === "sm" ? t.size.textXs : s === "lg" ? t.size.textBase : t.size.textMd;
50
+ const fonteDoTamanho = (t, s) => s === "sm" ? t.size.textSm : s === "lg" ? t.size.textLg : t.size.textBase; // ADR-0050: um degrau acima da web
51
51
  const respiroDoTamanho = (t, s) => s === "sm" ? t.size.space3 : s === "lg" ? t.size.space4 : 13;
52
52
  const folha = criarFolha((t) => ({
53
53
  campo: { gap: 7 },
package/dist/layout.d.ts CHANGED
@@ -81,15 +81,49 @@ interface CardDaMarca extends CardBase {
81
81
  interface CardComum extends CardBase {
82
82
  variant?: Exclude<AureaCardVariant, "brand">;
83
83
  action?: never;
84
+ onPress?: undefined;
84
85
  }
85
- export type CardProps = CardDaMarca | CardComum;
86
+ /**
87
+ * 🔴 **O cartão que É um alvo — R-04, 24/09/2026.** Até aqui a documentação mandava a tela
88
+ * embrulhar o cartão num `Pressable`, e o consumidor que segue a regra "só Aurea" ficava sem
89
+ * caminho. Agora o toque é do `Card`, e **as duas obrigações que a nota antiga deixava com a tela
90
+ * passam a ser do TIPO:** com `onPress` o nome para o leitor de tela é obrigatório, e o papel de
91
+ * botão vem de dentro. Mesma escolha do `action` do `brand` e do `label` do `IconButton`.
92
+ *
93
+ * ⚠ **E o `brand` NÃO aceita `onPress`, de propósito.** Ele exige `action`, e `action` é um botão
94
+ * DENTRO do cartão — botão dentro de botão, o defeito que o `check 43` barra. No iPhone o de
95
+ * dentro some para o VoiceOver.
96
+ */
97
+ interface CardTocavel extends CardBase {
98
+ variant?: Exclude<AureaCardVariant, "brand">;
99
+ action?: never;
100
+ /** O que acontece ao tocar no cartão. Com isto o cartão inteiro vira UM botão. */
101
+ onPress: () => void;
102
+ /** O nome do cartão para o leitor de tela. Obrigatório com `onPress`: é o que ele anuncia. */
103
+ accessibilityLabel: string;
104
+ disabled?: boolean;
105
+ }
106
+ export type CardProps = CardDaMarca | CardComum | CardTocavel;
86
107
  /**
87
108
  * Superfície flutuante, raio 22 (`--radius-card`) — identidade declarada INTOCÁVEL.
88
109
  *
89
- * ⚠ **`interactive` aqui NÃO responde ao toque sozinho.** Na web ele é a variante que responde ao
90
- * ponteiro; no nativo não há hover, e um cartão que vira alvo precisa de `Pressable` em volta,
91
- * com rótulo e papel de acessibilidade próprios. A variante existe para a **pele** de um cartão
92
- * que É um alvo — quem o torna tocável é a tela.
110
+ * ✅ **O cartão responde ao toque com `onPress`** (R-04, 24/09/2026):
111
+ *
112
+ * ```tsx
113
+ * <Card onPress={abrir} accessibilityLabel="Moto CG 160">…</Card>
114
+ * ```
115
+ *
116
+ * Com `onPress` a variante padrão passa a ser `interactive` — a pele de um cartão que é alvo — e
117
+ * o toque dá a MESMA reação do `Button` (`REACAO_AO_TOQUE`). Sem `onPress`, nada muda: `interactive`
118
+ * continua sendo só a pele.
119
+ *
120
+ * 🔴 **Um cartão com `onPress` NÃO PODE ter coisa tocável dentro** — nem `Button`, nem `Switch`,
121
+ * nem link. O cartão vira UM elemento para o leitor de tela, e no iPhone quem é elemento **não
122
+ * expõe os filhos**: o botão de dentro existiria na tela e não existiria para o VoiceOver. É o
123
+ * defeito que o `check 43` guarda no nosso código, e aqui ele não alcança, porque o conteúdo é
124
+ * do app. ⚠ **O exemplo do HeroUI faz exatamente isso** (`PressableFeedback` em volta de um
125
+ * `Card` com `Button` dentro, `heroui-native@1.0.10`) — é o ponto em que a referência não serve.
126
+ * Cartão com duas ações não tem `onPress`: cada ação é um botão dentro de um cartão comum.
93
127
  */
94
128
  export declare function Card({ variant, style, ...rest }: CardProps): React.JSX.Element;
95
129
  export {};
package/dist/layout.js CHANGED
@@ -12,12 +12,12 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
12
12
  // do `Stack` na web escreve o porquê — *"um primitivo de layout que aceita qualquer espaçamento é
13
13
  // como um sistema deixa de ter espaçamento"*. Reabrir isso no nativo criaria dois sistemas.
14
14
  import * as React from "react";
15
- import { View } from "react-native";
15
+ import { Pressable, View } from "react-native";
16
16
  // `ref` chega por PROPS, sem `forwardRef` — e' o padrao do React 19, e e' o que o
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 } from "./estilos.js";
20
+ import { criarFolha, REACAO_AO_TOQUE } from "./estilos.js";
21
21
  import { Text } from "./text.js";
22
22
  import { useAureaTokens, SobreAMarca } from "./theme.js";
23
23
  const folha = criarFolha((t) => ({
@@ -133,17 +133,38 @@ export function Separator({ orientation = "horizontal", label, style, ...rest })
133
133
  /**
134
134
  * Superfície flutuante, raio 22 (`--radius-card`) — identidade declarada INTOCÁVEL.
135
135
  *
136
- * ⚠ **`interactive` aqui NÃO responde ao toque sozinho.** Na web ele é a variante que responde ao
137
- * ponteiro; no nativo não há hover, e um cartão que vira alvo precisa de `Pressable` em volta,
138
- * com rótulo e papel de acessibilidade próprios. A variante existe para a **pele** de um cartão
139
- * que É um alvo — quem o torna tocável é a tela.
136
+ * ✅ **O cartão responde ao toque com `onPress`** (R-04, 24/09/2026):
137
+ *
138
+ * ```tsx
139
+ * <Card onPress={abrir} accessibilityLabel="Moto CG 160">…</Card>
140
+ * ```
141
+ *
142
+ * Com `onPress` a variante padrão passa a ser `interactive` — a pele de um cartão que é alvo — e
143
+ * o toque dá a MESMA reação do `Button` (`REACAO_AO_TOQUE`). Sem `onPress`, nada muda: `interactive`
144
+ * continua sendo só a pele.
145
+ *
146
+ * 🔴 **Um cartão com `onPress` NÃO PODE ter coisa tocável dentro** — nem `Button`, nem `Switch`,
147
+ * nem link. O cartão vira UM elemento para o leitor de tela, e no iPhone quem é elemento **não
148
+ * expõe os filhos**: o botão de dentro existiria na tela e não existiria para o VoiceOver. É o
149
+ * defeito que o `check 43` guarda no nosso código, e aqui ele não alcança, porque o conteúdo é
150
+ * do app. ⚠ **O exemplo do HeroUI faz exatamente isso** (`PressableFeedback` em volta de um
151
+ * `Card` com `Button` dentro, `heroui-native@1.0.10`) — é o ponto em que a referência não serve.
152
+ * Cartão com duas ações não tem `onPress`: cada ação é um botão dentro de um cartão comum.
140
153
  */
141
- export function Card({ variant = "base", style, ...rest }) {
154
+ export function Card({ variant, style, ...rest }) {
142
155
  const t = useAureaTokens();
143
156
  const s = folha(t);
144
- const { action, children, ...resto } = rest;
157
+ const { action, children, onPress, disabled, ...resto } = rest;
158
+ if (onPress != null) {
159
+ const pele = variant ?? "interactive";
160
+ return (_jsx(Pressable, { onPress: onPress, disabled: disabled, accessibilityRole: "button", accessibilityState: { disabled: !!disabled }, style: ({ pressed: tocando }) => [
161
+ s.cardBase, s[`card_${pele}`],
162
+ tocando && REACAO_AO_TOQUE.pressionado, disabled && REACAO_AO_TOQUE.inerte,
163
+ style,
164
+ ], ...resto, children: children }));
165
+ }
145
166
  const corpo = (_jsxs(_Fragment, { children: [children, action != null && _jsx(View, { style: s.acaoDaMarca, children: action })] }));
146
- const pele = _jsx(View, { style: [s.cardBase, s[`card_${variant}`], style], ...resto, children: corpo });
167
+ const pele = _jsx(View, { style: [s.cardBase, s[`card_${variant ?? "base"}`], style], ...resto, children: corpo });
147
168
  // 🔴 SOBRE O AMARELO A COR DO TEXTO NÃO É ESCOLHA, É OBRIGAÇÃO — e os números decidiram isto.
148
169
  // Medido nos dois temas, texto contra o `primary`:
149
170
  // texto comum ........ 10,34 no claro · **1,83 no escuro** 🔴 ilegível
@@ -11,6 +11,8 @@ export interface AureaNavItem {
11
11
  disabled?: boolean;
12
12
  }
13
13
  export type AureaBottomNavVariant = "floating" | "edge";
14
+ /** Quanto a pílula ocupa: a tela menos a margem (`full`, o de sempre) ou só as abas (`content`). */
15
+ export type AureaBottomNavWidth = "full" | "content";
14
16
  export type AureaBottomNavIndicator = "none" | "subtle" | "pill" | "circle" | "circle-raised" | "circle-outline" | "circle-bold";
15
17
  export interface BottomNavProps extends ViewProps {
16
18
  items: AureaNavItem[];
@@ -18,6 +20,11 @@ export interface BottomNavProps extends ViewProps {
18
20
  current?: string;
19
21
  variant?: AureaBottomNavVariant;
20
22
  indicator?: AureaBottomNavIndicator;
23
+ /**
24
+ * `content` põe a pílula do tamanho das abas, no centro, em vez de ir de uma borda à outra.
25
+ * Vale só no `floating`: a `edge` encosta na borda e continua da largura da tela.
26
+ */
27
+ width?: AureaBottomNavWidth;
21
28
  /** Nome da barra para o leitor de tela. Sem ele, a frase do provider. */
22
29
  label?: string;
23
30
  }
@@ -94,7 +101,7 @@ export interface BottomNavProps extends ViewProps {
94
101
  * usa `Screen` (uma fileira de botões presa no pé, por exemplo), o número está em
95
102
  * `useBottomNavSpace()`. Fora de um provedor os dois valem zero, e nada muda.
96
103
  */
97
- export declare function BottomNav({ items, current, variant, indicator, label, style, ...rest }: BottomNavProps): React.JSX.Element;
104
+ export declare function BottomNav({ items, current, variant, indicator, width, label, style, ...rest }: BottomNavProps): React.JSX.Element;
98
105
  export type AureaTopbarVariant = "floating" | "flush" | "pill";
99
106
  export interface TopbarProps extends ViewProps {
100
107
  variant?: AureaTopbarVariant;
@@ -45,7 +45,7 @@ const folha = criarFolha((t) => ({
45
45
  //
46
46
  // `zSticky` é token (20), o mesmo `--z-sticky` que a web usa na mesma peça.
47
47
  barra: {
48
- position: "absolute", left: 0, right: 0, bottom: 0, zIndex: t.size.zSticky,
48
+ position: "absolute", bottom: 0, zIndex: t.size.zSticky,
49
49
  flexDirection: "row", gap: t.size.space1, margin: t.size.space4, padding: t.size.space1,
50
50
  borderWidth: t.size.borderWidth, borderColor: t.color.border,
51
51
  borderRadius: t.size.radiusControl, backgroundColor: t.color.card,
@@ -58,11 +58,33 @@ const folha = criarFolha((t) => ({
58
58
  margin: 0, paddingHorizontal: 0, borderRadius: 0, backgroundColor: t.color.background,
59
59
  borderWidth: 0, borderTopWidth: t.size.borderWidth, boxShadow: undefined,
60
60
  },
61
+ // A pílula CHEIA, de uma borda à outra menos a margem — o de sempre. Mora fora da `barra` para
62
+ // o `content` nunca precisar DESFAZER estes dois (ver abaixo).
63
+ barra_cheia: { left: 0, right: 0 },
64
+ // 🔴 `width="content"` — R-08, 24/09/2026: *"ficou super largo"*. A pílula deixa de ir de uma
65
+ // borda à outra e fica do tamanho das abas, no centro. Nenhuma conta nossa: medido no Yoga do
66
+ // `react-native@0.87.1`, uma peça `absolute` SEM `left`/`right` se mede pelo conteúdo, limitada
67
+ // à largura do pai (`AbsoluteLayout.cpp`, o ramo `FitContent` de `layoutAbsoluteChild`), e é
68
+ // posicionada pelo `alignSelf` (`alignAbsoluteChild`, o caso `Align::Center`).
69
+ // ⚠ **Por isso `left/right` NÃO podem existir aqui**, e a forma importa: escrever
70
+ // `left: undefined` por cima de um `left: 0` apaga na montagem, mas NÃO numa atualização — o
71
+ // `restoreDeletedValuesInNestedArray` do `ReactNativeAttributePayload.js` pula `undefined` e
72
+ // devolve o valor do item anterior. Trocar `width` com a tela aberta deixaria a pílula cheia.
73
+ barra_content: { alignSelf: "center" },
61
74
  aba: {
62
75
  flex: 1, minWidth: 0, alignItems: "center", justifyContent: "center",
63
76
  gap: t.size.space1, minHeight: t.size.controlHLg, padding: t.size.space1,
64
77
  borderRadius: t.size.radiusControl,
65
78
  },
79
+ // Com a pílula do tamanho do conteúdo, `flex: 1` MATA as abas: no RN ele é base ZERO, e a soma
80
+ // de zeros é uma pílula de largura zero. Aqui cada aba mede o próprio conteúdo (base `auto`) e
81
+ // só encolhe se não couber. O mínimo é o alvo de toque da própria aba, `controlHLg`, para uma
82
+ // aba de rótulo curto não virar um alvo mais estreito que alto; e o respiro dos lados é o
83
+ // `space3` que o `.bottom-nav-content` da web usa na mesma peça.
84
+ aba_content: {
85
+ flexGrow: 0, flexShrink: 1, flexBasis: "auto",
86
+ minWidth: t.size.controlHLg, paddingHorizontal: t.size.space3,
87
+ },
66
88
  // A CAIXA QUE ANCORA O CONTADOR, e ela existe por um defeito visto em tela: pendurado no ITEM,
67
89
  // o número cai no meio do RÓTULO. O `navigation-client.tsx:336` conta a história inteira — o
68
90
  // Victor viu o contador cobrir o nome em 17/08/2026, e a pesquisa (Material 3 e os guias de
@@ -188,7 +210,7 @@ const folha = criarFolha((t) => ({
188
210
  * usa `Screen` (uma fileira de botões presa no pé, por exemplo), o número está em
189
211
  * `useBottomNavSpace()`. Fora de um provedor os dois valem zero, e nada muda.
190
212
  */
191
- export function BottomNav({ items, current, variant = "floating", indicator = "none", label, style, ...rest }) {
213
+ export function BottomNav({ items, current, variant = "floating", indicator = "none", width = "full", label, style, ...rest }) {
192
214
  const t = useAureaTokens();
193
215
  const s = folha(t);
194
216
  const strings = useAureaStrings();
@@ -196,12 +218,13 @@ export function BottomNav({ items, current, variant = "floating", indicator = "n
196
218
  const redondo = indicator.startsWith("circle");
197
219
  const anotar = useAnotarBottomNav();
198
220
  const flutua = variant !== "edge";
221
+ const justa = flutua && width === "content";
199
222
  return (_jsx(View, { accessibilityLabel: label ?? strings.bottomNavLabel,
200
223
  // 🔴 A BARRA CONTA A PRÓPRIA ALTURA — é o que permite o `Screen` reservar o fim da rolagem
201
224
  // sem o app calcular nada. A conta é a pílula (o que o layout mede) mais as DUAS margens
202
225
  // mais a folga do sistema; `edge` conta zero, porque ela fica no fluxo e já encurta a tela.
203
226
  onLayout: anotar == null ? undefined : (e) => anotar(flutua ? e.nativeEvent.layout.height + t.size.space4 * 2 + inset.bottom : 0), style: [
204
- s.barra, variant === "edge" && s.barra_edge,
227
+ s.barra, justa ? s.barra_content : s.barra_cheia, variant === "edge" && s.barra_edge,
205
228
  // 🔴 NO `floating` A FOLGA DO SISTEMA VAI POR FORA — conserto de 19/09/2026, visto em
206
229
  // aparelho Samsung com os três botões (|||, ○, <).
207
230
  //
@@ -229,7 +252,7 @@ export function BottomNav({ items, current, variant = "floating", indicator = "n
229
252
  return (_jsxs(Pressable, { onPress: it.onPress, disabled: it.disabled,
230
253
  // `link` e não `tab`: uma aba troca um painel DESTA tela; isto troca de tela.
231
254
  accessibilityRole: "link", accessibilityState: { selected: ativo, disabled: !!it.disabled }, style: [
232
- s.aba,
255
+ s.aba, justa && s.aba_content,
233
256
  indicator === "subtle" && { borderRadius: t.size.radiusCard - t.size.space1 },
234
257
  ativo && (indicator === "subtle" || indicator === "pill")
235
258
  && { backgroundColor: comOpacidade(t.color.primary, 0.12) },
package/dist/numero.js CHANGED
@@ -51,7 +51,7 @@ import { criarFolha } 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;
54
- const fonteDoTamanho = (t, s) => s === "sm" ? t.size.textXs : s === "lg" ? t.size.textBase : t.size.textMd;
54
+ const fonteDoTamanho = (t, s) => s === "sm" ? t.size.textSm : s === "lg" ? t.size.textLg : t.size.textBase; // ADR-0050: um degrau acima da web
55
55
  const folha = criarFolha((t) => ({
56
56
  // 🔴 ELE ESTICAVA, E NÃO DEVIA — achado em 12/09/2026, olhando a primeira imagem da vitrine.
57
57
  //
package/dist/text.js CHANGED
@@ -53,8 +53,14 @@ import { useAureaTokens, useSobreAMarca } from "./theme.js";
53
53
  // linha ~29. Isso cabe em toda cápsula, MENOS o controle `sm` na densidade compacta (28 de
54
54
  // altura), que estoura por 1 ponto. Em 1,5× vários estouram — e isso já era verdade na escala
55
55
  // antiga.
56
+ // ⚠ **ESCALA DO HEROUI, 24/09/2026 (ADR-0050, que substitui a 0049).** Os NÚMEROS são os da web —
57
+ // 12 · 14 · 16 · 18 · 20 · 24 · 30 · 36 · 48, a escala do Tailwind que o HeroUI usa. O que muda no
58
+ // telefone é o DEGRAU que cada papel pega, e isso também é do HeroUI, lido no pacote deles: na web
59
+ // a peça é `text-sm` (14) e o apoio `text-xs` (12); no HeroUI Native a peça é `text-base` (16) e o
60
+ // apoio `text-sm` (14). Por isso aqui os nomes pequenos sobem UM degrau: o mesmo `size="sm"` que é
61
+ // 14 na web é 16 no telefone. Os componentes não trocam de nome; o mapa é que traduz o papel.
56
62
  const TAMANHO = {
57
- xs: "textXs", sm: "textSm", md: "textMd", base: "textBase", lg: "textLg",
63
+ xs: "textSm", sm: "textBase", md: "textBase", base: "textBase", lg: "textLg",
58
64
  xl: "textXl", "2xl": "text2xl", "3xl": "text3xl", "4xl": "text4xl", "5xl": "text5xl",
59
65
  };
60
66
  const ENTRELINHA = {
@@ -93,7 +99,7 @@ export function Text({ size = "md", weight = 400, font = "ui", tone = "default",
93
99
  const s = folha(t);
94
100
  const sobreAMarca = useSobreAMarca();
95
101
  const proprio = React.useMemo(() => {
96
- const fontSize = t.size[TAMANHO[size]] ?? t.size.textMd;
102
+ const fontSize = t.size[TAMANHO[size]] ?? t.size.textBase;
97
103
  const escala = t.font[font];
98
104
  // O itálico é UMA fonte, não um estilo sintético: `fontStyle:"italic"` faria o sistema
99
105
  // inclinar o desenho reto, e o Plex tem itálico desenhado. Só o `ui` o tem — nos outros
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurea-uds/native",
3
- "version": "0.8.11",
3
+ "version": "0.8.13",
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.11"
50
+ "@aurea-uds/tokens": "^0.8.13"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@react-native-community/datetimepicker": ">=8",