@aurea-uds/native 0.30.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions.d.ts +15 -1
- package/dist/actions.js +40 -17
- package/dist/busca.js +16 -14
- package/dist/display.js +17 -3
- package/dist/escolha.d.ts +121 -0
- package/dist/escolha.js +466 -0
- package/dist/exibicao.d.ts +188 -0
- package/dist/exibicao.js +457 -0
- package/dist/feedback.d.ts +48 -4
- package/dist/feedback.js +92 -28
- package/dist/icon-names.d.ts +7 -1
- package/dist/icon-names.js +2 -0
- package/dist/icon.d.ts +6 -4
- package/dist/icon.js +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.js +10 -1
- package/dist/inputs.d.ts +12 -3
- package/dist/inputs.js +71 -25
- package/dist/layout.d.ts +1 -1
- package/dist/layout.js +3 -0
- package/dist/menu.d.ts +99 -0
- package/dist/menu.js +452 -0
- package/dist/navigation.d.ts +1 -1
- package/dist/navigation.js +35 -18
- package/dist/numero.d.ts +2 -2
- package/dist/numero.js +6 -2
- package/dist/overlays.js +35 -9
- package/dist/sistema.js +15 -10
- package/dist/strings.d.ts +4 -0
- package/dist/strings.js +4 -0
- package/dist/text.js +7 -1
- package/dist/toast.js +9 -12
- package/icons/index.d.ts +1 -0
- package/icons/index.js +2 -1
- package/icons/x-bold.d.ts +6 -0
- package/icons/x-bold.js +10 -0
- package/package.json +2 -2
package/dist/menu.js
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Aurea nativo — `Popover` e `DropdownMenu`: a camada que abre PRESA ao gatilho (0.32.0).
|
|
3
|
+
//
|
|
4
|
+
// Os nomes e a API são os da web (`overlays.tsx` do `@aurea-uds/react`): `trigger` é um elemento,
|
|
5
|
+
// `side` escolhe o lado, `arrow` liga a seta do `Popover`, e o menu recebe `items` na MESMA união
|
|
6
|
+
// `MenuEntry`. A anatomia, as medidas e o comportamento são os do pacote NATIVO da referência (o
|
|
7
|
+
// `Popover` e o `Menu` dela); a pele é a da Aurea — fundo `popover`, borda, canto 22 e sombra LG, a
|
|
8
|
+
// mesma superfície do `Dialog`.
|
|
9
|
+
//
|
|
10
|
+
// ── O QUE MUDA NA TRAVESSIA ──────────────────────────────────────────────────────────────────
|
|
11
|
+
// a web (Base UI) | aqui
|
|
12
|
+
// ------------------------------|------------------------------------------------------------
|
|
13
|
+
// portal + posicionador | o `Modal` do RN (a janela de cima, sem dependência nova) e a
|
|
14
|
+
// | conta de posição nossa, a partir do `measureInWindow` do gatilho
|
|
15
|
+
// `Escape` fecha | `onRequestClose` (o VOLTAR do Android) e `onAccessibilityEscape`
|
|
16
|
+
// | (o gesto de saída do VoiceOver, que o `Modal` não ouve)
|
|
17
|
+
// clique fora fecha | o fundo tocável, IRMÃO do painel — a lição do `overlays.tsx`
|
|
18
|
+
// submenu ao lado | abre NO LUGAR, dentro do mesmo painel, como o da referência:
|
|
19
|
+
// | num telefone não há "ao lado"
|
|
20
|
+
// `menuitemcheckbox`/`radio` | `checkbox` e `radio`: o RN não tem os papéis de menu com marca
|
|
21
|
+
//
|
|
22
|
+
// ⚠ **A posição não está medida em aparelho.** O `measureInWindow` do gatilho e o `Modal` com
|
|
23
|
+
// `statusBarTranslucent` precisam contar do MESMO zero (o topo da tela). Com a tela de ponta a ponta
|
|
24
|
+
// do Android (o padrão das versões novas) contam; num app sem ela, o painel pode sair deslocado pela
|
|
25
|
+
// altura da barra de status. É pergunta para o `apps/native-smoke`, não para o dublê.
|
|
26
|
+
import * as React from "react";
|
|
27
|
+
import { Animated, Easing, Linking, Modal, Pressable, ScrollView, View, useWindowDimensions, } from "react-native";
|
|
28
|
+
import Svg, { Path } from "react-native-svg";
|
|
29
|
+
import { SafeAreaInsetsContext, initialWindowMetrics } from "react-native-safe-area-context";
|
|
30
|
+
import { canto, criarFolha, estadoAcessivel, letraDoToken } from "./estilos.js";
|
|
31
|
+
import { Icon } from "./icon.js";
|
|
32
|
+
import { Text } from "./text.js";
|
|
33
|
+
import { ForaDaMarca, useTokensDoApp } from "./theme.js";
|
|
34
|
+
import { useReduceMotion, driverNativo } from "./movimento.js";
|
|
35
|
+
// ─────────────────────────────────────────────────────────────────────────────────────────────
|
|
36
|
+
// A folha
|
|
37
|
+
// ─────────────────────────────────────────────────────────────────────────────────────────────
|
|
38
|
+
// Medidas do pacote nativo da referência, escritas com o token que dá o mesmo número. Onde a escala
|
|
39
|
+
// da Aurea não tem o número dela, vale o token mais perto, e a linha diz qual era.
|
|
40
|
+
const folha = criarFolha((t) => ({
|
|
41
|
+
camada: { flex: 1 },
|
|
42
|
+
fundoDeToque: { position: "absolute", top: 0, right: 0, bottom: 0, left: 0 },
|
|
43
|
+
painel: {
|
|
44
|
+
position: "absolute",
|
|
45
|
+
backgroundColor: t.color.popover,
|
|
46
|
+
borderWidth: t.size.borderWidth, borderColor: t.color.border,
|
|
47
|
+
...canto(t.size.radiusCard),
|
|
48
|
+
boxShadow: [...t.shadowLayers.shadowLg],
|
|
49
|
+
},
|
|
50
|
+
// O `Popover` da referência: 12 em cima e embaixo, 16 dos lados.
|
|
51
|
+
painelPopover: { paddingVertical: t.size.space3, paddingHorizontal: t.size.space4 },
|
|
52
|
+
// O `Menu` da referência: 12 em cima e embaixo; dos lados ela usa 6, que a escala não tem — vale
|
|
53
|
+
// o `space1` (4), o recheio do `.menu` da web. O texto do item continua a 16 da borda (4 + 12).
|
|
54
|
+
painelMenu: { paddingVertical: t.size.space3, paddingHorizontal: t.size.space1 },
|
|
55
|
+
// O título do `Popover`: 18 em peso médio (no componente), e 4 até o corpo — o `gap-1` do exemplo
|
|
56
|
+
// da referência.
|
|
57
|
+
titulo: { marginBottom: t.size.space1 },
|
|
58
|
+
// A lista rola quando passa da janela; sem crescer, para o painel ter o tamanho do conteúdo.
|
|
59
|
+
rolagem: { flexGrow: 0, flexShrink: 1 },
|
|
60
|
+
// O item: 8 em cima e embaixo, como o dela. Dos lados ela usa 10 e entre as peças 10, que a escala
|
|
61
|
+
// não tem: aqui 12 (o texto fica a 16 da borda, o mesmo número dela) e 8. ⚠ A altura dela é 40
|
|
62
|
+
// (8 + a linha de 24 + 8); aqui o mínimo é o `targetMin` (44), e não `hitSlop` — o `actions.tsx`
|
|
63
|
+
// mediu que o TalkBack não enxerga o `hitSlop`.
|
|
64
|
+
item: {
|
|
65
|
+
minHeight: t.size.targetMin, flexDirection: "row", alignItems: "center",
|
|
66
|
+
gap: t.size.space2, paddingVertical: t.size.space2, paddingHorizontal: t.size.space3,
|
|
67
|
+
...canto(t.size.radiusLg),
|
|
68
|
+
},
|
|
69
|
+
// O toque: o fundo de destaque do `.menu-item` da web (`surface-3`) e o 0,98 da referência; no item
|
|
70
|
+
// que destrói, o fundo suave do perigo, como o dela.
|
|
71
|
+
itemTocando: { backgroundColor: t.color.surface3, transform: [{ scale: 0.98 }] },
|
|
72
|
+
itemTocandoPerigo: { backgroundColor: t.color.dangerBg, transform: [{ scale: 0.98 }] },
|
|
73
|
+
desabilitado: { opacity: t.size.opacityDisabled },
|
|
74
|
+
// Cresce, mas sem `flex: 1`: com base zero, num painel que tem a largura do conteúdo, o rótulo
|
|
75
|
+
// não empurraria a largura e quebraria letra a letra.
|
|
76
|
+
rotulo: { flexGrow: 1, flexShrink: 1, minWidth: 0 },
|
|
77
|
+
// A casa da marca: a caixa de 20 do indicador da referência, com o `check` de 16 — a mesma do
|
|
78
|
+
// `Select`. Largura FIXA, como o `.menu-mark` da web: o rótulo não anda quando a marca aparece.
|
|
79
|
+
indicador: { width: t.size.iconMd, height: t.size.iconMd, alignItems: "center", justifyContent: "center" },
|
|
80
|
+
// O ponto do rádio: 8, o da referência e o `.menu-ponto` da web. Forma, não ícone.
|
|
81
|
+
ponto: {
|
|
82
|
+
width: t.size.space2, height: t.size.space2, ...canto(t.size.radiusFull),
|
|
83
|
+
backgroundColor: t.color.primaryEmphasis,
|
|
84
|
+
},
|
|
85
|
+
// O rótulo de seção: 14 em peso médio e esmaecido (no componente), alinhado ao texto dos itens.
|
|
86
|
+
rotuloDoGrupo: { paddingHorizontal: t.size.space3, paddingTop: t.size.space2, paddingBottom: t.size.space1 },
|
|
87
|
+
separador: {
|
|
88
|
+
height: t.size.borderWidth, marginVertical: t.size.space2, marginHorizontal: t.size.space2,
|
|
89
|
+
backgroundColor: t.color.border,
|
|
90
|
+
},
|
|
91
|
+
// O submenu aberto é uma superfície acima do menu, como o da referência: o fundo, a linha e a
|
|
92
|
+
// sombra numa camada própria ATRÁS das linhas. Ela nasce já pintada (montada só com o submenu
|
|
93
|
+
// aberto) — caixa que ganha cor depois de montada perde o raio no Android (react-native#52415).
|
|
94
|
+
fundoDoSubmenu: {
|
|
95
|
+
position: "absolute", top: 0, right: 0, bottom: 0, left: 0,
|
|
96
|
+
backgroundColor: t.color.popover,
|
|
97
|
+
borderWidth: t.size.borderWidth, borderColor: t.color.border,
|
|
98
|
+
...canto(t.size.radiusLg),
|
|
99
|
+
boxShadow: [...t.shadowLayers.shadowMd],
|
|
100
|
+
},
|
|
101
|
+
}));
|
|
102
|
+
// A seta do `Popover`: a da referência tem 20 de largura e 12 de altura (`space5` × `space3`).
|
|
103
|
+
const larguraDaSeta = (t) => t.size.space5;
|
|
104
|
+
const alturaDaSeta = (t) => t.size.space3;
|
|
105
|
+
const preso = (v, min, max) => Math.max(min, Math.min(v, max));
|
|
106
|
+
/**
|
|
107
|
+
* Onde o painel fica. Centrado no gatilho, como o da referência (o alinhamento padrão dela e o da
|
|
108
|
+
* web), e preso dentro da janela com o recuo.
|
|
109
|
+
*
|
|
110
|
+
* ⚠ **Ele VIRA de lado quando não cabe e o outro lado tem mais espaço** — o que o posicionador da
|
|
111
|
+
* web faz. A referência não vira: só empurra o painel para dentro da tela, e um menu pedido para
|
|
112
|
+
* baixo num gatilho no pé da tela acaba EM CIMA do gatilho. Depois de virar, ele ainda é preso à
|
|
113
|
+
* janela, como o dela.
|
|
114
|
+
*/
|
|
115
|
+
function posicionar(a, c, W, H, r, d, pedido) {
|
|
116
|
+
const vertical = pedido === "top" || pedido === "bottom";
|
|
117
|
+
let lado = pedido;
|
|
118
|
+
if (vertical) {
|
|
119
|
+
const baixo = H - r.bottom - (a.y + a.height + d);
|
|
120
|
+
const cima = a.y - d - r.top;
|
|
121
|
+
if (pedido === "bottom" && c.height > baixo && cima > baixo)
|
|
122
|
+
lado = "top";
|
|
123
|
+
if (pedido === "top" && c.height > cima && baixo > cima)
|
|
124
|
+
lado = "bottom";
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
const direita = W - r.right - (a.x + a.width + d);
|
|
128
|
+
const esquerda = a.x - d - r.left;
|
|
129
|
+
if (pedido === "right" && c.width > direita && esquerda > direita)
|
|
130
|
+
lado = "left";
|
|
131
|
+
if (pedido === "left" && c.width > esquerda && direita > esquerda)
|
|
132
|
+
lado = "right";
|
|
133
|
+
}
|
|
134
|
+
const left = vertical ? a.x + a.width / 2 - c.width / 2
|
|
135
|
+
: lado === "right" ? a.x + a.width + d : a.x - d - c.width;
|
|
136
|
+
const top = !vertical ? a.y + a.height / 2 - c.height / 2
|
|
137
|
+
: lado === "bottom" ? a.y + a.height + d : a.y - d - c.height;
|
|
138
|
+
return {
|
|
139
|
+
lado,
|
|
140
|
+
left: preso(left, r.left, W - r.right - c.width),
|
|
141
|
+
top: preso(top, r.top, H - r.bottom - c.height),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* O gatilho da web é um ELEMENTO (`render={trigger}` no Base UI); aqui ele é clonado com o toque que
|
|
146
|
+
* abre, a REF que mede e o estado `expanded` — o toque do app continua valendo, depois do nosso.
|
|
147
|
+
*
|
|
148
|
+
* ⚠ **A medida vem da ref**, e o `Button` e o `IconButton` da Aurea a levam até o `Pressable` (no
|
|
149
|
+
* React 19 a `ref` é prop). Um gatilho que a engula ainda abre: cai no `currentTarget` do toque e,
|
|
150
|
+
* sem ele, no PONTO do dedo — o painel abre onde a pessoa tocou, em vez de não abrir.
|
|
151
|
+
*/
|
|
152
|
+
function useCamada(trigger, aoFecharTambem) {
|
|
153
|
+
const [aberto, setAberto] = React.useState(false);
|
|
154
|
+
const [ancora, setAncora] = React.useState(null);
|
|
155
|
+
const [tamanho, setTamanho] = React.useState(null);
|
|
156
|
+
const no = React.useRef(null);
|
|
157
|
+
const { width: W, height: H } = useWindowDimensions();
|
|
158
|
+
const props = trigger.props;
|
|
159
|
+
const refOriginal = props.ref;
|
|
160
|
+
const medir = React.useCallback((e) => {
|
|
161
|
+
const alvo = no.current ?? e?.currentTarget;
|
|
162
|
+
if (alvo && typeof alvo.measureInWindow === "function") {
|
|
163
|
+
alvo.measureInWindow((x, y, width, height) => {
|
|
164
|
+
if ([x, y, width, height].every(Number.isFinite))
|
|
165
|
+
setAncora({ x, y, width, height });
|
|
166
|
+
});
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const toque = e?.nativeEvent;
|
|
170
|
+
if (toque)
|
|
171
|
+
setAncora({ x: toque.pageX, y: toque.pageY, width: 0, height: 0 });
|
|
172
|
+
}, []);
|
|
173
|
+
// A janela girou (ou mudou de tamanho) com a camada aberta: o gatilho andou, mede de novo.
|
|
174
|
+
// Só a janela entra na lista: abrir já mede no toque, e medir de novo ao abrir seria dobrado.
|
|
175
|
+
const abertoAgora = React.useRef(aberto);
|
|
176
|
+
abertoAgora.current = aberto;
|
|
177
|
+
React.useEffect(() => { if (abertoAgora.current)
|
|
178
|
+
medir(); }, [W, H, medir]);
|
|
179
|
+
const fechar = React.useCallback(() => {
|
|
180
|
+
setAberto(false);
|
|
181
|
+
setAncora(null);
|
|
182
|
+
setTamanho(null);
|
|
183
|
+
aoFecharTambem?.();
|
|
184
|
+
}, [aoFecharTambem]);
|
|
185
|
+
const aoMedirPainel = React.useCallback((e) => {
|
|
186
|
+
const { width, height } = e.nativeEvent.layout;
|
|
187
|
+
// Mudar `left`/`top` dispara outro `onLayout` com o MESMO tamanho; sem a comparação, laço.
|
|
188
|
+
setTamanho((antes) => antes && antes.width === width && antes.height === height ? antes : { width, height });
|
|
189
|
+
}, []);
|
|
190
|
+
const ref = React.useCallback((n) => {
|
|
191
|
+
no.current = n ?? null;
|
|
192
|
+
if (typeof refOriginal === "function")
|
|
193
|
+
refOriginal(n);
|
|
194
|
+
else if (refOriginal && typeof refOriginal === "object")
|
|
195
|
+
refOriginal.current = n;
|
|
196
|
+
}, [refOriginal]);
|
|
197
|
+
const doApp = props.onPress;
|
|
198
|
+
const tocar = React.useCallback((e) => {
|
|
199
|
+
medir(e);
|
|
200
|
+
setAberto(true);
|
|
201
|
+
doApp?.(e);
|
|
202
|
+
}, [medir, doApp]);
|
|
203
|
+
// O estado do gatilho é ESCRITO por cima do que o botão calculou (o `...rest` dele vem depois),
|
|
204
|
+
// então o `disabled` e o `pressed` dele entram de novo aqui, para não se perderem.
|
|
205
|
+
const estado = {
|
|
206
|
+
...props.accessibilityState,
|
|
207
|
+
...(props.disabled != null ? { disabled: !!props.disabled } : null),
|
|
208
|
+
...(props.pressed !== undefined ? { checked: props.pressed } : null),
|
|
209
|
+
expanded: aberto,
|
|
210
|
+
};
|
|
211
|
+
const gatilho = React.cloneElement(trigger, {
|
|
212
|
+
ref, onPress: tocar, accessibilityState: estado, "aria-expanded": aberto,
|
|
213
|
+
});
|
|
214
|
+
return { aberto, ancora, tamanho, fechar, aoMedirPainel, gatilho };
|
|
215
|
+
}
|
|
216
|
+
// ─────────────────────────────────────────────────────────────────────────────────────────────
|
|
217
|
+
// A camada: o `Modal`, o fundo tocável, o painel e a seta
|
|
218
|
+
// ─────────────────────────────────────────────────────────────────────────────────────────────
|
|
219
|
+
const SEM_RECUO = { top: 0, right: 0, bottom: 0, left: 0 };
|
|
220
|
+
/**
|
|
221
|
+
* A entrada é a da referência: o painel nasce invisível, é MEDIDO, vai para o lugar e só então
|
|
222
|
+
* aparece — opacidade de 0 a 1, escala de 0,97 a 1 e um passo de 8 vindo do gatilho, no `durationBase`
|
|
223
|
+
* (a dela é 200; a escala de duração da Aurea tem 180). A saída é imediata: o `Modal` some na hora.
|
|
224
|
+
*/
|
|
225
|
+
function CamadaPresa({ c, side, seta = false, menu = false, label, testID, children }) {
|
|
226
|
+
// A camada sai do fluxo: o FUNDO é pintado com os tokens do APP (ADR-0063 — ver `useTokensDoApp`).
|
|
227
|
+
// O texto e o ícone de dentro leem o tema do app sozinhos, porque estão dentro do `ForaDaMarca`.
|
|
228
|
+
const tf = useTokensDoApp();
|
|
229
|
+
const s = folha(tf);
|
|
230
|
+
const { width: W, height: H } = useWindowDimensions();
|
|
231
|
+
const reduzir = useReduceMotion();
|
|
232
|
+
// O recuo da janela é o da referência (12) somado à área do sistema — do CONTEXTO, que atravessa o
|
|
233
|
+
// `Modal`; sem `SafeAreaProvider`, a medida da abertura (o mesmo caminho do `RecuoDaFolha`).
|
|
234
|
+
const sa = React.useContext(SafeAreaInsetsContext) ?? initialWindowMetrics?.insets ?? SEM_RECUO;
|
|
235
|
+
const recuo = {
|
|
236
|
+
top: tf.size.space3 + sa.top, right: tf.size.space3 + sa.right,
|
|
237
|
+
bottom: tf.size.space3 + sa.bottom, left: tf.size.space3 + sa.left,
|
|
238
|
+
};
|
|
239
|
+
// A distância do gatilho: a referência usa 9, que a escala não tem — vale o `space2` (8), o mesmo
|
|
240
|
+
// do `Popover` da web. Com a seta, a altura dela: a ponta encosta no gatilho, sem passar por cima.
|
|
241
|
+
const distancia = seta ? alturaDaSeta(tf) : tf.size.space2;
|
|
242
|
+
const pronto = c.aberto && c.ancora != null && c.tamanho != null;
|
|
243
|
+
const pos = pronto ? posicionar(c.ancora, c.tamanho, W, H, recuo, distancia, side) : null;
|
|
244
|
+
const progresso = React.useRef(new Animated.Value(0)).current;
|
|
245
|
+
React.useEffect(() => {
|
|
246
|
+
if (!pronto) {
|
|
247
|
+
progresso.setValue(0);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
// `!== false`, e não `=== true`: enquanto o sistema não respondeu, não anima (ver `movimento.ts`).
|
|
251
|
+
if (reduzir !== false) {
|
|
252
|
+
progresso.setValue(1);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const laco = Animated.timing(progresso, {
|
|
256
|
+
toValue: 1, duration: tf.size.durationBase, useNativeDriver: driverNativo(),
|
|
257
|
+
easing: Easing.bezier(...tf.easing.easeStandard),
|
|
258
|
+
});
|
|
259
|
+
laco.start();
|
|
260
|
+
return () => laco.stop();
|
|
261
|
+
}, [pronto, reduzir, progresso, tf.size.durationBase, tf.easing.easeStandard]);
|
|
262
|
+
// O passo vem do lado do gatilho: abaixo dele, o painel desce; acima, sobe. O da referência é a
|
|
263
|
+
// distância, no máximo 12.
|
|
264
|
+
const passo = Math.min(distancia, alturaDaSeta(tf));
|
|
265
|
+
const de = pos && (pos.lado === "bottom" || pos.lado === "right") ? -passo : passo;
|
|
266
|
+
const desloca = progresso.interpolate({ inputRange: [0, 1], outputRange: [de, 0] });
|
|
267
|
+
const entrada = pos
|
|
268
|
+
? {
|
|
269
|
+
left: pos.left, top: pos.top, opacity: progresso,
|
|
270
|
+
transform: [
|
|
271
|
+
pos.lado === "top" || pos.lado === "bottom" ? { translateY: desloca } : { translateX: desloca },
|
|
272
|
+
{ scale: progresso.interpolate({ inputRange: [0, 1], outputRange: [0.97, 1] }) },
|
|
273
|
+
],
|
|
274
|
+
}
|
|
275
|
+
// Antes de medido, invisível: é a medida dele que diz onde ele vai.
|
|
276
|
+
: { opacity: 0 };
|
|
277
|
+
return (_jsx(ForaDaMarca, { children: _jsx(Modal, { visible: c.aberto, transparent: true, animationType: "none", statusBarTranslucent: true, navigationBarTranslucent: true, onRequestClose: c.fechar, testID: testID, children: c.aberto ? (_jsxs(View, { style: s.camada, children: [_jsx(Pressable, { style: s.fundoDeToque, onPress: c.fechar, accessible: false, testID: testID ? `${testID}-fundo` : undefined }), _jsxs(Animated.View, { testID: testID ? `${testID}-painel` : undefined, onLayout: c.aoMedirPainel, onAccessibilityEscape: c.fechar, pointerEvents: pos ? "auto" : "none", accessibilityRole: menu ? "menu" : undefined, accessibilityLabel: label, style: [
|
|
278
|
+
s.painel, menu ? s.painelMenu : s.painelPopover,
|
|
279
|
+
{ left: recuo.left, top: recuo.top,
|
|
280
|
+
maxWidth: W - recuo.left - recuo.right, maxHeight: H - recuo.top - recuo.bottom },
|
|
281
|
+
entrada,
|
|
282
|
+
], children: [seta && pos && c.ancora && c.tamanho
|
|
283
|
+
? _jsx(Seta, { tf: tf, lado: pos.lado, ancora: c.ancora, painel: { ...c.tamanho, x: pos.left, y: pos.top } })
|
|
284
|
+
: null, children] })] })) : null }) }));
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* A seta: a medida e o lugar da referência (20 × 12, apontando para o MEIO do gatilho, a 12 das
|
|
288
|
+
* pontas do painel); o desenho é o da seta da web, uma curva só, e não um triângulo de bico.
|
|
289
|
+
* O fundo cobre a borda do painel embaixo dela, e o traço continua a borda.
|
|
290
|
+
*/
|
|
291
|
+
function Seta({ tf, lado, ancora, painel }) {
|
|
292
|
+
const w = larguraDaSeta(tf);
|
|
293
|
+
const h = alturaDaSeta(tf);
|
|
294
|
+
const b = tf.size.borderWidth;
|
|
295
|
+
const meio = b / 2; // o bico recua meio traço, para o traço não ser cortado pela caixa
|
|
296
|
+
const vertical = lado === "top" || lado === "bottom";
|
|
297
|
+
// Ao longo da borda, contado de dentro dela (o absoluto do RN conta da caixa de recheio).
|
|
298
|
+
const ao = vertical
|
|
299
|
+
? preso(ancora.x + ancora.width / 2 - painel.x - b - w / 2, tf.size.space3, painel.width - 2 * b - w - tf.size.space3)
|
|
300
|
+
: preso(ancora.y + ancora.height / 2 - painel.y - b - w / 2, tf.size.space3, painel.height - 2 * b - w - tf.size.space3);
|
|
301
|
+
// A curva: o ponto de controle a DUAS profundidades da base deixa o bico exatamente na ponta.
|
|
302
|
+
const linha = lado === "bottom" ? `M0 ${h} Q${w / 2} ${2 * meio - h} ${w} ${h}` // painel embaixo: aponta para cima
|
|
303
|
+
: lado === "top" ? `M0 0 Q${w / 2} ${2 * (h - meio)} ${w} 0` // painel em cima: para baixo
|
|
304
|
+
: lado === "right" ? `M${h} 0 Q${2 * meio - h} ${w / 2} ${h} ${w}` // painel à direita: para a esquerda
|
|
305
|
+
: `M0 0 Q${2 * (h - meio)} ${w / 2} 0 ${w}`; // painel à esquerda: para a direita
|
|
306
|
+
const lugar = lado === "bottom" ? { top: -h, left: ao }
|
|
307
|
+
: lado === "top" ? { bottom: -h, left: ao }
|
|
308
|
+
: lado === "right" ? { left: -h, top: ao }
|
|
309
|
+
: { right: -h, top: ao };
|
|
310
|
+
return (_jsx(View, { pointerEvents: "none", accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", style: [{ position: "absolute" }, lugar], children: _jsxs(Svg, { width: vertical ? w : h, height: vertical ? h : w, children: [_jsx(Path, { d: `${linha} Z`, fill: tf.color.popover }), _jsx(Path, { d: linha, fill: "none", stroke: tf.color.border, strokeWidth: b, strokeLinecap: "round", strokeLinejoin: "round" })] }) }));
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* A janela pequena presa ao gatilho: abre no toque, fecha no toque fora e no VOLTAR.
|
|
314
|
+
*
|
|
315
|
+
* ⚠ **Sem papel de diálogo**, pela razão medida no `overlays.tsx`: `role="dialog"` não mapeia em
|
|
316
|
+
* plataforma nenhuma. O confinamento do leitor de tela vem do `Modal`, que é uma janela do sistema;
|
|
317
|
+
* o nome vem do título, que é um cabeçalho. No iOS, o gesto de saída do VoiceOver fecha.
|
|
318
|
+
*/
|
|
319
|
+
export function Popover({ trigger, title, children, side = "bottom", arrow = false, testID }) {
|
|
320
|
+
const c = useCamada(trigger);
|
|
321
|
+
return (_jsxs(_Fragment, { children: [c.gatilho, _jsxs(CamadaPresa, { c: c, side: side, seta: arrow, testID: testID, children: [_jsx(TituloDoPopover, { title: title }), typeof children === "string" ? _jsx(Text, { size: "md", tone: "muted", children: children }) : children] })] }));
|
|
322
|
+
}
|
|
323
|
+
function TituloDoPopover({ title }) {
|
|
324
|
+
const s = folha(useTokensDoApp());
|
|
325
|
+
if (title == null || title === false)
|
|
326
|
+
return null;
|
|
327
|
+
return _jsx(Text, { size: "lg", weight: 500, accessibilityRole: "header", style: s.titulo, children: title });
|
|
328
|
+
}
|
|
329
|
+
// Com um submenu aberto, o resto do menu esmaece e não responde, como o da referência: o que está
|
|
330
|
+
// fora do caminho aberto. A chave de cada entrada é o caminho dela (`3/1/0`).
|
|
331
|
+
const apagado = (k, aberto) => aberto != null && k !== aberto && !k.startsWith(`${aberto}/`) && !aberto.startsWith(`${k}/`);
|
|
332
|
+
/**
|
|
333
|
+
* O menu de comandos preso ao gatilho.
|
|
334
|
+
*
|
|
335
|
+
* O estado de quem alterna sem ser controlado (`defaultChecked`, `defaultValue`) mora AQUI, e não no
|
|
336
|
+
* painel: o painel desmonta ao fechar, e o item marcado tem de continuar marcado na próxima vez.
|
|
337
|
+
*/
|
|
338
|
+
export function DropdownMenu({ trigger, items, side = "bottom", label, testID }) {
|
|
339
|
+
const tf = useTokensDoApp();
|
|
340
|
+
const s = folha(tf);
|
|
341
|
+
const [subAberto, setSubAberto] = React.useState(null);
|
|
342
|
+
const [marcado, setMarcado] = React.useState({});
|
|
343
|
+
// Fechar o menu fecha os submenus — ele reabre do começo.
|
|
344
|
+
const fecharSub = React.useCallback(() => setSubAberto(null), []);
|
|
345
|
+
const c = useCamada(trigger, fecharSub);
|
|
346
|
+
const marcar = React.useCallback((k, v) => setMarcado((m) => ({ ...m, [k]: v })), []);
|
|
347
|
+
const ctx = { tf, s, subAberto, setSubAberto, marcado, marcar, fechar: c.fechar };
|
|
348
|
+
return (_jsxs(_Fragment, { children: [c.gatilho, _jsx(CamadaPresa, { c: c, side: side, menu: true, label: label, testID: testID, children: _jsx(ScrollView, { style: s.rolagem, children: renderizar(items, "", null, ctx) }) })] }));
|
|
349
|
+
}
|
|
350
|
+
function renderizar(items, prefixo, paiSub, ctx) {
|
|
351
|
+
const { s, subAberto } = ctx;
|
|
352
|
+
return items.map((it, i) => {
|
|
353
|
+
const k = `${prefixo}${i}`;
|
|
354
|
+
if (it === "separator") {
|
|
355
|
+
return _jsx(View, { style: [s.separador, apagado(k, subAberto) && s.desabilitado], accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants" }, k);
|
|
356
|
+
}
|
|
357
|
+
switch (it.kind ?? "item") {
|
|
358
|
+
case "group": {
|
|
359
|
+
const g = it;
|
|
360
|
+
return (_jsxs(View, { children: [_jsx(RotuloDoGrupo, { ctx: ctx, k: k, children: g.label }), renderizar(g.items, `${k}/`, paiSub, ctx)] }, k));
|
|
361
|
+
}
|
|
362
|
+
case "radiogroup": {
|
|
363
|
+
const g = it;
|
|
364
|
+
const atual = g.value ?? ctx.marcado[k] ?? g.defaultValue;
|
|
365
|
+
return (_jsxs(View, { accessibilityRole: "radiogroup", accessibilityLabel: typeof g.label === "string" ? g.label : undefined, children: [_jsx(RotuloDoGrupo, { ctx: ctx, k: k, children: g.label }), g.items.map((r, j) => {
|
|
366
|
+
const kr = `${k}/${j}`;
|
|
367
|
+
const escolhido = r.value === atual;
|
|
368
|
+
return (_jsx(Linha, { ctx: ctx, papel: "radio", rotulo: r.label, icone: r.leadingIcon, estado: { checked: escolhido }, inativo: !!r.disabled || apagado(kr, subAberto), marca: escolhido ? _jsx(View, { style: s.ponto }) : null, aoTocar: () => {
|
|
369
|
+
if (!escolhido) {
|
|
370
|
+
if (g.value === undefined)
|
|
371
|
+
ctx.marcar(k, r.value);
|
|
372
|
+
g.onValueChange?.(r.value);
|
|
373
|
+
}
|
|
374
|
+
ctx.fechar();
|
|
375
|
+
} }, kr));
|
|
376
|
+
})] }, k));
|
|
377
|
+
}
|
|
378
|
+
case "checkbox": {
|
|
379
|
+
const cb = it;
|
|
380
|
+
const ligado = cb.checked ?? ctx.marcado[k] ?? cb.defaultChecked ?? false;
|
|
381
|
+
return (_jsx(Linha, { ctx: ctx, papel: "checkbox", rotulo: cb.label, icone: cb.leadingIcon, estado: { checked: ligado }, inativo: !!cb.disabled || apagado(k, subAberto), marca: ligado ? _jsx(Icon, { name: "check", size: "sm", color: ctx.tf.color.primaryEmphasis }) : null, aoTocar: () => {
|
|
382
|
+
// Alterna e FICA aberto — a escolha múltipla da referência e o item da web.
|
|
383
|
+
if (cb.checked === undefined)
|
|
384
|
+
ctx.marcar(k, !ligado);
|
|
385
|
+
cb.onCheckedChange?.(!ligado);
|
|
386
|
+
} }, k));
|
|
387
|
+
}
|
|
388
|
+
case "link": {
|
|
389
|
+
const l = it;
|
|
390
|
+
return (_jsx(Linha, { ctx: ctx, papel: "link", rotulo: l.label, icone: l.leadingIcon, inativo: apagado(k, subAberto), aoTocar: () => {
|
|
391
|
+
// Endereço que nenhum app abre rejeita a promessa; não há o que dizer, e não pode virar erro solto.
|
|
392
|
+
void Linking.openURL(l.href).catch(() => { });
|
|
393
|
+
if (l.closeOnClick ?? true)
|
|
394
|
+
ctx.fechar();
|
|
395
|
+
} }, k));
|
|
396
|
+
}
|
|
397
|
+
case "submenu": {
|
|
398
|
+
const sm = it;
|
|
399
|
+
const aberto = subAberto === k || (subAberto?.startsWith(`${k}/`) ?? false);
|
|
400
|
+
return (_jsx(LinhaDeSubmenu, { ctx: ctx, def: sm, aberto: aberto, inativo: !!sm.disabled || apagado(k, subAberto), alternar: () => ctx.setSubAberto(aberto ? paiSub : k), children: renderizar(sm.items, `${k}/`, k, ctx) }, k));
|
|
401
|
+
}
|
|
402
|
+
default: {
|
|
403
|
+
const a = it;
|
|
404
|
+
return (_jsx(Linha, { ctx: ctx, papel: "menuitem", rotulo: a.label, icone: a.leadingIcon, destrutivo: a.destructive, inativo: !!a.disabled || apagado(k, subAberto), aoTocar: () => { a.onClick?.(); ctx.fechar(); } }, k));
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
function RotuloDoGrupo({ ctx, k, children }) {
|
|
410
|
+
if (children == null || children === false)
|
|
411
|
+
return null;
|
|
412
|
+
return (_jsx(View, { style: [ctx.s.rotuloDoGrupo, apagado(k, ctx.subAberto) && ctx.s.desabilitado], children: typeof children === "string"
|
|
413
|
+
? _jsx(Text, { size: "xs", weight: 500, tone: "muted", accessibilityRole: "header", children: children })
|
|
414
|
+
: children }));
|
|
415
|
+
}
|
|
416
|
+
function Linha({ ctx, papel, rotulo, icone, marca, estado, inativo = false, destrutivo = false, final, aoTocar }) {
|
|
417
|
+
const { tf, s } = ctx;
|
|
418
|
+
const cor = destrutivo ? letraDoToken(tf, "destructive") ?? tf.color.destructive : tf.color.foreground;
|
|
419
|
+
return (_jsxs(Pressable, { onPress: inativo ? undefined : aoTocar, disabled: inativo,
|
|
420
|
+
// Escrito por extenso, e não `{papel}`: o check 41 lê os papéis no fonte, e só confere o que vê.
|
|
421
|
+
accessibilityRole: papel === "checkbox" ? "checkbox" : papel === "radio" ? "radio"
|
|
422
|
+
: papel === "link" ? "link" : "menuitem", ...estadoAcessivel({ ...estado, disabled: inativo }), style: ({ pressed }) => [
|
|
423
|
+
s.item, pressed && (destrutivo ? s.itemTocandoPerigo : s.itemTocando), inativo && s.desabilitado,
|
|
424
|
+
], children: [marca !== undefined ? _jsx(View, { style: s.indicador, children: marca }) : null, icone ? _jsx(Icon, { name: icone, size: "md", color: cor }) : null, typeof rotulo === "string" || typeof rotulo === "number"
|
|
425
|
+
// 16 em peso médio, o título do item da referência.
|
|
426
|
+
? _jsx(Text, { size: "md", weight: 500, tone: destrutivo ? "danger" : "default", style: s.rotulo, children: rotulo })
|
|
427
|
+
: _jsx(View, { style: s.rotulo, children: rotulo }), final] }));
|
|
428
|
+
}
|
|
429
|
+
/** O gatilho do submenu: a seta de 16 gira 90° ao abrir, como a da referência. */
|
|
430
|
+
function LinhaDeSubmenu({ ctx, def, aberto, inativo, alternar, children }) {
|
|
431
|
+
const { tf, s } = ctx;
|
|
432
|
+
const reduzir = useReduceMotion();
|
|
433
|
+
const giro = React.useRef(new Animated.Value(aberto ? 1 : 0)).current;
|
|
434
|
+
const antes = React.useRef(aberto);
|
|
435
|
+
React.useEffect(() => {
|
|
436
|
+
const mudou = antes.current !== aberto;
|
|
437
|
+
antes.current = aberto;
|
|
438
|
+
// Só anima o que MUDOU: a resposta do sistema chegando não pode virar um giro de 0 para 0.
|
|
439
|
+
if (!mudou || reduzir !== false) {
|
|
440
|
+
giro.setValue(aberto ? 1 : 0);
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
const laco = Animated.timing(giro, {
|
|
444
|
+
toValue: aberto ? 1 : 0, duration: tf.size.durationFast, useNativeDriver: driverNativo(),
|
|
445
|
+
easing: Easing.bezier(...tf.easing.easeStandard),
|
|
446
|
+
});
|
|
447
|
+
laco.start();
|
|
448
|
+
return () => laco.stop();
|
|
449
|
+
}, [aberto, reduzir, giro, tf.size.durationFast, tf.easing.easeStandard]);
|
|
450
|
+
const seta = (_jsx(Animated.View, { style: { transform: [{ rotate: giro.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "90deg"] }) }] }, children: _jsx(Icon, { name: "caret-right", size: "sm", color: tf.color.mutedForeground }) }));
|
|
451
|
+
return (_jsxs(View, { children: [aberto ? _jsx(View, { pointerEvents: "none", style: s.fundoDoSubmenu }) : null, _jsx(Linha, { ctx: ctx, papel: "menuitem", rotulo: def.label, icone: def.leadingIcon, estado: { expanded: aberto }, inativo: inativo, final: seta, aoTocar: alternar }), aberto ? children : null] }));
|
|
452
|
+
}
|
package/dist/navigation.d.ts
CHANGED
|
@@ -160,7 +160,7 @@ export interface AureaNavListItem {
|
|
|
160
160
|
disabled?: boolean;
|
|
161
161
|
/**
|
|
162
162
|
* A foto da linha (AN-04, 03/10/2026) — o formato do `Avatar` daqui (`source`, `fallback`), no
|
|
163
|
-
* tamanho dele
|
|
163
|
+
* tamanho padrão dele (`md`, 48 desde a 0.32.0). Toma o lugar do `icon`.
|
|
164
164
|
*/
|
|
165
165
|
avatar?: {
|
|
166
166
|
source?: ImageSourcePropType | string;
|
package/dist/navigation.js
CHANGED
|
@@ -164,37 +164,52 @@ const folha = criarFolha((t) => ({
|
|
|
164
164
|
rotuloEscondido: { position: "absolute", opacity: 0 },
|
|
165
165
|
// ── NavList ────────────────────────────────────────────────────────────────────────────────
|
|
166
166
|
lista: { gap: t.size.space05 },
|
|
167
|
+
// 0.32.0 (ADR-0066): a linha da lista do pacote NATIVO da referência — recheio de 16 em volta e vão
|
|
168
|
+
// de 12; título 16 em peso médio e descrição 14 (no componente). Até a 0.31.0 era a linha da web:
|
|
169
|
+
// altura mínima de controle (`controlHLg`), 8 em cima e embaixo, 12 dos lados. A altura mínima saiu:
|
|
170
|
+
// a altura vem do recheio e da linha do texto, como lá.
|
|
167
171
|
linha: {
|
|
168
172
|
flexDirection: "row", alignItems: "center", gap: t.size.space3, width: "100%",
|
|
169
|
-
|
|
170
|
-
paddingVertical: t.size.space2, paddingHorizontal: t.size.space3,
|
|
173
|
+
paddingHorizontal: t.size.space4,
|
|
171
174
|
...canto(t.size.radiusCard - t.size.space1),
|
|
172
175
|
},
|
|
173
176
|
// O MIOLO da linha: ícone + texto (+ valor em texto) + seta. Ele é quem toca; o que vem
|
|
174
177
|
// depois dele, na moldura, é IRMÃO — ver o comentário no componente.
|
|
175
|
-
//
|
|
176
|
-
|
|
178
|
+
// ⚠ O recheio de CIMA E DE BAIXO mora aqui, e não na moldura: é o miolo que toca, e na referência
|
|
179
|
+
// a linha inteira é o alvo. Na moldura ele ficaria fora do toque, e o miolo de uma linha só
|
|
180
|
+
// mediria a linha do título (24), abaixo dos 44 do alvo mínimo; aqui ele mede 16 + 24 + 16 = 56.
|
|
181
|
+
// O valor que é componente (irmão) fica no meio da altura, como antes.
|
|
182
|
+
linhaMiolo: {
|
|
183
|
+
flex: 1, minWidth: 0, flexDirection: "row", alignItems: "center", gap: t.size.space3,
|
|
184
|
+
paddingVertical: t.size.space4,
|
|
185
|
+
},
|
|
177
186
|
linhaTexto: { flex: 1, minWidth: 0 },
|
|
178
187
|
// AN-04: os sinais, com o vão de dentro do texto (`space1`), como o `.nav-list-indicators` da web.
|
|
179
188
|
sinais: { flexDirection: "row", alignItems: "center", gap: t.size.space1 },
|
|
180
189
|
// ── Tabs ───────────────────────────────────────────────────────────────────────────────────
|
|
181
|
-
// A cápsula é a MESMA do `SegmentedControl
|
|
182
|
-
//
|
|
183
|
-
//
|
|
190
|
+
// ~~A cápsula é a MESMA do `SegmentedControl` [...] `gap:3px; padding:3px`~~ — 0.32.0 (ADR-0066):
|
|
191
|
+
// a lista com cápsula do pacote NATIVO da referência. O trilho tem 3 de recheio lá; aqui é o
|
|
192
|
+
// `space1` (4), o token mais perto — a escala não tem 3, e escala nova não nasce no meio de um
|
|
193
|
+
// componente. É o mesmo 4 do `.tabs` da web desta versão. O vão entre as abas é 4, o dela.
|
|
194
|
+
// A altura sai da aba (6 + a linha de 24 + 6 = 36) mais o trilho: 44. A altura mínima de controle
|
|
195
|
+
// (`controlHMd`) saiu, como na referência.
|
|
184
196
|
abas: {
|
|
185
|
-
flexDirection: "row", gap:
|
|
186
|
-
|
|
197
|
+
flexDirection: "row", gap: t.size.space1, padding: t.size.space1,
|
|
198
|
+
...canto(t.size.radiusControl),
|
|
187
199
|
backgroundColor: t.color.muted,
|
|
188
200
|
},
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
//
|
|
201
|
+
// A aba da referência nativa: 12 dos lados, 6 em cima e embaixo, 6 de vão entre o que vai dentro
|
|
202
|
+
// (o rótulo e um ícone, quando o app passa os dois), e o rótulo 16 em peso médio (no componente).
|
|
203
|
+
// Era o `padding:0 14px` do `.tab` da web antiga. A aba NÃO estica (nada de `flex`): é isso que
|
|
204
|
+
// deixa a lista rolar quando não cabe, em vez de espremer todas.
|
|
192
205
|
// ⚠ O nome é `abaDeTab` porque `aba` JÁ EXISTE neste arquivo — é o item do `BottomNav`
|
|
193
206
|
// (linha 78), que tem `flex: 1` e cresce. Reusar o nome teria sobrescrito um dos dois em
|
|
194
207
|
// silêncio, e o `tsc` só pegou porque são chaves do mesmo objeto.
|
|
195
208
|
abaDeTab: {
|
|
196
|
-
alignItems: "center", justifyContent: "center",
|
|
197
|
-
|
|
209
|
+
flexDirection: "row", alignItems: "center", justifyContent: "center",
|
|
210
|
+
gap: t.size.space1 + t.size.space05,
|
|
211
|
+
paddingHorizontal: t.size.space3, paddingVertical: t.size.space1 + t.size.space05,
|
|
212
|
+
...canto(t.size.radiusControl),
|
|
198
213
|
},
|
|
199
214
|
// A aba escolhida: a mesma cápsula do `segmentoAtivo` (`inputs.tsx`), pelo mesmo motivo — ADR-0059.
|
|
200
215
|
abaDeTabAtiva: { backgroundColor: t.color.segment, boxShadow: [...t.shadowLayers.shadowSm] },
|
|
@@ -204,8 +219,10 @@ const folha = criarFolha((t) => ({
|
|
|
204
219
|
// fila gap de 1 unidade → space1
|
|
205
220
|
// aba padding-inline de 3 unidades → space3 · padding-block de 1,5
|
|
206
221
|
// → space1 + space05. Rótulo `text-base` + entrelinha 1.5 dá
|
|
207
|
-
// 36, que é o `controlHMd
|
|
208
|
-
// trocar de variante não muda a altura da fila.
|
|
222
|
+
// 36, que é o `controlHMd`. ~~a altura da fila da cápsula, então
|
|
223
|
+
// trocar de variante não muda a altura da fila~~ — 0.32.0: a
|
|
224
|
+
// aba da cápsula também tem 36, mas a fila dela soma o trilho
|
|
225
|
+
// de 4 de cada lado (44).
|
|
209
226
|
// indicador (secundária) border-bottom 2px na cor de destaque → `fioDoEscolhido`
|
|
210
227
|
abasSecundarias: {
|
|
211
228
|
flexDirection: "row", gap: t.size.space1,
|
|
@@ -489,7 +506,7 @@ export function NavList({ items, chevron = "caret-right", style, ...rest }) {
|
|
|
489
506
|
const miolo = (_jsxs(_Fragment, { children: [it.avatar
|
|
490
507
|
? _jsx(Avatar, { source: it.avatar.source, fallback: it.avatar.fallback })
|
|
491
508
|
: it.icon && _jsx(Icon, { name: it.icon, size: "md", color: t.color.foreground }), _jsxs(View, { style: s.linhaTexto, children: [typeof it.label === "string"
|
|
492
|
-
? _jsx(Text, { size: "sm", numberOfLines: 1, children: it.label }) : it.label, it.description != null && (typeof it.description === "string"
|
|
509
|
+
? _jsx(Text, { size: "sm", weight: 500, numberOfLines: 1, children: it.label }) : it.label, it.description != null && (typeof it.description === "string"
|
|
493
510
|
? _jsx(Text, { size: "xs", tone: "muted", numberOfLines: 1, children: it.description })
|
|
494
511
|
: it.description)] }), it.indicators && it.indicators.length > 0 && (_jsx(View, { style: s.sinais, children: it.indicators.map((x) => (_jsx(View, { accessibilityLabel: x.label, children: _jsx(Icon, { name: x.icon, size: "sm", color: t.color.mutedForeground }) }, x.label))) })), valorEhTexto && _jsx(Text, { size: "sm", tone: "muted", children: it.value }), temAcao && chevron
|
|
495
512
|
&& _jsx(Icon, { name: chevron, size: "sm", color: t.color.mutedForeground })] }));
|
|
@@ -574,7 +591,7 @@ export function Tabs({ tabs, value, onChange, label, justify, variant = "primary
|
|
|
574
591
|
ativa && !secundaria && s.abaDeTabAtiva,
|
|
575
592
|
it.disabled && { opacity: t.size.opacityDisabled },
|
|
576
593
|
], children: [typeof it.label === "string"
|
|
577
|
-
? _jsx(Text, { size: "sm", weight: ativa ? 600 : 400, style: { color: ativa ? t.color.foreground : t.color.mutedForeground }, children: it.label })
|
|
594
|
+
? _jsx(Text, { size: "sm", weight: secundaria ? (ativa ? 600 : 400) : 500, style: { color: ativa ? t.color.foreground : t.color.mutedForeground }, children: it.label })
|
|
578
595
|
: it.label, ativa && secundaria && _jsx(View, { style: s.fioDaAba })] }, it.id));
|
|
579
596
|
}) }) }), aberta && panel === "plain" ? (_jsx(View, { accessibilityLabel: typeof aberta.label === "string" ? aberta.label : undefined, style: s.painel, children: aberta.content })) : aberta ? (_jsx(Card, { variant: "inset", accessibilityLabel: typeof aberta.label === "string" ? aberta.label : undefined, style: s.painel, children: aberta.content })) : null] }));
|
|
580
597
|
}
|
package/dist/numero.d.ts
CHANGED
|
@@ -9,8 +9,8 @@ import { type AureaFieldSize } from "./inputs.js";
|
|
|
9
9
|
* peça nossa —
|
|
10
10
|
* e as medidas saem de escalas que JÁ existem, nenhuma nova:
|
|
11
11
|
* letra `text3xl` (30) em seminegrito — o título 2 (`h2` do B-02). Escolha do Victor.
|
|
12
|
-
* altura
|
|
13
|
-
*
|
|
12
|
+
* altura o degrau acima do `lg` na escala de toque (`touchControlHLg + space2`, 64 no
|
|
13
|
+
* confortável; até a 0.31.0 era o `controlHXl`, 50), como o `Button xl`.
|
|
14
14
|
* largura `space24` (96): o `space16` (64) do campo comum não cabe "1.234" em 30.
|
|
15
15
|
* botões os do `lg`, o maior do `IconButton`.
|
|
16
16
|
*/
|
package/dist/numero.js
CHANGED
|
@@ -51,8 +51,12 @@ import { IconButton } from "./actions.js";
|
|
|
51
51
|
import { canto, criarFolha, estadoAcessivel } from "./estilos.js";
|
|
52
52
|
import { useCampo } from "./inputs.js";
|
|
53
53
|
import { useAureaStrings, useAureaTokens, usePeleSobreAMarca } from "./theme.js";
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
// 0.32.0: o campo comum na altura de TOQUE, como o `Input` (40 · 48 · 56; era 32 · 36 · 40). O
|
|
55
|
+
// `display` (peça nossa, sem medida na referência) sobe para o degrau acima do `lg` que o `Button xl`
|
|
56
|
+
// também usa: `touchControlHLg + space2` = 64 (era o `controlHXl`, 50, que com a escala nova ficaria
|
|
57
|
+
// MAIS BAIXO que o `lg`).
|
|
58
|
+
const alturaDoTamanho = (t, s) => s === "sm" ? t.size.touchControlHSm : s === "lg" ? t.size.touchControlHLg
|
|
59
|
+
: s === "display" ? t.size.touchControlHLg + t.size.space2 : t.size.touchControlHMd;
|
|
56
60
|
const fonteDoTamanho = (t, s) => s === "sm" ? t.size.textSm : s === "lg" ? t.size.textLg
|
|
57
61
|
: s === "display" ? t.size.text3xl : t.size.textBase; // ADR-0050: um degrau acima da web
|
|
58
62
|
const folha = criarFolha((t) => ({
|