@retray-dev/ui-kit 6.1.0 → 7.0.1
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 +447 -13
- package/EXAMPLES.md +248 -0
- package/README.md +11 -10
- package/dist/Accordion.d.mts +28 -0
- package/dist/Accordion.d.ts +28 -0
- package/dist/Accordion.js +340 -0
- package/dist/Accordion.mjs +6 -0
- package/dist/AlertBanner.d.mts +16 -0
- package/dist/AlertBanner.d.ts +16 -0
- package/dist/AlertBanner.js +247 -0
- package/dist/AlertBanner.mjs +5 -0
- package/dist/Avatar.d.mts +20 -0
- package/dist/Avatar.d.ts +20 -0
- package/dist/Avatar.js +234 -0
- package/dist/Avatar.mjs +3 -0
- package/dist/Badge.d.mts +26 -0
- package/dist/Badge.d.ts +26 -0
- package/dist/Badge.js +247 -0
- package/dist/Badge.mjs +4 -0
- package/dist/Button.d.mts +25 -0
- package/dist/Button.d.ts +25 -0
- package/dist/Button.js +414 -0
- package/dist/Button.mjs +8 -0
- package/dist/ButtonGroup.d.mts +26 -0
- package/dist/ButtonGroup.d.ts +26 -0
- package/dist/ButtonGroup.js +52 -0
- package/dist/ButtonGroup.mjs +2 -0
- package/dist/Card.d.mts +39 -0
- package/dist/Card.d.ts +39 -0
- package/dist/Card.js +329 -0
- package/dist/Card.mjs +7 -0
- package/dist/CategoryStrip.d.mts +26 -0
- package/dist/CategoryStrip.d.ts +26 -0
- package/dist/CategoryStrip.js +396 -0
- package/dist/CategoryStrip.mjs +9 -0
- package/dist/Checkbox.d.mts +14 -0
- package/dist/Checkbox.d.ts +14 -0
- package/dist/Checkbox.js +304 -0
- package/dist/Checkbox.mjs +7 -0
- package/dist/Chip.d.mts +31 -0
- package/dist/Chip.d.ts +31 -0
- package/dist/Chip.js +370 -0
- package/dist/Chip.mjs +8 -0
- package/dist/ConfirmDialog.d.mts +15 -0
- package/dist/ConfirmDialog.d.ts +15 -0
- package/dist/ConfirmDialog.js +530 -0
- package/dist/ConfirmDialog.mjs +9 -0
- package/dist/CurrencyDisplay.d.mts +24 -0
- package/dist/CurrencyDisplay.d.ts +24 -0
- package/dist/CurrencyDisplay.js +189 -0
- package/dist/CurrencyDisplay.mjs +3 -0
- package/dist/CurrencyInput.d.mts +26 -0
- package/dist/CurrencyInput.d.ts +26 -0
- package/dist/CurrencyInput.js +404 -0
- package/dist/CurrencyInput.mjs +7 -0
- package/dist/DetailRow.d.mts +32 -0
- package/dist/DetailRow.d.ts +32 -0
- package/dist/DetailRow.js +275 -0
- package/dist/DetailRow.mjs +4 -0
- package/dist/EmptyState.d.mts +27 -0
- package/dist/EmptyState.d.ts +27 -0
- package/dist/EmptyState.js +503 -0
- package/dist/EmptyState.mjs +9 -0
- package/dist/Form.d.mts +52 -0
- package/dist/Form.d.ts +52 -0
- package/dist/Form.js +204 -0
- package/dist/Form.mjs +3 -0
- package/dist/IconButton.d.mts +22 -0
- package/dist/IconButton.d.ts +22 -0
- package/dist/IconButton.js +383 -0
- package/dist/IconButton.mjs +7 -0
- package/dist/Input.d.mts +23 -0
- package/dist/Input.d.ts +23 -0
- package/dist/Input.js +351 -0
- package/dist/Input.mjs +6 -0
- package/dist/LabelValue.d.mts +16 -0
- package/dist/LabelValue.d.ts +16 -0
- package/dist/LabelValue.js +225 -0
- package/dist/LabelValue.mjs +4 -0
- package/dist/ListGroup.d.mts +34 -0
- package/dist/ListGroup.d.ts +34 -0
- package/dist/ListGroup.js +217 -0
- package/dist/ListGroup.mjs +4 -0
- package/dist/ListItem.d.mts +64 -0
- package/dist/ListItem.d.ts +64 -0
- package/dist/ListItem.js +430 -0
- package/dist/ListItem.mjs +8 -0
- package/dist/MediaCard.d.mts +39 -0
- package/dist/MediaCard.d.ts +39 -0
- package/dist/MediaCard.js +427 -0
- package/dist/MediaCard.mjs +8 -0
- package/dist/MenuGroup.d.mts +34 -0
- package/dist/MenuGroup.d.ts +34 -0
- package/dist/MenuGroup.js +217 -0
- package/dist/MenuGroup.mjs +4 -0
- package/dist/MenuItem.d.mts +48 -0
- package/dist/MenuItem.d.ts +48 -0
- package/dist/MenuItem.js +403 -0
- package/dist/MenuItem.mjs +8 -0
- package/dist/MonthPicker.d.mts +20 -0
- package/dist/MonthPicker.d.ts +20 -0
- package/dist/MonthPicker.js +234 -0
- package/dist/MonthPicker.mjs +4 -0
- package/dist/Pressable.d.mts +34 -0
- package/dist/Pressable.d.ts +34 -0
- package/dist/Pressable.js +132 -0
- package/dist/Pressable.mjs +4 -0
- package/dist/Progress.d.mts +14 -0
- package/dist/Progress.d.ts +14 -0
- package/dist/Progress.js +191 -0
- package/dist/Progress.mjs +4 -0
- package/dist/RadioGroup.d.mts +19 -0
- package/dist/RadioGroup.d.ts +19 -0
- package/dist/RadioGroup.js +341 -0
- package/dist/RadioGroup.mjs +7 -0
- package/dist/Select.d.mts +22 -0
- package/dist/Select.d.ts +22 -0
- package/dist/Select.js +441 -0
- package/dist/Select.mjs +6 -0
- package/dist/Separator.d.mts +10 -0
- package/dist/Separator.d.ts +10 -0
- package/dist/Separator.js +156 -0
- package/dist/Separator.mjs +2 -0
- package/dist/Sheet.d.mts +81 -0
- package/dist/Sheet.d.ts +81 -0
- package/dist/Sheet.js +340 -0
- package/dist/Sheet.mjs +4 -0
- package/dist/Skeleton.d.mts +17 -0
- package/dist/Skeleton.d.ts +17 -0
- package/dist/Skeleton.js +205 -0
- package/dist/Skeleton.mjs +4 -0
- package/dist/Slider.d.mts +20 -0
- package/dist/Slider.d.ts +20 -0
- package/dist/Slider.js +232 -0
- package/dist/Slider.mjs +4 -0
- package/dist/Spinner.d.mts +12 -0
- package/dist/Spinner.d.ts +12 -0
- package/dist/Spinner.js +172 -0
- package/dist/Spinner.mjs +3 -0
- package/dist/Switch.d.mts +13 -0
- package/dist/Switch.d.ts +13 -0
- package/dist/Switch.js +261 -0
- package/dist/Switch.mjs +5 -0
- package/dist/Tabs.d.mts +27 -0
- package/dist/Tabs.d.ts +27 -0
- package/dist/Tabs.js +389 -0
- package/dist/Tabs.mjs +6 -0
- package/dist/Text.d.mts +12 -0
- package/dist/Text.d.ts +12 -0
- package/dist/Text.js +311 -0
- package/dist/Text.mjs +4 -0
- package/dist/Textarea.d.mts +16 -0
- package/dist/Textarea.d.ts +16 -0
- package/dist/Textarea.js +333 -0
- package/dist/Textarea.mjs +6 -0
- package/dist/Toast.d.mts +47 -0
- package/dist/Toast.d.ts +47 -0
- package/dist/Toast.js +185 -0
- package/dist/Toast.mjs +3 -0
- package/dist/Toggle.d.mts +33 -0
- package/dist/Toggle.d.ts +33 -0
- package/dist/Toggle.js +397 -0
- package/dist/Toggle.mjs +8 -0
- package/dist/VirtualList.d.mts +19 -0
- package/dist/VirtualList.d.ts +19 -0
- package/dist/VirtualList.js +38 -0
- package/dist/VirtualList.mjs +1 -0
- package/dist/chunk-2CE3TQVY.mjs +11 -0
- package/dist/chunk-2UYENBLV.mjs +49 -0
- package/dist/chunk-3BBOZ3OQ.mjs +41 -0
- package/dist/chunk-5IKW3VNC.mjs +43 -0
- package/dist/chunk-63357L2X.mjs +51 -0
- package/dist/chunk-6LQYY7HC.mjs +127 -0
- package/dist/chunk-6Q64UFIA.mjs +71 -0
- package/dist/chunk-76PFOSM2.mjs +41 -0
- package/dist/chunk-7H2OR44A.mjs +14 -0
- package/dist/chunk-A4MDAP7G.mjs +42 -0
- package/dist/chunk-AU2VDY4P.mjs +190 -0
- package/dist/chunk-BRKYVJVV.mjs +60 -0
- package/dist/chunk-CRYBX2CM.mjs +146 -0
- package/dist/chunk-DITNP6PL.mjs +106 -0
- package/dist/chunk-FTLJOUOQ.mjs +97 -0
- package/dist/chunk-GCWOGZYL.mjs +104 -0
- package/dist/chunk-GNGLDL6Z.mjs +60 -0
- package/dist/chunk-GPOUINK5.mjs +148 -0
- package/dist/chunk-HSPSMN6U.mjs +115 -0
- package/dist/chunk-IRRY3CRZ.mjs +82 -0
- package/dist/chunk-JB67UOB5.mjs +92 -0
- package/dist/chunk-JBLL7U3U.mjs +64 -0
- package/dist/chunk-KWCPOM6W.mjs +136 -0
- package/dist/chunk-KZJRQOIU.mjs +64 -0
- package/dist/chunk-L7E7TVEZ.mjs +145 -0
- package/dist/chunk-LG4DO3DK.mjs +174 -0
- package/dist/chunk-LWG526VX.mjs +139 -0
- package/dist/chunk-MN7OG7IY.mjs +96 -0
- package/dist/chunk-MX6HRKMI.mjs +29 -0
- package/dist/chunk-NC5ZTR2Y.mjs +32 -0
- package/dist/chunk-NQGVLMWG.mjs +90 -0
- package/dist/chunk-QCNARS3X.mjs +46 -0
- package/dist/chunk-QXGYKWI7.mjs +134 -0
- package/dist/chunk-QY3X2UYR.mjs +191 -0
- package/dist/chunk-RKLHUDZS.mjs +92 -0
- package/dist/chunk-RMMK64W5.mjs +54 -0
- package/dist/chunk-RR2VQLKE.mjs +190 -0
- package/dist/chunk-RTC3CFXF.mjs +29 -0
- package/dist/chunk-SBZYEV4S.mjs +61 -0
- package/dist/chunk-SOA2Z4RB.mjs +82 -0
- package/dist/chunk-SOYNZDVY.mjs +151 -0
- package/dist/chunk-T7XZ7H7Y.mjs +57 -0
- package/dist/chunk-TAJ2PQ2O.mjs +163 -0
- package/dist/chunk-U4N7WF4Z.mjs +108 -0
- package/dist/chunk-URDE3EUU.mjs +132 -0
- package/dist/chunk-URLL5JBR.mjs +245 -0
- package/dist/chunk-XDMN67KV.mjs +59 -0
- package/dist/chunk-Y6MXOREN.mjs +120 -0
- package/dist/chunk-YZJAFS4P.mjs +131 -0
- package/dist/index.d.mts +94 -852
- package/dist/index.d.ts +94 -852
- package/dist/index.js +1387 -942
- package/dist/index.mjs +50 -3844
- package/package.json +23 -14
- package/src/assets/fonts/Sohne-Bold.otf +0 -0
- package/src/assets/fonts/Sohne-BoldItalic.otf +0 -0
- package/src/assets/fonts/Sohne-ExtraBold.otf +0 -0
- package/src/assets/fonts/Sohne-ExtraBoldItalic.otf +0 -0
- package/src/assets/fonts/Sohne-ExtraLight.otf +0 -0
- package/src/assets/fonts/Sohne-ExtraLightItalic.otf +0 -0
- package/src/assets/fonts/Sohne-Italic.otf +0 -0
- package/src/assets/fonts/Sohne-Light.otf +0 -0
- package/src/assets/fonts/Sohne-LightItalic.otf +0 -0
- package/src/assets/fonts/Sohne-Medium.otf +0 -0
- package/src/assets/fonts/Sohne-MediumItalic.otf +0 -0
- package/src/assets/fonts/Sohne-Regular.otf +0 -0
- package/src/assets/fonts/Sohne-SemiBold.otf +0 -0
- package/src/assets/fonts/Sohne-SemiBoldItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-Bold.otf +0 -0
- package/src/assets/fonts/SohneMono-BoldItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-ExtraBold.otf +0 -0
- package/src/assets/fonts/SohneMono-ExtraBoldItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-ExtraLight.otf +0 -0
- package/src/assets/fonts/SohneMono-ExtraLightItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-Italic.otf +0 -0
- package/src/assets/fonts/SohneMono-Light.otf +0 -0
- package/src/assets/fonts/SohneMono-LightItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-Medium.otf +0 -0
- package/src/assets/fonts/SohneMono-MediumItalic.otf +0 -0
- package/src/assets/fonts/SohneMono-Regular.otf +0 -0
- package/src/assets/fonts/SohneMono-SemiBold.otf +0 -0
- package/src/assets/fonts/SohneMono-SemiBoldItalic.otf +0 -0
- package/src/components/Accordion/Accordion.tsx +13 -15
- package/src/components/AlertBanner/AlertBanner.tsx +33 -12
- package/src/components/Avatar/Avatar.tsx +4 -2
- package/src/components/Badge/Badge.tsx +4 -2
- package/src/components/Button/Button.tsx +30 -29
- package/src/components/ButtonGroup/ButtonGroup.tsx +13 -10
- package/src/components/Card/Card.tsx +36 -65
- package/src/components/CategoryStrip/CategoryStrip.tsx +68 -58
- package/src/components/Checkbox/Checkbox.tsx +41 -55
- package/src/components/Chip/Chip.tsx +49 -84
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +2 -2
- package/src/components/CurrencyDisplay/CurrencyDisplay.tsx +4 -2
- package/src/components/CurrencyInput/CurrencyInput.tsx +2 -2
- package/src/components/DetailRow/DetailRow.tsx +9 -7
- package/src/components/EmptyState/EmptyState.tsx +2 -2
- package/src/components/Form/Form.tsx +149 -0
- package/src/components/Form/index.ts +1 -0
- package/src/components/IconButton/IconButton.tsx +24 -20
- package/src/components/Input/Input.tsx +63 -50
- package/src/components/LabelValue/LabelValue.tsx +6 -4
- package/src/components/ListGroup/ListGroup.tsx +145 -0
- package/src/components/ListGroup/index.ts +1 -0
- package/src/components/ListItem/ListItem.tsx +30 -43
- package/src/components/MediaCard/MediaCard.tsx +31 -29
- package/src/components/MenuGroup/MenuGroup.tsx +145 -0
- package/src/components/MenuGroup/index.ts +1 -0
- package/src/components/MenuItem/MenuItem.tsx +29 -40
- package/src/components/MonthPicker/MonthPicker.tsx +14 -4
- package/src/components/Pressable/Pressable.tsx +27 -46
- package/src/components/Progress/Progress.tsx +21 -12
- package/src/components/RadioGroup/RadioGroup.tsx +55 -32
- package/src/components/Select/Select.tsx +23 -21
- package/src/components/Separator/Separator.tsx +1 -3
- package/src/components/Sheet/Sheet.tsx +85 -18
- package/src/components/Skeleton/Skeleton.tsx +25 -14
- package/src/components/Slider/Slider.tsx +13 -3
- package/src/components/Spinner/Spinner.tsx +1 -1
- package/src/components/Switch/Switch.tsx +70 -52
- package/src/components/Tabs/Tabs.tsx +59 -47
- package/src/components/Text/Text.tsx +3 -1
- package/src/components/Textarea/Textarea.tsx +44 -23
- package/src/components/Toast/Toast.tsx +6 -6
- package/src/components/Toggle/Toggle.tsx +86 -68
- package/src/components/VirtualList/VirtualList.tsx +60 -0
- package/src/components/VirtualList/index.ts +1 -0
- package/src/fonts.ts +38 -20
- package/src/index.ts +5 -1
- package/src/theme/colors.ts +53 -39
- package/src/theme/types.ts +3 -0
- package/src/tokens.ts +49 -39
- package/src/utils/animations.ts +58 -0
- package/src/utils/icons.ts +47 -20
- package/src/utils/useColorTransition.ts +40 -0
- package/src/utils/usePressScale.ts +75 -0
- package/src/assets/fonts/Poppins-Black.ttf +0 -0
- package/src/assets/fonts/Poppins-BlackItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Bold.ttf +0 -0
- package/src/assets/fonts/Poppins-BoldItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraBold.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraBoldItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraLight.ttf +0 -0
- package/src/assets/fonts/Poppins-ExtraLightItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Italic.ttf +0 -0
- package/src/assets/fonts/Poppins-Light.ttf +0 -0
- package/src/assets/fonts/Poppins-LightItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Medium.ttf +0 -0
- package/src/assets/fonts/Poppins-MediumItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Regular.ttf +0 -0
- package/src/assets/fonts/Poppins-SemiBold.ttf +0 -0
- package/src/assets/fonts/Poppins-SemiBoldItalic.ttf +0 -0
- package/src/assets/fonts/Poppins-Thin.ttf +0 -0
- package/src/assets/fonts/Poppins-ThinItalic.ttf +0 -0
|
@@ -1,58 +1,48 @@
|
|
|
1
|
-
import React, { useState
|
|
2
|
-
import { TextInput, View, Text,
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { TextInput, View, Text, StyleSheet, TextInputProps, ViewStyle, TextStyle, TouchableOpacity, Platform } from 'react-native'
|
|
3
|
+
import Animated, {
|
|
4
|
+
useAnimatedStyle,
|
|
5
|
+
interpolateColor,
|
|
6
|
+
interpolate,
|
|
7
|
+
} from 'react-native-reanimated'
|
|
3
8
|
import { AntDesign } from '@expo/vector-icons'
|
|
4
9
|
import { useTheme } from '../../theme'
|
|
5
10
|
import { s, vs, ms } from '../../utils/scaling'
|
|
6
11
|
import { renderIcon } from '../../utils/icons'
|
|
12
|
+
import { useColorTransition } from '../../utils/useColorTransition'
|
|
13
|
+
import { TIMINGS } from '../../utils/animations'
|
|
7
14
|
|
|
8
|
-
const webInputResetStyle:
|
|
15
|
+
const webInputResetStyle: Record<string, unknown> =
|
|
9
16
|
Platform.OS === 'web'
|
|
10
17
|
? { outlineStyle: 'none', outlineWidth: 0, outlineColor: 'transparent', boxShadow: 'none' }
|
|
11
18
|
: {}
|
|
12
19
|
|
|
13
20
|
export interface InputProps extends TextInputProps {
|
|
14
21
|
label?: string
|
|
15
|
-
/** Red helper text below the input; also changes border to `destructive` color. Takes priority over `hint`. */
|
|
16
22
|
error?: string
|
|
17
|
-
/** Helper text shown below the input when there is no error. */
|
|
18
23
|
hint?: string
|
|
19
|
-
/** Disabled visual state — dimmed appearance, not editable. Also sets `editable={false}`. */
|
|
20
24
|
disabled?: boolean
|
|
21
|
-
/** Text or component rendered before the input text. */
|
|
22
25
|
prefix?: React.ReactNode
|
|
23
|
-
/** Text or component rendered after the input text. */
|
|
24
26
|
suffix?: React.ReactNode
|
|
25
|
-
/** Style applied to prefix text if prefix is a string. */
|
|
26
27
|
prefixStyle?: TextStyle
|
|
27
|
-
/** Style applied to suffix text if suffix is a string. */
|
|
28
28
|
suffixStyle?: TextStyle
|
|
29
|
-
/**
|
|
30
|
-
* Icon name from `@expo/vector-icons` rendered before the input text.
|
|
31
|
-
* See https://icons.expo.fyi. Takes precedence over `prefix`.
|
|
32
|
-
*/
|
|
33
29
|
prefixIcon?: string
|
|
34
|
-
/**
|
|
35
|
-
* Icon name from `@expo/vector-icons` rendered after the input text.
|
|
36
|
-
* See https://icons.expo.fyi. Takes precedence over `suffix` (unless `type="password"`).
|
|
37
|
-
*/
|
|
38
30
|
suffixIcon?: string
|
|
39
|
-
/** Override the resolved prefix icon color. Defaults to `mutedForeground`. */
|
|
40
31
|
prefixIconColor?: string
|
|
41
|
-
/** Override the resolved suffix icon color. Defaults to `mutedForeground`. */
|
|
42
32
|
suffixIconColor?: string
|
|
43
|
-
/** Input type. When set to \`'password'\`, shows a toggle button to reveal/hide text. */
|
|
44
33
|
type?: 'text' | 'password'
|
|
45
|
-
/** Style for the outer container \`View\`. Use \`style\` (from \`TextInputProps\`) to style the \`TextInput\` itself. */
|
|
46
34
|
containerStyle?: ViewStyle
|
|
47
|
-
/** Style for the inner border wrapper (overrides padding, etc). */
|
|
48
35
|
inputWrapperStyle?: ViewStyle
|
|
49
36
|
}
|
|
50
37
|
|
|
51
|
-
export function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = 'text', containerStyle, inputWrapperStyle, style, onFocus, onBlur, secureTextEntry, editable, ...props }: InputProps) {
|
|
38
|
+
export function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = 'text', containerStyle, inputWrapperStyle, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }: InputProps) {
|
|
52
39
|
const { colors } = useTheme()
|
|
53
40
|
const [focused, setFocused] = useState(false)
|
|
54
41
|
const [showPassword, setShowPassword] = useState(false)
|
|
55
|
-
|
|
42
|
+
|
|
43
|
+
const focusProgress = useColorTransition(focused, {
|
|
44
|
+
duration: focused ? TIMINGS.focusIn.duration : TIMINGS.focusOut.duration,
|
|
45
|
+
})
|
|
56
46
|
|
|
57
47
|
const isDisabled = disabled || editable === false
|
|
58
48
|
const isPassword = type === 'password'
|
|
@@ -62,33 +52,45 @@ export function Input({ label, error, hint, disabled, prefix, suffix, prefixStyl
|
|
|
62
52
|
? renderIcon(prefixIcon, 20, prefixIconColor ?? colors.foregroundMuted)
|
|
63
53
|
: prefix
|
|
64
54
|
|
|
65
|
-
// If type is password and no suffix override is provided, add the toggle button
|
|
66
55
|
const effectiveSuffix: React.ReactNode = isPassword && !suffix && !suffixIcon ? (
|
|
67
|
-
<TouchableOpacity
|
|
56
|
+
<TouchableOpacity
|
|
57
|
+
onPress={() => setShowPassword(!showPassword)}
|
|
58
|
+
// AUDIT FIX: was padding: s(4) → ~28px target (below 44px minimum).
|
|
59
|
+
// padding: s(12) with negative margin keeps visual size but expands hit area.
|
|
60
|
+
style={styles.passwordToggle}
|
|
61
|
+
activeOpacity={0.6}
|
|
62
|
+
accessibilityRole="button"
|
|
63
|
+
accessibilityLabel={showPassword ? 'Hide password' : 'Show password'}
|
|
64
|
+
>
|
|
68
65
|
<AntDesign name={showPassword ? 'eye' : 'eye-invisible'} size={20} color={colors.foregroundMuted} />
|
|
69
66
|
</TouchableOpacity>
|
|
70
67
|
) : suffixIcon
|
|
71
68
|
? renderIcon(suffixIcon, 20, suffixIconColor ?? colors.foregroundMuted)
|
|
72
69
|
: suffix
|
|
73
70
|
|
|
71
|
+
// Border drawn on an absolute overlay so the 1px→2px weight change never
|
|
72
|
+
// resizes the layout box (which would reflow content / shift the interface).
|
|
73
|
+
// Wrapper keeps borderWidth: 0; overlay grows inward and is non-interactive.
|
|
74
|
+
const borderAnimStyle = useAnimatedStyle(() => ({
|
|
75
|
+
borderColor: error
|
|
76
|
+
? colors.destructive
|
|
77
|
+
: interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary]),
|
|
78
|
+
borderWidth: error
|
|
79
|
+
? 2
|
|
80
|
+
: interpolate(focusProgress.value, [0, 1], [1, 2]),
|
|
81
|
+
}))
|
|
82
|
+
|
|
74
83
|
return (
|
|
75
84
|
<View style={[styles.container, isDisabled && styles.containerDisabled, containerStyle]}>
|
|
76
85
|
{label ? <Text style={[styles.label, { color: colors.foreground }]} allowFontScaling={true}>{label}</Text> : null}
|
|
77
86
|
<Animated.View
|
|
78
87
|
style={[
|
|
79
88
|
styles.inputWrapper,
|
|
80
|
-
{
|
|
81
|
-
borderColor: error
|
|
82
|
-
? colors.destructive
|
|
83
|
-
: focusAnim.interpolate({
|
|
84
|
-
inputRange: [0, 1],
|
|
85
|
-
outputRange: [colors.border, colors.primary],
|
|
86
|
-
}),
|
|
87
|
-
backgroundColor: isDisabled ? colors.surface : colors.background,
|
|
88
|
-
},
|
|
89
|
+
{ backgroundColor: isDisabled ? colors.surface : colors.background },
|
|
89
90
|
inputWrapperStyle,
|
|
90
91
|
]}
|
|
91
92
|
>
|
|
93
|
+
<Animated.View style={[styles.borderOverlay, borderAnimStyle]} pointerEvents="none" />
|
|
92
94
|
{effectivePrefix ? (
|
|
93
95
|
typeof effectivePrefix === 'string' ? (
|
|
94
96
|
<Text style={[styles.prefixText, { color: colors.foregroundMuted }, prefixStyle]} allowFontScaling={true}>
|
|
@@ -101,26 +103,23 @@ export function Input({ label, error, hint, disabled, prefix, suffix, prefixStyl
|
|
|
101
103
|
<TextInput
|
|
102
104
|
style={[
|
|
103
105
|
styles.input,
|
|
104
|
-
{
|
|
105
|
-
color: colors.foreground,
|
|
106
|
-
},
|
|
106
|
+
{ color: colors.foreground },
|
|
107
107
|
webInputResetStyle,
|
|
108
108
|
style,
|
|
109
109
|
]}
|
|
110
110
|
onFocus={(e) => {
|
|
111
111
|
setFocused(true)
|
|
112
|
-
Animated.timing(focusAnim, { toValue: 1, duration: 120, easing: Easing.out(Easing.ease), useNativeDriver: false }).start()
|
|
113
112
|
onFocus?.(e)
|
|
114
113
|
}}
|
|
115
114
|
onBlur={(e) => {
|
|
116
115
|
setFocused(false)
|
|
117
|
-
Animated.timing(focusAnim, { toValue: 0, duration: 80, easing: Easing.out(Easing.ease), useNativeDriver: false }).start()
|
|
118
116
|
onBlur?.(e)
|
|
119
117
|
}}
|
|
120
118
|
placeholderTextColor={colors.foregroundMuted}
|
|
121
119
|
allowFontScaling={true}
|
|
122
120
|
secureTextEntry={effectiveSecure}
|
|
123
121
|
editable={isDisabled ? false : editable}
|
|
122
|
+
accessibilityLabel={accessibilityLabel ?? label}
|
|
124
123
|
{...props}
|
|
125
124
|
/>
|
|
126
125
|
{effectiveSuffix ? (
|
|
@@ -134,7 +133,13 @@ export function Input({ label, error, hint, disabled, prefix, suffix, prefixStyl
|
|
|
134
133
|
) : null}
|
|
135
134
|
</Animated.View>
|
|
136
135
|
{error ? (
|
|
137
|
-
<Text
|
|
136
|
+
<Text
|
|
137
|
+
style={[styles.helperText, { color: colors.destructive }]}
|
|
138
|
+
allowFontScaling={true}
|
|
139
|
+
accessibilityLiveRegion="polite"
|
|
140
|
+
>
|
|
141
|
+
{error}
|
|
142
|
+
</Text>
|
|
138
143
|
) : null}
|
|
139
144
|
{!error && hint ? (
|
|
140
145
|
<Text style={[styles.helperText, { color: colors.foregroundMuted }]} allowFontScaling={true}>{hint}</Text>
|
|
@@ -151,20 +156,25 @@ const styles = StyleSheet.create({
|
|
|
151
156
|
opacity: 0.6,
|
|
152
157
|
},
|
|
153
158
|
label: {
|
|
154
|
-
fontFamily: '
|
|
155
|
-
fontSize: ms(14),
|
|
159
|
+
fontFamily: 'Sohne-Medium',
|
|
160
|
+
fontSize: ms(14),
|
|
156
161
|
},
|
|
157
162
|
inputWrapper: {
|
|
158
163
|
flexDirection: 'row',
|
|
159
164
|
alignItems: 'center',
|
|
160
|
-
|
|
165
|
+
// Border lives on borderOverlay (absolute) so its 1px→2px focus change
|
|
166
|
+
// never resizes this box. Wrapper itself carries no border.
|
|
161
167
|
borderRadius: 8,
|
|
162
168
|
paddingHorizontal: s(14),
|
|
163
169
|
paddingVertical: vs(11),
|
|
164
170
|
minHeight: 48,
|
|
165
171
|
},
|
|
172
|
+
borderOverlay: {
|
|
173
|
+
...StyleSheet.absoluteFillObject,
|
|
174
|
+
borderRadius: 8,
|
|
175
|
+
},
|
|
166
176
|
input: {
|
|
167
|
-
fontFamily: '
|
|
177
|
+
fontFamily: 'Sohne-Regular',
|
|
168
178
|
flex: 1,
|
|
169
179
|
fontSize: ms(16),
|
|
170
180
|
paddingVertical: vs(2),
|
|
@@ -174,7 +184,7 @@ const styles = StyleSheet.create({
|
|
|
174
184
|
marginRight: s(8),
|
|
175
185
|
},
|
|
176
186
|
prefixText: {
|
|
177
|
-
fontFamily: '
|
|
187
|
+
fontFamily: 'Sohne-Regular',
|
|
178
188
|
fontSize: ms(15),
|
|
179
189
|
marginRight: s(8),
|
|
180
190
|
},
|
|
@@ -182,15 +192,18 @@ const styles = StyleSheet.create({
|
|
|
182
192
|
marginLeft: s(8),
|
|
183
193
|
},
|
|
184
194
|
suffixText: {
|
|
185
|
-
fontFamily: '
|
|
195
|
+
fontFamily: 'Sohne-Regular',
|
|
186
196
|
fontSize: ms(15),
|
|
187
197
|
marginLeft: s(8),
|
|
188
198
|
},
|
|
199
|
+
// AUDIT FIX: was padding: s(4) → ~28px tap target. Now 12px padding → ~44px.
|
|
200
|
+
// Negative margin compensates so the visual icon position is unchanged.
|
|
189
201
|
passwordToggle: {
|
|
190
|
-
padding: s(
|
|
202
|
+
padding: s(12),
|
|
203
|
+
margin: -s(8),
|
|
191
204
|
},
|
|
192
205
|
helperText: {
|
|
193
|
-
fontFamily: '
|
|
206
|
+
fontFamily: 'Sohne-Regular',
|
|
194
207
|
fontSize: ms(13),
|
|
195
208
|
},
|
|
196
209
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
3
3
|
import { useTheme } from '../../theme'
|
|
4
|
-
import { s,
|
|
4
|
+
import { s, ms, mvs } from '../../utils/scaling'
|
|
5
5
|
import { renderIcon } from '../../utils/icons'
|
|
6
6
|
|
|
7
7
|
export interface LabelValueProps {
|
|
@@ -14,7 +14,7 @@ export interface LabelValueProps {
|
|
|
14
14
|
style?: ViewStyle
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
function LabelValueBase({ label, value, iconName, iconColor, style }: LabelValueProps) {
|
|
18
18
|
const { colors } = useTheme()
|
|
19
19
|
|
|
20
20
|
const resolvedIcon = iconName
|
|
@@ -40,6 +40,8 @@ export function LabelValue({ label, value, iconName, iconColor, style }: LabelVa
|
|
|
40
40
|
)
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
export const LabelValue = React.memo(LabelValueBase)
|
|
44
|
+
|
|
43
45
|
const styles = StyleSheet.create({
|
|
44
46
|
container: {
|
|
45
47
|
flexDirection: 'row',
|
|
@@ -57,12 +59,12 @@ const styles = StyleSheet.create({
|
|
|
57
59
|
justifyContent: 'center',
|
|
58
60
|
},
|
|
59
61
|
label: {
|
|
60
|
-
fontFamily: '
|
|
62
|
+
fontFamily: 'Sohne-Regular',
|
|
61
63
|
fontSize: ms(13),
|
|
62
64
|
lineHeight: mvs(18),
|
|
63
65
|
},
|
|
64
66
|
value: {
|
|
65
|
-
fontFamily: '
|
|
67
|
+
fontFamily: 'Sohne-Medium',
|
|
66
68
|
fontSize: ms(14),
|
|
67
69
|
lineHeight: mvs(20),
|
|
68
70
|
textAlign: 'right',
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
3
|
+
import { useTheme } from '../../theme'
|
|
4
|
+
import { s, vs } from '../../utils/scaling'
|
|
5
|
+
import { RADIUS } from '../../tokens'
|
|
6
|
+
|
|
7
|
+
export type ListGroupVariant = 'plain' | 'card'
|
|
8
|
+
|
|
9
|
+
export interface ListGroupProps {
|
|
10
|
+
children: React.ReactNode
|
|
11
|
+
/**
|
|
12
|
+
* - `plain` (default): no background, plain ListItems inside.
|
|
13
|
+
* - `card`: card surface with background + border wrapping plain ListItems.
|
|
14
|
+
*/
|
|
15
|
+
variant?: ListGroupVariant
|
|
16
|
+
style?: ViewStyle
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ListGroupHeaderProps {
|
|
20
|
+
children: React.ReactNode
|
|
21
|
+
style?: ViewStyle
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ListGroupFooterProps {
|
|
25
|
+
children: React.ReactNode
|
|
26
|
+
style?: ViewStyle
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* ListGroup wraps multiple ListItems and auto-adds separators between them.
|
|
31
|
+
* Use variant="card" for a standalone surface or "plain" for items inside another container.
|
|
32
|
+
*/
|
|
33
|
+
export function ListGroup({ children, variant = 'plain', style }: ListGroupProps) {
|
|
34
|
+
const { colors } = useTheme()
|
|
35
|
+
|
|
36
|
+
// Auto-inject showSeparator={true} to all ListItem children except the last
|
|
37
|
+
const processedChildren = React.Children.map(children, (child, index) => {
|
|
38
|
+
if (!React.isValidElement(child)) return child
|
|
39
|
+
|
|
40
|
+
// Skip ListGroup.Header and ListGroup.Footer
|
|
41
|
+
if (child.type === ListGroupHeader || child.type === ListGroupFooter) {
|
|
42
|
+
return child
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Check if it's a ListItem (has title prop as a heuristic)
|
|
46
|
+
const childProps = child.props as Record<string, unknown>
|
|
47
|
+
const isListItem = 'title' in childProps
|
|
48
|
+
if (!isListItem) return child
|
|
49
|
+
|
|
50
|
+
const isLast = index === React.Children.count(children) - 1
|
|
51
|
+
|
|
52
|
+
// Only add separator if not already explicitly set and not last item
|
|
53
|
+
if (childProps['showSeparator'] === undefined && !isLast) {
|
|
54
|
+
return React.cloneElement(child as React.ReactElement<Record<string, unknown>>, {
|
|
55
|
+
showSeparator: true,
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return child
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
const cardStyle: ViewStyle =
|
|
63
|
+
variant === 'card'
|
|
64
|
+
? {
|
|
65
|
+
backgroundColor: colors.card,
|
|
66
|
+
borderRadius: RADIUS.md,
|
|
67
|
+
borderWidth: 1,
|
|
68
|
+
borderColor: colors.border,
|
|
69
|
+
shadowColor: '#000',
|
|
70
|
+
shadowOffset: { width: 0, height: 2 },
|
|
71
|
+
shadowOpacity: 0.06,
|
|
72
|
+
shadowRadius: 6,
|
|
73
|
+
elevation: 2,
|
|
74
|
+
paddingVertical: vs(4),
|
|
75
|
+
}
|
|
76
|
+
: {}
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<View style={[styles.container, cardStyle, style]}>
|
|
80
|
+
{processedChildren}
|
|
81
|
+
</View>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function ListGroupHeader({ children, style }: ListGroupHeaderProps) {
|
|
86
|
+
const { colors } = useTheme()
|
|
87
|
+
|
|
88
|
+
if (typeof children === 'string') {
|
|
89
|
+
return (
|
|
90
|
+
<View style={[styles.header, { borderBottomColor: colors.separator }, style]}>
|
|
91
|
+
<Text style={[styles.headerText, { color: colors.foregroundMuted }]} allowFontScaling={true}>
|
|
92
|
+
{children}
|
|
93
|
+
</Text>
|
|
94
|
+
</View>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return <View style={[styles.header, { borderBottomColor: colors.separator }, style]}>{children}</View>
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function ListGroupFooter({ children, style }: ListGroupFooterProps) {
|
|
102
|
+
const { colors } = useTheme()
|
|
103
|
+
|
|
104
|
+
if (typeof children === 'string') {
|
|
105
|
+
return (
|
|
106
|
+
<View style={[styles.footer, style]}>
|
|
107
|
+
<Text style={[styles.footerText, { color: colors.foregroundMuted }]} allowFontScaling={true}>
|
|
108
|
+
{children}
|
|
109
|
+
</Text>
|
|
110
|
+
</View>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return <View style={[styles.footer, style]}>{children}</View>
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
ListGroup.Header = ListGroupHeader
|
|
118
|
+
ListGroup.Footer = ListGroupFooter
|
|
119
|
+
|
|
120
|
+
const styles = StyleSheet.create({
|
|
121
|
+
container: {
|
|
122
|
+
overflow: 'hidden',
|
|
123
|
+
},
|
|
124
|
+
header: {
|
|
125
|
+
paddingHorizontal: s(16),
|
|
126
|
+
paddingTop: vs(12),
|
|
127
|
+
paddingBottom: vs(8),
|
|
128
|
+
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
129
|
+
},
|
|
130
|
+
headerText: {
|
|
131
|
+
fontFamily: 'Sohne-SemiBold',
|
|
132
|
+
fontSize: 13,
|
|
133
|
+
letterSpacing: 0.32,
|
|
134
|
+
textTransform: 'uppercase',
|
|
135
|
+
},
|
|
136
|
+
footer: {
|
|
137
|
+
paddingHorizontal: s(16),
|
|
138
|
+
paddingTop: vs(8),
|
|
139
|
+
paddingBottom: vs(12),
|
|
140
|
+
},
|
|
141
|
+
footerText: {
|
|
142
|
+
fontFamily: 'Sohne-Regular',
|
|
143
|
+
fontSize: 12,
|
|
144
|
+
},
|
|
145
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ListGroup'
|
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react'
|
|
2
2
|
import {
|
|
3
3
|
TouchableOpacity,
|
|
4
|
-
Animated,
|
|
5
4
|
View,
|
|
6
5
|
Text,
|
|
7
6
|
StyleSheet,
|
|
8
7
|
ViewStyle,
|
|
9
8
|
TextStyle,
|
|
10
|
-
Platform,
|
|
11
9
|
} from 'react-native'
|
|
10
|
+
import Animated from 'react-native-reanimated'
|
|
12
11
|
import { Entypo } from '@expo/vector-icons'
|
|
13
12
|
import { selectionAsync as hapticSelection } from '../../utils/haptics'
|
|
14
13
|
import { useTheme } from '../../theme'
|
|
15
14
|
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
16
15
|
import { renderIcon } from '../../utils/icons'
|
|
17
16
|
import { RADIUS } from '../../tokens'
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
import { usePressScale } from '../../utils/usePressScale'
|
|
18
|
+
import { SPRINGS, PRESS_SCALE } from '../../utils/animations'
|
|
20
19
|
|
|
21
20
|
export type ListItemVariant = 'plain' | 'card'
|
|
22
21
|
|
|
@@ -78,9 +77,11 @@ export interface ListItemProps {
|
|
|
78
77
|
subtitleStyle?: TextStyle
|
|
79
78
|
/** Style applied to the caption Text. */
|
|
80
79
|
captionStyle?: TextStyle
|
|
80
|
+
/** Accessibility label override. Defaults to the title. */
|
|
81
|
+
accessibilityLabel?: string
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
|
|
84
|
+
function ListItemBase({
|
|
84
85
|
leftRender,
|
|
85
86
|
rightRender,
|
|
86
87
|
trailing,
|
|
@@ -101,30 +102,15 @@ export function ListItem({
|
|
|
101
102
|
titleStyle,
|
|
102
103
|
subtitleStyle,
|
|
103
104
|
captionStyle,
|
|
105
|
+
accessibilityLabel,
|
|
104
106
|
}: ListItemProps) {
|
|
105
107
|
const { colors } = useTheme()
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
useNativeDriver: nativeDriver,
|
|
113
|
-
stiffness: 350,
|
|
114
|
-
damping: 28,
|
|
115
|
-
mass: 0.9,
|
|
116
|
-
}).start()
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const handlePressOut = () => {
|
|
120
|
-
Animated.spring(scale, {
|
|
121
|
-
toValue: 1,
|
|
122
|
-
useNativeDriver: nativeDriver,
|
|
123
|
-
stiffness: 220,
|
|
124
|
-
damping: 20,
|
|
125
|
-
mass: 0.9,
|
|
126
|
-
}).start()
|
|
127
|
-
}
|
|
108
|
+
const { animatedStyle, onPressIn, onPressOut, hoverHandlers } = usePressScale({
|
|
109
|
+
pressScale: PRESS_SCALE.row,
|
|
110
|
+
pressInSpring: SPRINGS.surfacePressIn,
|
|
111
|
+
pressOutSpring: SPRINGS.surfacePressOut,
|
|
112
|
+
disabled: !onPress || disabled,
|
|
113
|
+
})
|
|
128
114
|
|
|
129
115
|
const handlePress = () => {
|
|
130
116
|
hapticSelection()
|
|
@@ -154,16 +140,21 @@ export function ListItem({
|
|
|
154
140
|
}
|
|
155
141
|
: {}
|
|
156
142
|
|
|
143
|
+
const a11yLabel = accessibilityLabel ?? [title, subtitle, caption].filter(Boolean).join('. ')
|
|
144
|
+
|
|
157
145
|
return (
|
|
158
|
-
<Animated.View style={[
|
|
146
|
+
<Animated.View style={[animatedStyle, disabled && styles.disabled]} {...hoverHandlers}>
|
|
159
147
|
<TouchableOpacity
|
|
160
148
|
style={[styles.container, cardStyle, style]}
|
|
161
149
|
onPress={onPress ? handlePress : undefined}
|
|
162
|
-
onPressIn={
|
|
163
|
-
onPressOut={
|
|
150
|
+
onPressIn={onPressIn}
|
|
151
|
+
onPressOut={onPressOut}
|
|
164
152
|
disabled={disabled}
|
|
165
153
|
activeOpacity={1}
|
|
166
154
|
touchSoundDisabled={true}
|
|
155
|
+
accessibilityRole={onPress ? 'button' : undefined}
|
|
156
|
+
accessibilityLabel={onPress ? a11yLabel : undefined}
|
|
157
|
+
accessibilityState={onPress ? { disabled: !!disabled } : undefined}
|
|
167
158
|
>
|
|
168
159
|
{effectiveLeft ? (
|
|
169
160
|
<View style={styles.leftContainer}>{effectiveLeft}</View>
|
|
@@ -219,10 +210,7 @@ export function ListItem({
|
|
|
219
210
|
<View
|
|
220
211
|
style={[
|
|
221
212
|
styles.separator,
|
|
222
|
-
{
|
|
223
|
-
backgroundColor: colors.border,
|
|
224
|
-
marginLeft: effectiveLeft ? s(44) + s(12) : 0
|
|
225
|
-
},
|
|
213
|
+
{ backgroundColor: colors.separator },
|
|
226
214
|
]}
|
|
227
215
|
/>
|
|
228
216
|
) : null}
|
|
@@ -230,11 +218,13 @@ export function ListItem({
|
|
|
230
218
|
)
|
|
231
219
|
}
|
|
232
220
|
|
|
221
|
+
export const ListItem = React.memo(ListItemBase)
|
|
222
|
+
|
|
233
223
|
const styles = StyleSheet.create({
|
|
234
224
|
container: {
|
|
235
225
|
flexDirection: 'row',
|
|
236
226
|
alignItems: 'center',
|
|
237
|
-
paddingHorizontal:
|
|
227
|
+
paddingHorizontal: s(16),
|
|
238
228
|
paddingVertical: vs(10),
|
|
239
229
|
gap: s(12),
|
|
240
230
|
},
|
|
@@ -250,17 +240,17 @@ const styles = StyleSheet.create({
|
|
|
250
240
|
gap: vs(4),
|
|
251
241
|
},
|
|
252
242
|
title: {
|
|
253
|
-
fontFamily: '
|
|
243
|
+
fontFamily: 'Sohne-Medium',
|
|
254
244
|
fontSize: ms(15),
|
|
255
245
|
lineHeight: mvs(22),
|
|
256
246
|
},
|
|
257
247
|
subtitle: {
|
|
258
|
-
fontFamily: '
|
|
248
|
+
fontFamily: 'Sohne-Regular',
|
|
259
249
|
fontSize: ms(13),
|
|
260
250
|
lineHeight: mvs(18),
|
|
261
251
|
},
|
|
262
252
|
caption: {
|
|
263
|
-
fontFamily: '
|
|
253
|
+
fontFamily: 'Sohne-Regular',
|
|
264
254
|
fontSize: ms(12),
|
|
265
255
|
lineHeight: mvs(16),
|
|
266
256
|
opacity: 0.7,
|
|
@@ -272,12 +262,9 @@ const styles = StyleSheet.create({
|
|
|
272
262
|
maxWidth: s(160),
|
|
273
263
|
},
|
|
274
264
|
rightText: {
|
|
275
|
-
fontFamily: '
|
|
265
|
+
fontFamily: 'Sohne-Regular',
|
|
276
266
|
fontSize: ms(14),
|
|
277
267
|
},
|
|
278
|
-
chevron: {
|
|
279
|
-
marginLeft: s(4),
|
|
280
|
-
},
|
|
281
268
|
separator: {
|
|
282
269
|
height: StyleSheet.hairlineWidth,
|
|
283
270
|
marginRight: 0,
|