@expokit/cli 0.4.3 → 0.5.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 +30 -3
- package/bin/expo-kit.js +749 -288
- package/bin/lib.mjs +313 -4
- package/package.json +1 -1
- package/registry/_docs/action-sheet.json +1 -1
- package/registry/_docs/alert.json +6 -0
- package/registry/_docs/bottom-sheet.json +6 -0
- package/registry/_docs/bullet.json +6 -0
- package/registry/_docs/dialog.json +1 -1
- package/registry/_docs/drawer.json +3 -3
- package/registry/_docs/flip-calendar.json +106 -0
- package/registry/_docs/glass-search-bar.json +1 -1
- package/registry/_docs/grain.json +6 -1
- package/registry/_docs/isometric-bar.json +6 -0
- package/registry/_docs/liquidglass-tab.json +1 -1
- package/registry/_docs/password-input.json +1 -1
- package/registry/_docs/paywall.json +144 -0
- package/registry/_docs/pixel-bar.json +6 -0
- package/registry/_docs/polar-area.json +6 -0
- package/registry/_docs/qr-code-button.json +9 -3
- package/registry/_docs/ruler-time-picker.json +147 -0
- package/registry/_docs/scratch-card.json +7 -1
- package/registry/_docs/search-bar.json +1 -1
- package/registry/_docs/select.json +2 -2
- package/registry/_docs/slide-to-confirm.json +2 -2
- package/registry/_docs/spinner.json +1 -1
- package/registry/_docs/stateful-button.json +2 -2
- package/registry/_docs/swipe-deck.json +1 -1
- package/registry/_docs/time-picker.json +2 -2
- package/registry/_docs/timeline-chart.json +6 -0
- package/registry/_docs/toast.json +15 -3
- package/registry/_docs/treemap.json +6 -0
- package/registry/_docs/waterfall.json +6 -0
- package/registry/accordion/files/src/components/ui/accordion.tsx +6 -4
- package/registry/accordion/files/src/lib/kit.tsx +462 -12
- package/registry/accordion.json +1 -0
- package/registry/action-sheet/files/src/components/ui/action-sheet.tsx +50 -58
- package/registry/action-sheet/files/src/lib/kit.tsx +462 -12
- package/registry/action-sheet.json +1 -0
- package/registry/alert/files/src/components/ui/alert.tsx +20 -13
- package/registry/alert/files/src/lib/kit.tsx +462 -12
- package/registry/alert.json +3 -4
- package/registry/assistant-app.json +1 -0
- package/registry/avatar/files/src/components/ui/avatar.tsx +89 -74
- package/registry/avatar/files/src/lib/kit.tsx +462 -12
- package/registry/avatar.json +1 -0
- package/registry/badge/files/src/components/ui/badge.tsx +36 -36
- package/registry/badge/files/src/lib/kit.tsx +462 -12
- package/registry/badge.json +1 -0
- package/registry/bottom-nav/files/src/components/ui/bottom-nav.tsx +39 -44
- package/registry/bottom-nav/files/src/lib/kit.tsx +462 -12
- package/registry/bottom-nav.json +5 -0
- package/registry/bottom-sheet/files/src/components/ui/bottom-sheet.tsx +357 -300
- package/registry/bottom-sheet/files/src/lib/kit.tsx +462 -12
- package/registry/bottom-sheet.json +5 -1
- package/registry/bullet.json +1 -0
- package/registry/button/files/src/components/ui/button.tsx +23 -34
- package/registry/button/files/src/lib/kit.tsx +462 -12
- package/registry/button-3d/files/src/components/ui/button-3d.tsx +6 -9
- package/registry/button-3d/files/src/lib/kit.tsx +462 -12
- package/registry/button-3d.json +1 -0
- package/registry/button.json +1 -0
- package/registry/calendar/files/src/components/ui/calendar.tsx +77 -79
- package/registry/calendar/files/src/lib/kit.tsx +462 -12
- package/registry/calendar.json +1 -0
- package/registry/card/files/src/components/ui/card.tsx +7 -6
- package/registry/card/files/src/lib/kit.tsx +462 -12
- package/registry/card-stack.json +1 -0
- package/registry/card.json +1 -0
- package/registry/carousel.json +1 -0
- package/registry/chat.json +7 -0
- package/registry/checkbox/files/src/components/ui/checkbox.tsx +4 -4
- package/registry/checkbox/files/src/lib/kit.tsx +462 -12
- package/registry/checkbox.json +1 -0
- package/registry/checkout.json +1 -0
- package/registry/chip-group/files/src/components/ui/chip-group.tsx +24 -24
- package/registry/chip-group/files/src/lib/kit.tsx +462 -12
- package/registry/chip-group.json +1 -0
- package/registry/confetti/files/src/components/ui/confetti.tsx +15 -14
- package/registry/confetti.json +3 -6
- package/registry/coupon/files/src/components/ui/coupon.tsx +47 -52
- package/registry/coupon/files/src/components/ui/flip-card.tsx +9 -14
- package/registry/coupon/files/src/components/ui/tilt-card.tsx +80 -101
- package/registry/coupon/files/src/lib/kit.tsx +462 -12
- package/registry/coupon/files/src/lib/ticket-shape.tsx +54 -44
- package/registry/coupon.json +1 -0
- package/registry/cube-pager.json +1 -0
- package/registry/dashboard.json +1 -0
- package/registry/date-picker/files/src/components/ui/calendar.tsx +77 -79
- package/registry/date-picker/files/src/components/ui/date-picker.tsx +64 -71
- package/registry/date-picker/files/src/lib/kit.tsx +462 -12
- package/registry/date-picker.json +1 -0
- package/registry/dialog/files/src/components/ui/dialog.tsx +66 -68
- package/registry/dialog/files/src/lib/kit.tsx +462 -12
- package/registry/dialog.json +1 -0
- package/registry/donut-shop.json +1 -0
- package/registry/drawer/files/src/components/ui/drawer.tsx +76 -88
- package/registry/drawer/files/src/lib/kit.tsx +462 -12
- package/registry/drawer.json +1 -0
- package/registry/fab.json +1 -0
- package/registry/fintech-app.json +1 -0
- package/registry/flip-calendar/files/src/components/ui/flip-calendar.tsx +632 -0
- package/registry/flip-calendar/files/src/lib/kit.tsx +672 -0
- package/registry/flip-calendar.json +24 -0
- package/registry/flip-card/files/src/components/ui/flip-card.tsx +9 -14
- package/registry/flip-card/files/src/lib/kit.tsx +462 -12
- package/registry/flip-card.json +1 -0
- package/registry/floating-input/files/src/components/ui/floating-input.tsx +33 -33
- package/registry/floating-input/files/src/lib/kit.tsx +462 -12
- package/registry/floating-input.json +1 -0
- package/registry/food-app.json +1 -0
- package/registry/gift-card.json +1 -0
- package/registry/glass-button.json +5 -0
- package/registry/glass-nav-bar.json +1 -0
- package/registry/glass-search-bar.json +1 -0
- package/registry/glass-segmented.json +1 -0
- package/registry/glass-sheet.json +1 -0
- package/registry/glass-tab-bar.json +5 -0
- package/registry/glass.json +1 -0
- package/registry/grain/files/src/components/ui/grain.tsx +16 -14
- package/registry/grain.json +8 -6
- package/registry/inbox.json +1 -0
- package/registry/isometric-bar.json +1 -0
- package/registry/kit/files/src/lib/kit.tsx +462 -12
- package/registry/kit.json +1 -0
- package/registry/liquidglass-tab/files/src/app/_layout.tsx +0 -1
- package/registry/liquidglass-tab/files/src/components/GlassTabBar.tsx +29 -16
- package/registry/liquidglass-tab/files/src/components/TabScreen.tsx +33 -19
- package/registry/liquidglass-tab/files/src/lib/tab-icons.ts +1 -1
- package/registry/liquidglass-tab.json +1 -0
- package/registry/list-item/files/src/components/ui/list-item.tsx +43 -43
- package/registry/list-item/files/src/lib/kit.tsx +462 -12
- package/registry/list-item.json +1 -0
- package/registry/loyalty-card.json +1 -0
- package/registry/morphing-button-group.json +1 -0
- package/registry/number-ticker.json +1 -0
- package/registry/offers.json +1 -0
- package/registry/onboarding.json +1 -0
- package/registry/orb-reveal.json +1 -0
- package/registry/otp-input/files/src/components/ui/otp-input.tsx +49 -30
- package/registry/otp-input/files/src/lib/kit.tsx +462 -12
- package/registry/otp-input.json +1 -0
- package/registry/parallax-layers.json +1 -0
- package/registry/parallax-scroll.json +1 -0
- package/registry/password-input/files/src/components/ui/floating-input.tsx +33 -33
- package/registry/password-input/files/src/components/ui/password-input.tsx +29 -25
- package/registry/password-input/files/src/lib/kit.tsx +462 -12
- package/registry/password-input.json +1 -0
- package/registry/payment-card/files/src/components/ui/flip-card.tsx +9 -14
- package/registry/payment-card/files/src/components/ui/payment-card.tsx +26 -20
- package/registry/payment-card/files/src/components/ui/tilt-card.tsx +80 -101
- package/registry/payment-card/files/src/lib/kit.tsx +462 -12
- package/registry/payment-card.json +1 -0
- package/registry/paywall.json +23 -0
- package/registry/pixel-bar.json +1 -0
- package/registry/polar-area.json +1 -0
- package/registry/profile.json +1 -0
- package/registry/progress/files/src/components/ui/progress.tsx +31 -29
- package/registry/progress/files/src/lib/kit.tsx +462 -12
- package/registry/progress-steps/files/src/components/ui/progress-steps.tsx +21 -21
- package/registry/progress-steps/files/src/lib/kit.tsx +462 -12
- package/registry/progress-steps.json +1 -0
- package/registry/progress.json +1 -0
- package/registry/qr-code-button.json +1 -0
- package/registry/radio-group/files/src/components/ui/radio-group.tsx +19 -19
- package/registry/radio-group/files/src/lib/kit.tsx +462 -12
- package/registry/radio-group.json +1 -0
- package/registry/rating.json +1 -0
- package/registry/ring-carousel.json +1 -0
- package/registry/ruler-time-picker/files/src/components/ui/ruler-time-picker.tsx +832 -0
- package/registry/ruler-time-picker/files/src/lib/kit.tsx +672 -0
- package/registry/ruler-time-picker.json +26 -0
- package/registry/scratch-card.json +1 -0
- package/registry/search-bar/files/src/components/ui/search-bar.tsx +28 -28
- package/registry/search-bar/files/src/lib/kit.tsx +462 -12
- package/registry/search-bar.json +1 -0
- package/registry/search-results.json +4 -0
- package/registry/segmented-control/files/src/components/ui/segmented-control.tsx +11 -17
- package/registry/segmented-control/files/src/lib/kit.tsx +462 -12
- package/registry/segmented-control.json +1 -0
- package/registry/select/files/src/components/ui/select.tsx +107 -104
- package/registry/select/files/src/lib/kit.tsx +462 -12
- package/registry/select.json +6 -0
- package/registry/settings.json +1 -0
- package/registry/sign-in.json +1 -0
- package/registry/skeleton/files/src/components/ui/skeleton.tsx +149 -80
- package/registry/skeleton/files/src/lib/kit.tsx +462 -12
- package/registry/skeleton.json +1 -0
- package/registry/slide-to-confirm.json +1 -0
- package/registry/slider/files/src/components/ui/slider.tsx +106 -108
- package/registry/slider/files/src/lib/kit.tsx +462 -12
- package/registry/slider.json +5 -0
- package/registry/spin-wheel.json +1 -0
- package/registry/spinner/files/src/components/ui/spinner.tsx +39 -29
- package/registry/spinner/files/src/lib/kit.tsx +462 -12
- package/registry/spinner.json +6 -0
- package/registry/stateful-button/files/src/components/ui/stateful-button.tsx +39 -32
- package/registry/stateful-button/files/src/lib/kit.tsx +462 -12
- package/registry/stateful-button.json +5 -0
- package/registry/stepper/files/src/components/ui/stepper.tsx +40 -38
- package/registry/stepper/files/src/lib/kit.tsx +462 -12
- package/registry/stepper.json +1 -0
- package/registry/swipe-deck.json +1 -0
- package/registry/swipeable-row.json +4 -0
- package/registry/switch/files/src/components/ui/switch.tsx +41 -47
- package/registry/switch/files/src/lib/kit.tsx +462 -12
- package/registry/switch.json +1 -0
- package/registry/tabs/files/src/components/ui/tabs.tsx +61 -64
- package/registry/tabs/files/src/lib/kit.tsx +462 -12
- package/registry/tabs.json +1 -0
- package/registry/text-animation/files/src/components/ui/text-animation.tsx +55 -42
- package/registry/text-animation/files/src/lib/kit.tsx +462 -12
- package/registry/text-animation.json +7 -0
- package/registry/textarea/files/src/components/ui/textarea.tsx +10 -10
- package/registry/textarea/files/src/lib/kit.tsx +462 -12
- package/registry/textarea.json +1 -0
- package/registry/ticket-card.json +1 -0
- package/registry/ticket-shape/files/src/lib/kit.tsx +462 -12
- package/registry/ticket-shape/files/src/lib/ticket-shape.tsx +54 -44
- package/registry/ticket-shape.json +1 -0
- package/registry/tilt-card/files/src/components/ui/tilt-card.tsx +80 -101
- package/registry/tilt-card/files/src/lib/kit.tsx +462 -12
- package/registry/tilt-card.json +1 -0
- package/registry/time-picker/files/src/components/ui/time-picker.tsx +136 -131
- package/registry/time-picker/files/src/lib/kit.tsx +462 -12
- package/registry/time-picker.json +1 -0
- package/registry/timeline/files/src/components/ui/avatar.tsx +89 -74
- package/registry/timeline/files/src/components/ui/timeline.tsx +49 -57
- package/registry/timeline/files/src/lib/kit.tsx +462 -12
- package/registry/timeline-chart.json +1 -0
- package/registry/timeline.json +1 -0
- package/registry/toast/files/src/components/ui/toast.tsx +543 -465
- package/registry/toast/files/src/lib/kit.tsx +462 -12
- package/registry/toast.json +7 -5
- package/registry/treemap.json +1 -0
- package/registry/waterfall.json +1 -0
- package/registry/wheel-list.json +1 -0
- package/schema/components.schema.json +1 -0
- package/registry/alert/files/src/components/ui/button.tsx +0 -303
- package/registry/confetti/files/src/lib/kit.tsx +0 -222
- package/registry/grain/files/src/lib/kit.tsx +0 -222
- package/registry/toast/files/src/components/ui/button.tsx +0 -303
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
Text,
|
|
7
7
|
View,
|
|
8
8
|
useColorScheme,
|
|
9
|
+
useWindowDimensions,
|
|
9
10
|
} from 'react-native';
|
|
10
11
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
11
12
|
|
|
@@ -17,7 +18,7 @@ interface TabScreenProps {
|
|
|
17
18
|
description: string;
|
|
18
19
|
accent: string;
|
|
19
20
|
/** Label of a button pinned to the bottom of the screen, above the tab bar. */
|
|
20
|
-
action?: string;
|
|
21
|
+
action?: string | undefined;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export function TabScreen({ title, description, accent, action }: TabScreenProps) {
|
|
@@ -27,6 +28,12 @@ export function TabScreen({ title, description, accent, action }: TabScreenProps
|
|
|
27
28
|
const bottomInset = useTabBarInset(24);
|
|
28
29
|
// Bottom-anchored UI sits on top of the bar's footprint, not on the screen edge.
|
|
29
30
|
const actionBottom = useTabBarInset(12);
|
|
31
|
+
// Phones: full width, one card per row. Tablets and open foldables: a centred column, two cards per row.
|
|
32
|
+
const { width } = useWindowDimensions();
|
|
33
|
+
const columnW = Math.min(width, COLUMN_MAX);
|
|
34
|
+
const side = Math.max(0, (width - columnW) / 2) + 20;
|
|
35
|
+
const columns = width >= 600 ? 2 : 1;
|
|
36
|
+
const cardW = columns > 1 ? (columnW - 40 - CARD_GAP * (columns - 1)) / columns : undefined;
|
|
30
37
|
const bg = isDark ? '#0f0f1a' : '#f2f2f7';
|
|
31
38
|
const text = isDark ? '#fff' : '#1c1c1e';
|
|
32
39
|
const sub = isDark ? '#9898a8' : '#6c6c70';
|
|
@@ -38,6 +45,7 @@ export function TabScreen({ title, description, accent, action }: TabScreenProps
|
|
|
38
45
|
contentContainerStyle={[
|
|
39
46
|
styles.scroll,
|
|
40
47
|
{ paddingTop: insets.top + 12, paddingBottom: bottomInset },
|
|
48
|
+
{ width: '100%', maxWidth: COLUMN_MAX, alignSelf: 'center' },
|
|
41
49
|
]}
|
|
42
50
|
showsVerticalScrollIndicator={false}
|
|
43
51
|
// Pad by hand on every bar: useTabBarInset() already counts the floating bar and home indicator.
|
|
@@ -54,27 +62,29 @@ export function TabScreen({ title, description, accent, action }: TabScreenProps
|
|
|
54
62
|
<Text style={[styles.title, { color: text }]}>{title}</Text>
|
|
55
63
|
<Text style={[styles.subtitle, { color: sub }]}>{description}</Text>
|
|
56
64
|
|
|
57
|
-
{
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
<View style={columns > 1 ? styles.grid : undefined}>
|
|
66
|
+
{SECTIONS.map((n) => (
|
|
67
|
+
<View
|
|
68
|
+
key={n}
|
|
69
|
+
style={[
|
|
70
|
+
styles.card,
|
|
71
|
+
{ width: cardW, backgroundColor: isDark ? '#1c1c2e' : '#ffffff' },
|
|
72
|
+
]}
|
|
73
|
+
>
|
|
74
|
+
<Text style={[styles.cardTitle, { color: text }]}>Section {n}</Text>
|
|
75
|
+
<Text style={[styles.cardSub, { color: sub }]}>
|
|
76
|
+
iOS 26+ gets the system Liquid Glass bar. Older iOS, Android and web get the
|
|
77
|
+
blur glass fallback — both merge into a glass circle when you scroll down.
|
|
78
|
+
</Text>
|
|
79
|
+
</View>
|
|
80
|
+
))}
|
|
81
|
+
</View>
|
|
72
82
|
{action ? <View style={{ height: 64 }} /> : null}
|
|
73
83
|
</ScrollView>
|
|
74
84
|
{action ? (
|
|
75
85
|
<Pressable
|
|
76
86
|
accessibilityRole="button"
|
|
77
|
-
style={({ pressed }) => [styles.action, { bottom: actionBottom, backgroundColor: accent, opacity: pressed ? 0.85 : 1 }]}
|
|
87
|
+
style={({ pressed }) => [styles.action, { left: side, right: side, bottom: actionBottom, backgroundColor: accent, opacity: pressed ? 0.85 : 1 }]}
|
|
78
88
|
>
|
|
79
89
|
<Text style={styles.actionText}>{action}</Text>
|
|
80
90
|
</Pressable>
|
|
@@ -83,7 +93,7 @@ export function TabScreen({ title, description, accent, action }: TabScreenProps
|
|
|
83
93
|
);
|
|
84
94
|
}
|
|
85
95
|
|
|
86
|
-
export function TabScreenFromConfig({ tabName, action }: { tabName: string; action?: string }) {
|
|
96
|
+
export function TabScreenFromConfig({ tabName, action }: { tabName: string; action?: string | undefined }) {
|
|
87
97
|
const tab = getTab(tabName);
|
|
88
98
|
if (!tab) {
|
|
89
99
|
return null;
|
|
@@ -103,6 +113,9 @@ export function TabScreenFromConfig({ tabName, action }: { tabName: string; acti
|
|
|
103
113
|
}
|
|
104
114
|
|
|
105
115
|
const SECTIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
|
116
|
+
/** Widest the screen's column gets on tablets. */
|
|
117
|
+
const COLUMN_MAX = 720;
|
|
118
|
+
const CARD_GAP = 10;
|
|
106
119
|
|
|
107
120
|
const styles = StyleSheet.create({
|
|
108
121
|
root: { flex: 1 },
|
|
@@ -127,6 +140,7 @@ const styles = StyleSheet.create({
|
|
|
127
140
|
},
|
|
128
141
|
title: { fontSize: 34, fontWeight: '400', letterSpacing: -0.5 },
|
|
129
142
|
subtitle: { fontSize: 15, marginTop: 8, marginBottom: 20, lineHeight: 22 },
|
|
143
|
+
grid: { flexDirection: 'row', flexWrap: 'wrap', columnGap: CARD_GAP },
|
|
130
144
|
card: {
|
|
131
145
|
borderRadius: 14,
|
|
132
146
|
padding: 16,
|
|
@@ -143,5 +157,5 @@ const styles = StyleSheet.create({
|
|
|
143
157
|
alignItems: 'center',
|
|
144
158
|
justifyContent: 'center',
|
|
145
159
|
},
|
|
146
|
-
actionText: { color: '#fff', fontSize: 16, fontWeight: '500' },
|
|
160
|
+
actionText: { color: '#fff', fontSize: 16, fontWeight: '500', includeFontPadding: false, textAlignVertical: 'center' },
|
|
147
161
|
});
|
|
@@ -106,7 +106,7 @@ export function resolveIconNames(tab: {
|
|
|
106
106
|
icon?: TabIconPreset;
|
|
107
107
|
iconName?: string;
|
|
108
108
|
iconSelected?: string;
|
|
109
|
-
}): { name?: string; selected?: string } {
|
|
109
|
+
}): { name?: string | undefined; selected?: string | undefined } {
|
|
110
110
|
if (tab.icon?.name) {
|
|
111
111
|
return { name: tab.icon.name, selected: tab.icon.selected };
|
|
112
112
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"title": "Native bottom tabs (Liquid Glass)",
|
|
5
5
|
"description": "Real Liquid Glass NativeTabs on iOS 26+, and a floating blur glass tab bar with the same scroll-collapse on iOS 18 and older, Android and web.",
|
|
6
6
|
"tier": "free",
|
|
7
|
+
"aliases": [],
|
|
7
8
|
"dependencies": [
|
|
8
9
|
"expo-router",
|
|
9
10
|
"expo-glass-effect",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
4
|
Image,
|
|
@@ -41,61 +41,61 @@ export interface ListItemIconProps {
|
|
|
41
41
|
|
|
42
42
|
export interface ListItemAvatar {
|
|
43
43
|
/** Image URL. Falls back to initials while loading or when it fails. */
|
|
44
|
-
src?: string;
|
|
44
|
+
src?: string | undefined;
|
|
45
45
|
/** Used for the initials and the fallback colour. */
|
|
46
|
-
name?: string;
|
|
46
|
+
name?: string | undefined;
|
|
47
47
|
/** Fallback circle colour (default: picked from the name). */
|
|
48
|
-
color?: string;
|
|
48
|
+
color?: string | undefined;
|
|
49
49
|
/** Shows a green presence dot. */
|
|
50
|
-
online?: boolean;
|
|
50
|
+
online?: boolean | undefined;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export interface ListItemProps {
|
|
54
54
|
title: string;
|
|
55
55
|
/** One muted line under the title. */
|
|
56
|
-
subtitle?: string;
|
|
56
|
+
subtitle?: string | undefined;
|
|
57
57
|
/** Longer muted text under the subtitle, clamped to `numberOfLines`. */
|
|
58
|
-
description?: string;
|
|
58
|
+
description?: string | undefined;
|
|
59
59
|
/** Lines shown of `description` (default 2). */
|
|
60
|
-
numberOfLines?: number;
|
|
60
|
+
numberOfLines?: number | undefined;
|
|
61
61
|
/** Small text at the right end of the title row, e.g. a time ("9:41"). */
|
|
62
|
-
meta?: string;
|
|
62
|
+
meta?: string | undefined;
|
|
63
63
|
|
|
64
64
|
/** Built-in icon name or your own icon, drawn in a rounded tile. */
|
|
65
|
-
icon?: ListItemIconName | ((props: ListItemIconProps) => React.ReactNode);
|
|
65
|
+
icon?: (ListItemIconName | ((props: ListItemIconProps) => React.ReactNode)) | undefined;
|
|
66
66
|
/** Tile colour (default: theme accent; the danger colour when `destructive`). */
|
|
67
|
-
iconColor?: string;
|
|
67
|
+
iconColor?: string | undefined;
|
|
68
68
|
/** 'filled' white glyph on a solid tile (iOS Settings) · 'tinted' coloured glyph on a soft tile. */
|
|
69
|
-
iconVariant?: 'filled' | 'tinted';
|
|
69
|
+
iconVariant?: 'filled' | 'tinted' | undefined;
|
|
70
70
|
/** Round avatar instead of an icon tile. */
|
|
71
|
-
avatar?: ListItemAvatar;
|
|
71
|
+
avatar?: ListItemAvatar | undefined;
|
|
72
72
|
/** Anything else on the left (overrides `icon` / `avatar`). */
|
|
73
|
-
leading?: React.ReactNode;
|
|
73
|
+
leading?: React.ReactNode | undefined;
|
|
74
74
|
|
|
75
75
|
/** Muted value text on the right, e.g. "English" or "1.2 GB". */
|
|
76
|
-
value?: string;
|
|
76
|
+
value?: string | undefined;
|
|
77
77
|
/** `true` draws a dot; a number or string draws a pill (99+ above 99). */
|
|
78
|
-
badge?: boolean | number | string;
|
|
78
|
+
badge?: boolean | number | string | undefined;
|
|
79
79
|
/** Shows a chevron. Defaults to true when the row is pressable and has no `trailing` / `checked`. */
|
|
80
|
-
chevron?: boolean;
|
|
80
|
+
chevron?: boolean | undefined;
|
|
81
81
|
/** Shows an accent check mark (for pickers). */
|
|
82
|
-
checked?: boolean;
|
|
82
|
+
checked?: boolean | undefined;
|
|
83
83
|
/** Anything on the right, e.g. a <Switch />. Rendered after `value` and `badge`. */
|
|
84
|
-
trailing?: React.ReactNode;
|
|
84
|
+
trailing?: React.ReactNode | undefined;
|
|
85
85
|
|
|
86
|
-
onPress?: () => void;
|
|
87
|
-
onLongPress?: () => void;
|
|
86
|
+
onPress?: (() => void) | undefined;
|
|
87
|
+
onLongPress?: (() => void) | undefined;
|
|
88
88
|
/** Red title and icon, for "Sign out" or "Delete account". */
|
|
89
|
-
destructive?: boolean;
|
|
90
|
-
disabled?: boolean;
|
|
91
|
-
size?: ListItemSize;
|
|
89
|
+
destructive?: boolean | undefined;
|
|
90
|
+
disabled?: boolean | undefined;
|
|
91
|
+
size?: ListItemSize | undefined;
|
|
92
92
|
/** Hairline under the row that starts past the leading slot. ListGroup / ListSection set it for you. */
|
|
93
|
-
divider?: boolean;
|
|
93
|
+
divider?: boolean | undefined;
|
|
94
94
|
/** Highlight colour for checks, badges and default icon tiles (default: theme accent). */
|
|
95
|
-
accent?: string;
|
|
96
|
-
titleStyle?: StyleProp<TextStyle
|
|
97
|
-
accessibilityLabel?: string;
|
|
98
|
-
style?: StyleProp<ViewStyle
|
|
95
|
+
accent?: string | undefined;
|
|
96
|
+
titleStyle?: StyleProp<TextStyle> | undefined;
|
|
97
|
+
accessibilityLabel?: string | undefined;
|
|
98
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
const SIZES: Record<ListItemSize, { minH: number; tile: number; glyph: number; avatar: number; title: number; sub: number; padY: number }> = {
|
|
@@ -109,7 +109,7 @@ const SIZES: Record<ListItemSize, { minH: number; tile: number; glyph: number; a
|
|
|
109
109
|
const FONT_CAP = 1.35;
|
|
110
110
|
const PAD_X = 16;
|
|
111
111
|
const GAP = 12;
|
|
112
|
-
const AVATAR_COLORS = ['#f97316', '#0ea5e9', '#22c55e', '#a855f7', '#ec4899', '#14b8a6', '#6366f1', '#eab308'];
|
|
112
|
+
const AVATAR_COLORS: [string, ...string[]] = ['#f97316', '#0ea5e9', '#22c55e', '#a855f7', '#ec4899', '#14b8a6', '#6366f1', '#eab308'];
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
115
|
* Settings / contacts style row: icon tile, avatar or custom leading; title, subtitle and
|
|
@@ -143,7 +143,7 @@ export function ListItem({
|
|
|
143
143
|
accessibilityLabel,
|
|
144
144
|
style,
|
|
145
145
|
}: ListItemProps) {
|
|
146
|
-
const { colors, radius, font } = useKit();
|
|
146
|
+
const { colors, radius, font, labels } = useKit();
|
|
147
147
|
const ff = font.family ? { fontFamily: font.family } : null;
|
|
148
148
|
const tint = accent ?? colors.accent;
|
|
149
149
|
const s = SIZES[size];
|
|
@@ -152,7 +152,7 @@ export function ListItem({
|
|
|
152
152
|
const titleColor = destructive ? colors.danger : colors.foreground;
|
|
153
153
|
|
|
154
154
|
// Press highlight: an overlay whose opacity runs on the native driver.
|
|
155
|
-
const highlight =
|
|
155
|
+
const [highlight] = useState(() => new Animated.Value(0));
|
|
156
156
|
const fade = (to: number, duration: number) =>
|
|
157
157
|
Animated.timing(highlight, { toValue: to, duration, useNativeDriver: true }).start();
|
|
158
158
|
|
|
@@ -257,7 +257,7 @@ export function ListItem({
|
|
|
257
257
|
onPressOut={() => fade(0, 320)}
|
|
258
258
|
accessibilityRole="button"
|
|
259
259
|
accessibilityState={{ disabled: !!disabled, checked: checked === undefined ? undefined : checked }}
|
|
260
|
-
accessibilityLabel={accessibilityLabel ?? [title, subtitle, value, badgeText ?
|
|
260
|
+
accessibilityLabel={accessibilityLabel ?? [title, subtitle, value, badgeText ? labels.newCount(String(badgeText)) : null].filter(Boolean).join(', ')}
|
|
261
261
|
style={rowStyle}
|
|
262
262
|
>
|
|
263
263
|
<Animated.View
|
|
@@ -274,13 +274,13 @@ export function ListItem({
|
|
|
274
274
|
|
|
275
275
|
export interface ListGroupProps {
|
|
276
276
|
/** Small uppercase heading above the card. */
|
|
277
|
-
header?: string;
|
|
277
|
+
header?: string | undefined;
|
|
278
278
|
/** Muted explanation under the card. */
|
|
279
|
-
footer?: string;
|
|
279
|
+
footer?: string | undefined;
|
|
280
280
|
/** Card colour (default: theme card). */
|
|
281
|
-
background?: string;
|
|
281
|
+
background?: string | undefined;
|
|
282
282
|
children: React.ReactNode;
|
|
283
|
-
style?: StyleProp<ViewStyle
|
|
283
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
/**
|
|
@@ -312,12 +312,12 @@ export function ListGroup({ header, footer, background, children, style }: ListG
|
|
|
312
312
|
|
|
313
313
|
export interface ListSectionProps {
|
|
314
314
|
/** Section heading, e.g. "A" in a contacts list or "Today" in an inbox. */
|
|
315
|
-
header?: string;
|
|
316
|
-
footer?: string;
|
|
315
|
+
header?: string | undefined;
|
|
316
|
+
footer?: string | undefined;
|
|
317
317
|
/** Hairline under the last row too (default false). */
|
|
318
|
-
dividerAfterLast?: boolean;
|
|
318
|
+
dividerAfterLast?: boolean | undefined;
|
|
319
319
|
children: React.ReactNode;
|
|
320
|
-
style?: StyleProp<ViewStyle
|
|
320
|
+
style?: StyleProp<ViewStyle> | undefined;
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
/** Plain full-width section: header text, then rows with inset separators. */
|
|
@@ -360,7 +360,7 @@ function AvatarCircle({ src, name = '', color, online, size, ring }: ListItemAva
|
|
|
360
360
|
.join('');
|
|
361
361
|
let hash = 0;
|
|
362
362
|
for (let i = 0; i < name.length; i++) hash = (hash * 31 + name.charCodeAt(i)) | 0;
|
|
363
|
-
const bg = color ?? AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];
|
|
363
|
+
const bg = color ?? AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length] ?? AVATAR_COLORS[0];
|
|
364
364
|
const dot = Math.max(10, Math.round(size * 0.28));
|
|
365
365
|
return (
|
|
366
366
|
<View style={{ width: size, height: size }}>
|
|
@@ -507,7 +507,7 @@ const styles = StyleSheet.create({
|
|
|
507
507
|
value: { fontSize: 15, flexShrink: 1 },
|
|
508
508
|
dot: { width: 9, height: 9, borderRadius: 5 },
|
|
509
509
|
badge: { minWidth: 22, minHeight: 22, paddingHorizontal: 7, alignItems: 'center', justifyContent: 'center' },
|
|
510
|
-
badgeText: { fontSize: 12, fontWeight: '400', fontVariant: ['tabular-nums'] },
|
|
510
|
+
badgeText: { fontSize: 12, fontWeight: '400', fontVariant: ['tabular-nums'], includeFontPadding: false, textAlignVertical: 'center' },
|
|
511
511
|
divider: { position: 'absolute', right: 0, bottom: 0, height: StyleSheet.hairlineWidth },
|
|
512
512
|
avatar: { alignItems: 'center', justifyContent: 'center', overflow: 'hidden' },
|
|
513
513
|
online: { position: 'absolute', right: -1, bottom: -1, borderWidth: 2 },
|