@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.
Files changed (50) hide show
  1. package/README.md +92 -89
  2. package/lib/commonjs/components/Badge.js +159 -36
  3. package/lib/commonjs/components/Badge.js.map +1 -1
  4. package/lib/commonjs/components/Choice.js +35 -37
  5. package/lib/commonjs/components/Choice.js.map +1 -1
  6. package/lib/commonjs/components/SegmentControl.js +197 -0
  7. package/lib/commonjs/components/SegmentControl.js.map +1 -0
  8. package/lib/commonjs/editor/editorHtml.generated.js +1 -1
  9. package/lib/commonjs/editor/editorHtml.generated.js.map +1 -1
  10. package/lib/commonjs/hooks/useThemeColor.js +42 -42
  11. package/lib/commonjs/hooks/useThemeColor.js.map +1 -1
  12. package/lib/commonjs/index.js +31 -0
  13. package/lib/commonjs/index.js.map +1 -1
  14. package/lib/commonjs/lib/raised-surface.js +24 -0
  15. package/lib/commonjs/lib/raised-surface.js.map +1 -0
  16. package/lib/module/components/Badge.js +159 -36
  17. package/lib/module/components/Badge.js.map +1 -1
  18. package/lib/module/components/Choice.js +35 -37
  19. package/lib/module/components/Choice.js.map +1 -1
  20. package/lib/module/components/SegmentControl.js +189 -0
  21. package/lib/module/components/SegmentControl.js.map +1 -0
  22. package/lib/module/editor/editorHtml.generated.js +1 -1
  23. package/lib/module/editor/editorHtml.generated.js.map +1 -1
  24. package/lib/module/hooks/useThemeColor.js +42 -42
  25. package/lib/module/hooks/useThemeColor.js.map +1 -1
  26. package/lib/module/index.js +2 -0
  27. package/lib/module/index.js.map +1 -1
  28. package/lib/module/lib/raised-surface.js +22 -0
  29. package/lib/module/lib/raised-surface.js.map +1 -0
  30. package/lib/typescript/components/Badge.d.ts +14 -4
  31. package/lib/typescript/components/Badge.d.ts.map +1 -1
  32. package/lib/typescript/components/Chip.d.ts +2 -2
  33. package/lib/typescript/components/Choice.d.ts.map +1 -1
  34. package/lib/typescript/components/SegmentControl.d.ts +37 -0
  35. package/lib/typescript/components/SegmentControl.d.ts.map +1 -0
  36. package/lib/typescript/components/Tag.d.ts +2 -2
  37. package/lib/typescript/editor/editorHtml.generated.d.ts.map +1 -1
  38. package/lib/typescript/index.d.ts +3 -1
  39. package/lib/typescript/index.d.ts.map +1 -1
  40. package/lib/typescript/lib/raised-surface.d.ts +3 -0
  41. package/lib/typescript/lib/raised-surface.d.ts.map +1 -0
  42. package/package.json +2 -2
  43. package/setup/tokens.native.css +49 -22
  44. package/src/components/Badge.tsx +207 -61
  45. package/src/components/Choice.tsx +66 -45
  46. package/src/components/SegmentControl.tsx +265 -0
  47. package/src/editor/editorHtml.generated.ts +1 -1
  48. package/src/hooks/useThemeColor.ts +42 -42
  49. package/src/index.ts +21 -1
  50. 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 components for iOS and Android (Expo). Same visual API as `@medway-ui/core`, built on NativeWind + `@rn-primitives`.
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
- **Minimum recommended version for npm brownfield setup:** `1.1.2+`
5
+ **Versão mínima recomendada para setup brownfield via npm:** `1.1.2+`
6
6
 
7
7
  ---
8
8
 
9
- ## Installation
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 (aligns versions with your SDK)
17
- # expo-linear-gradient + masked-view: optional peers for IndexLevel `animated` ring
18
- # and Toast gradient variants (solid color fallback when missing)
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` is an optional peer used by `ToastProvider` for top inset. Expo apps usually already have it (and a root `SafeAreaProvider` via React Navigation). Without a provider, the toast falls back to the previous `pt-12` offset.
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
- Brownfield apps that already use `babel-plugin-module-resolver` with `@/` aliases pointing at the app `src/` also need:
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
- ## Brownfield setup (Expo + legacy UI / Restyle)
38
+ ## Setup brownfield (Expo + UI legada / Restyle)
37
39
 
38
- NativeWind applies **only** to `@medway-ui/native` + screens/components that use the library (e.g. `src/pages/medway-ui/`, partially migrated features).
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
- Reference implementation: **test-prep-app** (`metro.config.js`, `babel.config.js`, `tailwind.config.js`, `src/pages/medway-ui/`).
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: auto-detected (npm or monorepo)
52
+ // linkedMedwayUiRoot: detectado automaticamente (npm ou monorepo)
51
53
  });
52
54
  ```
53
55
 
54
- | Scenario | `linkedMedwayUiRoot` |
56
+ | Cenário | `linkedMedwayUiRoot` |
55
57
  | --- | --- |
56
- | npm packages (`npm install`) | **Omit** — auto-detects `node_modules/@medway-ui` |
57
- | Monorepo with local clone | `"../medway-ui"` (optional; also auto-detected) |
58
- | Symlink `file:../medway-ui/native` | Auto-detected as monorepo |
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
- > Do **not** set `resolveNativeSource: false` — the compiled lib still references internal `@/` aliases. The default (`true`) resolves to `native/src` and works with npm.
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
- // add extra folders that use className + @medway-ui/native:
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` already includes globs for `node_modules/@medway-ui/native/src` and loads tokens from `@medway-ui/core` (Node 22+ compatible).
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
- The app default preset must **not** enable NativeWind globally. Use `createBrownfieldOverride` to scope NativeWind to the library + migrated screens folder.
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
- If the app defines `@/` aliases for `./src/*` via `babel-plugin-module-resolver`, you **must** redirect `@/` imports from `@medway-ui/native` files to the library source — otherwise imports like `@/components/Badge` resolve to the app `src/` and break the bundle.
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
- // ... other app aliases
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
- // other app plugins (no reanimated here)
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 subfolder with NativeWind screens
123
+ appPagesDir: "medway-ui", // subpasta de src/pages com as telas NativeWind
122
124
  plugins: [
123
- // repeat any plugins needed in the medway-ui scope
124
- "react-native-reanimated/plugin", // always last
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 **without** `@/` Babel aliases do not need `createMedwayUiAliasResolver`.
134
+ Apps **sem** aliases `@/` no Babel não precisam de `createMedwayUiAliasResolver`.
133
135
 
134
136
  ### 4. Provider + CSS
135
137
 
136
- Wrap the subtree that uses `@medway-ui/native` with `MedwayUiProvider` and import CSS once:
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:** pass `colorScheme="light" | "dark"` when the app already resolves theme (Redux, Zustand, etc.):
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` includes `PortalHost` (required for Select, Dialog, Popover, Tooltip).
161
+ `MedwayUiProvider` inclui o `PortalHost` (obrigatório para Select, Dialog, Popover, Tooltip).
160
162
 
161
- > Do **not** import `@medway-ui/core/tokens.css` directly — incompatible with NativeWind v4. Tokens come from `setup/global.css` + `setup/tokens.native.css`.
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. Auto navigator (catalog / isolated screens)
165
+ ### 5. Navigator automático (catálogo / telas isoladas)
164
166
 
165
- Create once `src/pages/medway-ui/navigator.tsx`:
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
- Register in the app stack:
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
- New screen = new folder `src/pages/medway-ui/MyScreen/index.tsx` — no manual route registration.
194
+ Nova tela = nova pasta `src/pages/medway-ui/MyScreen/index.tsx`, sem registro manual de rota.
193
195
 
194
- ### 6. Using components in existing screens (Restyle + Medway UI mix)
196
+ ### 6. Usando componentes em telas existentes (mistura de Restyle + Medway UI)
195
197
 
196
- Pattern used in Content Hub and partially migrated features:
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
- Add the feature folder to `content` in `tailwind.config.js`.
216
+ Adicione a pasta da feature ao `content` do `tailwind.config.js`.
215
217
 
216
218
  ---
217
219
 
218
- ## Monorepo development (`file:../medway-ui/native`)
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 and Babel auto-detect the local clone. After library changes:
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 # if testing the compiled lib
232
+ cd ../medway-ui/native && npm run build:lib # se estiver testando a lib compilada
231
233
  ```
232
234
 
233
- Restart Metro with a clean cache: `npx expo start --clear`.
235
+ Reinicie o Metro com cache limpo: `npx expo start --clear`.
234
236
 
235
237
  ---
236
238
 
237
- ## Troubleshooting
239
+ ## Solução de problemas
238
240
 
239
- | Error | Cause | Fix |
241
+ | Erro | Causa | Correção |
240
242
  | --- | --- | --- |
241
- | `Unable to resolve .../src/components/Badge` | App `@/` alias overrides lib `@/` | Add `createMedwayUiAliasResolver` in Babel |
242
- | `Unable to resolve @/lib/medwayIcons` | Bug in `@medway-ui/native@1.1.1` | Upgrade to `1.1.2+` |
243
- | `Unable to resolve ../../../../../src/...` from `lib/module/` | `resolveNativeSource: false` | Remove the option (use default `true`) |
244
- | Tokens / tailwind fail to load (Node 22+) | `require` of `.ts` inside `node_modules` | Use `@medway-ui/native@1.1.2+` (`createMedwayUiTailwindConfig` uses jiti fallback) |
245
- | NativeWind styles not applied | File outside brownfield scope | Move to `src/pages/medway-ui/` or add a tailwind glob |
246
- | Select/Dialog not opening | Missing `PortalHost` | Use `MedwayUiProvider` |
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
- ## Greenfield setup (100% NativeWind app)
252
+ ## Setup greenfield (app 100% NativeWind)
251
253
 
252
- For new apps without legacy UI:
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
- Import `@medway-ui/native/setup/global.css` in the root layout.
280
+ Importe `@medway-ui/native/setup/global.css` no layout raiz.
279
281
 
280
282
  ---
281
283
 
282
- ## Usage
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
- Continue
302
+ Continuar
301
303
  </Button>
302
304
 
303
305
  <Input
304
- label="Email"
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>Done</AlertTitle>
316
- <AlertDescription>Operation completed successfully.</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
- ## Icons
329
+ ## Ícones
328
330
 
329
- The `@medway-ui/icons` package includes a native entry point:
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
- ## Components — status
339
+ ## Componentes: status
338
340
 
339
- | Component | Status | Notes |
341
+ | Componente | Status | Notas |
340
342
  | --- | --- | --- |
341
- | Button | ✅ | Variants, loading, badge, alert dot |
343
+ | Button | ✅ | Variantes, loading, badge, ponto de alerta |
342
344
  | Input | ✅ | text, email, password, numeric |
343
- | Alert | ✅ | Sub-components, all variants |
344
- | Badge | ✅ | Variants, icon-only |
345
- | Loading | ✅ | Reanimated spin |
346
- | LoadingOverlay | ✅ | Card + Modal overlay, custom center icon |
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 (side-aware) |
356
- | Tag | ✅ | 16+ variants |
357
- | Toast | ✅ | useToast + toast(); gradient variants + safe-area inset |
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 | ✅ | Composable card (Content Hub) |
364
- | IndexLevel | ✅ | Levels p/h/m/l, variants, `animated` gradient ring |
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
- | Chip | ✅ | Sizes and variants |
367
- | Choice | ✅ | Selectable pill with theme colors |
368
- | Filter | ✅ | Pill with criteria and dropdown indicator |
369
- | Text | ✅ | Montserrat font resolution |
370
- | ThemedIcon | ✅ | Icon colored by theme token |
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 | ✅ | Media and metric slides |
373
- | EmptyState | ✅ | Empty list/screen placeholder |
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 | ✅ | Feed notice banner |
376
- | Feedback | ✅ | Feedback card |
377
- | InvitePopover | ✅ | Composable invite popover |
378
- | LeaderboardCard | ✅ | Header and ranked list |
379
- | MemberRow | ✅ | Member row with rank indicator |
380
- | PageHeader | ✅ | Screen header |
381
- | PostForm | ✅ | Composable post form (media, date/time, options) |
382
- | PrizeCollection | ✅ | Stats, shelf, rows and items |
383
- | SectionHeader | ✅ | Section title header |
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
- const ICON_ONLY_SIZES = {
17
- sm: "h-4 w-4 p-0",
18
- md: "h-5 w-5 p-0",
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
- freemium: "bg-primary-background-fill"
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: "regular",
63
+ variant: "secondary",
45
64
  size: "md"
46
65
  }
47
66
  });
48
- const badgeTextVariants = (0, _classVarianceAuthority.cva)("font-semibold", {
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
- freemium: "text-white"
99
+ neutral: "text-primary-foreground"
55
100
  },
56
101
  size: {
57
- sm: "text-xs",
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: "regular",
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-full",
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
- const childText = typeof children === "string" || typeof children === "number" ? String(children).trim() : "";
110
- const isSingleAlphaNum = /^[A-Za-z0-9]$/.test(childText);
111
- const isShortAlnumUpTo3 = /^[A-Za-z0-9]{2,3}$/.test(childText);
112
- const isDigitsWithSuffix = /^\d{1,2}\S$/.test(childText);
113
- const isIconOnly = !!icon && !children;
114
- const isShortUpTo3 = isShortAlnumUpTo3 || isDigitsWithSuffix;
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
- }), (isIconOnly || isSingleAlphaNum) && ICON_ONLY_SIZES[size ?? "md"], !isIconOnly && isShortUpTo3 && CHAR_PADDING[size ?? "md"], className),
234
+ }), isIconOnly && ICON_ONLY_PADDING[resolvedSize], className),
235
+ style: variant === "freemium" ? [FREEMIUM_GRADIENT, style] : style,
120
236
  ...props,
121
- children: [animation === "shine" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(BadgeShine, {}) : null, icon, children != null && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.Text, {
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