@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
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * FieldBase — the unified field-box primitive.
5
+ *
6
+ * Every input-like control in the library (Input, Select, SearchBar,
7
+ * NumberInput, OTPInput cell, PickerTrigger) composes FieldBase so the
8
+ * height / radius / padding / border / fill / focus + disabled + error
9
+ * states stay identical across the library. Differences (pill SearchBar,
10
+ * OTP underline, NumberInput steppers) become explicit overrides via
11
+ * props or via theme tokens — never accidental drift.
12
+ *
13
+ * Responsibilities:
14
+ * - Resolve size / variant dimensions from `theme.components.field`.
15
+ * - Animate the border + background between idle / focused / error.
16
+ * - Render leading + trailing slots either side of `children`.
17
+ * - Become Pressable when `onPress` is set (Select, PickerTrigger).
18
+ * - Apply disabled fill + cursor semantics.
19
+ *
20
+ * Non-responsibilities (the parent owns these):
21
+ * - The actual TextInput / Text / nested editor.
22
+ * - Floating / static labels rendered above the field.
23
+ * - Helper / error / counter text rendered below the field.
24
+ * - Shake-on-error or any cross-field animation.
25
+ */
26
+
27
+ import React, { useEffect, useMemo, useRef } from 'react';
28
+ import { Animated, Easing, Pressable, StyleSheet, View } from 'react-native';
29
+ import { useTheme, createAnimatedValue, fontFor } from "../../theme/index.js";
30
+
31
+ /**
32
+ * Resolved text styling for the editable / displayed content inside a field.
33
+ * Single source of truth so every field component (Input, NumberInput,
34
+ * Select, SearchBar, PickerTrigger) renders identical colour + weight +
35
+ * fontFamily for value text — and reads the placeholder colour from the
36
+ * same place. OTPInput intentionally overrides this with its own semibold
37
+ * display weight.
38
+ */
39
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
40
+ /**
41
+ * Resolve the canonical text style chunk for a field's value. Reads from
42
+ * `theme.components.field.{textColor,disabledTextColor,placeholderColor,fontWeight}`
43
+ * with library-default fallbacks; brand fonts wired via `typography.fontFamily`
44
+ * apply via the shared `fontFor` helper.
45
+ */
46
+ export const resolveFieldTextStyle = (theme, options = {}) => {
47
+ const {
48
+ disabled = false
49
+ } = options;
50
+ const tokens = theme.components.field;
51
+ const color = disabled ? tokens?.disabledTextColor ?? theme.colors.text.disabled : tokens?.textColor ?? theme.colors.text.primary;
52
+ const placeholderColor = tokens?.placeholderColor ?? theme.colors.text.tertiary;
53
+
54
+ // If a consumer sets `field.fontWeight` directly (raw RN weight string),
55
+ // honour it verbatim — they've opted out of the brand-font path. Otherwise
56
+ // resolve weight through `fontFor` so `typography.fontFamily.<weight>`
57
+ // takes precedence when a custom face is registered.
58
+ const weightStyle = tokens?.fontWeight ? {
59
+ fontWeight: tokens.fontWeight
60
+ } : fontFor(theme, 'medium');
61
+ return {
62
+ color,
63
+ placeholderColor,
64
+ weightStyle
65
+ };
66
+ };
67
+
68
+ /**
69
+ * Public re-export of the resolved size tokens — components that need to
70
+ * compute their own padding adjustments (e.g. multiline Input, icon-slot
71
+ * sizing) read from this rather than re-hardcoding the size table.
72
+ */
73
+ export const resolveFieldSize = (theme, size) => {
74
+ const sizeFromTheme = theme.components.field?.[size];
75
+ return {
76
+ paddingHorizontal: sizeFromTheme?.paddingHorizontal ?? DEFAULT_SIZES[size].paddingHorizontal,
77
+ paddingVertical: sizeFromTheme?.paddingVertical ?? DEFAULT_SIZES[size].paddingVertical,
78
+ minHeight: sizeFromTheme?.minHeight ?? DEFAULT_SIZES[size].minHeight,
79
+ fontSize: sizeFromTheme?.fontSize ?? DEFAULT_SIZES[size].fontSize,
80
+ borderRadius: sizeFromTheme?.borderRadius ?? DEFAULT_SIZES[size].borderRadius,
81
+ iconSize: sizeFromTheme?.iconSize ?? DEFAULT_SIZES[size].iconSize
82
+ };
83
+ };
84
+
85
+ // Library defaults for when consumers haven't supplied per-size tokens. The
86
+ // numbers here MUST stay in sync with the `fieldSizes` table in tokens.ts —
87
+ // these are the same values, duplicated so resolveFieldSize works even when
88
+ // the consumer passes a custom theme without `components.field` set.
89
+ const DEFAULT_SIZES = {
90
+ sm: {
91
+ paddingHorizontal: 12,
92
+ paddingVertical: 8,
93
+ minHeight: 38,
94
+ fontSize: 13,
95
+ borderRadius: 10,
96
+ iconSize: 16
97
+ },
98
+ md: {
99
+ paddingHorizontal: 14,
100
+ paddingVertical: 11,
101
+ minHeight: 46,
102
+ fontSize: 15,
103
+ borderRadius: 12,
104
+ iconSize: 18
105
+ },
106
+ lg: {
107
+ paddingHorizontal: 16,
108
+ paddingVertical: 14,
109
+ minHeight: 54,
110
+ fontSize: 16,
111
+ borderRadius: 14,
112
+ iconSize: 20
113
+ }
114
+ };
115
+
116
+ /**
117
+ * Strict, fully-resolved colour set used internally. Mirrors `FieldVariantTokens`
118
+ * but every field is non-optional — every state has a concrete colour by the
119
+ * time the box renders, so downstream code can rely on string-typed fills.
120
+ */
121
+
122
+ /**
123
+ * Resolve the full set of state-aware fill + border colours for a given
124
+ * variant. Order: explicit override → theme token → library default.
125
+ */
126
+ export const resolveVariantColors = (theme, variant, override) => {
127
+ const tokenSet = theme.components.field?.[variant];
128
+ const isOutlined = variant === 'outlined';
129
+ const idleEmpty = isOutlined ? theme.colors.background.primary : theme.colors.background.secondary;
130
+ const borderIdle = isOutlined ? theme.colors.border.primary : 'transparent';
131
+ const borderWidth = isOutlined ? theme.colors.border.width : 0;
132
+ return {
133
+ backgroundIdleEmpty: override?.backgroundIdleEmpty ?? tokenSet?.backgroundIdleEmpty ?? idleEmpty,
134
+ backgroundIdleFilled: override?.backgroundIdleFilled ?? tokenSet?.backgroundIdleFilled ?? override?.backgroundIdleEmpty ?? tokenSet?.backgroundIdleEmpty ?? idleEmpty,
135
+ backgroundFocused: override?.backgroundFocused ?? tokenSet?.backgroundFocused ?? undefined,
136
+ backgroundError: override?.backgroundError ?? tokenSet?.backgroundError ?? undefined,
137
+ backgroundDisabled: override?.backgroundDisabled ?? tokenSet?.backgroundDisabled ?? theme.colors.surface.disabled,
138
+ borderIdle: override?.borderIdle ?? tokenSet?.borderIdle ?? borderIdle,
139
+ borderFocused: override?.borderFocused ?? tokenSet?.borderFocused ?? theme.colors.border.focus,
140
+ borderError: override?.borderError ?? tokenSet?.borderError ?? theme.colors.border.error,
141
+ borderDisabled: override?.borderDisabled ?? tokenSet?.borderDisabled ?? borderIdle,
142
+ borderWidth: override?.borderWidth ?? tokenSet?.borderWidth ?? borderWidth
143
+ };
144
+ };
145
+ export const FieldBase = props => {
146
+ const {
147
+ size = 'md',
148
+ variant: variantProp,
149
+ focused = false,
150
+ disabled = false,
151
+ error = false,
152
+ filled = false,
153
+ leading,
154
+ trailing,
155
+ children,
156
+ onPress,
157
+ minHeight: minHeightProp,
158
+ maxHeight,
159
+ width,
160
+ height,
161
+ paddingHorizontal: paddingHorizontalProp,
162
+ paddingVertical: paddingVerticalProp,
163
+ borderRadius: borderRadiusProp,
164
+ borderWidth: borderWidthProp,
165
+ gap: gapProp,
166
+ fillOverrides,
167
+ style,
168
+ testID,
169
+ accessibilityRole,
170
+ accessibilityLabel,
171
+ accessibilityState,
172
+ accessibilityHint
173
+ } = props;
174
+ const theme = useTheme();
175
+ const styles = useMemo(() => buildStyles(), []);
176
+ const variant = variantProp ?? theme.components.field?.defaultVariant ?? 'outlined';
177
+ const sizeTokens = resolveFieldSize(theme, size);
178
+ const colors = useMemo(() => resolveVariantColors(theme, variant, fillOverrides), [theme, variant, fillOverrides]);
179
+ const focusAnim = useRef(createAnimatedValue(focused ? 1 : 0)).current;
180
+ const errorAnim = useRef(createAnimatedValue(error ? 1 : 0)).current;
181
+ useEffect(() => {
182
+ Animated.timing(focusAnim, {
183
+ toValue: focused ? 1 : 0,
184
+ duration: theme.motion.duration.fast,
185
+ easing: Easing.bezier(...theme.motion.easing.standard),
186
+ useNativeDriver: false
187
+ }).start();
188
+ }, [focused, focusAnim, theme.motion.duration.fast, theme.motion.easing.standard]);
189
+ useEffect(() => {
190
+ Animated.timing(errorAnim, {
191
+ toValue: error ? 1 : 0,
192
+ duration: theme.motion.duration.fast,
193
+ easing: Easing.bezier(...theme.motion.easing.standard),
194
+ useNativeDriver: false
195
+ }).start();
196
+ }, [error, errorAnim, theme.motion.duration.fast, theme.motion.easing.standard]);
197
+
198
+ // Resting border + fill (pre-animation). Error wins over focus when both
199
+ // happen at once; we drive a single interpolation between blurred ↔ active.
200
+ const idleFill = filled ? colors.backgroundIdleFilled : colors.backgroundIdleEmpty;
201
+ const focusedFill = colors.backgroundFocused ?? idleFill;
202
+ const errorFill = colors.backgroundError ?? idleFill;
203
+ const animatedBorderColor = disabled ? colors.borderDisabled : error ? errorAnim.interpolate({
204
+ inputRange: [0, 1],
205
+ outputRange: [colors.borderIdle, colors.borderError]
206
+ }) : focusAnim.interpolate({
207
+ inputRange: [0, 1],
208
+ outputRange: [colors.borderIdle, colors.borderFocused]
209
+ });
210
+ const animatedBackgroundColor = disabled ? colors.backgroundDisabled : error ? errorAnim.interpolate({
211
+ inputRange: [0, 1],
212
+ outputRange: [idleFill, errorFill]
213
+ }) : focusAnim.interpolate({
214
+ inputRange: [0, 1],
215
+ outputRange: [idleFill, focusedFill]
216
+ });
217
+ const boxStyle = {
218
+ minHeight: height ?? minHeightProp ?? sizeTokens.minHeight,
219
+ maxHeight,
220
+ paddingHorizontal: paddingHorizontalProp ?? sizeTokens.paddingHorizontal,
221
+ paddingVertical: paddingVerticalProp ?? sizeTokens.paddingVertical,
222
+ borderRadius: borderRadiusProp ?? sizeTokens.borderRadius,
223
+ borderWidth: borderWidthProp ?? colors.borderWidth,
224
+ borderColor: animatedBorderColor,
225
+ backgroundColor: animatedBackgroundColor,
226
+ columnGap: gapProp ?? theme.spacing.sm
227
+ };
228
+ if (width !== undefined) boxStyle.width = width;
229
+ if (height !== undefined) boxStyle.height = height;
230
+ const a11yState = {
231
+ disabled,
232
+ ...accessibilityState
233
+ };
234
+ const innerContent = /*#__PURE__*/_jsxs(_Fragment, {
235
+ children: [leading != null ? /*#__PURE__*/_jsx(View, {
236
+ style: styles.slot,
237
+ children: leading
238
+ }) : null, /*#__PURE__*/_jsx(View, {
239
+ style: styles.content,
240
+ children: children
241
+ }), trailing != null ? /*#__PURE__*/_jsx(View, {
242
+ style: styles.slot,
243
+ children: trailing
244
+ }) : null]
245
+ });
246
+ if (onPress) {
247
+ return /*#__PURE__*/_jsx(Pressable, {
248
+ onPress: onPress,
249
+ disabled: disabled,
250
+ android_ripple: {
251
+ color: theme.colors.surface.pressed,
252
+ borderless: false
253
+ },
254
+ accessibilityRole: accessibilityRole ?? 'button',
255
+ accessibilityLabel: accessibilityLabel,
256
+ accessibilityHint: accessibilityHint,
257
+ accessibilityState: a11yState,
258
+ testID: testID,
259
+ children: ({
260
+ pressed
261
+ }) => /*#__PURE__*/_jsx(Animated.View, {
262
+ style: [styles.box, boxStyle, pressed && !disabled ? {
263
+ backgroundColor: theme.colors.surface.pressed
264
+ } : null, style],
265
+ children: innerContent
266
+ })
267
+ });
268
+ }
269
+ return /*#__PURE__*/_jsx(Animated.View, {
270
+ style: [styles.box, boxStyle, style],
271
+ accessibilityRole: accessibilityRole,
272
+ accessibilityLabel: accessibilityLabel,
273
+ accessibilityHint: accessibilityHint,
274
+ accessibilityState: a11yState,
275
+ testID: testID,
276
+ children: innerContent
277
+ });
278
+ };
279
+ FieldBase.displayName = 'FieldBase';
280
+ const buildStyles = () => StyleSheet.create({
281
+ box: {
282
+ flexDirection: 'row',
283
+ alignItems: 'center',
284
+ overflow: 'visible'
285
+ },
286
+ slot: {
287
+ alignItems: 'center',
288
+ justifyContent: 'center'
289
+ },
290
+ content: {
291
+ flex: 1,
292
+ flexDirection: 'row',
293
+ alignItems: 'center'
294
+ }
295
+ });
296
+ export default FieldBase;
297
+ //# sourceMappingURL=FieldBase.js.map
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export { FieldBase, resolveFieldSize, resolveFieldTextStyle, default } from "./FieldBase.js";
4
+ //# sourceMappingURL=index.js.map
@@ -6,7 +6,10 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
6
6
  import { useTheme, createAnimatedValue, setNativeValue } from "../../theme/index.js";
7
7
  import { usePressAnimation } from "../../hooks/usePressAnimation.js";
8
8
  import { triggerHaptic } from "../../utils/hapticUtils.js";
9
- import { AppIcon } from "../AppIcon/index.js";
9
+
10
+ // Local shape mirror — see types.ts FloatingActionButtonTokens for the canonical
11
+ // definition. Declared here so the component can read tokens before types.ts is
12
+ // regenerated; will collapse to a direct import once that lands.
10
13
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
14
  const sizeMap = {
12
15
  sm: {
@@ -47,9 +50,6 @@ const toneForeground = (theme, tone) => {
47
50
  if (tone === 'neutral') return theme.colors.text.primary;
48
51
  return theme.colors.text.inverse;
49
52
  };
50
- const isIconConfig = value => {
51
- return typeof value === 'object' && value !== null && ! /*#__PURE__*/React.isValidElement(value) && typeof value.name === 'string';
52
- };
53
53
  const FloatingActionButton = /*#__PURE__*/forwardRef((props, ref) => {
54
54
  const {
55
55
  icon,
@@ -65,6 +65,8 @@ const FloatingActionButton = /*#__PURE__*/forwardRef((props, ref) => {
65
65
  accessibilityLabel,
66
66
  accessibilityHint,
67
67
  style,
68
+ containerStyle,
69
+ labelStyle,
68
70
  testID
69
71
  } = props;
70
72
  const theme = useTheme();
@@ -78,6 +80,10 @@ const FloatingActionButton = /*#__PURE__*/forwardRef((props, ref) => {
78
80
  } = usePressAnimation({
79
81
  enabled: !disabled
80
82
  });
83
+ const fabTokens = theme.components.floatingActionButton;
84
+ const edgeOffset = fabTokens?.edgeOffset ?? 24;
85
+ const defaultBottomOffset = fabTokens?.bottomOffset ?? 24;
86
+ const pressHaptic = fabTokens?.pressHaptic ?? false;
81
87
  const hideAnim = useRef(createAnimatedValue(0)).current;
82
88
  useEffect(() => {
83
89
  if (!hideOnScroll) {
@@ -93,7 +99,7 @@ const FloatingActionButton = /*#__PURE__*/forwardRef((props, ref) => {
93
99
  }, [hideOnScroll, isScrolling, hideAnim, theme.motion.duration.normal, theme.motion.easing.standard]);
94
100
  const hideTranslateY = hideAnim.interpolate({
95
101
  inputRange: [0, 1],
96
- outputRange: [0, sizeStyles.diameter + (bottomOffset ?? 24) + insets.bottom + 24]
102
+ outputRange: [0, sizeStyles.diameter + (bottomOffset ?? defaultBottomOffset) + insets.bottom + edgeOffset]
97
103
  });
98
104
  const hideOpacity = hideAnim.interpolate({
99
105
  inputRange: [0, 1],
@@ -101,27 +107,22 @@ const FloatingActionButton = /*#__PURE__*/forwardRef((props, ref) => {
101
107
  });
102
108
  const handlePress = _event => {
103
109
  if (disabled) return;
104
- triggerHaptic('impactLight');
110
+ if (pressHaptic) triggerHaptic('impactLight');
105
111
  onPress();
106
112
  };
107
- const renderedIcon = isIconConfig(icon) ? /*#__PURE__*/_jsx(AppIcon, {
108
- name: icon.name,
109
- family: icon.family ?? 'feather',
110
- size: sizeStyles.iconSize,
111
- color: toneForeground(theme, tone)
112
- }) : icon;
113
+ const renderedIcon = icon;
113
114
  const isExtended = typeof label === 'string' && label.length > 0;
114
115
  const backgroundColor = disabled ? theme.colors.surface.disabled : toneBackground(theme, tone);
115
116
  const foregroundColor = disabled ? theme.colors.text.disabled : toneForeground(theme, tone);
116
117
  const positionStyle = useMemo(() => {
117
118
  if (!position) return null;
118
- const bottom = (bottomOffset ?? 24) + insets.bottom;
119
+ const bottom = (bottomOffset ?? defaultBottomOffset) + insets.bottom;
119
120
  switch (position) {
120
121
  case 'bottomLeft':
121
122
  return {
122
123
  position: 'absolute',
123
124
  bottom,
124
- left: 24
125
+ left: edgeOffset
125
126
  };
126
127
  case 'bottomCenter':
127
128
  return {
@@ -134,10 +135,10 @@ const FloatingActionButton = /*#__PURE__*/forwardRef((props, ref) => {
134
135
  return {
135
136
  position: 'absolute',
136
137
  bottom,
137
- right: 24
138
+ right: edgeOffset
138
139
  };
139
140
  }
140
- }, [position, bottomOffset, insets.bottom]);
141
+ }, [position, bottomOffset, insets.bottom, defaultBottomOffset, edgeOffset]);
141
142
  return /*#__PURE__*/_jsx(Animated.View, {
142
143
  style: [positionStyle, {
143
144
  transform: [{
@@ -146,7 +147,7 @@ const FloatingActionButton = /*#__PURE__*/forwardRef((props, ref) => {
146
147
  scale
147
148
  }],
148
149
  opacity: hideOpacity
149
- }, style],
150
+ }, containerStyle, style],
150
151
  pointerEvents: hideOnScroll && isScrolling ? 'none' : 'auto',
151
152
  children: /*#__PURE__*/_jsxs(Pressable, {
152
153
  ref: ref,
@@ -183,7 +184,7 @@ const FloatingActionButton = /*#__PURE__*/forwardRef((props, ref) => {
183
184
  fontSize: sizeStyles.fontSize,
184
185
  fontWeight: theme.typography.fontWeight.semibold,
185
186
  marginLeft: theme.spacing.sm
186
- }],
187
+ }, labelStyle],
187
188
  numberOfLines: 1,
188
189
  children: label
189
190
  }) : null]
@@ -209,8 +210,6 @@ const buildStyles = _theme => StyleSheet.create({
209
210
  // so they remain smooth during JS thread work.
210
211
  // =====================================================================
211
212
 
212
- const SECONDARY_GAP = 16;
213
- const STAGGER_MS = 50;
214
213
  const FloatingActionButtonGroup = props => {
215
214
  const {
216
215
  primaryIcon,
@@ -223,28 +222,54 @@ const FloatingActionButtonGroup = props => {
223
222
  bottomOffset,
224
223
  size = 'md',
225
224
  accessibilityLabel = 'Quick actions',
225
+ containerStyle,
226
+ secondaryActionStyle,
227
+ labelPillStyle,
228
+ labelStyle,
226
229
  testID
227
230
  } = props;
228
231
  const theme = useTheme();
229
232
  const insets = useSafeAreaInsets();
230
233
  const sizeStyles = sizeMap[size];
231
234
  const styles = useMemo(() => buildGroupStyles(theme), [theme]);
235
+ const fabTokens = theme.components.floatingActionButton;
236
+ const edgeOffset = fabTokens?.edgeOffset ?? 24;
237
+ const defaultBottomOffset = fabTokens?.bottomOffset ?? 24;
238
+ const secondaryGap = fabTokens?.secondaryGap ?? 16;
239
+ const staggerMs = fabTokens?.staggerMs ?? 50;
240
+ const pressHaptic = fabTokens?.pressHaptic ?? false;
232
241
  const isControlled = typeof controlledOpen === 'boolean';
233
242
  const [internalOpen, setInternalOpen] = useState(defaultOpen);
234
243
  const isOpen = isControlled ? controlledOpen : internalOpen;
235
244
 
236
245
  // Animation drivers
237
246
  const progress = useRef(createAnimatedValue(isOpen ? 1 : 0)).current;
247
+ // Stable refs for per-item Animated.Values. Reconciled inside useEffect — never
248
+ // mutated during render — so re-renders don't recreate Animated.Value instances
249
+ // (previous implementation leaked one Animated.Value per re-render when the
250
+ // actions array length changed).
238
251
  const itemAnims = useRef([]);
239
-
240
- // Resize per-item anim array if action count changes
241
- if (itemAnims.current.length !== actions.length) {
242
- const next = [];
243
- for (let i = 0; i < actions.length; i += 1) {
244
- next.push(itemAnims.current[i] ?? new Animated.Value(isOpen ? 1 : 0));
252
+ // Bump this when the underlying refs array is re-shaped so downstream effects
253
+ // and mapping reads see the new length.
254
+ const [itemAnimsVersion, setItemAnimsVersion] = useState(0);
255
+ useEffect(() => {
256
+ const current = itemAnims.current;
257
+ if (current.length === actions.length) return;
258
+ if (current.length < actions.length) {
259
+ const next = current.slice();
260
+ for (let i = current.length; i < actions.length; i += 1) {
261
+ next.push(new Animated.Value(isOpen ? 1 : 0));
262
+ }
263
+ itemAnims.current = next;
264
+ } else {
265
+ // Drop stale refs when actions array shrinks.
266
+ itemAnims.current = current.slice(0, actions.length);
245
267
  }
246
- itemAnims.current = next;
247
- }
268
+ setItemAnimsVersion(v => v + 1);
269
+ // isOpen intentionally not in deps — only used to seed brand-new values; the
270
+ // open/close effect below will animate them to the correct target anyway.
271
+ // eslint-disable-next-line react-hooks/exhaustive-deps
272
+ }, [actions.length]);
248
273
  useEffect(() => {
249
274
  Animated.timing(progress, {
250
275
  toValue: isOpen ? 1 : 0,
@@ -260,34 +285,34 @@ const FloatingActionButtonGroup = props => {
260
285
  }));
261
286
  // Reverse stagger order on close so items closest to primary collapse last
262
287
  const ordered = isOpen ? animations : [...animations].reverse();
263
- Animated.stagger(STAGGER_MS, ordered).start();
264
- }, [isOpen, progress, theme.motion.duration.normal, theme.motion.easing.standard, actions.length]);
288
+ Animated.stagger(staggerMs, ordered).start();
289
+ }, [isOpen, progress, theme.motion.duration.normal, theme.motion.easing.standard, actions.length, itemAnimsVersion, staggerMs]);
265
290
  const setOpen = useCallback(next => {
266
- triggerHaptic('impactLight');
291
+ if (pressHaptic) triggerHaptic('impactLight');
267
292
  if (!isControlled) setInternalOpen(next);
268
293
  onOpenChange?.(next);
269
- }, [isControlled, onOpenChange]);
294
+ }, [isControlled, onOpenChange, pressHaptic]);
270
295
  const handlePrimaryPress = useCallback(() => {
271
296
  setOpen(!isOpen);
272
297
  }, [isOpen, setOpen]);
273
298
  const handleActionPress = useCallback(action => {
274
- triggerHaptic('selection');
299
+ if (pressHaptic) triggerHaptic('selection');
275
300
  action.onPress();
276
301
  // Close after action runs
277
302
  if (!isControlled) setInternalOpen(false);
278
303
  onOpenChange?.(false);
279
- }, [isControlled, onOpenChange]);
304
+ }, [isControlled, onOpenChange, pressHaptic]);
280
305
  const handleBackdropPress = useCallback(() => {
281
306
  if (isOpen) setOpen(false);
282
307
  }, [isOpen, setOpen]);
283
308
  const positionStyle = useMemo(() => {
284
- const bottom = (bottomOffset ?? 24) + insets.bottom;
309
+ const bottom = (bottomOffset ?? defaultBottomOffset) + insets.bottom;
285
310
  switch (position) {
286
311
  case 'bottomLeft':
287
312
  return {
288
313
  position: 'absolute',
289
314
  bottom,
290
- left: 24,
315
+ left: edgeOffset,
291
316
  alignItems: 'flex-start'
292
317
  };
293
318
  case 'bottomCenter':
@@ -302,14 +327,14 @@ const FloatingActionButtonGroup = props => {
302
327
  return {
303
328
  position: 'absolute',
304
329
  bottom,
305
- right: 24,
330
+ right: edgeOffset,
306
331
  alignItems: 'flex-end'
307
332
  };
308
333
  }
309
- }, [position, bottomOffset, insets.bottom]);
334
+ }, [position, bottomOffset, insets.bottom, defaultBottomOffset, edgeOffset]);
310
335
 
311
336
  // Vertical slot offset per index: secondary at index i sits (diameter + gap) * (i + 1) above primary
312
- const slotOffset = index => -((sizeStyles.diameter + SECONDARY_GAP) * (index + 1));
337
+ const slotOffset = index => -((sizeStyles.diameter + secondaryGap) * (index + 1));
313
338
  const backdropOpacity = progress.interpolate({
314
339
  inputRange: [0, 1],
315
340
  outputRange: [0, 0.4]
@@ -333,7 +358,7 @@ const FloatingActionButtonGroup = props => {
333
358
  testID: testID ? `${testID}-backdrop` : undefined
334
359
  })
335
360
  }) : null, /*#__PURE__*/_jsxs(View, {
336
- style: positionStyle,
361
+ style: [positionStyle, containerStyle],
337
362
  accessibilityRole: 'menu',
338
363
  testID: testID,
339
364
  children: [actions.map((action, index) => {
@@ -369,13 +394,13 @@ const FloatingActionButtonGroup = props => {
369
394
  paddingVertical: theme.spacing.xs,
370
395
  borderRadius: theme.radius.sm,
371
396
  marginRight: theme.spacing.sm
372
- }],
397
+ }, labelPillStyle],
373
398
  children: /*#__PURE__*/_jsx(Text, {
374
- style: {
399
+ style: [{
375
400
  color: theme.colors.text.primary,
376
401
  fontSize: theme.typography.fontSize.sm,
377
402
  fontWeight: theme.typography.fontWeight.medium
378
- },
403
+ }, labelStyle],
379
404
  numberOfLines: 1,
380
405
  children: action.label
381
406
  })
@@ -392,7 +417,7 @@ const FloatingActionButtonGroup = props => {
392
417
  height: secondaryDiameter,
393
418
  borderRadius: secondaryDiameter / 2,
394
419
  backgroundColor: itemBackground
395
- }],
420
+ }, secondaryActionStyle],
396
421
  testID: testID ? `${testID}-action-${action.key}` : undefined,
397
422
  children: /*#__PURE__*/React.isValidElement(action.icon) ? action.icon : /*#__PURE__*/_jsx(Text, {
398
423
  style: {
@@ -27,7 +27,10 @@ export const ForceUpdateDialog = ({
27
27
  title = 'Update available',
28
28
  message = 'A new version of the app is available. Please update to continue using the latest features and security improvements.',
29
29
  updateLabel = 'Update now',
30
- laterLabel = 'Later'
30
+ laterLabel = 'Later',
31
+ containerStyle,
32
+ titleStyle,
33
+ messageStyle
31
34
  }) => {
32
35
  const [updating, setUpdating] = useState(false);
33
36
  const handleUpdate = useCallback(() => {
@@ -68,7 +71,10 @@ export const ForceUpdateDialog = ({
68
71
  message: message,
69
72
  variant: "info",
70
73
  actions: actions,
71
- dismissOnAction: false
74
+ dismissOnAction: false,
75
+ containerStyle: containerStyle,
76
+ titleStyle: titleStyle,
77
+ messageStyle: messageStyle
72
78
  });
73
79
  };
74
80
  export default ForceUpdateDialog;
@@ -16,6 +16,7 @@ const FormField = /*#__PURE__*/forwardRef((props, ref) => {
16
16
  helperStyle,
17
17
  errorStyle,
18
18
  containerStyle,
19
+ inputContainerStyle: inputContainerStyleProp,
19
20
  accessibilityLabel,
20
21
  testID
21
22
  } = props;
@@ -56,12 +57,12 @@ const FormField = /*#__PURE__*/forwardRef((props, ref) => {
56
57
  testID: testID,
57
58
  children: [layout === 'inline' ? /*#__PURE__*/_jsxs(_Fragment, {
58
59
  children: [labelNode, /*#__PURE__*/_jsx(View, {
59
- style: inputContainerStyle,
60
+ style: [inputContainerStyle, inputContainerStyleProp],
60
61
  children: children
61
62
  })]
62
63
  }) : /*#__PURE__*/_jsxs(_Fragment, {
63
64
  children: [labelNode, /*#__PURE__*/_jsx(View, {
64
- style: inputContainerStyle,
65
+ style: [inputContainerStyle, inputContainerStyleProp],
65
66
  children: children
66
67
  })]
67
68
  }), showHelper ? /*#__PURE__*/_jsx(Text, {