@webority-technologies/mobile 0.0.15 → 0.0.20

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 (202) hide show
  1. package/lib/commonjs/components/Accordion/Accordion.js +60 -19
  2. package/lib/commonjs/components/AppBar/AppBar.js +29 -20
  3. package/lib/commonjs/components/Avatar/Avatar.js +38 -8
  4. package/lib/commonjs/components/Badge/Badge.js +66 -4
  5. package/lib/commonjs/components/Banner/Banner.js +146 -66
  6. package/lib/commonjs/components/BottomNavigation/BottomNavigation.js +37 -15
  7. package/lib/commonjs/components/BottomSheet/BottomSheet.js +78 -53
  8. package/lib/commonjs/components/Button/Button.js +12 -5
  9. package/lib/commonjs/components/Card/Card.js +106 -16
  10. package/lib/commonjs/components/Carousel/Carousel.js +66 -12
  11. package/lib/commonjs/components/Checkbox/Checkbox.js +11 -7
  12. package/lib/commonjs/components/Chip/Chip.js +44 -12
  13. package/lib/commonjs/components/DatePicker/DatePicker.js +185 -76
  14. package/lib/commonjs/components/DateRangePicker/DateRangePicker.js +133 -59
  15. package/lib/commonjs/components/Dialog/Dialog.js +16 -10
  16. package/lib/commonjs/components/Drawer/Drawer.js +13 -10
  17. package/lib/commonjs/components/FieldBase/FieldBase.js +306 -0
  18. package/lib/commonjs/components/FieldBase/index.js +32 -0
  19. package/lib/commonjs/components/FloatingActionButton/FloatingActionButton.js +69 -44
  20. package/lib/commonjs/components/ForceUpdateDialog/ForceUpdateDialog.js +8 -2
  21. package/lib/commonjs/components/FormField/FormField.js +3 -2
  22. package/lib/commonjs/components/ImageGallery/ImageGallery.js +132 -44
  23. package/lib/commonjs/components/Input/Input.js +144 -181
  24. package/lib/commonjs/components/ListItem/ListItem.js +90 -11
  25. package/lib/commonjs/components/Modal/Modal.js +55 -27
  26. package/lib/commonjs/components/NumberInput/NumberInput.js +60 -106
  27. package/lib/commonjs/components/OTPInput/OTPInput.js +65 -58
  28. package/lib/commonjs/components/PickerTrigger/PickerTrigger.js +185 -0
  29. package/lib/commonjs/components/{AppIcon → PickerTrigger}/index.js +4 -4
  30. package/lib/commonjs/components/ProgressBar/ProgressBar.js +19 -11
  31. package/lib/commonjs/components/Radio/Radio.js +11 -6
  32. package/lib/commonjs/components/Rating/Rating.js +85 -19
  33. package/lib/commonjs/components/SearchBar/SearchBar.js +84 -107
  34. package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +22 -11
  35. package/lib/commonjs/components/Select/Select.js +62 -91
  36. package/lib/commonjs/components/Skeleton/Skeleton.js +131 -174
  37. package/lib/commonjs/components/Skeleton/SkeletonClock.js +117 -0
  38. package/lib/commonjs/components/Skeleton/SkeletonContent.js +164 -81
  39. package/lib/commonjs/components/Skeleton/SkeletonProvider.js +72 -10
  40. package/lib/commonjs/components/Skeleton/index.js +17 -16
  41. package/lib/commonjs/components/Slider/Slider.js +44 -25
  42. package/lib/commonjs/components/Stepper/Stepper.js +199 -29
  43. package/lib/commonjs/components/Swipeable/Swipeable.js +36 -19
  44. package/lib/commonjs/components/Switch/Switch.js +9 -2
  45. package/lib/commonjs/components/Tabs/Tabs.js +84 -21
  46. package/lib/commonjs/components/TimePicker/TimePicker.js +123 -45
  47. package/lib/commonjs/components/Toast/Toast.js +27 -16
  48. package/lib/commonjs/components/Tooltip/Tooltip.js +56 -32
  49. package/lib/commonjs/components/index.js +37 -37
  50. package/lib/commonjs/theme/tokens.js +55 -7
  51. package/lib/module/components/Accordion/Accordion.js +61 -20
  52. package/lib/module/components/AppBar/AppBar.js +29 -20
  53. package/lib/module/components/Avatar/Avatar.js +39 -9
  54. package/lib/module/components/Badge/Badge.js +67 -5
  55. package/lib/module/components/Banner/Banner.js +147 -67
  56. package/lib/module/components/BottomNavigation/BottomNavigation.js +37 -15
  57. package/lib/module/components/BottomSheet/BottomSheet.js +80 -55
  58. package/lib/module/components/Button/Button.js +12 -5
  59. package/lib/module/components/Card/Card.js +107 -17
  60. package/lib/module/components/Carousel/Carousel.js +67 -13
  61. package/lib/module/components/Checkbox/Checkbox.js +11 -7
  62. package/lib/module/components/Chip/Chip.js +45 -13
  63. package/lib/module/components/DatePicker/DatePicker.js +185 -76
  64. package/lib/module/components/DateRangePicker/DateRangePicker.js +134 -60
  65. package/lib/module/components/Dialog/Dialog.js +16 -10
  66. package/lib/module/components/Drawer/Drawer.js +13 -10
  67. package/lib/module/components/FieldBase/FieldBase.js +297 -0
  68. package/lib/module/components/FieldBase/index.js +4 -0
  69. package/lib/module/components/FloatingActionButton/FloatingActionButton.js +69 -44
  70. package/lib/module/components/ForceUpdateDialog/ForceUpdateDialog.js +8 -2
  71. package/lib/module/components/FormField/FormField.js +3 -2
  72. package/lib/module/components/ImageGallery/ImageGallery.js +128 -40
  73. package/lib/module/components/Input/Input.js +144 -179
  74. package/lib/module/components/ListItem/ListItem.js +91 -12
  75. package/lib/module/components/Modal/Modal.js +55 -27
  76. package/lib/module/components/NumberInput/NumberInput.js +60 -106
  77. package/lib/module/components/OTPInput/OTPInput.js +65 -58
  78. package/lib/module/components/PickerTrigger/PickerTrigger.js +181 -0
  79. package/lib/module/components/PickerTrigger/index.js +4 -0
  80. package/lib/module/components/ProgressBar/ProgressBar.js +19 -11
  81. package/lib/module/components/Radio/Radio.js +11 -6
  82. package/lib/module/components/Rating/Rating.js +86 -20
  83. package/lib/module/components/SearchBar/SearchBar.js +84 -107
  84. package/lib/module/components/SegmentedControl/SegmentedControl.js +22 -11
  85. package/lib/module/components/Select/Select.js +62 -91
  86. package/lib/module/components/Skeleton/Skeleton.js +135 -175
  87. package/lib/module/components/Skeleton/SkeletonClock.js +110 -0
  88. package/lib/module/components/Skeleton/SkeletonContent.js +167 -84
  89. package/lib/module/components/Skeleton/SkeletonProvider.js +71 -10
  90. package/lib/module/components/Skeleton/index.js +3 -2
  91. package/lib/module/components/Slider/Slider.js +44 -25
  92. package/lib/module/components/Stepper/Stepper.js +201 -31
  93. package/lib/module/components/Swipeable/Swipeable.js +36 -19
  94. package/lib/module/components/Switch/Switch.js +9 -2
  95. package/lib/module/components/Tabs/Tabs.js +84 -21
  96. package/lib/module/components/TimePicker/TimePicker.js +123 -45
  97. package/lib/module/components/Toast/Toast.js +27 -16
  98. package/lib/module/components/Tooltip/Tooltip.js +56 -32
  99. package/lib/module/components/index.js +2 -2
  100. package/lib/module/theme/tokens.js +55 -7
  101. package/lib/typescript/commonjs/components/Accordion/Accordion.d.ts +10 -5
  102. package/lib/typescript/commonjs/components/AppBar/AppBar.d.ts +8 -0
  103. package/lib/typescript/commonjs/components/Avatar/Avatar.d.ts +12 -6
  104. package/lib/typescript/commonjs/components/Badge/Badge.d.ts +7 -6
  105. package/lib/typescript/commonjs/components/Banner/Banner.d.ts +17 -6
  106. package/lib/typescript/commonjs/components/BottomSheet/BottomSheet.d.ts +7 -0
  107. package/lib/typescript/commonjs/components/Card/Card.d.ts +17 -6
  108. package/lib/typescript/commonjs/components/Carousel/Carousel.d.ts +7 -6
  109. package/lib/typescript/commonjs/components/Checkbox/Checkbox.d.ts +9 -1
  110. package/lib/typescript/commonjs/components/Chip/Chip.d.ts +13 -6
  111. package/lib/typescript/commonjs/components/DatePicker/DatePicker.d.ts +38 -3
  112. package/lib/typescript/commonjs/components/DateRangePicker/DateRangePicker.d.ts +36 -3
  113. package/lib/typescript/commonjs/components/Dialog/Dialog.d.ts +13 -1
  114. package/lib/typescript/commonjs/components/FieldBase/FieldBase.d.ts +141 -0
  115. package/lib/typescript/commonjs/components/FieldBase/index.d.ts +3 -0
  116. package/lib/typescript/commonjs/components/FloatingActionButton/FloatingActionButton.d.ts +8 -6
  117. package/lib/typescript/commonjs/components/FloatingActionButton/index.d.ts +1 -1
  118. package/lib/typescript/commonjs/components/ForceUpdateDialog/ForceUpdateDialog.d.ts +7 -0
  119. package/lib/typescript/commonjs/components/FormField/FormField.d.ts +7 -0
  120. package/lib/typescript/commonjs/components/ImageGallery/ImageGallery.d.ts +6 -4
  121. package/lib/typescript/commonjs/components/Input/Input.d.ts +6 -0
  122. package/lib/typescript/commonjs/components/ListItem/ListItem.d.ts +13 -6
  123. package/lib/typescript/commonjs/components/NumberInput/NumberInput.d.ts +3 -0
  124. package/lib/typescript/commonjs/components/PickerTrigger/PickerTrigger.d.ts +57 -0
  125. package/lib/typescript/commonjs/components/PickerTrigger/index.d.ts +3 -0
  126. package/lib/typescript/commonjs/components/ProgressBar/ProgressBar.d.ts +2 -0
  127. package/lib/typescript/commonjs/components/Radio/Radio.d.ts +3 -0
  128. package/lib/typescript/commonjs/components/Rating/Rating.d.ts +9 -6
  129. package/lib/typescript/commonjs/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  130. package/lib/typescript/commonjs/components/Skeleton/Skeleton.d.ts +49 -20
  131. package/lib/typescript/commonjs/components/Skeleton/SkeletonClock.d.ts +60 -0
  132. package/lib/typescript/commonjs/components/Skeleton/SkeletonContent.d.ts +80 -19
  133. package/lib/typescript/commonjs/components/Skeleton/SkeletonProvider.d.ts +39 -5
  134. package/lib/typescript/commonjs/components/Skeleton/index.d.ts +6 -4
  135. package/lib/typescript/commonjs/components/Slider/Slider.d.ts +12 -1
  136. package/lib/typescript/commonjs/components/Stepper/Stepper.d.ts +18 -6
  137. package/lib/typescript/commonjs/components/Swipeable/Swipeable.d.ts +2 -0
  138. package/lib/typescript/commonjs/components/Switch/Switch.d.ts +1 -0
  139. package/lib/typescript/commonjs/components/Tabs/Tabs.d.ts +26 -2
  140. package/lib/typescript/commonjs/components/TimePicker/TimePicker.d.ts +36 -3
  141. package/lib/typescript/commonjs/components/Toast/Toast.d.ts +8 -0
  142. package/lib/typescript/commonjs/components/Tooltip/Tooltip.d.ts +7 -1
  143. package/lib/typescript/commonjs/components/index.d.ts +5 -5
  144. package/lib/typescript/commonjs/index.d.ts +1 -1
  145. package/lib/typescript/commonjs/theme/index.d.ts +1 -1
  146. package/lib/typescript/commonjs/theme/types.d.ts +553 -11
  147. package/lib/typescript/module/components/Accordion/Accordion.d.ts +10 -5
  148. package/lib/typescript/module/components/AppBar/AppBar.d.ts +8 -0
  149. package/lib/typescript/module/components/Avatar/Avatar.d.ts +12 -6
  150. package/lib/typescript/module/components/Badge/Badge.d.ts +7 -6
  151. package/lib/typescript/module/components/Banner/Banner.d.ts +17 -6
  152. package/lib/typescript/module/components/BottomSheet/BottomSheet.d.ts +7 -0
  153. package/lib/typescript/module/components/Card/Card.d.ts +17 -6
  154. package/lib/typescript/module/components/Carousel/Carousel.d.ts +7 -6
  155. package/lib/typescript/module/components/Checkbox/Checkbox.d.ts +9 -1
  156. package/lib/typescript/module/components/Chip/Chip.d.ts +13 -6
  157. package/lib/typescript/module/components/DatePicker/DatePicker.d.ts +38 -3
  158. package/lib/typescript/module/components/DateRangePicker/DateRangePicker.d.ts +36 -3
  159. package/lib/typescript/module/components/Dialog/Dialog.d.ts +13 -1
  160. package/lib/typescript/module/components/FieldBase/FieldBase.d.ts +141 -0
  161. package/lib/typescript/module/components/FieldBase/index.d.ts +3 -0
  162. package/lib/typescript/module/components/FloatingActionButton/FloatingActionButton.d.ts +8 -6
  163. package/lib/typescript/module/components/FloatingActionButton/index.d.ts +1 -1
  164. package/lib/typescript/module/components/ForceUpdateDialog/ForceUpdateDialog.d.ts +7 -0
  165. package/lib/typescript/module/components/FormField/FormField.d.ts +7 -0
  166. package/lib/typescript/module/components/ImageGallery/ImageGallery.d.ts +6 -4
  167. package/lib/typescript/module/components/Input/Input.d.ts +6 -0
  168. package/lib/typescript/module/components/ListItem/ListItem.d.ts +13 -6
  169. package/lib/typescript/module/components/NumberInput/NumberInput.d.ts +3 -0
  170. package/lib/typescript/module/components/PickerTrigger/PickerTrigger.d.ts +57 -0
  171. package/lib/typescript/module/components/PickerTrigger/index.d.ts +3 -0
  172. package/lib/typescript/module/components/ProgressBar/ProgressBar.d.ts +2 -0
  173. package/lib/typescript/module/components/Radio/Radio.d.ts +3 -0
  174. package/lib/typescript/module/components/Rating/Rating.d.ts +9 -6
  175. package/lib/typescript/module/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  176. package/lib/typescript/module/components/Skeleton/Skeleton.d.ts +49 -20
  177. package/lib/typescript/module/components/Skeleton/SkeletonClock.d.ts +60 -0
  178. package/lib/typescript/module/components/Skeleton/SkeletonContent.d.ts +80 -19
  179. package/lib/typescript/module/components/Skeleton/SkeletonProvider.d.ts +39 -5
  180. package/lib/typescript/module/components/Skeleton/index.d.ts +6 -4
  181. package/lib/typescript/module/components/Slider/Slider.d.ts +12 -1
  182. package/lib/typescript/module/components/Stepper/Stepper.d.ts +18 -6
  183. package/lib/typescript/module/components/Swipeable/Swipeable.d.ts +2 -0
  184. package/lib/typescript/module/components/Switch/Switch.d.ts +1 -0
  185. package/lib/typescript/module/components/Tabs/Tabs.d.ts +26 -2
  186. package/lib/typescript/module/components/TimePicker/TimePicker.d.ts +36 -3
  187. package/lib/typescript/module/components/Toast/Toast.d.ts +8 -0
  188. package/lib/typescript/module/components/Tooltip/Tooltip.d.ts +7 -1
  189. package/lib/typescript/module/components/index.d.ts +5 -5
  190. package/lib/typescript/module/index.d.ts +1 -1
  191. package/lib/typescript/module/theme/index.d.ts +1 -1
  192. package/lib/typescript/module/theme/types.d.ts +553 -11
  193. package/package.json +2 -6
  194. package/lib/commonjs/components/AppIcon/AppIcon.js +0 -120
  195. package/lib/commonjs/types/vector-icons.d.js +0 -2
  196. package/lib/module/components/AppIcon/AppIcon.js +0 -111
  197. package/lib/module/components/AppIcon/index.js +0 -4
  198. package/lib/module/types/vector-icons.d.js +0 -2
  199. package/lib/typescript/commonjs/components/AppIcon/AppIcon.d.ts +0 -20
  200. package/lib/typescript/commonjs/components/AppIcon/index.d.ts +0 -3
  201. package/lib/typescript/module/components/AppIcon/AppIcon.d.ts +0 -20
  202. package/lib/typescript/module/components/AppIcon/index.d.ts +0 -3
@@ -5,31 +5,8 @@ import { Animated, Easing, Pressable, StyleSheet, Text, TextInput, View } from '
5
5
  import { fontFor, useTheme, createAnimatedValue } from "../../theme/index.js";
6
6
  import { triggerHaptic } from "../../utils/hapticUtils.js";
7
7
  import { useDebounce } from "../../hooks/useDebounce.js";
8
- import { AppIcon } from "../AppIcon/index.js";
8
+ import { FieldBase, resolveFieldSize, resolveFieldTextStyle, resolveVariantColors } from "../FieldBase/FieldBase.js";
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
- const sizeMap = {
11
- sm: {
12
- height: 36,
13
- paddingHorizontal: 10,
14
- fontSize: 13,
15
- iconSize: 16,
16
- gap: 6
17
- },
18
- md: {
19
- height: 44,
20
- paddingHorizontal: 12,
21
- fontSize: 15,
22
- iconSize: 18,
23
- gap: 8
24
- },
25
- lg: {
26
- height: 52,
27
- paddingHorizontal: 14,
28
- fontSize: 16,
29
- iconSize: 20,
30
- gap: 10
31
- }
32
- };
33
10
  const CANCEL_WIDTH = 72;
34
11
  const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
35
12
  const {
@@ -45,7 +22,7 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
45
22
  leftIcon,
46
23
  debounceMs,
47
24
  size = 'md',
48
- variant = 'filled',
25
+ variant: variantProp,
49
26
  cancelLabel = 'Cancel',
50
27
  style,
51
28
  accessibilityLabel,
@@ -53,11 +30,21 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
53
30
  ...rest
54
31
  } = props;
55
32
  const theme = useTheme();
33
+ // Resolution chain mirrors every other field-family control: caller prop →
34
+ // component-specific token (`components.searchBar.defaultVariant`) → shared
35
+ // field-family token (`components.field.defaultVariant`) → library default.
36
+ // Library default stays `'filled'` so SearchBar reads as the traditional
37
+ // pill-shaped, borderless search box when no theme opinion is expressed.
38
+ const variant = variantProp ?? theme.components.searchBar?.defaultVariant ?? theme.components.field?.defaultVariant ?? 'filled';
39
+ const fieldTokens = resolveFieldSize(theme, size);
56
40
  const sizeStyles = {
57
- ...sizeMap[size],
41
+ ...fieldTokens,
58
42
  ...(theme.components.searchBar?.[size] ?? {})
59
43
  };
60
44
  const cancelWidth = theme.components.searchBar?.cancelButtonWidth ?? CANCEL_WIDTH;
45
+ const fieldText = resolveFieldTextStyle(theme, {
46
+ disabled
47
+ });
61
48
  const styles = useMemo(() => buildStyles(theme), [theme]);
62
49
 
63
50
  // Coerce nullable inputs to '' once at the top so every downstream read is
@@ -68,15 +55,11 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
68
55
  const [internalValue, setInternalValue] = useState(value);
69
56
  const debouncedValue = useDebounce(internalValue, debounceMs ?? 0);
70
57
  const cancelAnim = useRef(createAnimatedValue(0)).current;
71
-
72
- // Keep internal value in sync with controlled value when debouncing.
73
58
  useEffect(() => {
74
59
  if (debounceMs === undefined) return;
75
60
  if (value !== internalValue) setInternalValue(value);
76
61
  // eslint-disable-next-line react-hooks/exhaustive-deps
77
62
  }, [value, debounceMs]);
78
-
79
- // Fire debounced onChangeText when debounce is configured.
80
63
  const lastSentRef = useRef(value);
81
64
  useEffect(() => {
82
65
  if (debounceMs === undefined) return;
@@ -90,7 +73,6 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
90
73
  toValue: showCancelButton ? 1 : 0,
91
74
  duration: 200,
92
75
  easing: Easing.bezier(...theme.motion.easing.standard),
93
- // Container width / margin animates with this value, so layout-aware.
94
76
  useNativeDriver: false
95
77
  }).start();
96
78
  }, [showCancelButton, cancelAnim, theme.motion.easing.standard]);
@@ -125,81 +107,86 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
125
107
  }, [onSubmit, debounceMs, internalValue, value]);
126
108
  const displayValue = debounceMs !== undefined ? internalValue : value;
127
109
  const hasValue = displayValue.length > 0;
128
- const containerBackground = variant === 'filled' ? theme.colors.background.secondary : theme.colors.background.primary;
129
- const containerBorder = variant === 'outlined' ? theme.colors.border.primary : 'transparent';
130
-
131
- // Container shrinks left to make room for cancel button on right.
132
110
  const cancelTranslateX = cancelAnim.interpolate({
133
111
  inputRange: [0, 1],
134
112
  outputRange: [cancelWidth, 0]
135
113
  });
136
114
  const cancelOpacity = cancelAnim;
115
+ const fieldMarginRight = cancelAnim.interpolate({
116
+ inputRange: [0, 1],
117
+ outputRange: [0, cancelWidth + theme.spacing.sm]
118
+ });
119
+ const leading = leftIcon ? leftIcon : theme.icons?.search ? theme.icons.search({
120
+ size: sizeStyles.iconSize,
121
+ color: theme.colors.text.tertiary
122
+ }) : /*#__PURE__*/_jsx(Text, {
123
+ style: {
124
+ fontSize: sizeStyles.iconSize,
125
+ color: theme.colors.text.tertiary
126
+ },
127
+ children: "\uD83D\uDD0D"
128
+ });
129
+ const trailing = hasValue && !disabled ? /*#__PURE__*/_jsx(Pressable, {
130
+ onPress: handleClear,
131
+ hitSlop: 8,
132
+ accessibilityRole: "button",
133
+ accessibilityLabel: "Clear search",
134
+ children: theme.icons?.close ? theme.icons.close({
135
+ size: sizeStyles.iconSize,
136
+ color: theme.colors.text.secondary
137
+ }) : /*#__PURE__*/_jsx(Text, {
138
+ style: {
139
+ fontSize: sizeStyles.iconSize,
140
+ color: theme.colors.text.secondary
141
+ },
142
+ children: "\xD7"
143
+ })
144
+ }) : null;
137
145
  return /*#__PURE__*/_jsxs(View, {
138
146
  style: [styles.root, style],
139
147
  testID: testID,
140
- children: [/*#__PURE__*/_jsxs(Animated.View, {
141
- style: [styles.searchContainer, {
142
- height: sizeStyles.height,
143
- paddingHorizontal: sizeStyles.paddingHorizontal,
144
- backgroundColor: containerBackground,
145
- borderColor: containerBorder,
146
- borderWidth: variant === 'outlined' ? 1 : 0,
147
- borderRadius: theme.radius.full,
148
- opacity: disabled ? 0.55 : 1,
149
- marginRight: cancelAnim.interpolate({
150
- inputRange: [0, 1],
151
- outputRange: [0, cancelWidth + theme.spacing.sm]
152
- })
148
+ children: [/*#__PURE__*/_jsx(Animated.View, {
149
+ style: [styles.fieldWrap, {
150
+ marginRight: fieldMarginRight
153
151
  }],
154
- accessibilityRole: "search",
155
- accessibilityLabel: accessibilityLabel ?? placeholder,
156
- children: [/*#__PURE__*/_jsx(View, {
157
- style: [styles.leftSlot, {
158
- marginRight: sizeStyles.gap
159
- }],
160
- children: leftIcon ? leftIcon : /*#__PURE__*/_jsx(AppIcon, {
161
- name: "search",
162
- family: "feather",
163
- size: sizeStyles.iconSize,
164
- color: theme.colors.text.tertiary
165
- })
166
- }), /*#__PURE__*/_jsx(TextInput, {
167
- ref: ref,
168
- style: [styles.input, {
169
- fontSize: sizeStyles.fontSize,
170
- color: disabled ? theme.colors.text.disabled : theme.colors.text.primary
171
- }],
172
- value: displayValue,
173
- onChangeText: handleChangeText,
174
- onSubmitEditing: handleSubmit,
175
- onFocus: () => setIsFocused(true),
176
- onBlur: () => setIsFocused(false),
177
- placeholder: placeholder,
178
- placeholderTextColor: theme.colors.text.tertiary,
179
- autoFocus: autoFocus,
180
- editable: !disabled,
181
- returnKeyType: "search",
182
- selectionColor: theme.colors.border.focus,
152
+ children: /*#__PURE__*/_jsx(FieldBase, {
153
+ size: size,
154
+ variant: variant,
155
+ focused: isFocused,
156
+ disabled: disabled,
157
+ filled: hasValue,
158
+ minHeight: sizeStyles.minHeight,
159
+ paddingHorizontal: sizeStyles.paddingHorizontal,
160
+ borderRadius: sizeStyles.borderRadius,
161
+ leading: leading,
162
+ trailing: trailing,
163
+ accessibilityRole: "search",
183
164
  accessibilityLabel: accessibilityLabel ?? placeholder,
184
- accessibilityState: {
185
- disabled
186
- },
187
- ...rest
188
- }), hasValue && !disabled ? /*#__PURE__*/_jsx(Pressable, {
189
- onPress: handleClear,
190
- hitSlop: 8,
191
- accessibilityRole: "button",
192
- accessibilityLabel: "Clear search",
193
- style: [styles.rightSlot, {
194
- marginLeft: sizeStyles.gap
195
- }],
196
- children: /*#__PURE__*/_jsx(AppIcon, {
197
- name: "x",
198
- family: "feather",
199
- size: sizeStyles.iconSize,
200
- color: theme.colors.text.secondary
165
+ children: /*#__PURE__*/_jsx(TextInput, {
166
+ ref: ref,
167
+ style: [styles.input, {
168
+ fontSize: sizeStyles.fontSize,
169
+ color: fieldText.color,
170
+ ...fieldText.weightStyle
171
+ }],
172
+ value: displayValue,
173
+ onChangeText: handleChangeText,
174
+ onSubmitEditing: handleSubmit,
175
+ onFocus: () => setIsFocused(true),
176
+ onBlur: () => setIsFocused(false),
177
+ placeholder: placeholder,
178
+ placeholderTextColor: fieldText.placeholderColor,
179
+ autoFocus: autoFocus,
180
+ editable: !disabled,
181
+ returnKeyType: "search",
182
+ selectionColor: resolveVariantColors(theme, variant).borderFocused,
183
+ accessibilityLabel: accessibilityLabel ?? placeholder,
184
+ accessibilityState: {
185
+ disabled
186
+ },
187
+ ...rest
201
188
  })
202
- }) : null]
189
+ })
203
190
  }), showCancel ? /*#__PURE__*/_jsx(Animated.View, {
204
191
  pointerEvents: showCancelButton ? 'auto' : 'none',
205
192
  style: [styles.cancelWrap, {
@@ -237,14 +224,8 @@ const buildStyles = _theme => StyleSheet.create({
237
224
  position: 'relative',
238
225
  overflow: 'hidden'
239
226
  },
240
- searchContainer: {
241
- flex: 1,
242
- flexDirection: 'row',
243
- alignItems: 'center'
244
- },
245
- leftSlot: {
246
- alignItems: 'center',
247
- justifyContent: 'center'
227
+ fieldWrap: {
228
+ flex: 1
248
229
  },
249
230
  input: {
250
231
  flex: 1,
@@ -252,10 +233,6 @@ const buildStyles = _theme => StyleSheet.create({
252
233
  margin: 0,
253
234
  includeFontPadding: false
254
235
  },
255
- rightSlot: {
256
- alignItems: 'center',
257
- justifyContent: 'center'
258
- },
259
236
  cancelWrap: {
260
237
  position: 'absolute',
261
238
  right: 0,
@@ -37,13 +37,24 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
37
37
  tone = 'primary',
38
38
  accessibilityLabel,
39
39
  style,
40
+ containerStyle,
40
41
  segmentStyle,
42
+ selectedIndicatorStyle,
41
43
  textStyle,
44
+ labelStyle,
42
45
  testID
43
46
  } = props;
44
47
  const theme = useTheme();
48
+ const segTheme = theme.components.segmentedControl;
45
49
  const styles = useMemo(() => buildStyles(theme), [theme]);
46
- const sizeStyles = sizeMap[size];
50
+ const baseSize = sizeMap[size];
51
+ const sizeStyles = {
52
+ height: segTheme?.[size]?.height ?? baseSize.height,
53
+ fontSize: segTheme?.[size]?.fontSize ?? baseSize.fontSize,
54
+ paddingHorizontal: segTheme?.[size]?.paddingHorizontal ?? baseSize.paddingHorizontal
55
+ };
56
+ const trackPadding = segTheme?.trackPadding ?? TRACK_PADDING;
57
+ const changeHapticEnabled = segTheme?.changeHaptic ?? false;
47
58
 
48
59
  // Track width is measured from onLayout. Thumb width is a regular number (not
49
60
  // animated) — `width` cannot be driven by the native animated module, and mixing
@@ -54,10 +65,10 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
54
65
  const [trackWidth, setTrackWidth] = useState(0);
55
66
  const thumbTranslateX = useRef(createAnimatedValue(0)).current;
56
67
  const activeIndex = Math.max(0, segments.findIndex(s => s.value === value));
57
- const segmentWidth = trackWidth > 0 ? (trackWidth - TRACK_PADDING * 2) / Math.max(segments.length, 1) : 0;
68
+ const segmentWidth = trackWidth > 0 ? (trackWidth - trackPadding * 2) / Math.max(segments.length, 1) : 0;
58
69
  const animateThumb = useCallback((index, segWidth) => {
59
70
  if (segWidth <= 0) return;
60
- const targetX = TRACK_PADDING + segWidth * index;
71
+ const targetX = trackPadding + segWidth * index;
61
72
  const spring = theme.motion.spring.snappy;
62
73
  Animated.spring(thumbTranslateX, {
63
74
  toValue: targetX,
@@ -81,9 +92,9 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
81
92
  const handlePress = useCallback(segment => {
82
93
  if (disabled) return;
83
94
  if (segment.value === value) return;
84
- triggerHaptic('selection');
95
+ if (changeHapticEnabled) triggerHaptic('selection');
85
96
  onChange(segment.value);
86
- }, [disabled, onChange, value]);
97
+ }, [disabled, onChange, value, changeHapticEnabled]);
87
98
  const thumbBg = tone === 'primary' ? theme.colors.background.elevated : theme.colors.background.elevated;
88
99
  const activeTextColor = tone === 'primary' ? theme.colors.text.primary : theme.colors.text.primary;
89
100
  return /*#__PURE__*/_jsxs(View, {
@@ -95,23 +106,24 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
95
106
  height: sizeStyles.height,
96
107
  borderRadius: theme.radius.md,
97
108
  backgroundColor: theme.colors.background.tertiary,
98
- padding: TRACK_PADDING,
109
+ padding: trackPadding,
99
110
  opacity: disabled ? 0.55 : 1,
100
111
  alignSelf: fullWidth ? 'stretch' : 'flex-start'
101
- }, style],
112
+ }, containerStyle, style],
102
113
  onLayout: handleTrackLayout,
103
114
  children: [segmentWidth > 0 ? /*#__PURE__*/_jsx(Animated.View, {
104
115
  pointerEvents: "none",
105
116
  style: [styles.thumb, {
117
+ top: trackPadding,
106
118
  width: segmentWidth,
107
- height: sizeStyles.height - TRACK_PADDING * 2,
119
+ height: sizeStyles.height - trackPadding * 2,
108
120
  borderRadius: theme.radius.sm,
109
121
  backgroundColor: thumbBg,
110
122
  transform: [{
111
123
  translateX: thumbTranslateX
112
124
  }],
113
125
  ...theme.shadows.sm
114
- }]
126
+ }, selectedIndicatorStyle]
115
127
  }) : null, segments.map(segment => {
116
128
  const isActive = segment.value === value;
117
129
  return /*#__PURE__*/_jsxs(Pressable, {
@@ -137,7 +149,7 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
137
149
  color: isActive ? activeTextColor : theme.colors.text.tertiary,
138
150
  fontSize: sizeStyles.fontSize,
139
151
  fontWeight: isActive ? theme.typography.fontWeight.semibold : theme.typography.fontWeight.medium
140
- }, textStyle],
152
+ }, textStyle, labelStyle],
141
153
  numberOfLines: 1,
142
154
  children: segment.label
143
155
  })]
@@ -154,7 +166,6 @@ const buildStyles = _theme => StyleSheet.create({
154
166
  },
155
167
  thumb: {
156
168
  position: 'absolute',
157
- top: TRACK_PADDING,
158
169
  left: 0
159
170
  },
160
171
  segment: {
@@ -10,36 +10,11 @@
10
10
 
11
11
  import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
12
12
  import { Animated, Dimensions, Easing, FlatList, Modal, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
13
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
13
14
  import { useTheme, createAnimatedValue } from "../../theme/index.js";
14
15
  import { triggerHaptic } from "../../utils/index.js";
16
+ import { FieldBase, resolveFieldSize, resolveFieldTextStyle, resolveVariantColors } from "../FieldBase/FieldBase.js";
15
17
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16
- const sizeMap = {
17
- sm: {
18
- paddingHorizontal: 12,
19
- paddingVertical: 8,
20
- minHeight: 38,
21
- fontSize: 13,
22
- borderRadius: 10,
23
- iconSize: 16
24
- },
25
- md: {
26
- paddingHorizontal: 14,
27
- paddingVertical: 11,
28
- minHeight: 46,
29
- fontSize: 15,
30
- borderRadius: 12,
31
- iconSize: 18
32
- },
33
- lg: {
34
- paddingHorizontal: 16,
35
- paddingVertical: 14,
36
- minHeight: 54,
37
- fontSize: 16,
38
- borderRadius: 14,
39
- iconSize: 20
40
- }
41
- };
42
-
43
18
  // `unknown` here keeps the forwardRef signature non-generic — consumers who
44
19
  // pass non-`SelectOption` shapes use the accessor props; type inference is
45
20
  // preserved at the call site via the `SelectProps<T>` union.
@@ -71,8 +46,12 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
71
46
  const disabledOf = useCallback(o => getOptionDisabled ? getOptionDisabled(o) : o.disabled === true, [getOptionDisabled]);
72
47
  const descriptionOf = useCallback(o => getOptionDescription ? getOptionDescription(o) : o.description, [getOptionDescription]);
73
48
  const theme = useTheme();
49
+ const insets = useSafeAreaInsets();
74
50
  const styles = useMemo(() => buildStyles(theme), [theme]);
75
- const sizeStyles = sizeMap[size];
51
+ const sizeTokens = resolveFieldSize(theme, size);
52
+ const fieldText = resolveFieldTextStyle(theme, {
53
+ disabled
54
+ });
76
55
  const [open, setOpen] = useState(false);
77
56
  const [query, setQuery] = useState('');
78
57
  const screenHeight = Dimensions.get('window').height;
@@ -83,11 +62,13 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
83
62
  const sheetAnim = useRef(createAnimatedValue(sheetMaxHeight)).current;
84
63
  useEffect(() => {
85
64
  if (open) {
86
- Animated.parallel([Animated.timing(backdropAnim, {
65
+ Animated.parallel([
66
+ // Backdrop opacity uses JS driver — see Modal.tsx for the Fabric reason.
67
+ Animated.timing(backdropAnim, {
87
68
  toValue: 1,
88
69
  duration: theme.motion.duration.fast,
89
70
  easing: Easing.bezier(...theme.motion.easing.standard),
90
- useNativeDriver: true
71
+ useNativeDriver: false
91
72
  }), Animated.spring(sheetAnim, {
92
73
  toValue: 0,
93
74
  damping: theme.motion.spring.snappy.damping,
@@ -100,7 +81,7 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
100
81
  toValue: 0,
101
82
  duration: theme.motion.duration.fast,
102
83
  easing: Easing.bezier(...theme.motion.easing.standard),
103
- useNativeDriver: true
84
+ useNativeDriver: false
104
85
  }), Animated.timing(sheetAnim, {
105
86
  toValue: sheetMaxHeight,
106
87
  duration: theme.motion.duration.fast,
@@ -160,7 +141,6 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
160
141
  const triggerText = selectedOptions.length === 0 ? placeholder ?? 'Select…' : selectedOptions.map(o => labelOf(o)).join(', ');
161
142
  const showingPlaceholder = selectedOptions.length === 0;
162
143
  const hasError = typeof error === 'string' && error.length > 0;
163
- const borderColor = hasError ? theme.colors.border.error : theme.colors.border.primary;
164
144
  const a11ySummary = selectedOptions.length === 0 ? placeholder ?? 'No selection' : `Selected: ${selectedOptions.map(o => labelOf(o)).join(', ')}`;
165
145
  const a11yLabel = accessibilityLabel ?? `${label ?? 'Select'}. ${a11ySummary}`;
166
146
  const renderOption = ({
@@ -240,45 +220,37 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
240
220
  marginBottom: theme.spacing.xxs
241
221
  }],
242
222
  children: label
243
- }) : null, /*#__PURE__*/_jsxs(Pressable, {
223
+ }) : null, /*#__PURE__*/_jsx(View, {
244
224
  ref: ref,
245
- onPress: handleOpen,
246
- disabled: disabled,
247
- accessibilityRole: "button",
248
- accessibilityLabel: a11yLabel,
249
- accessibilityState: {
250
- disabled,
251
- expanded: open
252
- },
253
- android_ripple: {
254
- color: theme.colors.surface.pressed,
255
- borderless: false
256
- },
257
- style: ({
258
- pressed
259
- }) => [styles.trigger, {
260
- minHeight: sizeStyles.minHeight,
261
- paddingHorizontal: sizeStyles.paddingHorizontal,
262
- paddingVertical: sizeStyles.paddingVertical,
263
- borderRadius: sizeStyles.borderRadius,
264
- borderColor,
265
- borderWidth: 1.5,
266
- backgroundColor: disabled ? theme.colors.surface.disabled : pressed ? theme.colors.surface.pressed : theme.colors.background.primary,
267
- opacity: disabled ? 0.65 : 1
268
- }, triggerStyle],
269
- children: [/*#__PURE__*/_jsx(Text, {
270
- style: [styles.triggerText, {
271
- color: showingPlaceholder ? theme.colors.text.tertiary : theme.colors.text.primary,
272
- fontSize: sizeStyles.fontSize,
273
- fontWeight: theme.typography.fontWeight.medium
274
- }, textStyle],
275
- numberOfLines: 1,
276
- children: triggerText
277
- }), /*#__PURE__*/_jsx(Chevron, {
278
- color: disabled ? theme.colors.text.disabled : theme.colors.text.tertiary,
279
- size: sizeStyles.iconSize,
280
- open: open
281
- })]
225
+ collapsable: false,
226
+ children: /*#__PURE__*/_jsx(FieldBase, {
227
+ size: size,
228
+ disabled: disabled,
229
+ error: hasError,
230
+ filled: selectedOptions.length > 0,
231
+ onPress: handleOpen,
232
+ accessibilityRole: "button",
233
+ accessibilityLabel: a11yLabel,
234
+ accessibilityState: {
235
+ disabled,
236
+ expanded: open
237
+ },
238
+ style: triggerStyle,
239
+ trailing: /*#__PURE__*/_jsx(Chevron, {
240
+ color: disabled ? theme.colors.text.disabled : theme.colors.text.tertiary,
241
+ size: sizeTokens.iconSize,
242
+ open: open
243
+ }),
244
+ children: /*#__PURE__*/_jsx(Text, {
245
+ style: [styles.triggerText, {
246
+ color: showingPlaceholder ? fieldText.placeholderColor : fieldText.color,
247
+ fontSize: sizeTokens.fontSize,
248
+ ...fieldText.weightStyle
249
+ }, textStyle],
250
+ numberOfLines: 1,
251
+ children: triggerText
252
+ })
253
+ })
282
254
  }), hasError ? /*#__PURE__*/_jsx(Text, {
283
255
  style: [styles.errorText, {
284
256
  color: theme.colors.error,
@@ -292,25 +264,29 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
292
264
  transparent: true,
293
265
  animationType: "none",
294
266
  onRequestClose: handleClose,
295
- statusBarTranslucent: true,
296
- children: /*#__PURE__*/_jsxs(View, {
297
- style: StyleSheet.absoluteFill,
298
- children: [/*#__PURE__*/_jsx(Animated.View, {
299
- style: [StyleSheet.absoluteFillObject, {
300
- backgroundColor: theme.colors.background.overlay,
301
- opacity: backdropAnim
302
- }],
303
- children: /*#__PURE__*/_jsx(Pressable, {
304
- style: StyleSheet.absoluteFill,
305
- onPress: handleClose,
306
- accessibilityRole: "button",
307
- accessibilityLabel: "Close picker"
308
- })
267
+ statusBarTranslucent: true
268
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
269
+ // @ts-ignore — Android-only RN 0.71+; iOS ignores it.
270
+ ,
271
+ navigationBarTranslucent: true,
272
+ children: /*#__PURE__*/_jsxs(View
273
+ // Backdrop wraps the sheet — see Modal.tsx for the Fabric reason.
274
+ , {
275
+ collapsable: false,
276
+ style: [StyleSheet.absoluteFill, {
277
+ backgroundColor: theme.colors.background.overlay
278
+ }],
279
+ children: [/*#__PURE__*/_jsx(Pressable, {
280
+ style: StyleSheet.absoluteFill,
281
+ onPress: handleClose,
282
+ accessibilityRole: "button",
283
+ accessibilityLabel: "Close picker"
309
284
  }), /*#__PURE__*/_jsxs(Animated.View, {
310
285
  accessibilityViewIsModal: true,
311
286
  accessibilityLabel: label ?? placeholder ?? 'Options',
312
287
  style: [styles.sheet, {
313
288
  maxHeight: sheetMaxHeight,
289
+ paddingBottom: insets.bottom + 16,
314
290
  backgroundColor: theme.colors.background.elevated,
315
291
  borderTopLeftRadius: theme.radius.xl,
316
292
  borderTopRightRadius: theme.radius.xl,
@@ -323,7 +299,7 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
323
299
  style: styles.sheetHandleRow,
324
300
  children: /*#__PURE__*/_jsx(View, {
325
301
  style: [styles.sheetHandle, {
326
- backgroundColor: theme.colors.border.primary
302
+ backgroundColor: theme.components.select?.handleColor ?? theme.components.bottomSheet?.handleColor ?? theme.colors.border.primary
327
303
  }]
328
304
  })
329
305
  }), label ? /*#__PURE__*/_jsx(Text, {
@@ -345,7 +321,7 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
345
321
  onChangeText: setQuery,
346
322
  placeholder: "Search\u2026",
347
323
  placeholderTextColor: theme.colors.text.tertiary,
348
- selectionColor: theme.colors.border.focus,
324
+ selectionColor: resolveVariantColors(theme, theme.components.field?.defaultVariant ?? 'outlined').borderFocused,
349
325
  accessibilityLabel: "Search options",
350
326
  style: [styles.searchInput, {
351
327
  color: theme.colors.text.primary,
@@ -456,11 +432,6 @@ const buildStyles = _theme => StyleSheet.create({
456
432
  label: {
457
433
  includeFontPadding: false
458
434
  },
459
- trigger: {
460
- flexDirection: 'row',
461
- alignItems: 'center',
462
- justifyContent: 'space-between'
463
- },
464
435
  triggerText: {
465
436
  flex: 1,
466
437
  includeFontPadding: false