@medway-ui/native 1.7.1 → 1.8.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/README.md +92 -89
- package/lib/commonjs/components/Badge.js +159 -36
- package/lib/commonjs/components/Badge.js.map +1 -1
- package/lib/commonjs/components/Choice.js +35 -37
- package/lib/commonjs/components/Choice.js.map +1 -1
- package/lib/commonjs/components/SegmentControl.js +197 -0
- package/lib/commonjs/components/SegmentControl.js.map +1 -0
- package/lib/commonjs/editor/editorHtml.generated.js +1 -1
- package/lib/commonjs/editor/editorHtml.generated.js.map +1 -1
- package/lib/commonjs/hooks/useThemeColor.js +42 -42
- package/lib/commonjs/hooks/useThemeColor.js.map +1 -1
- package/lib/commonjs/index.js +31 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/lib/raised-surface.js +24 -0
- package/lib/commonjs/lib/raised-surface.js.map +1 -0
- package/lib/module/components/Badge.js +159 -36
- package/lib/module/components/Badge.js.map +1 -1
- package/lib/module/components/Choice.js +35 -37
- package/lib/module/components/Choice.js.map +1 -1
- package/lib/module/components/SegmentControl.js +189 -0
- package/lib/module/components/SegmentControl.js.map +1 -0
- package/lib/module/editor/editorHtml.generated.js +1 -1
- package/lib/module/editor/editorHtml.generated.js.map +1 -1
- package/lib/module/hooks/useThemeColor.js +42 -42
- package/lib/module/hooks/useThemeColor.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/lib/raised-surface.js +22 -0
- package/lib/module/lib/raised-surface.js.map +1 -0
- package/lib/typescript/components/Badge.d.ts +14 -4
- package/lib/typescript/components/Badge.d.ts.map +1 -1
- package/lib/typescript/components/Chip.d.ts +2 -2
- package/lib/typescript/components/Choice.d.ts.map +1 -1
- package/lib/typescript/components/SegmentControl.d.ts +37 -0
- package/lib/typescript/components/SegmentControl.d.ts.map +1 -0
- package/lib/typescript/components/Tag.d.ts +2 -2
- package/lib/typescript/editor/editorHtml.generated.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +3 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/lib/raised-surface.d.ts +3 -0
- package/lib/typescript/lib/raised-surface.d.ts.map +1 -0
- package/package.json +2 -2
- package/setup/tokens.native.css +49 -22
- package/src/components/Badge.tsx +207 -61
- package/src/components/Choice.tsx +66 -45
- package/src/components/SegmentControl.tsx +265 -0
- package/src/editor/editorHtml.generated.ts +1 -1
- package/src/hooks/useThemeColor.ts +42 -42
- package/src/index.ts +21 -1
- package/src/lib/raised-surface.tsx +21 -0
package/README.md
CHANGED
|
@@ -1,31 +1,33 @@
|
|
|
1
1
|
# @medway-ui/native
|
|
2
2
|
|
|
3
|
-
React Native
|
|
3
|
+
Componentes React Native para iOS e Android (Expo). Mesma API visual do `@medway-ui/core`, construída sobre NativeWind + `@rn-primitives`.
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**Versão mínima recomendada para setup brownfield via npm:** `1.1.2+`
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Instalação
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
npm install @medway-ui/native @medway-ui/core @medway-ui/icons \
|
|
13
13
|
class-variance-authority clsx tailwind-merge nativewind \
|
|
14
14
|
react-native-reanimated react-native-svg
|
|
15
15
|
|
|
16
|
-
# Expo (
|
|
17
|
-
# expo-linear-gradient + masked-view:
|
|
18
|
-
#
|
|
16
|
+
# Expo (alinha as versões com o seu SDK)
|
|
17
|
+
# expo-linear-gradient + masked-view: peers opcionais para o anel `animated` do IndexLevel
|
|
18
|
+
# e as variantes com gradiente do Toast (fallback para cor sólida quando ausentes)
|
|
19
19
|
npx expo install react-native-reanimated react-native-svg expo-linear-gradient @react-native-masked-view/masked-view
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
`react-native-safe-area-context`
|
|
22
|
+
`react-native-safe-area-context` é uma peer dependency opcional usada pelo `ToastProvider` para o inset superior. Apps Expo normalmente já têm (e um `SafeAreaProvider` na raiz via React Navigation). Sem um provider, o toast volta para o offset anterior de `pt-12`.
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
npx expo install react-native-safe-area-context
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
A sombra do card selecionado do `Choice` e do `SegmentControl` (`boxShadow`) e o gradiente do `Badge` freemium (`experimental_backgroundImage`) precisam do React Native 0.76+ com a nova arquitetura. Abaixo disso, o card fica sem sombra e o freemium fica com o fundo navy sólido.
|
|
29
|
+
|
|
30
|
+
Apps brownfield que já usam `babel-plugin-module-resolver` com aliases `@/` apontando para o `src/` do app também precisam de:
|
|
29
31
|
|
|
30
32
|
```bash
|
|
31
33
|
npm install -D babel-plugin-module-resolver
|
|
@@ -33,11 +35,11 @@ npm install -D babel-plugin-module-resolver
|
|
|
33
35
|
|
|
34
36
|
---
|
|
35
37
|
|
|
36
|
-
##
|
|
38
|
+
## Setup brownfield (Expo + UI legada / Restyle)
|
|
37
39
|
|
|
38
|
-
NativeWind
|
|
40
|
+
O NativeWind se aplica **apenas** ao `@medway-ui/native` + telas/componentes que usam a biblioteca (ex.: `src/pages/medway-ui/`, features parcialmente migradas).
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
Implementação de referência: **test-prep-app** (`metro.config.js`, `babel.config.js`, `tailwind.config.js`, `src/pages/medway-ui/`).
|
|
41
43
|
|
|
42
44
|
### 1. `metro.config.js`
|
|
43
45
|
|
|
@@ -47,17 +49,17 @@ const { withMedwayUi } = require("@medway-ui/native/metro");
|
|
|
47
49
|
|
|
48
50
|
module.exports = withMedwayUi(getDefaultConfig(__dirname), {
|
|
49
51
|
projectRoot: __dirname,
|
|
50
|
-
// linkedMedwayUiRoot:
|
|
52
|
+
// linkedMedwayUiRoot: detectado automaticamente (npm ou monorepo)
|
|
51
53
|
});
|
|
52
54
|
```
|
|
53
55
|
|
|
54
|
-
|
|
|
56
|
+
| Cenário | `linkedMedwayUiRoot` |
|
|
55
57
|
| --- | --- |
|
|
56
|
-
| npm
|
|
57
|
-
| Monorepo
|
|
58
|
-
| Symlink `file:../medway-ui/native` |
|
|
58
|
+
| Pacotes npm (`npm install`) | **Omita**: detecta `node_modules/@medway-ui` automaticamente |
|
|
59
|
+
| Monorepo com clone local | `"../medway-ui"` (opcional; também detectado automaticamente) |
|
|
60
|
+
| Symlink `file:../medway-ui/native` | Detectado automaticamente como monorepo |
|
|
59
61
|
|
|
60
|
-
>
|
|
62
|
+
> **Não** defina `resolveNativeSource: false`: a lib compilada ainda referencia aliases internos `@/`. O padrão (`true`) resolve para `native/src` e funciona com npm.
|
|
61
63
|
|
|
62
64
|
### 2. `tailwind.config.js`
|
|
63
65
|
|
|
@@ -68,19 +70,19 @@ module.exports = createMedwayUiTailwindConfig({
|
|
|
68
70
|
projectRoot: __dirname,
|
|
69
71
|
content: [
|
|
70
72
|
"./src/pages/medway-ui/**/*.{ts,tsx}",
|
|
71
|
-
//
|
|
73
|
+
// adicione pastas extras que usam className + @medway-ui/native:
|
|
72
74
|
// "./src/pages/MyFeature/**/*.{ts,tsx}",
|
|
73
75
|
],
|
|
74
76
|
});
|
|
75
77
|
```
|
|
76
78
|
|
|
77
|
-
`createMedwayUiTailwindConfig`
|
|
79
|
+
`createMedwayUiTailwindConfig` já inclui os globs de `node_modules/@medway-ui/native/src` e carrega os tokens de `@medway-ui/core` (compatível com Node 22+).
|
|
78
80
|
|
|
79
81
|
### 3. `babel.config.js`
|
|
80
82
|
|
|
81
|
-
|
|
83
|
+
O preset padrão do app **não** deve habilitar o NativeWind globalmente. Use `createBrownfieldOverride` para restringir o NativeWind à biblioteca + pasta de telas migradas.
|
|
82
84
|
|
|
83
|
-
|
|
85
|
+
Se o app define aliases `@/` para `./src/*` via `babel-plugin-module-resolver`, você **precisa** redirecionar os imports `@/` dos arquivos do `@medway-ui/native` para o código-fonte da biblioteca. Caso contrário, imports como `@/components/Badge` resolvem para o `src/` do app e quebram o bundle.
|
|
84
86
|
|
|
85
87
|
```js
|
|
86
88
|
const {
|
|
@@ -102,14 +104,14 @@ module.exports = function (api) {
|
|
|
102
104
|
alias: {
|
|
103
105
|
"@/components": "./src/components",
|
|
104
106
|
"@/pages": "./src/pages",
|
|
105
|
-
// ...
|
|
107
|
+
// ... outros aliases do app
|
|
106
108
|
},
|
|
107
109
|
resolvePath(sourcePath, currentFile) {
|
|
108
110
|
return resolveMedwayUiAlias(sourcePath, currentFile);
|
|
109
111
|
},
|
|
110
112
|
},
|
|
111
113
|
],
|
|
112
|
-
//
|
|
114
|
+
// outros plugins do app (sem reanimated aqui)
|
|
113
115
|
];
|
|
114
116
|
|
|
115
117
|
return {
|
|
@@ -118,10 +120,10 @@ module.exports = function (api) {
|
|
|
118
120
|
overrides: [
|
|
119
121
|
createBrownfieldOverride({
|
|
120
122
|
projectRoot: __dirname,
|
|
121
|
-
appPagesDir: "medway-ui", // src/pages
|
|
123
|
+
appPagesDir: "medway-ui", // subpasta de src/pages com as telas NativeWind
|
|
122
124
|
plugins: [
|
|
123
|
-
//
|
|
124
|
-
"react-native-reanimated/plugin", //
|
|
125
|
+
// repita os plugins necessários no escopo do medway-ui
|
|
126
|
+
"react-native-reanimated/plugin", // sempre por último
|
|
125
127
|
],
|
|
126
128
|
}),
|
|
127
129
|
],
|
|
@@ -129,11 +131,11 @@ module.exports = function (api) {
|
|
|
129
131
|
};
|
|
130
132
|
```
|
|
131
133
|
|
|
132
|
-
Apps **
|
|
134
|
+
Apps **sem** aliases `@/` no Babel não precisam de `createMedwayUiAliasResolver`.
|
|
133
135
|
|
|
134
136
|
### 4. Provider + CSS
|
|
135
137
|
|
|
136
|
-
|
|
138
|
+
Envolva a subárvore que usa `@medway-ui/native` com `MedwayUiProvider` e importe o CSS uma única vez:
|
|
137
139
|
|
|
138
140
|
```tsx
|
|
139
141
|
import { MedwayUiProvider } from "@medway-ui/native/setup";
|
|
@@ -148,7 +150,7 @@ function MyScreen() {
|
|
|
148
150
|
}
|
|
149
151
|
```
|
|
150
152
|
|
|
151
|
-
**Dark mode:**
|
|
153
|
+
**Dark mode:** passe `colorScheme="light" | "dark"` quando o app já resolve o tema (Redux, Zustand, etc.):
|
|
152
154
|
|
|
153
155
|
```tsx
|
|
154
156
|
<MedwayUiProvider colorScheme={appColorScheme}>
|
|
@@ -156,13 +158,13 @@ function MyScreen() {
|
|
|
156
158
|
</MedwayUiProvider>
|
|
157
159
|
```
|
|
158
160
|
|
|
159
|
-
`MedwayUiProvider`
|
|
161
|
+
`MedwayUiProvider` inclui o `PortalHost` (obrigatório para Select, Dialog, Popover, Tooltip).
|
|
160
162
|
|
|
161
|
-
>
|
|
163
|
+
> **Não** importe `@medway-ui/core/tokens.css` diretamente: é incompatível com o NativeWind v4. Os tokens vêm de `setup/global.css` + `setup/tokens.native.css`.
|
|
162
164
|
|
|
163
|
-
### 5.
|
|
165
|
+
### 5. Navigator automático (catálogo / telas isoladas)
|
|
164
166
|
|
|
165
|
-
|
|
167
|
+
Crie uma única vez `src/pages/medway-ui/navigator.tsx`:
|
|
166
168
|
|
|
167
169
|
```tsx
|
|
168
170
|
import { createMedwayUiNavigator, MedwayUiProvider } from "@medway-ui/native/setup";
|
|
@@ -183,17 +185,17 @@ function MedwayUiRoot() {
|
|
|
183
185
|
export { MedwayUiRoot, MedwayUiNavigator };
|
|
184
186
|
```
|
|
185
187
|
|
|
186
|
-
|
|
188
|
+
Registre no stack do app:
|
|
187
189
|
|
|
188
190
|
```tsx
|
|
189
191
|
<Stack.Screen name="MedwayUi" component={MedwayUiRoot} options={{ headerShown: false }} />
|
|
190
192
|
```
|
|
191
193
|
|
|
192
|
-
|
|
194
|
+
Nova tela = nova pasta `src/pages/medway-ui/MyScreen/index.tsx`, sem registro manual de rota.
|
|
193
195
|
|
|
194
|
-
### 6.
|
|
196
|
+
### 6. Usando componentes em telas existentes (mistura de Restyle + Medway UI)
|
|
195
197
|
|
|
196
|
-
|
|
198
|
+
Padrão usado no Content Hub e em features parcialmente migradas:
|
|
197
199
|
|
|
198
200
|
```tsx
|
|
199
201
|
import { Button, CardNews } from "@medway-ui/native";
|
|
@@ -211,11 +213,11 @@ function ContentHubScreen() {
|
|
|
211
213
|
}
|
|
212
214
|
```
|
|
213
215
|
|
|
214
|
-
|
|
216
|
+
Adicione a pasta da feature ao `content` do `tailwind.config.js`.
|
|
215
217
|
|
|
216
218
|
---
|
|
217
219
|
|
|
218
|
-
##
|
|
220
|
+
## Desenvolvimento em monorepo (`file:../medway-ui/native`)
|
|
219
221
|
|
|
220
222
|
```json
|
|
221
223
|
{
|
|
@@ -224,32 +226,32 @@ Add the feature folder to `content` in `tailwind.config.js`.
|
|
|
224
226
|
}
|
|
225
227
|
```
|
|
226
228
|
|
|
227
|
-
Metro
|
|
229
|
+
Metro e Babel detectam o clone local automaticamente. Depois de mudanças na biblioteca:
|
|
228
230
|
|
|
229
231
|
```bash
|
|
230
|
-
cd ../medway-ui/native && npm run build:lib #
|
|
232
|
+
cd ../medway-ui/native && npm run build:lib # se estiver testando a lib compilada
|
|
231
233
|
```
|
|
232
234
|
|
|
233
|
-
|
|
235
|
+
Reinicie o Metro com cache limpo: `npx expo start --clear`.
|
|
234
236
|
|
|
235
237
|
---
|
|
236
238
|
|
|
237
|
-
##
|
|
239
|
+
## Solução de problemas
|
|
238
240
|
|
|
239
|
-
|
|
|
241
|
+
| Erro | Causa | Correção |
|
|
240
242
|
| --- | --- | --- |
|
|
241
|
-
| `Unable to resolve .../src/components/Badge` |
|
|
242
|
-
| `Unable to resolve @/lib/medwayIcons` | Bug
|
|
243
|
-
| `Unable to resolve ../../../../../src/...`
|
|
244
|
-
| Tokens / tailwind
|
|
245
|
-
| NativeWind
|
|
246
|
-
| Select/Dialog
|
|
243
|
+
| `Unable to resolve .../src/components/Badge` | Alias `@/` do app sobrescreve o `@/` da lib | Adicione `createMedwayUiAliasResolver` no Babel |
|
|
244
|
+
| `Unable to resolve @/lib/medwayIcons` | Bug no `@medway-ui/native@1.1.1` | Atualize para `1.1.2+` |
|
|
245
|
+
| `Unable to resolve ../../../../../src/...` a partir de `lib/module/` | `resolveNativeSource: false` | Remova a opção (use o padrão `true`) |
|
|
246
|
+
| Tokens / tailwind não carregam (Node 22+) | `require` de `.ts` dentro de `node_modules` | Use `@medway-ui/native@1.1.2+` (`createMedwayUiTailwindConfig` usa fallback com jiti) |
|
|
247
|
+
| Estilos do NativeWind não aplicados | Arquivo fora do escopo brownfield | Mova para `src/pages/medway-ui/` ou adicione um glob no tailwind |
|
|
248
|
+
| Select/Dialog não abre | `PortalHost` ausente | Use `MedwayUiProvider` |
|
|
247
249
|
|
|
248
250
|
---
|
|
249
251
|
|
|
250
|
-
##
|
|
252
|
+
## Setup greenfield (app 100% NativeWind)
|
|
251
253
|
|
|
252
|
-
|
|
254
|
+
Para apps novos, sem UI legada:
|
|
253
255
|
|
|
254
256
|
```js
|
|
255
257
|
// babel.config.js
|
|
@@ -275,11 +277,11 @@ module.exports = withMedwayUi(getDefaultConfig(__dirname), {
|
|
|
275
277
|
});
|
|
276
278
|
```
|
|
277
279
|
|
|
278
|
-
|
|
280
|
+
Importe `@medway-ui/native/setup/global.css` no layout raiz.
|
|
279
281
|
|
|
280
282
|
---
|
|
281
283
|
|
|
282
|
-
##
|
|
284
|
+
## Uso
|
|
283
285
|
|
|
284
286
|
```tsx
|
|
285
287
|
import {
|
|
@@ -297,11 +299,11 @@ export default function Screen() {
|
|
|
297
299
|
return (
|
|
298
300
|
<>
|
|
299
301
|
<Button variant="regular" size="md" onPress={() => {}}>
|
|
300
|
-
|
|
302
|
+
Continuar
|
|
301
303
|
</Button>
|
|
302
304
|
|
|
303
305
|
<Input
|
|
304
|
-
label="
|
|
306
|
+
label="E-mail"
|
|
305
307
|
type="email"
|
|
306
308
|
size="lg"
|
|
307
309
|
value={email}
|
|
@@ -312,8 +314,8 @@ export default function Screen() {
|
|
|
312
314
|
<Alert variant="success" onClose={() => {}}>
|
|
313
315
|
<AlertContainer>
|
|
314
316
|
<AlertContent>
|
|
315
|
-
<AlertTitle>
|
|
316
|
-
<AlertDescription>
|
|
317
|
+
<AlertTitle>Pronto</AlertTitle>
|
|
318
|
+
<AlertDescription>Operação concluída com sucesso.</AlertDescription>
|
|
317
319
|
</AlertContent>
|
|
318
320
|
</AlertContainer>
|
|
319
321
|
</Alert>
|
|
@@ -324,9 +326,9 @@ export default function Screen() {
|
|
|
324
326
|
}
|
|
325
327
|
```
|
|
326
328
|
|
|
327
|
-
##
|
|
329
|
+
## Ícones
|
|
328
330
|
|
|
329
|
-
|
|
331
|
+
O pacote `@medway-ui/icons` inclui um entry point nativo:
|
|
330
332
|
|
|
331
333
|
```tsx
|
|
332
334
|
import { Check, CloseMd } from "@medway-ui/icons/native";
|
|
@@ -334,53 +336,54 @@ import { Check, CloseMd } from "@medway-ui/icons/native";
|
|
|
334
336
|
|
|
335
337
|
---
|
|
336
338
|
|
|
337
|
-
##
|
|
339
|
+
## Componentes: status
|
|
338
340
|
|
|
339
|
-
|
|
|
341
|
+
| Componente | Status | Notas |
|
|
340
342
|
| --- | --- | --- |
|
|
341
|
-
| Button | ✅ |
|
|
343
|
+
| Button | ✅ | Variantes, loading, badge, ponto de alerta |
|
|
342
344
|
| Input | ✅ | text, email, password, numeric |
|
|
343
|
-
| Alert | ✅ |
|
|
344
|
-
| Badge | ✅ |
|
|
345
|
-
| Loading | ✅ | Reanimated
|
|
346
|
-
| LoadingOverlay | ✅ | Card + Modal
|
|
345
|
+
| Alert | ✅ | Subcomponentes, todas as variantes |
|
|
346
|
+
| Badge | ✅ | Primary, secondary e grandes áreas, cheias ou `-soft`; freemium, só ícone e ponto |
|
|
347
|
+
| Loading | ✅ | Spin com Reanimated |
|
|
348
|
+
| LoadingOverlay | ✅ | Overlay de Card + Modal, ícone central customizável |
|
|
347
349
|
| Checkbox | ✅ | @rn-primitives/checkbox |
|
|
348
350
|
| RadioGroup | ✅ | @rn-primitives/radio-group |
|
|
349
351
|
| Switch | ✅ | @rn-primitives/switch |
|
|
350
352
|
| Select | ✅ | @rn-primitives/select |
|
|
351
353
|
| Label | ✅ | Pressable + Text |
|
|
352
|
-
| Separator | ✅ | View 1px |
|
|
354
|
+
| Separator | ✅ | View de 1px |
|
|
353
355
|
| Dialog | ✅ | @rn-primitives/dialog |
|
|
354
356
|
| AlertDialog | ✅ | @rn-primitives/alert-dialog |
|
|
355
|
-
| Sheet | ✅ | @rn-primitives/dialog (
|
|
356
|
-
| Tag | ✅ | 16+
|
|
357
|
-
| Toast | ✅ | useToast + toast();
|
|
357
|
+
| Sheet | ✅ | @rn-primitives/dialog (ciente do lado) |
|
|
358
|
+
| Tag | ✅ | 16+ variantes |
|
|
359
|
+
| Toast | ✅ | useToast + toast(); variantes com gradiente + inset de safe area |
|
|
358
360
|
| Tooltip | ✅ | @rn-primitives/tooltip |
|
|
359
361
|
| Popover | ✅ | @rn-primitives/popover |
|
|
360
362
|
| Skeleton | ✅ | Shimmer |
|
|
361
363
|
| Avatar | ✅ | @rn-primitives/avatar |
|
|
362
364
|
| FallbackImage | ✅ | react-native-svg |
|
|
363
|
-
| CardNews | ✅ |
|
|
364
|
-
| IndexLevel | ✅ |
|
|
365
|
+
| CardNews | ✅ | Card composable (Content Hub) |
|
|
366
|
+
| IndexLevel | ✅ | Níveis p/h/m/l, variantes, anel com gradiente `animated` |
|
|
365
367
|
| Tabs | ✅ | Tabs, TabsList, TabsTrigger, TabsContent |
|
|
366
|
-
|
|
|
367
|
-
|
|
|
368
|
-
|
|
|
369
|
-
|
|
|
370
|
-
|
|
|
368
|
+
| SegmentControl | ✅ | SegmentControl, SegmentControlList, SegmentControlTrigger (ícone e badge), SegmentControlContent |
|
|
369
|
+
| Chip | ✅ | Tamanhos e variantes |
|
|
370
|
+
| Choice | ✅ | Pill selecionável com cores do tema |
|
|
371
|
+
| Filter | ✅ | Pill com critérios e indicador de dropdown |
|
|
372
|
+
| Text | ✅ | Resolução da fonte Montserrat |
|
|
373
|
+
| ThemedIcon | ✅ | Ícone colorido por token do tema |
|
|
371
374
|
| DropdownMenu | ✅ | @rn-primitives/dropdown-menu |
|
|
372
|
-
| Carousel | ✅ |
|
|
373
|
-
| EmptyState | ✅ |
|
|
375
|
+
| Carousel | ✅ | Slides de mídia e de métrica |
|
|
376
|
+
| EmptyState | ✅ | Placeholder de lista/tela vazia |
|
|
374
377
|
| Feed | ✅ | Feed, FeedTitle, FeedComposer |
|
|
375
|
-
| FeedNotice | ✅ |
|
|
376
|
-
| Feedback | ✅ |
|
|
377
|
-
| InvitePopover | ✅ |
|
|
378
|
-
| LeaderboardCard | ✅ |
|
|
379
|
-
| MemberRow | ✅ |
|
|
380
|
-
| PageHeader | ✅ |
|
|
381
|
-
| PostForm | ✅ |
|
|
382
|
-
| PrizeCollection | ✅ |
|
|
383
|
-
| SectionHeader | ✅ |
|
|
378
|
+
| FeedNotice | ✅ | Banner de aviso do feed |
|
|
379
|
+
| Feedback | ✅ | Card de feedback |
|
|
380
|
+
| InvitePopover | ✅ | Popover de convite composable |
|
|
381
|
+
| LeaderboardCard | ✅ | Cabeçalho e lista ranqueada |
|
|
382
|
+
| MemberRow | ✅ | Linha de membro com indicador de posição |
|
|
383
|
+
| PageHeader | ✅ | Cabeçalho de tela |
|
|
384
|
+
| PostForm | ✅ | Formulário de post composable (mídia, data/hora, opções) |
|
|
385
|
+
| PrizeCollection | ✅ | Estatísticas, prateleira, linhas e itens |
|
|
386
|
+
| SectionHeader | ✅ | Cabeçalho com título de seção |
|
|
384
387
|
| Progress | 🔜 | @rn-primitives/progress |
|
|
385
388
|
| ProgressCircle | 🔜 | react-native-svg |
|
|
386
389
|
| Cards | 🔜 | CardModule, CardLesson, etc. |
|
|
@@ -13,58 +13,163 @@ var _classVarianceAuthority = require("class-variance-authority");
|
|
|
13
13
|
var _utils = require("@/lib/utils");
|
|
14
14
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
15
15
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
lg: "h-6 w-6 p-0",
|
|
20
|
-
xl: "h-7 w-7 p-0"
|
|
21
|
-
};
|
|
22
|
-
const CHAR_PADDING = {
|
|
23
|
-
sm: "px-1",
|
|
24
|
-
md: "px-1",
|
|
25
|
-
lg: "px-1",
|
|
26
|
-
xl: "px-1.5"
|
|
27
|
-
};
|
|
28
|
-
const badgeVariants = exports.badgeVariants = (0, _classVarianceAuthority.cva)("flex-row items-center justify-center rounded-full px-2", {
|
|
16
|
+
// A dot has no content, so the types flag what it would drop.
|
|
17
|
+
|
|
18
|
+
const badgeVariants = exports.badgeVariants = (0, _classVarianceAuthority.cva)("flex-row items-center justify-center rounded-pill", {
|
|
29
19
|
variants: {
|
|
30
20
|
variant: {
|
|
21
|
+
primary: "bg-primary-background-fill",
|
|
22
|
+
"primary-soft": "bg-surface-card",
|
|
23
|
+
secondary: "bg-secondary-background-fill",
|
|
24
|
+
"secondary-soft": "bg-surface-card",
|
|
31
25
|
regular: "bg-secondary-background-fill",
|
|
26
|
+
cm: "bg-cm-background-fill",
|
|
27
|
+
"cm-soft": "bg-surface-card",
|
|
28
|
+
go: "bg-go-background-fill",
|
|
29
|
+
"go-soft": "bg-surface-card",
|
|
30
|
+
cir: "bg-cir-background-fill",
|
|
31
|
+
"cir-soft": "bg-surface-card",
|
|
32
|
+
// The design paints pediatrics with the warning tokens, all but the filled label.
|
|
33
|
+
ped: "bg-yellow-background-fill",
|
|
34
|
+
"ped-soft": "bg-surface-card",
|
|
35
|
+
prev: "bg-prev-background-fill",
|
|
36
|
+
"prev-soft": "bg-surface-card",
|
|
37
|
+
freemium: "bg-primary",
|
|
32
38
|
error: "bg-red-background-soft",
|
|
33
39
|
warning: "bg-yellow-background-soft",
|
|
34
|
-
|
|
40
|
+
neutral: "bg-gray-background-soft"
|
|
35
41
|
},
|
|
36
42
|
size: {
|
|
37
|
-
sm: "min-h-4 min-w-4",
|
|
38
|
-
md: "min-h-5 min-w-5",
|
|
39
|
-
lg: "min-h-6 min-w-6",
|
|
40
|
-
xl: "min-h-7 min-w-7"
|
|
43
|
+
sm: "min-h-4 min-w-4 gap-1 px-1 py-0.5",
|
|
44
|
+
md: "min-h-5 min-w-5 gap-1 px-1 py-0.5",
|
|
45
|
+
lg: "min-h-6 min-w-6 gap-1.5 px-1.5 py-1",
|
|
46
|
+
xl: "min-h-7 min-w-7 gap-2 px-2 py-1"
|
|
41
47
|
}
|
|
42
48
|
},
|
|
49
|
+
compoundVariants: [{
|
|
50
|
+
variant: "freemium",
|
|
51
|
+
size: "md",
|
|
52
|
+
className: "px-1.5 py-1"
|
|
53
|
+
}, {
|
|
54
|
+
variant: "freemium",
|
|
55
|
+
size: "lg",
|
|
56
|
+
className: "px-2"
|
|
57
|
+
}, {
|
|
58
|
+
variant: "freemium",
|
|
59
|
+
size: "xl",
|
|
60
|
+
className: "px-2.5"
|
|
61
|
+
}],
|
|
43
62
|
defaultVariants: {
|
|
44
|
-
variant: "
|
|
63
|
+
variant: "secondary",
|
|
45
64
|
size: "md"
|
|
46
65
|
}
|
|
47
66
|
});
|
|
48
|
-
|
|
67
|
+
// Laid over `surface-card`, as in the design, so a soft badge stays opaque on any surface.
|
|
68
|
+
const SOFT_TINT = {
|
|
69
|
+
"primary-soft": "bg-primary-background-soft",
|
|
70
|
+
"secondary-soft": "bg-secondary-background-soft",
|
|
71
|
+
"cm-soft": "bg-cm-background-soft",
|
|
72
|
+
"go-soft": "bg-go-background-soft",
|
|
73
|
+
"cir-soft": "bg-cir-background-soft",
|
|
74
|
+
"ped-soft": "bg-yellow-background-soft",
|
|
75
|
+
"prev-soft": "bg-prev-background-soft"
|
|
76
|
+
};
|
|
77
|
+
const badgeTextVariants = (0, _classVarianceAuthority.cva)("font-bold", {
|
|
49
78
|
variants: {
|
|
50
79
|
variant: {
|
|
80
|
+
primary: "text-primary-foreground-onfill",
|
|
81
|
+
"primary-soft": "text-primary-foreground",
|
|
82
|
+
secondary: "text-secondary-foreground-onfill",
|
|
83
|
+
"secondary-soft": "text-secondary-foreground",
|
|
51
84
|
regular: "text-secondary-foreground-onfill",
|
|
85
|
+
cm: "text-cm-foreground-onfill",
|
|
86
|
+
"cm-soft": "text-cm-foreground",
|
|
87
|
+
go: "text-go-foreground-onfill",
|
|
88
|
+
"go-soft": "text-go-foreground",
|
|
89
|
+
cir: "text-cir-foreground-onfill",
|
|
90
|
+
"cir-soft": "text-cir-foreground",
|
|
91
|
+
ped: "text-ped-foreground-onfill",
|
|
92
|
+
"ped-soft": "text-yellow-foreground",
|
|
93
|
+
prev: "text-prev-foreground-onfill",
|
|
94
|
+
"prev-soft": "text-prev-foreground",
|
|
95
|
+
// White, not the design's onfill token: that one turns dark in dark mode, on a fill that stays navy.
|
|
96
|
+
freemium: "font-semibold text-white",
|
|
52
97
|
error: "text-red-stroke-emphasis",
|
|
53
98
|
warning: "text-yellow-foreground",
|
|
54
|
-
|
|
99
|
+
neutral: "text-primary-foreground"
|
|
55
100
|
},
|
|
56
101
|
size: {
|
|
57
|
-
sm: "text-
|
|
58
|
-
md: "text-xs",
|
|
59
|
-
lg: "text-xs",
|
|
60
|
-
xl: "text-sm"
|
|
102
|
+
sm: "text-xxs leading-xxs",
|
|
103
|
+
md: "text-xs leading-xs",
|
|
104
|
+
lg: "text-xs leading-xs",
|
|
105
|
+
xl: "text-sm leading-sm"
|
|
61
106
|
}
|
|
62
107
|
},
|
|
108
|
+
compoundVariants: [{
|
|
109
|
+
variant: "freemium",
|
|
110
|
+
size: "md",
|
|
111
|
+
className: "text-xxs leading-xxs"
|
|
112
|
+
}],
|
|
63
113
|
defaultVariants: {
|
|
64
|
-
variant: "
|
|
114
|
+
variant: "secondary",
|
|
65
115
|
size: "md"
|
|
66
116
|
}
|
|
67
117
|
});
|
|
118
|
+
const badgeDotVariants = (0, _classVarianceAuthority.cva)("rounded-circular", {
|
|
119
|
+
variants: {
|
|
120
|
+
variant: {
|
|
121
|
+
primary: "bg-primary-background-fill",
|
|
122
|
+
"primary-soft": "bg-primary-background-fill",
|
|
123
|
+
secondary: "bg-secondary-background-fill",
|
|
124
|
+
"secondary-soft": "bg-secondary-background-fill",
|
|
125
|
+
regular: "bg-secondary-background-fill",
|
|
126
|
+
cm: "bg-cm-background-fill",
|
|
127
|
+
"cm-soft": "bg-cm-background-fill",
|
|
128
|
+
go: "bg-go-background-fill",
|
|
129
|
+
"go-soft": "bg-go-background-fill",
|
|
130
|
+
cir: "bg-cir-background-fill",
|
|
131
|
+
"cir-soft": "bg-cir-background-fill",
|
|
132
|
+
ped: "bg-yellow-background-fill",
|
|
133
|
+
"ped-soft": "bg-yellow-background-fill",
|
|
134
|
+
prev: "bg-prev-background-fill",
|
|
135
|
+
"prev-soft": "bg-prev-background-fill",
|
|
136
|
+
freemium: "bg-primary",
|
|
137
|
+
error: "bg-red-background-fill",
|
|
138
|
+
warning: "bg-yellow-background-fill",
|
|
139
|
+
neutral: "bg-gray-background-fill"
|
|
140
|
+
},
|
|
141
|
+
size: {
|
|
142
|
+
sm: "size-1",
|
|
143
|
+
md: "size-2",
|
|
144
|
+
lg: "size-3",
|
|
145
|
+
xl: "size-4"
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
defaultVariants: {
|
|
149
|
+
variant: "secondary",
|
|
150
|
+
size: "md"
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// The design's 10, 12, 16 and 20px as a minimum: a bigger icon grows the badge instead of
|
|
155
|
+
// spilling over its gap and padding.
|
|
156
|
+
const ICON_BOX = {
|
|
157
|
+
sm: "min-h-2.5 min-w-2.5",
|
|
158
|
+
md: "min-h-3 min-w-3",
|
|
159
|
+
lg: "min-h-4 min-w-4",
|
|
160
|
+
xl: "min-h-5 min-w-5"
|
|
161
|
+
};
|
|
162
|
+
const ICON_ONLY_PADDING = {
|
|
163
|
+
sm: "p-0.5",
|
|
164
|
+
md: "px-1 py-0.5",
|
|
165
|
+
lg: "p-1",
|
|
166
|
+
xl: "p-1"
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Corner to corner like the design's at any width, unlike the web's fixed 46deg.
|
|
170
|
+
const FREEMIUM_GRADIENT = {
|
|
171
|
+
experimental_backgroundImage: "radial-gradient(135.09% 111.8% at 0% 50%, rgba(24, 98, 188, 0.02) 0%, rgba(0, 32, 91, 0) 100%), linear-gradient(to top right, rgba(62, 218, 199, 0.56) 6.54%, rgba(24, 98, 188, 0.17) 85.21%)"
|
|
172
|
+
};
|
|
68
173
|
const SHINE_DURATION_MS = 2000;
|
|
69
174
|
function BadgeShine() {
|
|
70
175
|
const progress = (0, _reactNativeReanimated.useSharedValue)(0);
|
|
@@ -89,7 +194,7 @@ function BadgeShine() {
|
|
|
89
194
|
}, [progress]);
|
|
90
195
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
91
196
|
pointerEvents: "none",
|
|
92
|
-
className: "absolute inset-0 overflow-hidden rounded-
|
|
197
|
+
className: "absolute inset-0 overflow-hidden rounded-pill",
|
|
93
198
|
onLayout: handleLayout,
|
|
94
199
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
|
95
200
|
className: "absolute bottom-0 top-0 bg-white-24",
|
|
@@ -103,28 +208,46 @@ function Badge({
|
|
|
103
208
|
size,
|
|
104
209
|
icon,
|
|
105
210
|
animation,
|
|
211
|
+
layout = "tag",
|
|
212
|
+
style,
|
|
106
213
|
children,
|
|
107
214
|
...props
|
|
108
215
|
}) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
216
|
+
if (layout === "dot") {
|
|
217
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
218
|
+
className: (0, _utils.cn)(badgeDotVariants({
|
|
219
|
+
variant,
|
|
220
|
+
size
|
|
221
|
+
}), className),
|
|
222
|
+
style: style,
|
|
223
|
+
...props
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
const resolvedSize = size ?? "md";
|
|
227
|
+
const tint = SOFT_TINT[variant ?? "secondary"];
|
|
228
|
+
const hasContent = children != null && typeof children !== "boolean" && children !== "";
|
|
229
|
+
const isIconOnly = !!icon && !hasContent;
|
|
115
230
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
116
231
|
className: (0, _utils.cn)(badgeVariants({
|
|
117
232
|
variant,
|
|
118
233
|
size
|
|
119
|
-
}),
|
|
234
|
+
}), isIconOnly && ICON_ONLY_PADDING[resolvedSize], className),
|
|
235
|
+
style: variant === "freemium" ? [FREEMIUM_GRADIENT, style] : style,
|
|
120
236
|
...props,
|
|
121
|
-
children: [
|
|
237
|
+
children: [tint ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
238
|
+
pointerEvents: "none",
|
|
239
|
+
className: (0, _utils.cn)("absolute inset-0 rounded-pill", tint)
|
|
240
|
+
}) : null, animation === "shine" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(BadgeShine, {}) : null, icon ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
241
|
+
className: (0, _utils.cn)("items-center justify-center", ICON_BOX[resolvedSize]),
|
|
242
|
+
children: icon
|
|
243
|
+
}) : null, hasContent ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.Text, {
|
|
244
|
+
numberOfLines: 1,
|
|
122
245
|
className: (0, _utils.cn)(badgeTextVariants({
|
|
123
246
|
variant,
|
|
124
247
|
size
|
|
125
248
|
})),
|
|
126
249
|
children: children
|
|
127
|
-
})]
|
|
250
|
+
}) : null]
|
|
128
251
|
});
|
|
129
252
|
}
|
|
130
253
|
//# sourceMappingURL=Badge.js.map
|