@retray-dev/ui-kit 9.0.0 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/COMPONENTS.md +178 -7
  2. package/CONSUMER.md +247 -0
  3. package/DESIGN.md +668 -0
  4. package/EXAMPLES.md +19 -12
  5. package/FONTS.md +107 -0
  6. package/README.md +3 -3
  7. package/dist/AlertBanner.d.mts +3 -1
  8. package/dist/AlertBanner.d.ts +3 -1
  9. package/dist/AlertBanner.js +18 -2
  10. package/dist/AlertBanner.mjs +1 -1
  11. package/dist/ConfirmDialog.d.mts +3 -1
  12. package/dist/ConfirmDialog.d.ts +3 -1
  13. package/dist/ConfirmDialog.js +3 -0
  14. package/dist/ConfirmDialog.mjs +1 -1
  15. package/dist/CurrencyInput.d.mts +3 -1
  16. package/dist/CurrencyInput.d.ts +3 -1
  17. package/dist/CurrencyInput.js +31 -4
  18. package/dist/CurrencyInput.mjs +2 -2
  19. package/dist/ImageUpload.d.mts +27 -0
  20. package/dist/ImageUpload.d.ts +27 -0
  21. package/dist/ImageUpload.js +399 -0
  22. package/dist/ImageUpload.mjs +9 -0
  23. package/dist/Input.d.mts +3 -1
  24. package/dist/Input.d.ts +3 -1
  25. package/dist/Input.js +27 -2
  26. package/dist/Input.mjs +1 -1
  27. package/dist/ListItem.d.mts +3 -1
  28. package/dist/ListItem.d.ts +3 -1
  29. package/dist/ListItem.js +2 -1
  30. package/dist/ListItem.mjs +1 -1
  31. package/dist/SheetSelect.d.mts +25 -0
  32. package/dist/SheetSelect.d.ts +25 -0
  33. package/dist/SheetSelect.js +440 -0
  34. package/dist/SheetSelect.mjs +9 -0
  35. package/dist/{chunk-M6ZXVBTK.mjs → chunk-6MKGPAR2.mjs} +21 -5
  36. package/dist/{chunk-7QHVVCB3.mjs → chunk-FZZLPJ6B.mjs} +3 -0
  37. package/dist/{chunk-MAC465BB.mjs → chunk-KNSENOV4.mjs} +5 -3
  38. package/dist/{chunk-756RAKE4.mjs → chunk-LVYEU5ZK.mjs} +27 -2
  39. package/dist/{chunk-BNP626TY.mjs → chunk-T4I5WVHA.mjs} +2 -1
  40. package/dist/chunk-URI2WBIV.mjs +147 -0
  41. package/dist/chunk-Y4GL2MHX.mjs +112 -0
  42. package/dist/index.d.mts +26 -1
  43. package/dist/index.d.ts +26 -1
  44. package/dist/index.js +327 -8
  45. package/dist/index.mjs +51 -12
  46. package/package.json +18 -5
  47. package/src/components/AlertBanner/AlertBanner.tsx +21 -3
  48. package/src/components/ConfirmDialog/ConfirmDialog.tsx +5 -0
  49. package/src/components/CurrencyInput/CurrencyInput.tsx +4 -0
  50. package/src/components/ImageUpload/ImageUpload.tsx +158 -0
  51. package/src/components/ImageUpload/index.ts +1 -0
  52. package/src/components/Input/Input.tsx +51 -23
  53. package/src/components/ListItem/ListItem.tsx +4 -1
  54. package/src/components/SheetSelect/SheetSelect.tsx +192 -0
  55. package/src/components/SheetSelect/index.ts +1 -0
  56. package/src/hooks/useConfirmDialog.ts +67 -0
  57. package/src/index.ts +6 -0
@@ -0,0 +1,399 @@
1
+ 'use strict';
2
+
3
+ var React3 = require('react');
4
+ var reactNative = require('react-native');
5
+ var vectorIcons = require('@expo/vector-icons');
6
+ var reactNativeSizeMatters = require('react-native-size-matters');
7
+ var pressto = require('pressto');
8
+ var reactNativeReanimated = require('react-native-reanimated');
9
+
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
+
12
+ var React3__default = /*#__PURE__*/_interopDefault(React3);
13
+
14
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
15
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
16
+ }) : x)(function(x) {
17
+ if (typeof require !== "undefined") return require.apply(this, arguments);
18
+ throw Error('Dynamic require of "' + x + '" is not supported');
19
+ });
20
+ var _haptics = null;
21
+ var _hapticsLoaded = false;
22
+ async function getHaptics() {
23
+ if (reactNative.Platform.OS === "web") return null;
24
+ if (!_hapticsLoaded) {
25
+ _hapticsLoaded = true;
26
+ try {
27
+ _haptics = await import('expo-haptics');
28
+ } catch {
29
+ _haptics = null;
30
+ }
31
+ }
32
+ return _haptics;
33
+ }
34
+ var _pulsar = null;
35
+ var _pulsarChecked = false;
36
+ var _pulsarAvailable = false;
37
+ function isPulsarNativeRegistered() {
38
+ try {
39
+ const g = globalThis;
40
+ if (typeof g.__turboModuleProxy === "function") {
41
+ return g.__turboModuleProxy("RNPulsar") != null;
42
+ }
43
+ return reactNative.NativeModules?.RNPulsar != null;
44
+ } catch {
45
+ return false;
46
+ }
47
+ }
48
+ function getPulsar() {
49
+ if (reactNative.Platform.OS === "web") return null;
50
+ if (!_pulsarChecked) {
51
+ _pulsarChecked = true;
52
+ try {
53
+ if (isPulsarNativeRegistered()) {
54
+ _pulsar = __require("react-native-pulsar");
55
+ _pulsarAvailable = true;
56
+ }
57
+ } catch {
58
+ _pulsar = null;
59
+ _pulsarAvailable = false;
60
+ }
61
+ }
62
+ return _pulsarAvailable ? _pulsar : null;
63
+ }
64
+ function impactLight() {
65
+ if (reactNative.Platform.OS === "web") return;
66
+ getHaptics().then((h) => {
67
+ if (h) {
68
+ h.impactAsync(h.ImpactFeedbackStyle.Light);
69
+ } else {
70
+ getPulsar()?.Presets.System.impactLight();
71
+ }
72
+ });
73
+ }
74
+
75
+ // src/theme/colorUtils.ts
76
+ function hexToRgb(hex) {
77
+ const clean = hex.replace("#", "");
78
+ const full = clean.length === 3 ? clean.split("").map((c) => c + c).join("") : clean;
79
+ if (full.length !== 6) return null;
80
+ return {
81
+ r: parseInt(full.slice(0, 2), 16),
82
+ g: parseInt(full.slice(2, 4), 16),
83
+ b: parseInt(full.slice(4, 6), 16)
84
+ };
85
+ }
86
+ function componentToHex(c) {
87
+ return Math.round(Math.max(0, Math.min(255, c))).toString(16).padStart(2, "0");
88
+ }
89
+ function rgbToHex(r, g, b) {
90
+ return `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
91
+ }
92
+ function withAlphaOnWhite(hex, alpha) {
93
+ const rgb = hexToRgb(hex);
94
+ if (!rgb) return hex;
95
+ const r = rgb.r * alpha + 255 * (1 - alpha);
96
+ const g = rgb.g * alpha + 255 * (1 - alpha);
97
+ const b = rgb.b * alpha + 255 * (1 - alpha);
98
+ return rgbToHex(r, g, b);
99
+ }
100
+ function withAlphaOnDark(hex, alpha, bgHex = "#0f0f0f") {
101
+ const rgb = hexToRgb(hex);
102
+ const bg = hexToRgb(bgHex);
103
+ if (!rgb || !bg) return hex;
104
+ const r = rgb.r * alpha + bg.r * (1 - alpha);
105
+ const g = rgb.g * alpha + bg.g * (1 - alpha);
106
+ const b = rgb.b * alpha + bg.b * (1 - alpha);
107
+ return rgbToHex(r, g, b);
108
+ }
109
+ function mixWithBackground(fgHex, bgHex, opacity) {
110
+ const fg = hexToRgb(fgHex);
111
+ const bg = hexToRgb(bgHex);
112
+ if (!fg || !bg) return fgHex;
113
+ const r = fg.r * opacity + bg.r * (1 - opacity);
114
+ const g = fg.g * opacity + bg.g * (1 - opacity);
115
+ const b = fg.b * opacity + bg.b * (1 - opacity);
116
+ return rgbToHex(r, g, b);
117
+ }
118
+ function lighten(hex, amount) {
119
+ return withAlphaOnWhite(hex, 1 - amount);
120
+ }
121
+ function darken(hex, amount) {
122
+ const rgb = hexToRgb(hex);
123
+ if (!rgb) return hex;
124
+ return rgbToHex(rgb.r * (1 - amount), rgb.g * (1 - amount), rgb.b * (1 - amount));
125
+ }
126
+
127
+ // src/theme/colors.ts
128
+ var defaultLight = {
129
+ background: "#ffffff",
130
+ foreground: "#1a1a1a",
131
+ card: "#ffffff",
132
+ primary: "#1a1a1a",
133
+ primaryForeground: "#ffffff",
134
+ // AUDIT FIX: brand accent — was undefined; falls back to primary when omitted
135
+ accent: "#d4561d",
136
+ accentForeground: "#ffffff",
137
+ border: "#dddddd",
138
+ // AUDIT FIX: was #e53935 (4.22:1 on white — fails AA); #c72828 = 5.59:1 ✓
139
+ destructive: "#c72828",
140
+ destructiveForeground: "#ffffff",
141
+ success: "#1a7a45",
142
+ successForeground: "#ffffff",
143
+ // AUDIT FIX: was #e67e00 (2.86:1 — severe fail); #9a5200 = 5.86:1 ✓ AAA-near
144
+ warning: "#9a5200",
145
+ warningForeground: "#ffffff"
146
+ };
147
+ function deriveColors(t, scheme) {
148
+ const dark = scheme === "dark";
149
+ const bg = t.background;
150
+ const foregroundSubtle = mixWithBackground(t.foreground, bg, 0.7);
151
+ const foregroundMuted = mixWithBackground(t.foreground, bg, 0.62);
152
+ const surface = dark ? lighten(bg, -0.06) : darken(bg, 0.04);
153
+ const surfaceStrong = dark ? lighten(bg, -0.12) : darken(bg, 0.08);
154
+ const destructiveTint = dark ? withAlphaOnDark(t.destructive, 0.15, bg) : withAlphaOnWhite(t.destructive, 0.08);
155
+ const destructiveBorder = dark ? withAlphaOnDark(t.destructive, 0.45, bg) : withAlphaOnWhite(t.destructive, 0.3);
156
+ const successTint = dark ? withAlphaOnDark(t.success, 0.15, bg) : withAlphaOnWhite(t.success, 0.08);
157
+ const successBorder = dark ? withAlphaOnDark(t.success, 0.45, bg) : withAlphaOnWhite(t.success, 0.3);
158
+ const warningTint = dark ? withAlphaOnDark(t.warning, 0.15, bg) : withAlphaOnWhite(t.warning, 0.08);
159
+ const warningBorder = dark ? withAlphaOnDark(t.warning, 0.45, bg) : withAlphaOnWhite(t.warning, 0.3);
160
+ return {
161
+ ...t,
162
+ foregroundSubtle,
163
+ foregroundMuted,
164
+ surface,
165
+ surfaceStrong,
166
+ destructiveTint,
167
+ destructiveBorder,
168
+ successTint,
169
+ successBorder,
170
+ warningTint,
171
+ warningBorder,
172
+ overlay: t.overlay ?? "rgba(0,0,0,0.45)",
173
+ accentResolved: t.accent ?? t.primary,
174
+ accentForegroundResolved: t.accentForeground ?? t.primaryForeground,
175
+ ring: t.accent ?? t.primary,
176
+ input: t.border,
177
+ separator: dark ? lighten(t.border, 0.22) : darken(t.border, 0.16)
178
+ };
179
+ }
180
+
181
+ // src/theme/ThemeProvider.tsx
182
+ var ThemeContext = React3.createContext({
183
+ colors: deriveColors(defaultLight, "light"),
184
+ colorScheme: "light"
185
+ });
186
+ function useTheme() {
187
+ const context = React3.useContext(ThemeContext);
188
+ if (!context) {
189
+ throw new Error("useTheme must be used within a ThemeProvider");
190
+ }
191
+ return context;
192
+ }
193
+ var isWeb = reactNative.Platform.OS === "web";
194
+ var s = isWeb ? (n) => n : reactNativeSizeMatters.scale;
195
+ var vs = isWeb ? (n) => n : reactNativeSizeMatters.verticalScale;
196
+ var ms = isWeb ? (n, _factor) => n : reactNativeSizeMatters.moderateScale;
197
+ var mvs = isWeb ? (n, _factor) => n : reactNativeSizeMatters.moderateVerticalScale;
198
+
199
+ // src/tokens.ts
200
+ var RADIUS = {
201
+ lg: 20};
202
+ var sizeMap = {
203
+ sm: "small",
204
+ md: "small",
205
+ lg: "large"
206
+ };
207
+ var labelFontSize = {
208
+ sm: ms(11),
209
+ md: ms(13),
210
+ lg: ms(14)
211
+ };
212
+ function Spinner({ size = "md", color, label, ...props }) {
213
+ const { colors } = useTheme();
214
+ const a11yLabel = label || "Loading";
215
+ if (label) {
216
+ return /* @__PURE__ */ React3__default.default.createElement(
217
+ reactNative.View,
218
+ {
219
+ style: styles.wrapper,
220
+ accessibilityRole: "progressbar",
221
+ accessibilityLabel: a11yLabel,
222
+ accessibilityState: { busy: true }
223
+ },
224
+ /* @__PURE__ */ React3__default.default.createElement(reactNative.ActivityIndicator, { size: sizeMap[size], color: color ?? colors.primary, ...props }),
225
+ /* @__PURE__ */ React3__default.default.createElement(
226
+ reactNative.Text,
227
+ {
228
+ style: [styles.label, { color: colors.foregroundMuted, fontSize: labelFontSize[size] }],
229
+ allowFontScaling: true
230
+ },
231
+ label
232
+ )
233
+ );
234
+ }
235
+ return /* @__PURE__ */ React3__default.default.createElement(
236
+ reactNative.ActivityIndicator,
237
+ {
238
+ size: sizeMap[size],
239
+ color: color ?? colors.primary,
240
+ accessibilityRole: "progressbar",
241
+ accessibilityLabel: a11yLabel,
242
+ accessibilityState: { busy: true },
243
+ ...props
244
+ }
245
+ );
246
+ }
247
+ var styles = reactNative.StyleSheet.create({
248
+ wrapper: {
249
+ alignItems: "center",
250
+ gap: vs(6)
251
+ },
252
+ label: {
253
+ fontFamily: "Sohne-Regular",
254
+ lineHeight: mvs(18)
255
+ }
256
+ });
257
+ ({
258
+ /** Material-style ease-out — natural deceleration for state changes. */
259
+ standard: reactNativeReanimated.Easing.bezier(0.2, 0, 0, 1),
260
+ /** Strong ease-out for expanding surfaces (Accordion open). */
261
+ expand: reactNativeReanimated.Easing.bezier(0.23, 1, 0.32, 1),
262
+ /** Quick ease-in for collapsing. */
263
+ collapse: reactNativeReanimated.Easing.in(reactNativeReanimated.Easing.ease)
264
+ });
265
+ var PRESS_SCALE = {
266
+ button: 0.95,
267
+ card: 0.98,
268
+ row: 0.97,
269
+ chip: 0.94
270
+ };
271
+ pressto.createAnimatedPressable((progress) => {
272
+ "worklet";
273
+ const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
274
+ return { transform: [{ scale: scale2 }] };
275
+ });
276
+ var PressableCard = pressto.createAnimatedPressable((progress) => {
277
+ "worklet";
278
+ const scale2 = 1 - (1 - PRESS_SCALE.card) * progress;
279
+ return { transform: [{ scale: scale2 }] };
280
+ });
281
+ pressto.createAnimatedPressable((progress) => {
282
+ "worklet";
283
+ const scale2 = 1 - (1 - PRESS_SCALE.row) * progress;
284
+ return { transform: [{ scale: scale2 }] };
285
+ });
286
+ pressto.createAnimatedPressable((progress) => {
287
+ "worklet";
288
+ const scale2 = 1 - (1 - PRESS_SCALE.chip) * progress;
289
+ return { transform: [{ scale: scale2 }] };
290
+ });
291
+ pressto.createAnimatedPressable((progress) => {
292
+ "worklet";
293
+ const scale2 = 1 - (1 - PRESS_SCALE.button) * progress;
294
+ return { transform: [{ scale: scale2 }] };
295
+ });
296
+
297
+ // src/components/ImageUpload/ImageUpload.tsx
298
+ function ImageUpload({
299
+ value,
300
+ onChange,
301
+ loading = false,
302
+ placeholder = "Tap to add image",
303
+ width,
304
+ height = 200,
305
+ borderRadius = RADIUS.lg,
306
+ resizeMode = "cover",
307
+ disabled = false,
308
+ style,
309
+ accessibilityLabel
310
+ }) {
311
+ const { colors } = useTheme();
312
+ const handlePress = async () => {
313
+ if (disabled || loading) return;
314
+ impactLight();
315
+ let ImagePicker;
316
+ try {
317
+ ImagePicker = await import('expo-image-picker');
318
+ } catch {
319
+ if (__DEV__) console.warn("[ImageUpload] expo-image-picker not installed. Add it as a dependency.");
320
+ return;
321
+ }
322
+ if (reactNative.Platform.OS !== "web") {
323
+ const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
324
+ if (status !== "granted") return;
325
+ }
326
+ const result = await ImagePicker.launchImageLibraryAsync({
327
+ mediaTypes: ["images"],
328
+ allowsEditing: true,
329
+ quality: 0.8
330
+ });
331
+ if (!result.canceled && result.assets[0]) {
332
+ onChange?.(result.assets[0].uri);
333
+ }
334
+ };
335
+ const containerStyle = {
336
+ width,
337
+ height,
338
+ borderRadius,
339
+ borderWidth: value ? 0 : 1,
340
+ borderStyle: "dashed",
341
+ borderColor: colors.border,
342
+ backgroundColor: value ? "transparent" : colors.surface,
343
+ overflow: "hidden"
344
+ };
345
+ return /* @__PURE__ */ React3__default.default.createElement(
346
+ PressableCard,
347
+ {
348
+ onPress: handlePress,
349
+ enabled: !disabled && !loading,
350
+ rippleColor: "transparent",
351
+ touchSoundDisabled: true,
352
+ accessibilityRole: "button",
353
+ accessibilityLabel: accessibilityLabel ?? (value ? "Change image" : placeholder),
354
+ accessibilityState: { disabled: disabled || loading },
355
+ style: [containerStyle, style]
356
+ },
357
+ value ? /* @__PURE__ */ React3__default.default.createElement(
358
+ reactNative.Image,
359
+ {
360
+ source: { uri: value },
361
+ style: [reactNative.StyleSheet.absoluteFillObject, { borderRadius }],
362
+ resizeMode
363
+ }
364
+ ) : /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles2.placeholder }, /* @__PURE__ */ React3__default.default.createElement(vectorIcons.Feather, { name: "image", size: ms(28), color: colors.foregroundMuted }), /* @__PURE__ */ React3__default.default.createElement(reactNative.Text, { style: [styles2.placeholderText, { color: colors.foregroundMuted }], allowFontScaling: true }, placeholder)),
365
+ loading ? /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: [styles2.loadingOverlay, { backgroundColor: colors.overlay }] }, /* @__PURE__ */ React3__default.default.createElement(Spinner, { size: "md" })) : null,
366
+ value && !loading ? /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles2.editBadge, pointerEvents: "none" }, /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: [styles2.editBadgeInner, { backgroundColor: colors.overlay }] }, /* @__PURE__ */ React3__default.default.createElement(vectorIcons.Feather, { name: "edit-2", size: ms(12), color: "#fff" }))) : null
367
+ );
368
+ }
369
+ var styles2 = reactNative.StyleSheet.create({
370
+ placeholder: {
371
+ flex: 1,
372
+ alignItems: "center",
373
+ justifyContent: "center",
374
+ gap: vs(8)
375
+ },
376
+ placeholderText: {
377
+ fontFamily: "Sohne-Regular",
378
+ fontSize: ms(13)
379
+ },
380
+ loadingOverlay: {
381
+ ...reactNative.StyleSheet.absoluteFillObject,
382
+ alignItems: "center",
383
+ justifyContent: "center"
384
+ },
385
+ editBadge: {
386
+ position: "absolute",
387
+ bottom: vs(8),
388
+ right: s(8)
389
+ },
390
+ editBadgeInner: {
391
+ width: s(28),
392
+ height: s(28),
393
+ borderRadius: 999,
394
+ alignItems: "center",
395
+ justifyContent: "center"
396
+ }
397
+ });
398
+
399
+ exports.ImageUpload = ImageUpload;
@@ -0,0 +1,9 @@
1
+ export { ImageUpload } from './chunk-Y4GL2MHX.mjs';
2
+ import './chunk-WBOOUHSS.mjs';
3
+ import './chunk-3DKJ2GIC.mjs';
4
+ import './chunk-EJ7ZPXOH.mjs';
5
+ import './chunk-DVK4G2GT.mjs';
6
+ import './chunk-QY3X2UYR.mjs';
7
+ import './chunk-SOYNZDVY.mjs';
8
+ import './chunk-2CE3TQVY.mjs';
9
+ import './chunk-Y6FXYEAI.mjs';
package/dist/Input.d.mts CHANGED
@@ -17,7 +17,9 @@ interface InputProps extends TextInputProps {
17
17
  type?: 'text' | 'password';
18
18
  containerStyle?: ViewStyle;
19
19
  inputWrapperStyle?: ViewStyle;
20
+ /** Use inside a Sheet/BottomSheet — swaps TextInput for BottomSheetTextInput to fix keyboard handling. */
21
+ sheetMode?: boolean;
20
22
  }
21
- declare function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type, containerStyle, inputWrapperStyle, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }: InputProps): React.JSX.Element;
23
+ declare function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type, containerStyle, inputWrapperStyle, sheetMode, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }: InputProps): React.JSX.Element;
22
24
 
23
25
  export { Input, type InputProps };
package/dist/Input.d.ts CHANGED
@@ -17,7 +17,9 @@ interface InputProps extends TextInputProps {
17
17
  type?: 'text' | 'password';
18
18
  containerStyle?: ViewStyle;
19
19
  inputWrapperStyle?: ViewStyle;
20
+ /** Use inside a Sheet/BottomSheet — swaps TextInput for BottomSheetTextInput to fix keyboard handling. */
21
+ sheetMode?: boolean;
20
22
  }
21
- declare function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type, containerStyle, inputWrapperStyle, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }: InputProps): React.JSX.Element;
23
+ declare function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type, containerStyle, inputWrapperStyle, sheetMode, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }: InputProps): React.JSX.Element;
22
24
 
23
25
  export { Input, type InputProps };
package/dist/Input.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var React3 = require('react');
4
4
  var reactNative = require('react-native');
5
+ var bottomSheet = require('@gorhom/bottom-sheet');
5
6
  var Animated = require('react-native-reanimated');
6
7
  var vectorIcons = require('@expo/vector-icons');
7
8
  var reactNativeSizeMatters = require('react-native-size-matters');
@@ -215,7 +216,7 @@ function useColorTransition(active, options = {}) {
215
216
 
216
217
  // src/components/Input/Input.tsx
217
218
  var webInputResetStyle = reactNative.Platform.OS === "web" ? { outlineStyle: "none", outlineWidth: 0, outlineColor: "transparent", boxShadow: "none" } : {};
218
- function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = "text", containerStyle, inputWrapperStyle, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }) {
219
+ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = "text", containerStyle, inputWrapperStyle, sheetMode = false, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }) {
219
220
  const { colors } = useTheme();
220
221
  const [focused, setFocused] = React3.useState(false);
221
222
  const [showPassword, setShowPassword] = React3.useState(false);
@@ -252,7 +253,31 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
252
253
  },
253
254
  /* @__PURE__ */ React3__default.default.createElement(Animated__default.default.View, { style: [styles.borderOverlay, borderAnimStyle], pointerEvents: "none" }),
254
255
  effectivePrefix ? typeof effectivePrefix === "string" ? /* @__PURE__ */ React3__default.default.createElement(reactNative.Text, { style: [styles.prefixText, { color: colors.foregroundMuted }, prefixStyle], allowFontScaling: true }, effectivePrefix) : /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles.prefixContainer }, effectivePrefix) : null,
255
- /* @__PURE__ */ React3__default.default.createElement(
256
+ sheetMode ? /* @__PURE__ */ React3__default.default.createElement(
257
+ bottomSheet.BottomSheetTextInput,
258
+ {
259
+ style: [
260
+ styles.input,
261
+ { color: colors.foreground },
262
+ webInputResetStyle,
263
+ style
264
+ ],
265
+ onFocus: (e) => {
266
+ setFocused(true);
267
+ onFocus?.(e);
268
+ },
269
+ onBlur: (e) => {
270
+ setFocused(false);
271
+ onBlur?.(e);
272
+ },
273
+ placeholderTextColor: colors.foregroundMuted,
274
+ allowFontScaling: true,
275
+ secureTextEntry: effectiveSecure,
276
+ editable: isDisabled ? false : editable,
277
+ accessibilityLabel: accessibilityLabel ?? label,
278
+ ...props
279
+ }
280
+ ) : /* @__PURE__ */ React3__default.default.createElement(
256
281
  reactNative.TextInput,
257
282
  {
258
283
  style: [
package/dist/Input.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { Input } from './chunk-756RAKE4.mjs';
1
+ export { Input } from './chunk-LVYEU5ZK.mjs';
2
2
  import './chunk-26BCI223.mjs';
3
3
  import './chunk-DVK4G2GT.mjs';
4
4
  import './chunk-T7XZ7H7Y.mjs';
@@ -53,12 +53,14 @@ interface ListItemProps {
53
53
  titleStyle?: TextStyle;
54
54
  /** Style applied to the subtitle Text. */
55
55
  subtitleStyle?: TextStyle;
56
+ /** Max lines for the subtitle. Defaults to 2. */
57
+ subtitleNumberOfLines?: number;
56
58
  /** Style applied to the caption Text. */
57
59
  captionStyle?: TextStyle;
58
60
  /** Accessibility label override. Defaults to the title. */
59
61
  accessibilityLabel?: string;
60
62
  }
61
- declare function ListItemBase({ leftRender, rightRender, trailing, icon, leftIcon, rightIcon, leftIconColor, rightIconColor, title, subtitle, caption, variant, showChevron, showSeparator, onPress, disabled, style, titleStyle, subtitleStyle, captionStyle, accessibilityLabel, }: ListItemProps): React.JSX.Element;
63
+ declare function ListItemBase({ leftRender, rightRender, trailing, icon, leftIcon, rightIcon, leftIconColor, rightIconColor, title, subtitle, caption, variant, showChevron, showSeparator, onPress, disabled, style, titleStyle, subtitleStyle, subtitleNumberOfLines, captionStyle, accessibilityLabel, }: ListItemProps): React.JSX.Element;
62
64
  declare const ListItem: React.MemoExoticComponent<typeof ListItemBase>;
63
65
 
64
66
  export { ListItem, type ListItemProps };
@@ -53,12 +53,14 @@ interface ListItemProps {
53
53
  titleStyle?: TextStyle;
54
54
  /** Style applied to the subtitle Text. */
55
55
  subtitleStyle?: TextStyle;
56
+ /** Max lines for the subtitle. Defaults to 2. */
57
+ subtitleNumberOfLines?: number;
56
58
  /** Style applied to the caption Text. */
57
59
  captionStyle?: TextStyle;
58
60
  /** Accessibility label override. Defaults to the title. */
59
61
  accessibilityLabel?: string;
60
62
  }
61
- declare function ListItemBase({ leftRender, rightRender, trailing, icon, leftIcon, rightIcon, leftIconColor, rightIconColor, title, subtitle, caption, variant, showChevron, showSeparator, onPress, disabled, style, titleStyle, subtitleStyle, captionStyle, accessibilityLabel, }: ListItemProps): React.JSX.Element;
63
+ declare function ListItemBase({ leftRender, rightRender, trailing, icon, leftIcon, rightIcon, leftIconColor, rightIconColor, title, subtitle, caption, variant, showChevron, showSeparator, onPress, disabled, style, titleStyle, subtitleStyle, subtitleNumberOfLines, captionStyle, accessibilityLabel, }: ListItemProps): React.JSX.Element;
62
64
  declare const ListItem: React.MemoExoticComponent<typeof ListItemBase>;
63
65
 
64
66
  export { ListItem, type ListItemProps };
package/dist/ListItem.js CHANGED
@@ -313,6 +313,7 @@ function ListItemBase({
313
313
  style,
314
314
  titleStyle,
315
315
  subtitleStyle,
316
+ subtitleNumberOfLines = 2,
316
317
  captionStyle,
317
318
  accessibilityLabel
318
319
  }) {
@@ -347,7 +348,7 @@ function ListItemBase({
347
348
  reactNative.Text,
348
349
  {
349
350
  style: [styles.subtitle, { color: colors.foregroundMuted }, subtitleStyle],
350
- numberOfLines: 2,
351
+ numberOfLines: subtitleNumberOfLines,
351
352
  allowFontScaling: true
352
353
  },
353
354
  subtitle
package/dist/ListItem.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { ListItem } from './chunk-BNP626TY.mjs';
1
+ export { ListItem } from './chunk-T4I5WVHA.mjs';
2
2
  import './chunk-3DKJ2GIC.mjs';
3
3
  import './chunk-EJ7ZPXOH.mjs';
4
4
  import './chunk-DVK4G2GT.mjs';
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import { ViewStyle } from 'react-native';
3
+
4
+ interface SheetSelectOption {
5
+ label: string;
6
+ value: string | number;
7
+ iconName?: string;
8
+ disabled?: boolean;
9
+ }
10
+ interface SheetSelectProps {
11
+ options: SheetSelectOption[];
12
+ value?: string | number | (string | number)[];
13
+ onValueChange?: (value: string | number | (string | number)[]) => void;
14
+ /** Allow multiple simultaneous selections. Defaults to false (radio). */
15
+ multiSelect?: boolean;
16
+ label?: string;
17
+ error?: string;
18
+ /** Wrap chips into multiple rows instead of a single horizontal scroll. Defaults to false. */
19
+ wrap?: boolean;
20
+ style?: ViewStyle;
21
+ accessibilityLabel?: string;
22
+ }
23
+ declare function SheetSelect({ options, value, onValueChange, multiSelect, label, error, wrap, style, accessibilityLabel, }: SheetSelectProps): React.JSX.Element;
24
+
25
+ export { SheetSelect, type SheetSelectOption, type SheetSelectProps };
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import { ViewStyle } from 'react-native';
3
+
4
+ interface SheetSelectOption {
5
+ label: string;
6
+ value: string | number;
7
+ iconName?: string;
8
+ disabled?: boolean;
9
+ }
10
+ interface SheetSelectProps {
11
+ options: SheetSelectOption[];
12
+ value?: string | number | (string | number)[];
13
+ onValueChange?: (value: string | number | (string | number)[]) => void;
14
+ /** Allow multiple simultaneous selections. Defaults to false (radio). */
15
+ multiSelect?: boolean;
16
+ label?: string;
17
+ error?: string;
18
+ /** Wrap chips into multiple rows instead of a single horizontal scroll. Defaults to false. */
19
+ wrap?: boolean;
20
+ style?: ViewStyle;
21
+ accessibilityLabel?: string;
22
+ }
23
+ declare function SheetSelect({ options, value, onValueChange, multiSelect, label, error, wrap, style, accessibilityLabel, }: SheetSelectProps): React.JSX.Element;
24
+
25
+ export { SheetSelect, type SheetSelectOption, type SheetSelectProps };