@retray-dev/ui-kit 5.1.0 → 5.4.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/COMPONENTS.md +257 -17
- package/EXAMPLES.md +666 -0
- package/README.md +12 -9
- package/dist/index.d.mts +117 -12
- package/dist/index.d.ts +117 -12
- package/dist/index.js +589 -364
- package/dist/index.mjs +527 -305
- package/package.json +3 -2
- package/src/components/Accordion/Accordion.tsx +25 -2
- package/src/components/Avatar/Avatar.tsx +21 -7
- package/src/components/Button/Button.tsx +16 -7
- package/src/components/ButtonGroup/ButtonGroup.tsx +60 -0
- package/src/components/ButtonGroup/index.ts +1 -0
- package/src/components/Chip/Chip.tsx +8 -1
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +7 -7
- package/src/components/CurrencyDisplay/CurrencyDisplay.tsx +25 -3
- package/src/components/DetailRow/DetailRow.tsx +140 -0
- package/src/components/DetailRow/index.ts +1 -0
- package/src/components/LabelValue/LabelValue.tsx +25 -4
- package/src/components/MonthPicker/MonthPicker.tsx +18 -6
- package/src/components/Sheet/Sheet.tsx +52 -16
- package/src/components/Textarea/Textarea.tsx +66 -29
- package/src/index.ts +5 -0
- package/src/tokens.ts +1 -1
- package/src/utils/typography.ts +24 -0
package/COMPONENTS.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @retray-dev/ui-kit — Component Reference (v5.
|
|
1
|
+
# @retray-dev/ui-kit — Component Reference (v5.4.0)
|
|
2
2
|
|
|
3
3
|
This file is the AI reference for this package. It is shipped inside the npm package so consuming projects can import it into their `CLAUDE.md` with:
|
|
4
4
|
|
|
@@ -499,6 +499,67 @@ const styles = StyleSheet.create({
|
|
|
499
499
|
|
|
500
500
|
---
|
|
501
501
|
|
|
502
|
+
### ButtonGroup
|
|
503
|
+
|
|
504
|
+
**Import:** `import { ButtonGroup } from '@retray-dev/ui-kit'`
|
|
505
|
+
|
|
506
|
+
**When to use:** Auto-distribute space equally between buttons in horizontal or vertical layouts. Perfect for side-by-side CTAs (Cancel/Confirm, Back/Next) where both buttons should occupy equal width.
|
|
507
|
+
|
|
508
|
+
| Prop | Type | Default | Notes |
|
|
509
|
+
|------|------|---------|-------|
|
|
510
|
+
| children | `React.ReactNode` | required | Button components to lay out |
|
|
511
|
+
| gap | `number` | `12` | Spacing between buttons (in points) |
|
|
512
|
+
| vertical | `boolean` | `false` | Stack buttons vertically instead of horizontally |
|
|
513
|
+
| style | `ViewStyle` | — | Override container style |
|
|
514
|
+
|
|
515
|
+
**Behavior:** Automatically applies `flex: 1` to all direct children. Children share space equally regardless of label length.
|
|
516
|
+
|
|
517
|
+
**Mobile best practice:** When using 2 buttons with icons in a ButtonGroup, use `size="sm"` to prevent text clipping on narrow screens:
|
|
518
|
+
```tsx
|
|
519
|
+
// ✅ Good — Small size prevents overflow
|
|
520
|
+
<ButtonGroup>
|
|
521
|
+
<Button label="Cancel" variant="secondary" size="sm" iconName="x" onPress={handleCancel} />
|
|
522
|
+
<Button label="Confirm" size="sm" iconName="check" onPress={handleConfirm} />
|
|
523
|
+
</ButtonGroup>
|
|
524
|
+
|
|
525
|
+
// ❌ Avoid — Default size may clip text when icons present
|
|
526
|
+
<ButtonGroup>
|
|
527
|
+
<Button label="Cancel" variant="secondary" iconName="x" onPress={handleCancel} />
|
|
528
|
+
<Button label="Confirm" iconName="check" onPress={handleConfirm} />
|
|
529
|
+
</ButtonGroup>
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
**Examples:**
|
|
533
|
+
```tsx
|
|
534
|
+
// Horizontal pair (50%/50%)
|
|
535
|
+
<ButtonGroup>
|
|
536
|
+
<Button label="Cancel" variant="secondary" onPress={handleCancel} />
|
|
537
|
+
<Button label="Confirm" onPress={handleConfirm} />
|
|
538
|
+
</ButtonGroup>
|
|
539
|
+
|
|
540
|
+
// Custom gap
|
|
541
|
+
<ButtonGroup gap={8}>
|
|
542
|
+
<Button label="Back" variant="text" onPress={handleBack} />
|
|
543
|
+
<Button label="Next" onPress={handleNext} />
|
|
544
|
+
</ButtonGroup>
|
|
545
|
+
|
|
546
|
+
// Vertical stack
|
|
547
|
+
<ButtonGroup vertical gap={8}>
|
|
548
|
+
<Button label="Primary Action" onPress={handlePrimary} />
|
|
549
|
+
<Button label="Secondary Action" variant="secondary" onPress={handleSecondary} />
|
|
550
|
+
<Button label="Delete" variant="destructive" onPress={handleDelete} />
|
|
551
|
+
</ButtonGroup>
|
|
552
|
+
|
|
553
|
+
// Three buttons (33%/33%/33%)
|
|
554
|
+
<ButtonGroup gap={6}>
|
|
555
|
+
<Button label="1D" variant="secondary" size="sm" onPress={() => setRange('1d')} />
|
|
556
|
+
<Button label="1W" variant="secondary" size="sm" onPress={() => setRange('1w')} />
|
|
557
|
+
<Button label="1M" size="sm" onPress={() => setRange('1m')} />
|
|
558
|
+
</ButtonGroup>
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
502
563
|
### IconButton
|
|
503
564
|
|
|
504
565
|
**Import:** `import { IconButton } from '@retray-dev/ui-kit'`
|
|
@@ -682,6 +743,9 @@ const styles = StyleSheet.create({
|
|
|
682
743
|
| error | `string` | — | Error text below; turns border destructive (2px) |
|
|
683
744
|
| hint | `string` | — | Helper text below (hidden when `error` is set) |
|
|
684
745
|
| rows | `number` | `4` | Minimum row count — each row ≈ 30px. Sets `numberOfLines` |
|
|
746
|
+
| prefixIcon | `string` | — | Icon name from `@expo/vector-icons` rendered inside top-left corner |
|
|
747
|
+
| prefixIconNode | `ReactNode` | — | Custom icon node rendered top-left |
|
|
748
|
+
| prefixIconColor | `string` | — | Override prefix icon color. Defaults to `foregroundMuted` |
|
|
685
749
|
| containerStyle | `ViewStyle` | — | Outer container style |
|
|
686
750
|
| style | `TextStyle` | — | TextInput element style |
|
|
687
751
|
|
|
@@ -689,9 +753,9 @@ const styles = StyleSheet.create({
|
|
|
689
753
|
|
|
690
754
|
**Examples:**
|
|
691
755
|
```tsx
|
|
692
|
-
<Textarea label="Bio" placeholder="Tell us about yourself" rows={5} />
|
|
693
|
-
<Textarea label="Review" hint="Be honest and helpful" />
|
|
694
|
-
<Textarea label="Notes" error="Notes are required" rows={3} />
|
|
756
|
+
<Textarea label="Bio" placeholder="Tell us about yourself" rows={5} prefixIcon="user" />
|
|
757
|
+
<Textarea label="Review" hint="Be honest and helpful" prefixIcon="message-circle" />
|
|
758
|
+
<Textarea label="Notes" error="Notes are required" rows={3} prefixIcon="edit-3" />
|
|
695
759
|
```
|
|
696
760
|
|
|
697
761
|
---
|
|
@@ -776,6 +840,9 @@ const [amount, setAmount] = useState(0)
|
|
|
776
840
|
| prefix | `string` | `'$'` | Symbol prepended to formatted value |
|
|
777
841
|
| showDecimals | `boolean` | `false` | Show two decimal places with comma separator (e.g. `$25.000,00`) |
|
|
778
842
|
| textColor | `string` | — | Override text color. Defaults to `foreground` token |
|
|
843
|
+
| variant | `'hero' \| 'large' \| 'medium' \| 'small'` | — | Predefined size (48/32/18/14pt). Overrides default 56pt |
|
|
844
|
+
| autoScale | `boolean` | `false` | Enable `adjustsFontSizeToFit` — long values shrink to fit one line |
|
|
845
|
+
| maxFontSize | `number` | — | Max font size when `autoScale` true. Defaults to variant size or 56pt |
|
|
779
846
|
| style | `ViewStyle` | — | Outer container style |
|
|
780
847
|
|
|
781
848
|
**Format:** Dot (`.`) as thousands separator, comma (`,`) as decimal separator — Latin American / European format.
|
|
@@ -874,9 +941,10 @@ const [amount, setAmount] = useState(0)
|
|
|
874
941
|
|
|
875
942
|
| Prop | Type | Default | Notes |
|
|
876
943
|
|------|------|---------|-------|
|
|
877
|
-
| src | `string` | — | Image URI (remote or local) |
|
|
878
|
-
| fallback | `string` | — |
|
|
879
|
-
|
|
|
944
|
+
| src | `string \| null` | — | Image URI (remote or local). `null` forces fallback |
|
|
945
|
+
| fallback | `string` | — | Manual initials (max 2 chars, uppercased) |
|
|
946
|
+
| fallbackText | `string` | — | Full name — extracts up to 2 initials (e.g. `"Julian Cruz"` → `"JC"`) |
|
|
947
|
+
| size | `'sm' \| 'md' \| 'lg' \| 'xl' \| number` | `'md'` | Named size or custom diameter in points |
|
|
880
948
|
| status | `'online' \| 'offline' \| 'busy' \| 'away'` | — | Status indicator dot, bottom-right |
|
|
881
949
|
| style | `ViewStyle` | — | — |
|
|
882
950
|
|
|
@@ -903,6 +971,8 @@ const [amount, setAmount] = useState(0)
|
|
|
903
971
|
<Avatar fallback="AN" size="md" />
|
|
904
972
|
<Avatar src={user.avatar} fallback={user.initials} size="xl" status="online" />
|
|
905
973
|
<Avatar fallback="BU" size="sm" status="busy" />
|
|
974
|
+
<Avatar fallbackText="Julian Cruz" size="md" /> // → "JC"
|
|
975
|
+
<Avatar src={avatarUrl} size={64} /> // custom numeric size
|
|
906
976
|
|
|
907
977
|
// In a ListItem
|
|
908
978
|
<ListItem
|
|
@@ -1773,7 +1843,14 @@ const [tab, setTab] = useState('profile')
|
|
|
1773
1843
|
|
|
1774
1844
|
**AccordionItem type:**
|
|
1775
1845
|
```ts
|
|
1776
|
-
{
|
|
1846
|
+
{
|
|
1847
|
+
value: string
|
|
1848
|
+
trigger: string
|
|
1849
|
+
content: ReactNode
|
|
1850
|
+
iconName?: string // Icon name from @expo/vector-icons
|
|
1851
|
+
icon?: ReactNode // Custom icon node
|
|
1852
|
+
iconColor?: string // Override icon color (defaults to foregroundMuted)
|
|
1853
|
+
}
|
|
1777
1854
|
```
|
|
1778
1855
|
|
|
1779
1856
|
**Animation:** `react-native-reanimated` `withTiming` (220ms) for height and chevron rotation (180°). Press scale uses `withSpring`. Runs on UI thread at 60fps.
|
|
@@ -1787,11 +1864,13 @@ const [tab, setTab] = useState('profile')
|
|
|
1787
1864
|
{
|
|
1788
1865
|
value: 'q1',
|
|
1789
1866
|
trigger: 'What payment methods do you accept?',
|
|
1867
|
+
iconName: 'credit-card',
|
|
1790
1868
|
content: <Text variant="body-sm">We accept Visa, Mastercard, and bank transfers.</Text>,
|
|
1791
1869
|
},
|
|
1792
1870
|
{
|
|
1793
1871
|
value: 'q2',
|
|
1794
1872
|
trigger: 'Can I cancel my booking?',
|
|
1873
|
+
iconName: 'x-circle',
|
|
1795
1874
|
content: <Text variant="body-sm">Yes — free cancellation within 48 hours of booking.</Text>,
|
|
1796
1875
|
},
|
|
1797
1876
|
]}
|
|
@@ -1828,11 +1907,16 @@ Add `react-native-worklets/plugin` (not `react-native-reanimated/plugin`) to `ba
|
|
|
1828
1907
|
| description | `string` | — | Supporting text below title |
|
|
1829
1908
|
| children | `ReactNode` | — | Sheet content |
|
|
1830
1909
|
| style | `ViewStyle` | — | Inner content container style |
|
|
1910
|
+
| scrollable | `boolean` | `false` | Wraps children in `BottomSheetScrollView` — fixes gesture conflict on both platforms when content needs to scroll |
|
|
1911
|
+
| maxHeight | `number` | — | Caps sheet height (dp). Automatically enables scrolling when content exceeds this value |
|
|
1912
|
+
| keyboardBehavior | `'padding' \| 'height' \| 'position' \| 'none'` | — | Wraps content in `KeyboardAvoidingView` when set. Use when sheet contains text inputs |
|
|
1913
|
+
| keyboardOffset | `number` | `0` | Extra vertical offset for `KeyboardAvoidingView` |
|
|
1831
1914
|
|
|
1832
1915
|
**Features:**
|
|
1833
1916
|
- `enableDynamicSizing` — height auto-fits content, no `snapPoints` needed
|
|
1834
1917
|
- `enablePanDownToClose` — swipe down to dismiss
|
|
1835
1918
|
- Backdrop press dismisses
|
|
1919
|
+
- **Scrollable content:** use `scrollable` prop (explicit) or `maxHeight` prop (capped height). Both use `BottomSheetScrollView` internally — do NOT use plain `ScrollView` inside Sheet, it breaks gesture handling on iOS
|
|
1836
1920
|
|
|
1837
1921
|
**Styling:** `RADIUS.lg = 20px` top corners, 16px horizontal + 20px bottom padding.
|
|
1838
1922
|
|
|
@@ -1855,6 +1939,18 @@ const [open, setOpen] = useState(false)
|
|
|
1855
1939
|
/>
|
|
1856
1940
|
</Sheet>
|
|
1857
1941
|
|
|
1942
|
+
// Scrollable sheet — long list
|
|
1943
|
+
<Sheet open={open} onClose={() => setOpen(false)} title="Logs" scrollable>
|
|
1944
|
+
{logs.map((log) => (
|
|
1945
|
+
<Text key={log.id}>{log.message}</Text>
|
|
1946
|
+
))}
|
|
1947
|
+
</Sheet>
|
|
1948
|
+
|
|
1949
|
+
// Capped height — scroll kicks in when content overflows 400dp
|
|
1950
|
+
<Sheet open={open} onClose={() => setOpen(false)} title="Results" maxHeight={400}>
|
|
1951
|
+
{results.map((r) => <ListItem key={r.id} title={r.name} />)}
|
|
1952
|
+
</Sheet>
|
|
1953
|
+
|
|
1858
1954
|
// Filter sheet
|
|
1859
1955
|
<Sheet open={filterOpen} onClose={() => setFilterOpen(false)} title="Filters">
|
|
1860
1956
|
<View style={{ gap: SPACING.lg }}>
|
|
@@ -2165,7 +2261,7 @@ toast({ title: 'Upload complete', variant: 'success' })
|
|
|
2165
2261
|
|
|
2166
2262
|
| Prop | Type | Default | Notes |
|
|
2167
2263
|
|------|------|---------|-------|
|
|
2168
|
-
| options | `ChipOption[]` | required | `{ label
|
|
2264
|
+
| options | `ChipOption[]` | required | `{ label, value, iconName?, iconColor?, disabled? }` |
|
|
2169
2265
|
| value | `string \| number \| (string \| number)[]` | — | Selected value(s) |
|
|
2170
2266
|
| onValueChange | `(value: ...) => void` | — | Returns single value or array depending on `multiSelect` |
|
|
2171
2267
|
| multiSelect | `boolean` | `false` | Allow multiple chips selected simultaneously |
|
|
@@ -2310,27 +2406,96 @@ const [categories, setCategories] = useState<number[]>([1, 3])
|
|
|
2310
2406
|
|------|------|---------|-------|
|
|
2311
2407
|
| label | `string` | required | Caption label on the left |
|
|
2312
2408
|
| value | `string \| ReactNode` | required | Value on the right. Strings auto-styled; pass `ReactNode` for custom content |
|
|
2409
|
+
| iconName | `string` | — | Icon name from `@expo/vector-icons` rendered left of label |
|
|
2410
|
+
| iconColor | `string` | — | Override icon color. Defaults to `foregroundMuted` |
|
|
2313
2411
|
| style | `ViewStyle` | — | — |
|
|
2314
2412
|
|
|
2315
2413
|
**Styling:** Row layout, `justifyContent: 'space-between'`. Label: 13pt / Regular / `foregroundMuted`. Value: 14pt / Medium / `foreground`. 12px gap.
|
|
2316
2414
|
|
|
2317
2415
|
**Examples:**
|
|
2318
2416
|
```tsx
|
|
2319
|
-
<LabelValue label="Date" value="12 mar 2025" />
|
|
2320
|
-
<LabelValue label="Category" value="Food & drink" />
|
|
2321
|
-
<LabelValue label="Status" value={<Badge label="Pending" variant="warningOutline" size="sm" />} />
|
|
2322
|
-
<LabelValue label="Amount" value="$45.000" />
|
|
2417
|
+
<LabelValue label="Date" value="12 mar 2025" iconName="calendar" />
|
|
2418
|
+
<LabelValue label="Category" value="Food & drink" iconName="tag" />
|
|
2419
|
+
<LabelValue label="Status" value={<Badge label="Pending" variant="warningOutline" size="sm" />} iconName="clock" />
|
|
2420
|
+
<LabelValue label="Amount" value="$45.000" iconName="dollar-sign" />
|
|
2323
2421
|
|
|
2324
2422
|
// Transaction detail
|
|
2325
2423
|
<View style={{ gap: SPACING.sm }}>
|
|
2326
|
-
<LabelValue label="Merchant" value={transaction.merchant} />
|
|
2327
|
-
<LabelValue label="Date" value={formatDate(transaction.date)} />
|
|
2328
|
-
<LabelValue label="Category" value={transaction.category} />
|
|
2424
|
+
<LabelValue label="Merchant" value={transaction.merchant} iconName="shopping-bag" />
|
|
2425
|
+
<LabelValue label="Date" value={formatDate(transaction.date)} iconName="calendar" />
|
|
2426
|
+
<LabelValue label="Category" value={transaction.category} iconName="tag" />
|
|
2427
|
+
<Separator />
|
|
2428
|
+
<LabelValue label="Amount" value={`$${transaction.amount}`} iconName="dollar-sign" />
|
|
2429
|
+
</View>
|
|
2430
|
+
```
|
|
2431
|
+
|
|
2432
|
+
---
|
|
2433
|
+
|
|
2434
|
+
### DetailRow
|
|
2435
|
+
|
|
2436
|
+
**Import:** `import { DetailRow } from '@retray-dev/ui-kit'`
|
|
2437
|
+
|
|
2438
|
+
**When to use:** "Label ··· Value" ticket/receipt rows — financial summaries, split bills, transaction breakdowns. Dotted separator fills the space between label and value.
|
|
2439
|
+
|
|
2440
|
+
| Prop | Type | Default | Notes |
|
|
2441
|
+
|------|------|---------|-------|
|
|
2442
|
+
| label | `string \| ReactNode` | required | Left side. Strings auto-styled in `foregroundMuted` caption |
|
|
2443
|
+
| value | `string` | required | Right side value text |
|
|
2444
|
+
| separator | `'dotted' \| 'solid' \| 'dashed' \| 'none'` | `'dotted'` | Fill line between label and value |
|
|
2445
|
+
| labelWeight | `'normal' \| 'medium' \| 'semibold' \| 'bold'` | `'normal'` | Font weight of label text |
|
|
2446
|
+
| valueColor | `string` | — | Override value text color (hex or theme token value) |
|
|
2447
|
+
| leftIcon | `ReactNode` | — | Node rendered left of label (e.g. `Avatar`, `Icon`) |
|
|
2448
|
+
| leftIconName | `string` | — | Icon name from `@expo/vector-icons` rendered left of label. Takes precedence over `leftIcon` |
|
|
2449
|
+
| leftIconColor | `string` | — | Override left icon color. Defaults to `foregroundMuted` |
|
|
2450
|
+
| rightIconName | `string` | — | Icon name from `@expo/vector-icons` rendered right of value |
|
|
2451
|
+
| rightIconColor | `string` | — | Override right icon color. Defaults to `foregroundMuted` |
|
|
2452
|
+
| style | `ViewStyle` | — | Row container style |
|
|
2453
|
+
| labelStyle | `TextStyle` | — | Label text style override |
|
|
2454
|
+
| valueStyle | `TextStyle` | — | Value text style override |
|
|
2455
|
+
|
|
2456
|
+
**Examples:**
|
|
2457
|
+
```tsx
|
|
2458
|
+
// Basic
|
|
2459
|
+
<DetailRow label="Total" value="$50.000" />
|
|
2460
|
+
|
|
2461
|
+
// With icons
|
|
2462
|
+
<DetailRow label="Food" value="$380.000" leftIconName="coffee" />
|
|
2463
|
+
<DetailRow label="Transport" value="$95.000" leftIconName="truck" />
|
|
2464
|
+
<DetailRow label="Total" value="$1.250.000" labelWeight="bold" rightIconName="trending-up" />
|
|
2465
|
+
|
|
2466
|
+
// Dotted separator with bold total
|
|
2467
|
+
<DetailRow label="Total" value="$50.000" labelWeight="bold" />
|
|
2468
|
+
|
|
2469
|
+
// With avatar left icon
|
|
2470
|
+
<DetailRow
|
|
2471
|
+
label="Juliana"
|
|
2472
|
+
value="$25.000"
|
|
2473
|
+
leftIcon={<Avatar src={avatarUrl} size={20} />}
|
|
2474
|
+
/>
|
|
2475
|
+
|
|
2476
|
+
// Destructive value
|
|
2477
|
+
<DetailRow label="Deuda" value="$150.000" valueColor={colors.destructive} />
|
|
2478
|
+
|
|
2479
|
+
// No separator
|
|
2480
|
+
<DetailRow label="Subtotal" value="$45.000" separator="none" />
|
|
2481
|
+
|
|
2482
|
+
// Full receipt block
|
|
2483
|
+
<View style={{ gap: SPACING.xs }}>
|
|
2484
|
+
<DetailRow label="Juliana" value="$25.000" leftIcon={<Avatar fallback="J" size={20} />} />
|
|
2485
|
+
<DetailRow label="Julián" value="$25.000" leftIcon={<Avatar fallback="JC" size={20} />} />
|
|
2329
2486
|
<Separator />
|
|
2330
|
-
<
|
|
2487
|
+
<DetailRow label="Total" value="$50.000" labelWeight="bold" />
|
|
2331
2488
|
</View>
|
|
2332
2489
|
```
|
|
2333
2490
|
|
|
2491
|
+
**Output:**
|
|
2492
|
+
```
|
|
2493
|
+
Juliana ············ $25.000
|
|
2494
|
+
Julián ············· $25.000
|
|
2495
|
+
─────────────────────────────
|
|
2496
|
+
Total ·············· $50.000
|
|
2497
|
+
```
|
|
2498
|
+
|
|
2334
2499
|
---
|
|
2335
2500
|
|
|
2336
2501
|
### MonthPicker
|
|
@@ -2343,6 +2508,8 @@ const [categories, setCategories] = useState<number[]>([1, 3])
|
|
|
2343
2508
|
|------|------|---------|-------|
|
|
2344
2509
|
| value | `MonthPickerValue` | required | `{ month: 1–12, year: number }` |
|
|
2345
2510
|
| onChange | `(value: MonthPickerValue) => void` | required | Called on navigation |
|
|
2511
|
+
| locale | `string` | `'en'` | BCP 47 locale. Built-in: `'en'`, `'es'`, `'pt'`, `'fr'`. Other locales: use `formatLabel` |
|
|
2512
|
+
| formatLabel | `(value: MonthPickerValue) => string` | — | Custom label formatter. Takes precedence over `locale` |
|
|
2346
2513
|
| style | `ViewStyle` | — | — |
|
|
2347
2514
|
|
|
2348
2515
|
**MonthPickerValue type:**
|
|
@@ -2366,6 +2533,16 @@ const [period, setPeriod] = useState({
|
|
|
2366
2533
|
<MonthPicker value={period} onChange={setPeriod} />
|
|
2367
2534
|
// Displays: "May 2026"
|
|
2368
2535
|
|
|
2536
|
+
<MonthPicker value={period} onChange={setPeriod} locale="es" />
|
|
2537
|
+
// Displays: "mayo 2026"
|
|
2538
|
+
|
|
2539
|
+
<MonthPicker
|
|
2540
|
+
value={period}
|
|
2541
|
+
onChange={setPeriod}
|
|
2542
|
+
formatLabel={({ month, year }) => `${month}/${year}`}
|
|
2543
|
+
/>
|
|
2544
|
+
// Displays: "5/2026"
|
|
2545
|
+
|
|
2369
2546
|
// In a transactions header
|
|
2370
2547
|
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
2371
2548
|
<Text variant="display-md">Transactions</Text>
|
|
@@ -2513,6 +2690,43 @@ All components with icon slots accept `iconName` — auto-resolved size and colo
|
|
|
2513
2690
|
|
|
2514
2691
|
---
|
|
2515
2692
|
|
|
2693
|
+
### `getResponsiveFontSize` utility
|
|
2694
|
+
|
|
2695
|
+
Calculates a stepped-down font size for long numeric strings (currency amounts, large numbers) that would overflow at full size.
|
|
2696
|
+
|
|
2697
|
+
```tsx
|
|
2698
|
+
import { getResponsiveFontSize } from '@retray-dev/ui-kit'
|
|
2699
|
+
|
|
2700
|
+
// Default steps: ≤10 chars → max, ≤12 → max-4, ≤14 → max-6, >14 → max-8
|
|
2701
|
+
const fontSize = getResponsiveFontSize(formatCOP(amount), 48)
|
|
2702
|
+
|
|
2703
|
+
<Text style={{ fontSize }} numberOfLines={1} adjustsFontSizeToFit>
|
|
2704
|
+
{formatCOP(amount)}
|
|
2705
|
+
</Text>
|
|
2706
|
+
```
|
|
2707
|
+
|
|
2708
|
+
**Signature:**
|
|
2709
|
+
```ts
|
|
2710
|
+
getResponsiveFontSize(
|
|
2711
|
+
text: string,
|
|
2712
|
+
maxSize: number,
|
|
2713
|
+
steps?: { maxLen: number; subtract: number }[]
|
|
2714
|
+
): number
|
|
2715
|
+
```
|
|
2716
|
+
|
|
2717
|
+
Custom steps example:
|
|
2718
|
+
```tsx
|
|
2719
|
+
getResponsiveFontSize(text, 48, [
|
|
2720
|
+
{ maxLen: 8, subtract: 0 },
|
|
2721
|
+
{ maxLen: 11, subtract: 6 },
|
|
2722
|
+
{ maxLen: 14, subtract: 10 },
|
|
2723
|
+
])
|
|
2724
|
+
```
|
|
2725
|
+
|
|
2726
|
+
**Alternative:** Use `<CurrencyDisplay autoScale maxFontSize={48} />` for currency values — no manual sizing needed.
|
|
2727
|
+
|
|
2728
|
+
---
|
|
2729
|
+
|
|
2516
2730
|
## Hover Support (Web)
|
|
2517
2731
|
|
|
2518
2732
|
```tsx
|
|
@@ -2577,3 +2791,29 @@ All `Text` and `TextInput` components have `allowFontScaling={true}` — respect
|
|
|
2577
2791
|
|
|
2578
2792
|
### Scaling utilities (internal)
|
|
2579
2793
|
Used internally — not exported. `s()` horizontal scale, `vs()` vertical scale, `ms()` moderate scale relative to 350×680 base.
|
|
2794
|
+
|
|
2795
|
+
---
|
|
2796
|
+
|
|
2797
|
+
## Full Composition Examples
|
|
2798
|
+
|
|
2799
|
+
The package includes **EXAMPLES.md** with complete, working code for 3 real-world app screens:
|
|
2800
|
+
|
|
2801
|
+
1. **Finance Dashboard** — MonthPicker, CurrencyDisplay, Progress, CategoryStrip, ListItem, DetailRow
|
|
2802
|
+
2. **Edit Profile** — Avatar, Badge, Input, Select, Switch, Card, AlertBanner
|
|
2803
|
+
3. **Onboarding Flow** — Badge, Progress, Input, RadioGroup, EmptyState (multi-step wizard)
|
|
2804
|
+
|
|
2805
|
+
**For AI agents:** Import EXAMPLES.md from the package for full source code and patterns:
|
|
2806
|
+
|
|
2807
|
+
```markdown
|
|
2808
|
+
## UI Kit Composition Examples
|
|
2809
|
+
@./node_modules/@retray-dev/ui-kit/EXAMPLES.md
|
|
2810
|
+
```
|
|
2811
|
+
|
|
2812
|
+
Each example includes:
|
|
2813
|
+
- Complete component code (copy-paste ready)
|
|
2814
|
+
- State management setup
|
|
2815
|
+
- Proper imports and theme usage
|
|
2816
|
+
- Common patterns (spacing, colors, navigation, toast feedback)
|
|
2817
|
+
- StyleSheet definitions
|
|
2818
|
+
|
|
2819
|
+
**For human developers:** Examples are also live in the `example/` app. Clone the repo, run `pnpm install && pnpm build`, then `cd example && pnpm start` to see them in action. Access via "🖥 App Screen Compositions" accordion.
|