@retray-dev/ui-kit 9.2.0 → 9.3.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.
Files changed (53) hide show
  1. package/COMPONENTS.md +2 -1
  2. package/dist/CurrencyInput.js +21 -35
  3. package/dist/CurrencyInput.mjs +2 -3
  4. package/dist/Input.js +21 -35
  5. package/dist/Input.mjs +1 -2
  6. package/dist/ListItem.d.mts +7 -2
  7. package/dist/ListItem.d.ts +7 -2
  8. package/dist/ListItem.js +7 -1
  9. package/dist/ListItem.mjs +1 -1
  10. package/dist/Textarea.mjs +1 -2
  11. package/dist/assets/fonts/Sohne-Bold.otf +0 -0
  12. package/dist/assets/fonts/Sohne-BoldItalic.otf +0 -0
  13. package/dist/assets/fonts/Sohne-ExtraBold.otf +0 -0
  14. package/dist/assets/fonts/Sohne-ExtraBoldItalic.otf +0 -0
  15. package/dist/assets/fonts/Sohne-ExtraLight.otf +0 -0
  16. package/dist/assets/fonts/Sohne-ExtraLightItalic.otf +0 -0
  17. package/dist/assets/fonts/Sohne-Italic.otf +0 -0
  18. package/dist/assets/fonts/Sohne-Light.otf +0 -0
  19. package/dist/assets/fonts/Sohne-LightItalic.otf +0 -0
  20. package/dist/assets/fonts/Sohne-Medium.otf +0 -0
  21. package/dist/assets/fonts/Sohne-MediumItalic.otf +0 -0
  22. package/dist/assets/fonts/Sohne-Regular.otf +0 -0
  23. package/dist/assets/fonts/Sohne-SemiBold.otf +0 -0
  24. package/dist/assets/fonts/Sohne-SemiBoldItalic.otf +0 -0
  25. package/dist/assets/fonts/SohneMono-Bold.otf +0 -0
  26. package/dist/assets/fonts/SohneMono-BoldItalic.otf +0 -0
  27. package/dist/assets/fonts/SohneMono-ExtraBold.otf +0 -0
  28. package/dist/assets/fonts/SohneMono-ExtraBoldItalic.otf +0 -0
  29. package/dist/assets/fonts/SohneMono-ExtraLight.otf +0 -0
  30. package/dist/assets/fonts/SohneMono-ExtraLightItalic.otf +0 -0
  31. package/dist/assets/fonts/SohneMono-Italic.otf +0 -0
  32. package/dist/assets/fonts/SohneMono-Light.otf +0 -0
  33. package/dist/assets/fonts/SohneMono-LightItalic.otf +0 -0
  34. package/dist/assets/fonts/SohneMono-Medium.otf +0 -0
  35. package/dist/assets/fonts/SohneMono-MediumItalic.otf +0 -0
  36. package/dist/assets/fonts/SohneMono-Regular.otf +0 -0
  37. package/dist/assets/fonts/SohneMono-SemiBold.otf +0 -0
  38. package/dist/assets/fonts/SohneMono-SemiBoldItalic.otf +0 -0
  39. package/dist/{chunk-EH745HE5.mjs → chunk-CZCQZHG6.mjs} +13 -4
  40. package/dist/{chunk-KNSENOV4.mjs → chunk-JUXSWN54.mjs} +1 -1
  41. package/dist/{chunk-T4I5WVHA.mjs → chunk-OHBNABL5.mjs} +8 -2
  42. package/dist/{chunk-LVYEU5ZK.mjs → chunk-ZUR7AU5R.mjs} +11 -18
  43. package/dist/fonts.d.mts +32 -0
  44. package/dist/fonts.d.ts +32 -0
  45. package/dist/fonts.js +44 -0
  46. package/dist/fonts.mjs +37 -0
  47. package/dist/index.js +98 -98
  48. package/dist/index.mjs +8 -9
  49. package/package.json +8 -3
  50. package/src/components/Input/Input.tsx +13 -30
  51. package/src/components/ListItem/ListItem.tsx +19 -3
  52. package/src/fonts.ts +3 -1
  53. package/dist/chunk-26BCI223.mjs +0 -14
package/dist/index.mjs CHANGED
@@ -1,14 +1,15 @@
1
+ export { Tabs, TabsContent } from './chunk-GQYFLP3D.mjs';
1
2
  export { Text } from './chunk-WJLKJMKR.mjs';
2
- export { Textarea } from './chunk-EH745HE5.mjs';
3
+ export { Textarea } from './chunk-CZCQZHG6.mjs';
3
4
  export { Toggle } from './chunk-KIHCWCWL.mjs';
4
5
  export { VirtualList } from './chunk-NC5ZTR2Y.mjs';
6
+ export { Separator } from './chunk-MX6HRKMI.mjs';
5
7
  export { BottomSheetModalProvider, Sheet, BottomSheetTextInput as SheetTextInput } from './chunk-PFZTM6D5.mjs';
6
8
  export { SheetSelect } from './chunk-URI2WBIV.mjs';
7
9
  export { Skeleton } from './chunk-AJ7ZDNBT.mjs';
8
10
  export { Slider } from './chunk-JMOZEC77.mjs';
9
11
  export { Switch } from './chunk-QKH5ZOD5.mjs';
10
12
  export { TabBar } from './chunk-MLF3EZFW.mjs';
11
- export { Tabs, TabsContent } from './chunk-GQYFLP3D.mjs';
12
13
  export { Pressable } from './chunk-MBMXYJJV.mjs';
13
14
  export { PricingCard } from './chunk-4I7D47FH.mjs';
14
15
  export { Progress } from './chunk-OB4JUQ3O.mjs';
@@ -17,14 +18,14 @@ export { RetrayProvider } from './chunk-YFZ3ELX5.mjs';
17
18
  export { ToastProvider, sonnerToast as toast, useToast } from './chunk-2UYENBLV.mjs';
18
19
  export { Select } from './chunk-A3A6KNQN.mjs';
19
20
  export { SelectableGrid } from './chunk-NA7PARID.mjs';
20
- export { Separator } from './chunk-MX6HRKMI.mjs';
21
21
  export { LabelValue } from './chunk-A4MDAP7G.mjs';
22
22
  export { ListGroup, ListGroupFooter, ListGroupHeader } from './chunk-SOA2Z4RB.mjs';
23
- export { ListItem } from './chunk-T4I5WVHA.mjs';
23
+ export { ListItem } from './chunk-OHBNABL5.mjs';
24
24
  export { MediaCard } from './chunk-VGTDN7SW.mjs';
25
25
  export { MenuGroup, MenuGroupFooter, MenuGroupHeader } from './chunk-IRRY3CRZ.mjs';
26
26
  export { MenuItem } from './chunk-ZJKGQMYH.mjs';
27
27
  export { MonthPicker, dateToMonthPickerValue, monthPickerValueToDate } from './chunk-GD6KXMG5.mjs';
28
+ export { DetailRow } from './chunk-JB67UOB5.mjs';
28
29
  export { EmptyState } from './chunk-6OAZJ577.mjs';
29
30
  export { ErrorBoundary } from './chunk-LXJIIOYQ.mjs';
30
31
  export { Form, FormField, FormFooter, FormSection } from './chunk-6Q64UFIA.mjs';
@@ -32,6 +33,7 @@ export { ImageUpload } from './chunk-Y4GL2MHX.mjs';
32
33
  export { Spinner } from './chunk-WBOOUHSS.mjs';
33
34
  export { ImageViewer } from './chunk-Z4BVUWW6.mjs';
34
35
  export { PagerDots } from './chunk-4K625MVM.mjs';
36
+ export { ButtonGroup } from './chunk-3BBOZ3OQ.mjs';
35
37
  export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './chunk-ID72TK46.mjs';
36
38
  export { CategoryStrip } from './chunk-VQ57HWPL.mjs';
37
39
  import './chunk-YNROWHQJ.mjs';
@@ -39,10 +41,8 @@ export { Checkbox } from './chunk-AV4EMIRH.mjs';
39
41
  export { Chip, ChipGroup } from './chunk-UREA2GYY.mjs';
40
42
  export { ConfirmDialog } from './chunk-FZZLPJ6B.mjs';
41
43
  export { CurrencyDisplay } from './chunk-BRKYVJVV.mjs';
42
- export { CurrencyInput } from './chunk-KNSENOV4.mjs';
43
- export { Input } from './chunk-LVYEU5ZK.mjs';
44
- import './chunk-26BCI223.mjs';
45
- export { DetailRow } from './chunk-JB67UOB5.mjs';
44
+ export { CurrencyInput } from './chunk-JUXSWN54.mjs';
45
+ export { Input } from './chunk-ZUR7AU5R.mjs';
46
46
  export { Accordion } from './chunk-O3HA6TYM.mjs';
47
47
  export { AlertBanner } from './chunk-6MKGPAR2.mjs';
48
48
  export { AppHeader } from './chunk-AZJF2BLK.mjs';
@@ -56,7 +56,6 @@ import './chunk-DVK4G2GT.mjs';
56
56
  export { BREAKPOINTS, ICON_SIZES, RADIUS, SHADOWS, SPACING, TYPOGRAPHY } from './chunk-QY3X2UYR.mjs';
57
57
  export { Icon, configureIconFamilies, renderIcon } from './chunk-T7XZ7H7Y.mjs';
58
58
  export { ThemeProvider, defaultDark, defaultLight, deriveColors, useTheme } from './chunk-SOYNZDVY.mjs';
59
- export { ButtonGroup } from './chunk-3BBOZ3OQ.mjs';
60
59
  import './chunk-2CE3TQVY.mjs';
61
60
  import './chunk-Y6FXYEAI.mjs';
62
61
  import { useState, useCallback } from 'react';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retray-dev/ui-kit",
3
- "version": "9.2.0",
3
+ "version": "9.3.1",
4
4
  "description": "Personal UI Kit for React Native / Expo",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -11,7 +11,11 @@
11
11
  "import": "./dist/index.mjs",
12
12
  "require": "./dist/index.js"
13
13
  },
14
- "./fonts": "./src/fonts.ts",
14
+ "./fonts": {
15
+ "types": "./dist/fonts.d.ts",
16
+ "import": "./dist/fonts.mjs",
17
+ "require": "./dist/fonts.js"
18
+ },
15
19
  "./*": {
16
20
  "types": "./dist/*.d.ts",
17
21
  "import": "./dist/*.mjs",
@@ -41,6 +45,7 @@
41
45
  "lint:all": "pnpm lint && pnpm --filter retray-ui-kit-example lint",
42
46
  "format:all": "pnpm format && pnpm --filter retray-ui-kit-example format",
43
47
  "verify": "pnpm typecheck && pnpm lint && pnpm test && pnpm build",
48
+ "test:fonts": "./scripts/test-consumer-fonts.sh",
44
49
  "deploy": "pnpm typecheck && pnpm build && npm publish --access public"
45
50
  },
46
51
  "keywords": [
@@ -72,7 +77,7 @@
72
77
  "react-native-screens": ">=3.0.0",
73
78
  "react-native-size-matters": ">=0.4.0",
74
79
  "react-native-svg": ">=15.0.0",
75
- "react-native-worklets": "~0.5.1",
80
+ "react-native-worklets": ">=0.5.1",
76
81
  "sonner-native": ">=0.22.0"
77
82
  },
78
83
  "peerDependenciesMeta": {
@@ -1,17 +1,12 @@
1
1
  import React, { useState } from 'react'
2
2
  import { TextInput, View, Text, StyleSheet, TextInputProps, ViewStyle, TextStyle, TouchableOpacity, Platform } from 'react-native'
3
3
  import { BottomSheetTextInput } from '@gorhom/bottom-sheet'
4
- import Animated, {
5
- useAnimatedStyle,
6
- interpolateColor,
7
- interpolate,
8
- } from 'react-native-reanimated'
4
+ import { EaseView } from 'react-native-ease'
9
5
  import { AntDesign } from '@expo/vector-icons'
10
6
  import { useTheme } from '../../theme'
11
7
  import { s, vs, ms } from '../../utils/scaling'
12
8
  import { renderIcon } from '../../utils/icons'
13
- import { useColorTransition } from '../../utils/useColorTransition'
14
- import { TIMINGS } from '../../utils/animations'
9
+ import { COLOR_TRANSITION } from '../../utils/animations'
15
10
 
16
11
  const webInputResetStyle: Record<string, unknown> =
17
12
  Platform.OS === 'web'
@@ -43,10 +38,6 @@ export function Input({ label, error, hint, disabled, prefix, suffix, prefixStyl
43
38
  const [focused, setFocused] = useState(false)
44
39
  const [showPassword, setShowPassword] = useState(false)
45
40
 
46
- const focusProgress = useColorTransition(focused, {
47
- duration: focused ? TIMINGS.focusIn.duration : TIMINGS.focusOut.duration,
48
- })
49
-
50
41
  const isDisabled = disabled || editable === false
51
42
  const isPassword = type === 'password'
52
43
  const effectiveSecure = isPassword ? !showPassword : secureTextEntry
@@ -71,29 +62,23 @@ export function Input({ label, error, hint, disabled, prefix, suffix, prefixStyl
71
62
  ? renderIcon(suffixIcon, 20, suffixIconColor ?? colors.foregroundMuted)
72
63
  : suffix
73
64
 
74
- // Border drawn on an absolute overlay so the 1px→2px weight change never
75
- // resizes the layout box (which would reflow content / shift the interface).
76
- // Wrapper keeps borderWidth: 0; overlay grows inward and is non-interactive.
77
- const borderAnimStyle = useAnimatedStyle(() => ({
78
- borderColor: error
79
- ? colors.destructive
80
- : interpolateColor(focusProgress.value, [0, 1], [colors.border, colors.primary]),
81
- borderWidth: error
82
- ? 2
83
- : interpolate(focusProgress.value, [0, 1], [1, 2]),
84
- }))
65
+ // Border color animated via EaseView. Width is static (1px normal, 2px error)
66
+ // to avoid worklets 0.9.x interpolation issues with borderWidth.
67
+ const borderColor = error ? colors.destructive : (focused ? colors.primary : colors.border)
85
68
 
86
69
  return (
87
70
  <View style={[styles.container, isDisabled && styles.containerDisabled, containerStyle]}>
88
71
  {label ? <Text style={[styles.label, { color: colors.foreground }]} allowFontScaling={true}>{label}</Text> : null}
89
- <Animated.View
72
+ <EaseView
90
73
  style={[
91
74
  styles.inputWrapper,
92
75
  { backgroundColor: isDisabled ? colors.surface : colors.background },
76
+ error && styles.inputWrapperError,
93
77
  inputWrapperStyle,
94
78
  ]}
79
+ animate={{ borderColor }}
80
+ transition={COLOR_TRANSITION}
95
81
  >
96
- <Animated.View style={[styles.borderOverlay, borderAnimStyle]} pointerEvents="none" />
97
82
  {effectivePrefix ? (
98
83
  typeof effectivePrefix === 'string' ? (
99
84
  <Text style={[styles.prefixText, { color: colors.foregroundMuted }, prefixStyle]} allowFontScaling={true}>
@@ -159,7 +144,7 @@ export function Input({ label, error, hint, disabled, prefix, suffix, prefixStyl
159
144
  <View style={styles.suffixContainer}>{effectiveSuffix}</View>
160
145
  )
161
146
  ) : null}
162
- </Animated.View>
147
+ </EaseView>
163
148
  {error ? (
164
149
  <Text
165
150
  style={[styles.helperText, { color: colors.destructive }]}
@@ -190,16 +175,14 @@ const styles = StyleSheet.create({
190
175
  inputWrapper: {
191
176
  flexDirection: 'row',
192
177
  alignItems: 'center',
193
- // Border lives on borderOverlay (absolute) so its 1px→2px focus change
194
- // never resizes this box. Wrapper itself carries no border.
195
178
  borderRadius: 8,
179
+ borderWidth: 1,
196
180
  paddingHorizontal: s(14),
197
181
  paddingVertical: vs(11),
198
182
  minHeight: 48,
199
183
  },
200
- borderOverlay: {
201
- ...StyleSheet.absoluteFillObject,
202
- borderRadius: 8,
184
+ inputWrapperError: {
185
+ borderWidth: 2,
203
186
  },
204
187
  input: {
205
188
  fontFamily: 'Sohne-Regular',
@@ -5,6 +5,8 @@ import {
5
5
  StyleSheet,
6
6
  ViewStyle,
7
7
  TextStyle,
8
+ Image,
9
+ ImageSourcePropType,
8
10
  } from 'react-native'
9
11
  import { Entypo } from '@expo/vector-icons'
10
12
  import { selectionAsync as hapticSelection } from '../../utils/haptics'
@@ -17,6 +19,11 @@ import { PressableRow } from '../../utils/pressable'
17
19
  export type ListItemVariant = 'plain' | 'card'
18
20
 
19
21
  export interface ListItemProps {
22
+ /**
23
+ * Image source for the left slot. If provided, renders an Image (40×40, borderRadius 8).
24
+ * Takes precedence over `leftRender` and `leftIcon`.
25
+ */
26
+ imageSource?: ImageSourcePropType
20
27
  /**
21
28
  * Arbitrary content rendered on the left (avatar, icon, image, etc.).
22
29
  * Rendered inside a 44×44 aligned container.
@@ -81,6 +88,7 @@ export interface ListItemProps {
81
88
  }
82
89
 
83
90
  function ListItemBase({
91
+ imageSource,
84
92
  leftRender,
85
93
  rightRender,
86
94
  trailing,
@@ -111,9 +119,12 @@ function ListItemBase({
111
119
  onPress?.()
112
120
  }
113
121
 
114
- const effectiveLeft: React.ReactNode = leftIcon
115
- ? renderIcon(leftIcon, 24, leftIconColor ?? colors.foreground)
116
- : leftRender ?? icon
122
+ // imageSource takes precedence, then leftIcon, then leftRender/icon
123
+ const effectiveLeft: React.ReactNode = imageSource
124
+ ? <Image source={imageSource} style={styles.image} />
125
+ : leftIcon
126
+ ? renderIcon(leftIcon, 24, leftIconColor ?? colors.foreground)
127
+ : leftRender ?? icon
117
128
 
118
129
  const effectiveRight: React.ReactNode | string | undefined = rightIcon
119
130
  ? renderIcon(rightIcon, 24, rightIconColor ?? colors.foregroundMuted)
@@ -241,6 +252,11 @@ const styles = StyleSheet.create({
241
252
  justifyContent: 'center',
242
253
  flexShrink: 0,
243
254
  },
255
+ image: {
256
+ width: s(40),
257
+ height: s(40),
258
+ borderRadius: 8,
259
+ },
244
260
  content: {
245
261
  flex: 1,
246
262
  gap: vs(4),
package/src/fonts.ts CHANGED
@@ -14,7 +14,9 @@
14
14
  * }
15
15
  */
16
16
  // `.otf` assets resolve to a Metro asset module id (number) via require() at the
17
- // consumer's build time. Declared locally so the dts build does not depend on @types/node.
17
+ // consumer's build time. Paths are relative to dist/fonts.js (the compiled output).
18
+ // The build step copies all .otf files into dist/assets/fonts/ so these paths
19
+ // resolve correctly without any ../traversal that Metro would reject.
18
20
  declare const require: (path: string) => number
19
21
 
20
22
  export const SohneFonts = {
@@ -1,14 +0,0 @@
1
- import { TIMINGS, EASINGS } from './chunk-DVK4G2GT.mjs';
2
- import { useEffect } from 'react';
3
- import { useSharedValue, withTiming } from 'react-native-reanimated';
4
-
5
- function useColorTransition(active, options = {}) {
6
- const { duration = TIMINGS.state.duration } = options;
7
- const progress = useSharedValue(active ? 1 : 0);
8
- useEffect(() => {
9
- progress.value = withTiming(active ? 1 : 0, { duration, easing: EASINGS.standard });
10
- }, [active, duration, progress]);
11
- return progress;
12
- }
13
-
14
- export { useColorTransition };