@aurea-uds/native 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/numero.js CHANGED
@@ -50,8 +50,10 @@ import { IconButton } from "./actions.js";
50
50
  import { criarFolha, estadoAcessivel } from "./estilos.js";
51
51
  import { useCampo } from "./inputs.js";
52
52
  import { useAureaStrings, useAureaTokens, usePeleSobreAMarca } from "./theme.js";
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.textSm : s === "lg" ? t.size.textLg : t.size.textBase; // ADR-0050: um degrau acima da web
53
+ const alturaDoTamanho = (t, s) => s === "sm" ? t.size.controlHSm : s === "lg" ? t.size.controlHLg
54
+ : s === "display" ? t.size.controlHXl : t.size.controlHMd;
55
+ const fonteDoTamanho = (t, s) => s === "sm" ? t.size.textSm : s === "lg" ? t.size.textLg
56
+ : s === "display" ? t.size.text3xl : t.size.textBase; // ADR-0050: um degrau acima da web
55
57
  const folha = criarFolha((t) => ({
56
58
  // 🔴 ELE ESTICAVA, E NÃO DEVIA — achado em 12/09/2026, olhando a primeira imagem da vitrine.
57
59
  //
@@ -79,6 +81,7 @@ const folha = criarFolha((t) => ({
79
81
  paddingVertical: 0, textAlignVertical: "center",
80
82
  },
81
83
  campoLargo: { width: undefined, flex: 1, minWidth: t.size.space16 },
84
+ campoDisplay: { width: t.size.space24 },
82
85
  invalido: { borderColor: t.color.danger400 ?? t.color.destructive },
83
86
  desabilitado: { opacity: t.size.opacityDisabled },
84
87
  }));
@@ -250,6 +253,7 @@ export function NumberField({ value, defaultValue, onValueChange, min, max, step
250
253
  const strings = useAureaStrings();
251
254
  const campo = useCampo();
252
255
  const tam = size ?? campo?.size ?? "md";
256
+ const tamDoBotao = tam === "display" ? "lg" : tam;
253
257
  const inativo = disabled ?? campo?.disabled;
254
258
  const [interno, setInterno] = React.useState(defaultValue ?? null);
255
259
  const numero = value !== undefined ? value : interno;
@@ -355,14 +359,15 @@ export function NumberField({ value, defaultValue, onValueChange, min, max, step
355
359
  // (`aurea.css:685`), com os dois botões FORA dela. O estado que faltava é o deles; a geometria
356
360
  // continua sendo a nossa.
357
361
  const [focado, setFocado] = React.useState(false);
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,
362
+ 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: tamDoBotao, 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
363
  // O nome vem do `Field`, como em todo controle deste pacote — e `label` cobre quem usa o
360
364
  // campo solto. Sem um dos dois, é um nó anônimo para o leitor de tela.
361
365
  accessibilityLabel: label ?? campo?.label, accessibilityHint: campo?.hint, ...estadoAcessivel({ disabled: !!inativo }), "aria-invalid": campo?.invalido, style: [
362
366
  s.campo,
367
+ tam === "display" && s.campoDisplay,
363
368
  fullWidth && s.campoLargo,
364
369
  { height: alturaDoTamanho(t, tam), fontSize: fonteDoTamanho(t, tam),
365
- fontFamily: t.font.ui[400], color: t.color.foreground },
370
+ fontFamily: t.font.ui[tam === "display" ? 600 : 400], color: t.color.foreground },
366
371
  campo?.invalido && s.invalido,
367
372
  // A ORDEM IMPORTA e é a mesma do `Input` do Lote 4: o inválido vem antes, o foco
368
373
  // depois. Um campo inválido que está sendo corrigido tem de mostrar que está ativo —
@@ -373,5 +378,5 @@ export function NumberField({ value, defaultValue, onValueChange, min, max, step
373
378
  // O foco continua existindo, por espessura.
374
379
  peleDaMarca,
375
380
  peleDaMarca && focado && { borderWidth: t.size.borderWidth * 2 },
376
- ] }), mostrarBotoes && (_jsx(IconButton, { name: icons.increment, label: strings.increment, appearance: "ghost", size: tam, disabled: inativo || noLimite(1), onPress: () => empurrar(1), testID: testID ? `${testID}-mais` : undefined }))] }));
381
+ ] }), mostrarBotoes && (_jsx(IconButton, { name: icons.increment, label: strings.increment, appearance: "ghost", size: tamDoBotao, disabled: inativo || noLimite(1), onPress: () => empurrar(1), testID: testID ? `${testID}-mais` : undefined }))] }));
377
382
  }
package/dist/overlays.js CHANGED
@@ -63,7 +63,7 @@ import { IconButton } from "./actions.js";
63
63
  import { RecuoDaFolha } from "./screen.js";
64
64
  import { Text } from "./text.js";
65
65
  import { useAureaStrings, useAureaTokens, ForaDaMarca } from "./theme.js";
66
- import { useReduceMotion } from "./movimento.js";
66
+ import { useReduceMotion, driverNativo } from "./movimento.js";
67
67
  const folha = criarFolha((t) => ({
68
68
  fundo: { flex: 1, backgroundColor: t.color.overlay },
69
69
  // 🔴 O FUNDO TOCÁVEL VIROU IRMÃO, NÃO ANCESTRAL — 10/09/2026, e a razão está no bloco
@@ -226,7 +226,7 @@ export function Drawer({ open, title, children, onClose, side = "right", scroll
226
226
  return;
227
227
  }
228
228
  const laco = Animated.timing(progresso, {
229
- toValue: 1, duration: DURACAO, useNativeDriver: true,
229
+ toValue: 1, duration: DURACAO, useNativeDriver: driverNativo(),
230
230
  easing: Easing.bezier(...t.easing.easeEmphasized),
231
231
  });
232
232
  laco.start();
@@ -289,7 +289,7 @@ export function BottomSheet({ open, title, children, onClose, grabber = true, dr
289
289
  return;
290
290
  }
291
291
  Animated.timing(arrasto, {
292
- toValue: 0, duration: DURACAO, useNativeDriver: true,
292
+ toValue: 0, duration: DURACAO, useNativeDriver: driverNativo(),
293
293
  easing: Easing.bezier(...t.easing.easeEmphasized),
294
294
  }).start();
295
295
  },
package/dist/sistema.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { type StyleProp, type ViewStyle } from "react-native";
3
- import { type IconName } from "./icon.js";
3
+ import { type AureaIcon } from "./icon.js";
4
4
  import { type AureaFieldSize } from "./inputs.js";
5
5
  export interface DatePickerProps {
6
6
  value?: Date;
@@ -14,7 +14,7 @@ export interface DatePickerProps {
14
14
  /** Como a data vira texto no gatilho. Padrão: o formato do aparelho. */
15
15
  format?: (d: Date) => string;
16
16
  placeholder?: string;
17
- icon?: IconName | false;
17
+ icon?: AureaIcon | false;
18
18
  style?: StyleProp<ViewStyle>;
19
19
  testID?: string;
20
20
  }
@@ -56,8 +56,8 @@ export interface PhotoInputProps {
56
56
  offerSettings?: boolean;
57
57
  /** Avisado quando a permissão foi negada — o app pode querer contar uma história própria. */
58
58
  onPermissionDenied?: () => void;
59
- addIcon?: IconName | false;
60
- removeIcon?: IconName;
59
+ addIcon?: AureaIcon | false;
60
+ removeIcon?: AureaIcon;
61
61
  style?: StyleProp<ViewStyle>;
62
62
  testID?: string;
63
63
  }
@@ -78,5 +78,17 @@ export interface PhotoInputProps {
78
78
  * | **quantas** cabem? | uma | `max` |
79
79
  *
80
80
  * ⚠ **O gatilho some quando o limite é atingido**, em vez de ficar aceso e não fazer nada.
81
+ *
82
+ * **R-22 (02/10/2026), achado do app: a pessoa não conseguia OLHAR a foto que escolheu.** A
83
+ * miniatura era um `Avatar` redondo de 42, sem toque, e o X (sem fundo, só 8 para fora) cobria
84
+ * metade dela. Agora, na "B" da prancha escolhida pelo Victor:
85
+ *
86
+ * | | |
87
+ * |---|---|
88
+ * | miniatura | quadrada de 64, a `Image` da `Gallery` (o `Avatar` `lg` do HeroUI) |
89
+ * | tocar nela | abre a foto grande, no MESMO zoom da `Gallery` (`FotoAmpliada`) |
90
+ * | o X | com fundo, TODO fora da foto, no canto de cima à direita |
91
+ * | leitor de tela | *"Foto 2 de 3"* (com uma só, *"Foto"*) e *"Abre a foto"*; o X, *"Remover foto 2"* |
92
+ * | inativo | a foto ainda abre (olhar não muda nada); o X não remove |
81
93
  */
82
94
  export declare function PhotoInput({ value, onChange, max, source, disabled, offerSettings, onPermissionDenied, addIcon, removeIcon, style, testID, }: PhotoInputProps): React.JSX.Element;
package/dist/sistema.js CHANGED
@@ -35,11 +35,11 @@ import { Linking, Platform, Pressable, View } from "react-native";
35
35
  import RNDateTimePicker, { DateTimePickerAndroid } from "@react-native-community/datetimepicker";
36
36
  import * as ImagePicker from "expo-image-picker";
37
37
  import { IconButton } from "./actions.js";
38
- import { Avatar } from "./display.js";
39
38
  import { criarFolha, estadoAcessivel } from "./estilos.js";
40
39
  import { Alert } from "./feedback.js";
41
40
  import { Icon } from "./icon.js";
42
41
  import { useCampo } from "./inputs.js";
42
+ import { FotoAmpliada, Image } from "./midia.js";
43
43
  import { Text } from "./text.js";
44
44
  import { useAureaStrings, useAureaTokens } from "./theme.js";
45
45
  const folha = criarFolha((t) => ({
@@ -50,16 +50,28 @@ const folha = criarFolha((t) => ({
50
50
  },
51
51
  invalido: { borderColor: t.color.danger400 ?? t.color.destructive },
52
52
  desabilitado: { opacity: t.size.opacityDisabled },
53
- galeria: { flexDirection: "row", flexWrap: "wrap", gap: t.size.space2 },
54
- miniatura: { position: "relative" },
55
- remover: { position: "absolute", top: -t.size.space2, right: -t.size.space2 },
53
+ // R-22 (02/10/2026), a "B" da prancha: miniatura QUADRADA de 64 — o `Avatar` `lg` do HeroUI
54
+ // Native, e a medida que o botão de pôr foto passou a ter também (era 72, número à mão) — e o X
55
+ // TODO FORA da foto. O X é o `IconButton` `sm` (30) com fundo; a área de toque dele é de 44
56
+ // (`targetMin`), com o desenho no centro, então o deslocamento que põe o canto do DESENHO no
57
+ // canto da foto é (30 + 44) / 2. A grade deixa esse espaço em cima, à direita e entre as linhas,
58
+ // porque no Android o toque fora da caixa do pai não chega.
59
+ galeria: {
60
+ flexDirection: "row", flexWrap: "wrap", columnGap: t.size.space4,
61
+ rowGap: foraDoX(t) + t.size.space2,
62
+ },
63
+ comX: { paddingTop: foraDoX(t), paddingRight: foraDoX(t) },
64
+ miniatura: { position: "relative", width: t.size.space16 },
65
+ remover: { position: "absolute", top: -foraDoX(t), right: -foraDoX(t) },
56
66
  adicionar: {
57
67
  alignItems: "center", justifyContent: "center", gap: t.size.space1,
58
- width: 72, height: 72, borderRadius: t.size.radiusMd,
68
+ width: t.size.space16, height: t.size.space16, borderRadius: t.size.radiusLg,
59
69
  borderWidth: t.size.borderWidth, borderColor: t.color.borderStrong,
60
70
  borderStyle: "dashed", backgroundColor: t.color.fieldBg,
61
71
  },
62
72
  }));
73
+ /** Quanto o X do `PhotoInput` sai da foto: metade do desenho (30) mais metade do alvo (44). */
74
+ const foraDoX = (t) => (t.size.controlHSm + Math.max(t.size.controlHSm, t.size.targetMin)) / 2;
63
75
  const alturaDoTamanho = (t, s) => s === "sm" ? t.size.controlHSm : s === "lg" ? t.size.controlHLg : t.size.controlHMd;
64
76
  /**
65
77
  * O campo de data — **a nossa pele, o calendário DELES**.
@@ -133,6 +145,18 @@ export function DatePicker({ value, onChange, mode = "date", minimumDate, maximu
133
145
  * | **quantas** cabem? | uma | `max` |
134
146
  *
135
147
  * ⚠ **O gatilho some quando o limite é atingido**, em vez de ficar aceso e não fazer nada.
148
+ *
149
+ * **R-22 (02/10/2026), achado do app: a pessoa não conseguia OLHAR a foto que escolheu.** A
150
+ * miniatura era um `Avatar` redondo de 42, sem toque, e o X (sem fundo, só 8 para fora) cobria
151
+ * metade dela. Agora, na "B" da prancha escolhida pelo Victor:
152
+ *
153
+ * | | |
154
+ * |---|---|
155
+ * | miniatura | quadrada de 64, a `Image` da `Gallery` (o `Avatar` `lg` do HeroUI) |
156
+ * | tocar nela | abre a foto grande, no MESMO zoom da `Gallery` (`FotoAmpliada`) |
157
+ * | o X | com fundo, TODO fora da foto, no canto de cima à direita |
158
+ * | leitor de tela | *"Foto 2 de 3"* (com uma só, *"Foto"*) e *"Abre a foto"*; o X, *"Remover foto 2"* |
159
+ * | inativo | a foto ainda abre (olhar não muda nada); o X não remove |
136
160
  */
137
161
  export function PhotoInput({ value = [], onChange, max = 1, source = "camera", disabled, offerSettings = true, onPermissionDenied, addIcon = "camera", removeIcon = "x", style, testID, }) {
138
162
  const t = useAureaTokens();
@@ -141,7 +165,12 @@ export function PhotoInput({ value = [], onChange, max = 1, source = "camera", d
141
165
  const campo = useCampo();
142
166
  const inativo = disabled ?? campo?.disabled;
143
167
  const [negadoDeVez, setNegadoDeVez] = React.useState(false);
168
+ const [aberta, setAberta] = React.useState(null);
144
169
  const cheio = value.length >= max;
170
+ // "Foto 2 de 3": a posição entre as que EXISTEM, e não entre as que cabem (`max`).
171
+ const nomeDa = (n) => value.length > 1
172
+ ? `${strings.photo} ${n + 1} ${strings.positionOf} ${value.length}` : strings.photo;
173
+ const fotoAberta = aberta != null ? value[aberta] : undefined;
145
174
  const escolher = React.useCallback(async () => {
146
175
  if (source === "camera") {
147
176
  const atual = await ImagePicker.getCameraPermissionsAsync();
@@ -166,5 +195,7 @@ export function PhotoInput({ value = [], onChange, max = 1, source = "camera", d
166
195
  .map((a) => ({ uri: a.uri, width: a.width, height: a.height }));
167
196
  onChange?.([...value, ...novas]);
168
197
  }, [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, ...estadoAcessivel({ disabled: !!inativo }), style: [s.adicionar, inativo && s.desabilitado], children: addIcon && _jsx(Icon, { name: addIcon, size: "lg", color: t.color.subtleForeground }) }))] })] }));
198
+ 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, value.length > 0 && s.comX], children: [value.map((foto, n) => (_jsxs(View, { style: s.miniatura, children: [_jsx(Pressable, { onPress: () => setAberta(n), accessibilityRole: "imagebutton", accessibilityLabel: nomeDa(n), accessibilityHint: strings.photoOpen, children: _jsx(Image, { source: foto.uri, alt: "", ratio: 1 }) }), _jsx(View, { style: s.remover, children: _jsx(IconButton, { appearance: "solid", size: "sm", name: removeIcon, label: `${strings.photoRemove} ${n + 1}`, disabled: inativo, onPress: () => onChange?.(value.filter((_, i) => i !== n)) }) })] }, `${foto.uri}-${n}`))), !cheio && (_jsx(Pressable, { onPress: inativo ? undefined : escolher, disabled: inativo, accessibilityRole: "button", accessibilityLabel: campo?.label ?? strings.photoAdd, ...estadoAcessivel({ disabled: !!inativo }), style: [s.adicionar, inativo && s.desabilitado], children: addIcon && _jsx(Icon, { name: addIcon, size: "lg", color: t.color.subtleForeground }) }))] }), _jsx(FotoAmpliada, { source: fotoAberta?.uri, title: aberta != null ? nomeDa(aberta) : "", alt: aberta != null ? nomeDa(aberta) : "",
199
+ // A proporção da foto, quando a câmera a deu: a grande aparece inteira, sem tarja à toa.
200
+ ratio: fotoAberta?.width && fotoAberta.height ? fotoAberta.width / fotoAberta.height : 1, onClose: () => setAberta(null) })] }));
170
201
  }
package/dist/strings.d.ts CHANGED
@@ -32,8 +32,18 @@ export interface AureaStrings {
32
32
  cameraDenied: string;
33
33
  /** O botão que leva às configurações do app. */
34
34
  openSettings: string;
35
- /** O rótulo do botão que tira uma foto anexada. */
35
+ /** O rótulo do botão que tira uma foto anexada. O número da foto vem depois (R-22). */
36
36
  photoRemove: string;
37
+ /**
38
+ * O nome de cada miniatura do `PhotoInput` (R-22): *"Foto 2 de 3"* — com uma foto só, só
39
+ * *"Foto"*. O `positionOf` é a mesma chave da web.
40
+ */
41
+ photo: string;
42
+ positionOf: string;
43
+ /** O que a miniatura faz, dito pelo leitor de tela depois do nome (R-22). */
44
+ photoOpen: string;
45
+ /** O nome do botão de pôr foto quando ele não está num `Field` (R-22): sem isto, ficava mudo. */
46
+ photoAdd: string;
37
47
  /**
38
48
  * O botão que revela a senha no `PasswordField`, e o que a esconde de volta. Mesmos nomes da
39
49
  * web (`pure.tsx`), porque é a mesma peça com a mesma decisão: **o rótulo é que anuncia o
@@ -83,6 +93,17 @@ export interface AureaStrings {
83
93
  searchClear: string;
84
94
  /** O nome da grade de fotos da `Gallery`. Mesmo nome da web. */
85
95
  galleryLabel: string;
96
+ /**
97
+ * O texto do gatilho do `FileInput` (R-21). **Não existe na web**: lá a área de soltar diz
98
+ * *"Arraste arquivos aqui ou clique para selecionar"*, e no telefone não há o que arrastar.
99
+ */
100
+ fileChoose: string;
101
+ /** O botão que tira um arquivo escolhido; o nome do arquivo vem depois. Mesmo nome da web. */
102
+ fileRemove: string;
103
+ /** O aviso do arquivo maior que o `maxSize`. Mesmo nome — e mesma frase — da web. */
104
+ fileTooLarge: string;
105
+ /** O aviso do arquivo de um tipo que o `accept` não aceita. Mesmo nome e frase da web. */
106
+ fileWrongType: string;
86
107
  /** A frase de cada estado universal. */
87
108
  universalState: Record<AureaUniversalState, string>;
88
109
  }
package/dist/strings.js CHANGED
@@ -38,6 +38,10 @@ export const defaultStrings = {
38
38
  cameraDenied: "Camera access is off. Turn it on in Settings to attach a photo.",
39
39
  openSettings: "Open Settings",
40
40
  photoRemove: "Remove photo",
41
+ photo: "Photo",
42
+ positionOf: "of",
43
+ photoOpen: "Opens the photo",
44
+ photoAdd: "Add photo",
41
45
  passwordShow: "Show password",
42
46
  passwordHide: "Hide password",
43
47
  close: "Close",
@@ -56,6 +60,10 @@ export const defaultStrings = {
56
60
  comboboxSearch: "Search",
57
61
  searchClear: "Clear search",
58
62
  galleryLabel: "Gallery",
63
+ fileChoose: "Choose file",
64
+ fileRemove: "Remove",
65
+ fileTooLarge: "File exceeds the size limit",
66
+ fileWrongType: "File type not allowed",
59
67
  universalState: {
60
68
  waiting_user: "Waiting for someone to act.",
61
69
  waiting_approval: "Waiting for approval.",
@@ -78,6 +86,10 @@ export const ptBR = {
78
86
  cameraDenied: "O acesso à câmera está desligado. Ligue nas configurações para anexar uma foto.",
79
87
  openSettings: "Abrir configurações",
80
88
  photoRemove: "Remover foto",
89
+ photo: "Foto",
90
+ positionOf: "de",
91
+ photoOpen: "Abre a foto",
92
+ photoAdd: "Adicionar foto",
81
93
  passwordShow: "Mostrar senha",
82
94
  passwordHide: "Ocultar senha",
83
95
  close: "Fechar",
@@ -96,6 +108,10 @@ export const ptBR = {
96
108
  comboboxSearch: "Buscar",
97
109
  searchClear: "Limpar busca",
98
110
  galleryLabel: "Galeria",
111
+ fileChoose: "Escolher arquivo",
112
+ fileRemove: "Remover",
113
+ fileTooLarge: "Arquivo maior que o limite",
114
+ fileWrongType: "Tipo de arquivo não aceito",
99
115
  universalState: {
100
116
  waiting_user: "Esperando alguém agir.",
101
117
  waiting_approval: "Esperando aprovação.",
package/dist/text.js CHANGED
@@ -3,7 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  //
4
4
  // É o **bloqueio 3** da §5.2 do NATIVE.md, e a razão dele é estrutural, não de escopo:
5
5
  //
6
- // web: body { font-family:var(--font-ui); font-size:var(--text-md);
6
+ // web: body { font-family:var(--font-ui); font-size:var(--text-sm);
7
7
  // line-height:var(--leading-normal) } ← e TODO <p>/<span>/<h1> herda
8
8
  // nativo: não há cascata de estilo de texto através de `View`, e não há `<p>`.
9
9
  //
package/dist/toast.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { type StyleProp, type ViewStyle } from "react-native";
3
- import { type IconName } from "./icon.js";
3
+ import { type AureaIcon } from "./icon.js";
4
4
  import { type AureaAlertVariant } from "./feedback.js";
5
5
  /** As mesmas quatro faces do `AureaToastType` da web (`system.tsx:65`). */
6
6
  export type AureaToastType = AureaAlertVariant;
@@ -17,7 +17,7 @@ export interface AureaToastInput {
17
17
  /** Uma ação curta — "Desfazer". Ver o aviso sobre `duration` acima. */
18
18
  action?: React.ReactNode;
19
19
  /** Deixe de fora para não desenhar ícone nenhum; sem isto vem o do tipo. */
20
- icon?: IconName | false;
20
+ icon?: AureaIcon | false;
21
21
  }
22
22
  export interface AureaToast extends AureaToastInput {
23
23
  id: string;
package/dist/toast.js CHANGED
@@ -60,7 +60,7 @@ import { IconButton } from "./actions.js";
60
60
  import { criarFolha } from "./estilos.js";
61
61
  import { Icon } from "./icon.js";
62
62
  import { ICONE_DA_VARIANTE } from "./feedback.js";
63
- import { useReduceMotion } from "./movimento.js";
63
+ import { useReduceMotion, driverNativo } from "./movimento.js";
64
64
  import { Text } from "./text.js";
65
65
  import { useAureaStrings, useAureaTokens } from "./theme.js";
66
66
  const folha = criarFolha((t) => ({
@@ -185,7 +185,7 @@ export function Toast({ toast, onClose }) {
185
185
  return;
186
186
  }
187
187
  const laco = Animated.timing(entrada, {
188
- toValue: 1, duration: ENTRADA, useNativeDriver: true,
188
+ toValue: 1, duration: ENTRADA, useNativeDriver: driverNativo(),
189
189
  easing: Easing.bezier(...t.easing.easeEmphasized),
190
190
  });
191
191
  laco.start();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurea-uds/native",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "A Aurea UDS para React Native: o provider de tema e densidade, os componentes e os ícones do Phosphor sobre react-native-svg.",
5
5
  "keywords": [
6
6
  "aurea",
@@ -36,6 +36,10 @@
36
36
  "types": "./dist/sistema.d.ts",
37
37
  "import": "./dist/sistema.js"
38
38
  },
39
+ "./system/file": {
40
+ "types": "./dist/arquivo.d.ts",
41
+ "import": "./dist/arquivo.js"
42
+ },
39
43
  "./icons": {
40
44
  "types": "./icons/index.d.ts",
41
45
  "import": "./icons/index.js"
@@ -51,10 +55,11 @@
51
55
  "NOTICE"
52
56
  ],
53
57
  "dependencies": {
54
- "@aurea-uds/tokens": "^0.13.0"
58
+ "@aurea-uds/tokens": "^0.15.0"
55
59
  },
56
60
  "peerDependencies": {
57
61
  "@react-native-community/datetimepicker": ">=8",
62
+ "expo-document-picker": ">=12",
58
63
  "expo-image-picker": ">=16",
59
64
  "react": ">=19",
60
65
  "react-native": ">=0.76",
@@ -64,6 +69,7 @@
64
69
  "devDependencies": {
65
70
  "@phosphor-icons/core": "2.1.1",
66
71
  "@react-native-community/datetimepicker": "9.1.0",
72
+ "expo-document-picker": "57.0.3",
67
73
  "expo-image-picker": "57.0.15",
68
74
  "react": "^19.2.0",
69
75
  "react-native": "^0.87.1",
@@ -74,6 +80,9 @@
74
80
  "@react-native-community/datetimepicker": {
75
81
  "optional": true
76
82
  },
83
+ "expo-document-picker": {
84
+ "optional": true
85
+ },
77
86
  "expo-image-picker": {
78
87
  "optional": true
79
88
  }