@utilitywarehouse/hearth-react-native 0.27.2-testid-fix-3 → 0.27.3

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 (38) hide show
  1. package/.turbo/turbo-build.log +4 -5
  2. package/.turbo/turbo-lint.log +69 -0
  3. package/CHANGELOG.md +39 -0
  4. package/build/components/Select/Select.d.ts +1 -1
  5. package/build/components/Select/Select.js +4 -5
  6. package/build/components/Select/Select.props.d.ts +0 -4
  7. package/build/components/Select/SelectOption.d.ts +1 -1
  8. package/build/components/Select/SelectOption.js +2 -2
  9. package/build/components/VerificationInput/VerificationInput.js +3 -3
  10. package/package.json +3 -3
  11. package/src/components/Select/Select.props.ts +0 -4
  12. package/src/components/Select/Select.tsx +1 -6
  13. package/src/components/Select/SelectOption.tsx +0 -2
  14. package/src/components/VerificationInput/VerificationInput.tsx +0 -3
  15. package/build/components/DatePicker/TimePicker.d.ts +0 -3
  16. package/build/components/DatePicker/TimePicker.js +0 -84
  17. package/build/components/DatePicker/time-picker/animated-math.d.ts +0 -4
  18. package/build/components/DatePicker/time-picker/animated-math.js +0 -19
  19. package/build/components/DatePicker/time-picker/period-native.d.ts +0 -6
  20. package/build/components/DatePicker/time-picker/period-native.js +0 -17
  21. package/build/components/DatePicker/time-picker/period-picker.d.ts +0 -6
  22. package/build/components/DatePicker/time-picker/period-picker.js +0 -10
  23. package/build/components/DatePicker/time-picker/period-web.d.ts +0 -6
  24. package/build/components/DatePicker/time-picker/period-web.js +0 -21
  25. package/build/components/DatePicker/time-picker/wheel-native.d.ts +0 -8
  26. package/build/components/DatePicker/time-picker/wheel-native.js +0 -19
  27. package/build/components/DatePicker/time-picker/wheel-picker/index.d.ts +0 -2
  28. package/build/components/DatePicker/time-picker/wheel-picker/index.js +0 -2
  29. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.d.ts +0 -16
  30. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.js +0 -97
  31. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.d.ts +0 -21
  32. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.js +0 -88
  33. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.d.ts +0 -23
  34. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.js +0 -21
  35. package/build/components/DatePicker/time-picker/wheel-web.d.ts +0 -8
  36. package/build/components/DatePicker/time-picker/wheel-web.js +0 -146
  37. package/build/components/DatePicker/time-picker/wheel.d.ts +0 -8
  38. package/build/components/DatePicker/time-picker/wheel.js +0 -10
@@ -1,5 +1,4 @@
1
-
2
- 
3
- > @utilitywarehouse/hearth-react-native@0.27.2-testid-fix-3 build /Users/filmondaniels/Projects/Work/hearth/packages/react-native
4
- > tsc
5
-
1
+
2
+ > @utilitywarehouse/hearth-react-native@0.27.3 build /home/runner/work/hearth/hearth/packages/react-native
3
+ > tsc
4
+
@@ -0,0 +1,69 @@
1
+
2
+ > @utilitywarehouse/hearth-react-native@0.27.3 lint /home/runner/work/hearth/hearth/packages/react-native
3
+ > TIMING=1 eslint .
4
+
5
+
6
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/Carousel/Carousel.context.tsx
7
+ 6:14 warning Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components react-refresh/only-export-components
8
+
9
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/Carousel/Carousel.tsx
10
+ 146:6 warning React Hook useMemo has a missing dependency: 'hasCarouselControlsInTree'. Either include it or remove the dependency array react-hooks/exhaustive-deps
11
+
12
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/DatePicker/DatePicker.tsx
13
+ 109:6 warning React Hook useCallback has an unnecessary dependency: 'modalRef.current'. Either exclude it or remove the dependency array. Mutable values like 'modalRef.current' aren't valid dependencies because mutating them doesn't re-render the component react-hooks/exhaustive-deps
14
+ 259:6 warning React Hook useEffect has a missing dependency: 'initialState'. Either include it or remove the dependency array react-hooks/exhaustive-deps
15
+ 346:6 warning React Hook useEffect has a missing dependency: 'onChange'. Either include it or remove the dependency array react-hooks/exhaustive-deps
16
+ 468:5 warning React Hook useCallback has a missing dependency: 'onChange'. Either include it or remove the dependency array react-hooks/exhaustive-deps
17
+ 536:6 warning React Hook useEffect has a missing dependency: 'onSelectMonth'. Either include it or remove the dependency array react-hooks/exhaustive-deps
18
+ 542:6 warning React Hook useEffect has a missing dependency: 'onSelectYear'. Either include it or remove the dependency array react-hooks/exhaustive-deps
19
+
20
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/DatePicker/DatePickerDay.tsx
21
+ 76:6 warning React Hook useMemo has an unnecessary dependency: 'styles.rangeRoot'. Either exclude it or remove the dependency array. Outer scope values like 'styles.rangeRoot' aren't valid dependencies because mutating them doesn't re-render the component react-hooks/exhaustive-deps
22
+ 84:6 warning React Hook useMemo has a missing dependency: 'isSelected'. Either include it or remove the dependency array react-hooks/exhaustive-deps
23
+
24
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/DatePicker/DatePickerDays.tsx
25
+ 179:6 warning React Hook useMemo has unnecessary dependencies: 'month' and 'year'. Either exclude them or remove the dependency array react-hooks/exhaustive-deps
26
+
27
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/DatePicker/DatePickerYears.tsx
28
+ 52:6 warning React Hook useCallback has a missing dependency: 'containerHeight'. Either include it or remove the dependency array. Outer scope values like 'styles' aren't valid dependencies because mutating them doesn't re-render the component react-hooks/exhaustive-deps
29
+
30
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/Input/Input.tsx
31
+ 78:8 warning React Hook useEffect has a missing dependency: 'formFieldContext'. Either include it or remove the dependency array react-hooks/exhaustive-deps
32
+
33
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/Modal/Modal.tsx
34
+ 93:6 warning React Hook useCallback has an unnecessary dependency: 'Platform.OS'. Either exclude it or remove the dependency array. Outer scope values like 'Platform.OS' aren't valid dependencies because mutating them doesn't re-render the component react-hooks/exhaustive-deps
35
+ 330:5 warning React Hook useCallback has a missing dependency: 'footer'. Either include it or remove the dependency array react-hooks/exhaustive-deps
36
+
37
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/Modal/Modal.web.tsx
38
+ 66:6 warning React Hook useCallback has an unnecessary dependency: 'Platform.OS'. Either exclude it or remove the dependency array. Outer scope values like 'Platform.OS' aren't valid dependencies because mutating them doesn't re-render the component react-hooks/exhaustive-deps
39
+
40
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/PillGroup/PillGroup.tsx
41
+ 17:9 warning The 'normalizedValue' conditional could make the dependencies of useMemo Hook (at line 33) change on every render. Move it inside the useMemo callback. Alternatively, wrap the initialization of 'normalizedValue' in its own useMemo() Hook react-hooks/exhaustive-deps
42
+
43
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/Tabs/Tabs.tsx
44
+ 53:6 warning React Hook useEffect has a missing dependency: 'tabValues'. Either include it or remove the dependency array react-hooks/exhaustive-deps
45
+ 53:7 warning React Hook useEffect has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked react-hooks/exhaustive-deps
46
+ 104:5 warning React Hook useMemo has an unnecessary dependency: 'tabValues'. Either exclude it or remove the dependency array react-hooks/exhaustive-deps
47
+ 127:62 warning React Hook useEffect has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked react-hooks/exhaustive-deps
48
+
49
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/Textarea/Textarea.tsx
50
+ 45:6 warning React Hook useEffect has a missing dependency: 'formFieldContext'. Either include it or remove the dependency array react-hooks/exhaustive-deps
51
+
52
+ /home/runner/work/hearth/hearth/packages/react-native/src/components/Toast/Toast.context.tsx
53
+ 14:14 warning Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components react-refresh/only-export-components
54
+ 106:14 warning Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components react-refresh/only-export-components
55
+
56
+ ✖ 24 problems (0 errors, 24 warnings)
57
+
58
+ Rule | Time (ms) | Relative
59
+ :-----------------------------------------|----------:|--------:
60
+ @typescript-eslint/no-unused-vars | 1647.829 | 61.5%
61
+ react-hooks/exhaustive-deps | 126.846 | 4.7%
62
+ no-global-assign | 85.087 | 3.2%
63
+ react-hooks/rules-of-hooks | 75.260 | 2.8%
64
+ no-misleading-character-class | 68.283 | 2.6%
65
+ no-unexpected-multiline | 54.599 | 2.0%
66
+ @typescript-eslint/ban-ts-comment | 52.506 | 2.0%
67
+ no-useless-escape | 31.809 | 1.2%
68
+ no-loss-of-precision | 30.517 | 1.1%
69
+ @typescript-eslint/triple-slash-reference | 29.522 | 1.1%
package/CHANGELOG.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # @utilitywarehouse/hearth-react-native
2
2
 
3
+ ## 0.27.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1006](https://github.com/utilitywarehouse/hearth/pull/1006) [`1996112`](https://github.com/utilitywarehouse/hearth/commit/1996112864146e86972ef6b9b07a8be5a72b552f) Thanks [@jordmccord](https://github.com/jordmccord)! - 🐛 [FIX]: Make `paddingNone` remove horizontal padding for ghost buttons in `md` size
8
+
9
+ Fixed an issue where setting `paddingNone` on a ghost button did not remove horizontal padding when using `md` size. The prop now removes horizontal padding for both `sm` and `md` ghost buttons.
10
+
11
+ **Components affected**:
12
+ - `Button`
13
+
14
+ **Developer changes**:
15
+
16
+ No changes required.
17
+
18
+ - [#1012](https://github.com/utilitywarehouse/hearth/pull/1012) [`4fda116`](https://github.com/utilitywarehouse/hearth/commit/4fda116c2a1bec383df7e630180ab57166ab9da4) Thanks [@jordmccord](https://github.com/jordmccord)! - 🐛 [FIX]: Prevent outlines from being clipped for scrollable children in `Modal`
19
+
20
+ Fixed an issue in in-nav modals where child components with outlines could be visually clipped at the horizontal edges when content was scrollable.
21
+
22
+ **Components affected**:
23
+ - `Modal`
24
+
25
+ **Developer changes**:
26
+
27
+ No changes required.
28
+
29
+ - [#1012](https://github.com/utilitywarehouse/hearth/pull/1012) [`4fda116`](https://github.com/utilitywarehouse/hearth/commit/4fda116c2a1bec383df7e630180ab57166ab9da4) Thanks [@jordmccord](https://github.com/jordmccord)! - 💅 [ENHANCEMENT]: Update horizontal padding values for scrollable in-nav `Modal` content
30
+
31
+ Adjusted horizontal padding behaviour in scrollable in-nav modals to preserve child outlines while keeping visual spacing consistent.
32
+
33
+ **Components affected**:
34
+ - `Modal`
35
+
36
+ **Developer changes**:
37
+
38
+ No changes required.
39
+
40
+ - [#1009](https://github.com/utilitywarehouse/hearth/pull/1009) [`3d65ef2`](https://github.com/utilitywarehouse/hearth/commit/3d65ef2f8f7701b128a9c679f1910cd3d0f5c0c3) Thanks [@fillyD](https://github.com/fillyD)! - 🐛 [FIX]: testID for `List` component
41
+
3
42
  ## 0.27.2
4
43
 
5
44
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  import SelectProps from './Select.props';
2
2
  declare const Select: {
3
- ({ options, value, onValueChange, label, labelVariant, placeholder, disabled, leadingIcon: LeadingIcon, validationStatus, helperText, helperIcon, invalidText, validText, required, children, bottomSheetProps, menuHeading, readonly, emptyText, listProps, searchable, searchPlaceholder, testID, ...rest }: SelectProps): import("react/jsx-runtime").JSX.Element;
3
+ ({ options, value, onValueChange, label, labelVariant, placeholder, disabled, leadingIcon: LeadingIcon, validationStatus, helperText, helperIcon, invalidText, validText, required, children, bottomSheetProps, menuHeading, readonly, emptyText, listProps, searchable, searchPlaceholder, ...rest }: SelectProps): import("react/jsx-runtime").JSX.Element;
4
4
  displayName: string;
5
5
  };
6
6
  export default Select;
@@ -11,7 +11,7 @@ import { Icon } from '../Icon';
11
11
  import { Input } from '../Input';
12
12
  import { SelectContext } from './Select.context';
13
13
  import SelectOption from './SelectOption';
14
- const Select = ({ options = [], value, onValueChange, label, labelVariant = 'body', placeholder = 'Select an option', disabled = false, leadingIcon: LeadingIcon, validationStatus = 'initial', helperText, helperIcon, invalidText, validText, required = true, children, bottomSheetProps, menuHeading, readonly = false, emptyText = 'No options available', listProps, searchable = false, searchPlaceholder = 'Search', testID, ...rest }) => {
14
+ const Select = ({ options = [], value, onValueChange, label, labelVariant = 'body', placeholder = 'Select an option', disabled = false, leadingIcon: LeadingIcon, validationStatus = 'initial', helperText, helperIcon, invalidText, validText, required = true, children, bottomSheetProps, menuHeading, readonly = false, emptyText = 'No options available', listProps, searchable = false, searchPlaceholder = 'Search', ...rest }) => {
15
15
  const formFieldContext = useFormFieldContext();
16
16
  const validationStatusFromContext = formFieldContext?.validationStatus ?? validationStatus;
17
17
  const isRequired = formFieldContext?.required ?? required;
@@ -64,10 +64,9 @@ const Select = ({ options = [], value, onValueChange, label, labelVariant = 'bod
64
64
  setIsOpen(false);
65
65
  setSearch('');
66
66
  }, []);
67
- const renderSelectOption = useCallback(({ item }) => (_jsx(SelectOption, { label: item.label, value: item.value, disabled: item.disabled, leadingIcon: item.leadingIcon, trailingIcon: item.trailingIcon, testID: testID ? `${testID}-option-${item.label}` : undefined })), [testID] // ← added testID dependency
68
- );
67
+ const renderSelectOption = useCallback(({ item }) => (_jsx(SelectOption, { label: item.label, value: item.value, disabled: item.disabled, leadingIcon: item.leadingIcon, trailingIcon: item.trailingIcon })), []);
69
68
  const renderEmptyComponent = useCallback(() => (_jsx(BottomSheetView, { style: styles.emptyContainer, children: _jsx(DetailText, { children: emptyText }) })), [emptyText]);
70
- return (_jsxs(View, { ...rest, style: [styles.container, rest.style], children: [_jsx(FormField, { label: label, labelVariant: labelVariant, helperText: helperText, helperIcon: helperIcon, validationStatus: validationStatusFromContext, required: isRequired, disabled: isDisabled, readonly: isReadonly, invalidText: invalidText, validText: validText, children: _jsxs(Pressable, { onPress: openBottomSheet, disabled: isDisabled || isReadonly, testID: testID, style: ({ pressed }) => [
69
+ return (_jsxs(View, { ...rest, style: [styles.container, rest.style], children: [_jsx(FormField, { label: label, labelVariant: labelVariant, helperText: helperText, helperIcon: helperIcon, validationStatus: validationStatusFromContext, required: isRequired, disabled: isDisabled, readonly: isReadonly, invalidText: invalidText, validText: validText, children: _jsxs(Pressable, { onPress: openBottomSheet, disabled: isDisabled || isReadonly, style: ({ pressed }) => [
71
70
  styles.selectContainer,
72
71
  styles.pressedContainer(pressed || isOpen),
73
72
  ], children: [!!LeadingIcon && (_jsx(View, { children: (() => {
@@ -77,7 +76,7 @@ const Select = ({ options = [], value, onValueChange, label, labelVariant = 'bod
77
76
  selectedValue: value,
78
77
  onValueChange,
79
78
  close: closeBottomSheet,
80
- }, children: [menuHeading && (_jsx(View, { style: styles.headingContainer, children: _jsx(DetailText, { size: "lg", children: menuHeading }) })), searchable && (_jsx(View, { style: styles.searchContainer, children: _jsx(Input, { placeholder: searchPlaceholder, value: search, inBottomSheet: true, onChangeText: setSearch, type: "search", testID: testID ? `${testID}-search` : undefined }) })), children ? (_jsx(BottomSheetScrollView, { children: children })) : (_jsx(BottomSheetFlatList, { data: filteredOptions, keyExtractor: (option) => option.value, renderItem: renderSelectOption, ListEmptyComponent: renderEmptyComponent, testID: testID ? `${testID}-options` : undefined, ...listProps }))] }) })] }));
79
+ }, children: [menuHeading && (_jsx(View, { style: styles.headingContainer, children: _jsx(DetailText, { size: "lg", children: menuHeading }) })), searchable && (_jsx(View, { style: styles.searchContainer, children: _jsx(Input, { placeholder: searchPlaceholder, value: search, inBottomSheet: true, onChangeText: setSearch, type: "search" }) })), children ? (_jsx(BottomSheetScrollView, { children: children })) : (_jsx(BottomSheetFlatList, { data: filteredOptions, keyExtractor: (option) => option.value, renderItem: renderSelectOption, ListEmptyComponent: renderEmptyComponent, ...listProps }))] }) })] }));
81
80
  };
82
81
  const styles = StyleSheet.create(theme => ({
83
82
  container: {
@@ -148,9 +148,5 @@ export interface SelectOptionProps {
148
148
  * Callback when this option is selected
149
149
  */
150
150
  onPress?: (value: string) => void;
151
- /**
152
- * Test ID for testing
153
- */
154
- testID?: string;
155
151
  }
156
152
  export default SelectProps;
@@ -1,6 +1,6 @@
1
1
  import { SelectOptionProps } from './Select.props';
2
2
  declare const SelectOption: {
3
- ({ label, value, leadingIcon: LeftIcon, trailingIcon: RightIcon, selected, disabled, onPress, testID, }: SelectOptionProps): import("react/jsx-runtime").JSX.Element;
3
+ ({ label, value, leadingIcon: LeftIcon, trailingIcon: RightIcon, selected, disabled, onPress, }: SelectOptionProps): import("react/jsx-runtime").JSX.Element;
4
4
  displayName: string;
5
5
  };
6
6
  export default SelectOption;
@@ -5,7 +5,7 @@ import { StyleSheet } from 'react-native-unistyles';
5
5
  import { BodyText } from '../BodyText';
6
6
  import { Icon } from '../Icon';
7
7
  import { useSelectContext } from './Select.context';
8
- const SelectOption = ({ label, value, leadingIcon: LeftIcon, trailingIcon: RightIcon, selected, disabled, onPress, testID, }) => {
8
+ const SelectOption = ({ label, value, leadingIcon: LeftIcon, trailingIcon: RightIcon, selected, disabled, onPress, }) => {
9
9
  const { selectedValue, onValueChange, close } = useSelectContext();
10
10
  const isSelected = selected !== undefined ? selected : selectedValue === value;
11
11
  styles.useVariants({ disabled });
@@ -22,7 +22,7 @@ const SelectOption = ({ label, value, leadingIcon: LeftIcon, trailingIcon: Right
22
22
  close();
23
23
  }
24
24
  };
25
- return (_jsxs(Pressable, { onPress: handlePress, disabled: disabled, testID: testID, style: ({ pressed }) => [styles.container, pressed && styles.pressed], children: [!!LeftIcon && (_jsx(View, { children: _jsx(Icon, { as: LeftIcon, style: styles.icon }) })), _jsx(View, { style: styles.labelContainer, children: _jsx(BodyText, { children: label }) }), isSelected && (_jsx(View, { children: _jsx(Icon, { as: TickSmallIcon, style: styles.icon }) })), !!RightIcon && !isSelected && (_jsx(View, { children: _jsx(Icon, { as: RightIcon, style: styles.icon }) }))] }));
25
+ return (_jsxs(Pressable, { onPress: handlePress, disabled: disabled, style: ({ pressed }) => [styles.container, pressed && styles.pressed], children: [!!LeftIcon && (_jsx(View, { children: _jsx(Icon, { as: LeftIcon, style: styles.icon }) })), _jsx(View, { style: styles.labelContainer, children: _jsx(BodyText, { children: label }) }), isSelected && (_jsx(View, { children: _jsx(Icon, { as: TickSmallIcon, style: styles.icon }) })), !!RightIcon && !isSelected && (_jsx(View, { children: _jsx(Icon, { as: RightIcon, style: styles.icon }) }))] }));
26
26
  };
27
27
  const styles = StyleSheet.create(theme => ({
28
28
  container: {
@@ -5,7 +5,7 @@ import { StyleSheet } from 'react-native-unistyles';
5
5
  import { FormField } from '../FormField';
6
6
  import { getNextIndexFromValueChange } from './VerificationInput.utils';
7
7
  import { VerificationInputSlot } from './VerificationInputSlot';
8
- const VerificationInput = forwardRef(({ value = '', onChangeText, label, labelVariant = 'body', helperText, helperIcon, validationStatus = 'initial', validText, invalidText, disabled = false, readonly = false, secureTextEntry = false, autoFocus = false, style, testID, ...props }, ref) => {
8
+ const VerificationInput = forwardRef(({ value = '', onChangeText, label, labelVariant = 'body', helperText, helperIcon, validationStatus = 'initial', validText, invalidText, disabled = false, readonly = false, secureTextEntry = false, autoFocus = false, style, ...props }, ref) => {
9
9
  const length = 6;
10
10
  const inputRef = useRef(null);
11
11
  const latestValueRef = useRef(value);
@@ -160,7 +160,7 @@ const VerificationInput = forwardRef(({ value = '', onChangeText, label, labelVa
160
160
  latestSelectionRef.current = nextSelection;
161
161
  setSelection(nextSelection);
162
162
  setFocusedIndex(Math.min(nextSelection.start, length - 1));
163
- }, onFocus: handleFocus, onBlur: handleBlur, selection: selection, keyboardType: "number-pad", textContentType: "oneTimeCode", autoComplete: "sms-otp", secureTextEntry: secureTextEntry, maxLength: length, caretHidden: true, style: styles.hiddenInput, testID: testID }), slots.map(index => {
163
+ }, onFocus: handleFocus, onBlur: handleBlur, selection: selection, keyboardType: "number-pad", textContentType: "oneTimeCode", autoComplete: "sms-otp", secureTextEntry: secureTextEntry, maxLength: length, caretHidden: true, style: styles.hiddenInput }), slots.map(index => {
164
164
  const char = displayValue[index] || '';
165
165
  const isActive = focusedIndex === index;
166
166
  const displayChar = secureTextEntry && char ? '*' : char;
@@ -168,7 +168,7 @@ const VerificationInput = forwardRef(({ value = '', onChangeText, label, labelVa
168
168
  pendingFocusIndexRef.current = index;
169
169
  inputRef.current?.focus();
170
170
  setSelectionIndex(index);
171
- }, testID: testID ? `${testID}-${index}` : undefined }, index));
171
+ } }, index));
172
172
  })] }) }));
173
173
  });
174
174
  const styles = StyleSheet.create(theme => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilitywarehouse/hearth-react-native",
3
- "version": "0.27.2-testid-fix-3",
3
+ "version": "0.27.3",
4
4
  "description": "Utility Warehouse React Native UI library",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -56,11 +56,11 @@
56
56
  "vite": "^7.1.3",
57
57
  "vite-plugin-svgr": "^4.5.0",
58
58
  "vitest": "^3.2.4",
59
- "@utilitywarehouse/hearth-tokens": "^0.2.4",
60
59
  "@utilitywarehouse/hearth-fonts": "^0.0.4",
61
60
  "@utilitywarehouse/hearth-react-icons": "^0.8.0",
61
+ "@utilitywarehouse/hearth-react-native-icons": "^0.8.0",
62
62
  "@utilitywarehouse/hearth-svg-assets": "^0.5.0",
63
- "@utilitywarehouse/hearth-react-native-icons": "^0.8.0"
63
+ "@utilitywarehouse/hearth-tokens": "^0.2.4"
64
64
  },
65
65
  "peerDependencies": {
66
66
  "@gorhom/bottom-sheet": "^5.0.0",
@@ -152,10 +152,6 @@ export interface SelectOptionProps {
152
152
  * Callback when this option is selected
153
153
  */
154
154
  onPress?: (value: string) => void;
155
- /**
156
- * Test ID for testing
157
- */
158
- testID?: string;
159
155
  }
160
156
 
161
157
  export default SelectProps;
@@ -40,7 +40,6 @@ const Select = ({
40
40
  listProps,
41
41
  searchable = false,
42
42
  searchPlaceholder = 'Search',
43
- testID,
44
43
  ...rest
45
44
  }: SelectProps) => {
46
45
  const formFieldContext = useFormFieldContext();
@@ -110,10 +109,9 @@ const Select = ({
110
109
  disabled={item.disabled}
111
110
  leadingIcon={item.leadingIcon}
112
111
  trailingIcon={item.trailingIcon}
113
- testID={testID ? `${testID}-option-${item.label}` : undefined} // ← restored
114
112
  />
115
113
  ),
116
- [testID] // ← added testID dependency
114
+ []
117
115
  );
118
116
 
119
117
  const renderEmptyComponent = useCallback(
@@ -142,7 +140,6 @@ const Select = ({
142
140
  <Pressable
143
141
  onPress={openBottomSheet}
144
142
  disabled={isDisabled || isReadonly}
145
- testID={testID}
146
143
  style={({ pressed }) => [
147
144
  styles.selectContainer,
148
145
  styles.pressedContainer(pressed || isOpen),
@@ -195,7 +192,6 @@ const Select = ({
195
192
  inBottomSheet
196
193
  onChangeText={setSearch}
197
194
  type="search"
198
- testID={testID ? `${testID}-search` : undefined}
199
195
  />
200
196
  </View>
201
197
  )}
@@ -208,7 +204,6 @@ const Select = ({
208
204
  keyExtractor={(option: any) => option.value}
209
205
  renderItem={renderSelectOption}
210
206
  ListEmptyComponent={renderEmptyComponent}
211
- testID={testID ? `${testID}-options` : undefined}
212
207
  {...listProps}
213
208
  />
214
209
  )}
@@ -14,7 +14,6 @@ const SelectOption = ({
14
14
  selected,
15
15
  disabled,
16
16
  onPress,
17
- testID,
18
17
  }: SelectOptionProps) => {
19
18
  const { selectedValue, onValueChange, close } = useSelectContext();
20
19
  const isSelected = selected !== undefined ? selected : selectedValue === value;
@@ -39,7 +38,6 @@ const SelectOption = ({
39
38
  <Pressable
40
39
  onPress={handlePress}
41
40
  disabled={disabled}
42
- testID={testID}
43
41
  style={({ pressed }) => [styles.container, pressed && styles.pressed]}
44
42
  >
45
43
  {!!LeftIcon && (
@@ -23,7 +23,6 @@ const VerificationInput = forwardRef<VerificationInputHandle, VerificationInputP
23
23
  secureTextEntry = false,
24
24
  autoFocus = false,
25
25
  style,
26
- testID,
27
26
  ...props
28
27
  },
29
28
  ref
@@ -240,7 +239,6 @@ const VerificationInput = forwardRef<VerificationInputHandle, VerificationInputP
240
239
  maxLength={length}
241
240
  caretHidden
242
241
  style={styles.hiddenInput}
243
- testID={testID}
244
242
  />
245
243
  {slots.map(index => {
246
244
  const char = displayValue[index] || '';
@@ -262,7 +260,6 @@ const VerificationInput = forwardRef<VerificationInputHandle, VerificationInputP
262
260
  inputRef.current?.focus();
263
261
  setSelectionIndex(index);
264
262
  }}
265
- testID={testID ? `${testID}-${index}` : undefined}
266
263
  />
267
264
  );
268
265
  })}
@@ -1,3 +0,0 @@
1
- export type Period = 'AM' | 'PM';
2
- declare const TimePicker: () => import("react/jsx-runtime").JSX.Element;
3
- export default TimePicker;
@@ -1,84 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import dayjs from 'dayjs';
3
- import { useCallback, useMemo } from 'react';
4
- import { ScrollView, View } from 'react-native';
5
- import { StyleSheet } from 'react-native-unistyles';
6
- import { BodyText } from '../BodyText';
7
- import { useDatePickerContext } from './DatePicker.context';
8
- import { CONTAINER_HEIGHT } from './enums';
9
- import PeriodPicker from './time-picker/period-picker';
10
- import Wheel from './time-picker/wheel';
11
- import { formatNumber, getParsedDate } from './utils';
12
- const createNumberList = (num, numerals, startFrom = 0) => {
13
- return Array.from({ length: num }, (_, i) => ({
14
- value: i + startFrom,
15
- text: i + startFrom < 10
16
- ? `${formatNumber(0, numerals)}${formatNumber(i + startFrom, numerals)}`
17
- : `${formatNumber(i + startFrom, numerals)}`,
18
- }));
19
- };
20
- const TimePicker = () => {
21
- const { currentDate, date, onSelectDate, timeZone, numerals = 'latn', use12Hours, } = useDatePickerContext();
22
- const hours = useMemo(() => createNumberList(use12Hours ? 12 : 24, numerals, use12Hours ? 1 : 0), [numerals, use12Hours]);
23
- const minutes = useMemo(() => createNumberList(60, numerals), [numerals]);
24
- const { hour, hour12, minute, period } = getParsedDate(date || currentDate);
25
- const handleChangeHour = useCallback((value) => {
26
- let hour24 = value;
27
- if (use12Hours) {
28
- if (period === 'AM' && value === 12) {
29
- hour24 = 0;
30
- }
31
- else if (period === 'PM' && value < 12) {
32
- hour24 = value + 12;
33
- }
34
- else {
35
- hour24 = value;
36
- }
37
- }
38
- const newDate = dayjs.tz(date, timeZone).hour(hour24).minute(minute);
39
- onSelectDate(newDate);
40
- }, [date, onSelectDate, timeZone, use12Hours, period, minute]);
41
- const handleChangeMinute = useCallback((value) => {
42
- const newDate = dayjs.tz(date, timeZone).minute(value);
43
- onSelectDate(newDate);
44
- }, [date, onSelectDate, timeZone]);
45
- const handlePeriodChange = useCallback((newPeriod) => {
46
- let newHour = hour12;
47
- if (newPeriod === 'PM' && hour12 < 12) {
48
- newHour = hour12 + 12;
49
- }
50
- else if (newPeriod === 'AM' && hour12 === 12) {
51
- newHour = 0;
52
- }
53
- else if (newPeriod === 'AM' && hour >= 12) {
54
- newHour = hour12;
55
- }
56
- const newDate = dayjs.tz(date || currentDate, timeZone).hour(newHour);
57
- onSelectDate(newDate);
58
- }, [date, currentDate, onSelectDate, timeZone, hour, hour12]);
59
- return (_jsxs(ScrollView, { horizontal: true, scrollEnabled: false, contentContainerStyle: styles.container, testID: "time-selector", children: [_jsxs(View, { style: styles.timePickerContainer, children: [_jsx(View, { style: styles.wheelContainer, children: _jsx(Wheel, { value: use12Hours ? hour12 : hour, items: hours, setValue: handleChangeHour }) }), _jsx(BodyText, { style: styles.timeSeparator, children: ":" }), _jsx(View, { style: styles.wheelContainer, children: _jsx(Wheel, { value: minute, items: minutes, setValue: handleChangeMinute }) })] }), use12Hours && period ? (_jsx(View, { style: styles.periodContainer, children: _jsx(PeriodPicker, { value: period, setValue: handlePeriodChange }) })) : null] }));
60
- };
61
- const styles = StyleSheet.create({
62
- container: {
63
- flex: 1,
64
- alignItems: 'center',
65
- justifyContent: 'center',
66
- },
67
- wheelContainer: {
68
- flex: 1,
69
- },
70
- timePickerContainer: {
71
- alignItems: 'center',
72
- justifyContent: 'center',
73
- width: CONTAINER_HEIGHT / 2,
74
- height: CONTAINER_HEIGHT / 2,
75
- flexDirection: 'row',
76
- },
77
- timeSeparator: {
78
- marginHorizontal: 5,
79
- },
80
- periodContainer: {
81
- marginLeft: 10,
82
- },
83
- });
84
- export default TimePicker;
@@ -1,4 +0,0 @@
1
- import { Animated } from 'react-native';
2
- declare function sin(animated: Animated.Animated): Animated.AnimatedAddition<string | number>;
3
- declare function normalize(animated: Animated.Animated): Animated.Animated;
4
- export { sin, normalize };
@@ -1,19 +0,0 @@
1
- import { Animated } from 'react-native';
2
- const FACTORIAL_3 = 3 * 2;
3
- const FACTORIAL_5 = 5 * 4 * FACTORIAL_3;
4
- const FACTORIAL_7 = 7 * 6 * FACTORIAL_5;
5
- function sin(animated) {
6
- const normalized = normalize(animated);
7
- const square = Animated.multiply(normalized, normalized);
8
- const pow3 = Animated.multiply(normalized, square);
9
- const pow5 = Animated.multiply(pow3, square);
10
- const pow7 = Animated.multiply(pow5, square);
11
- return Animated.add(Animated.add(normalized, Animated.multiply(pow3, -1 / FACTORIAL_3)), Animated.add(Animated.multiply(pow5, 1 / FACTORIAL_5), Animated.multiply(pow7, -1 / FACTORIAL_7)));
12
- }
13
- function normalize(animated) {
14
- return Animated.add(Animated.modulo(Animated.add(animated, Math.PI), Math.PI * 2), -Math.PI).interpolate({
15
- inputRange: [-Math.PI, -Math.PI / 2, Math.PI / 2, Math.PI],
16
- outputRange: [0, -Math.PI / 2, Math.PI / 2, 0],
17
- });
18
- }
19
- export { sin, normalize };
@@ -1,6 +0,0 @@
1
- interface PeriodProps {
2
- value: string;
3
- setValue?: (value: any) => void;
4
- }
5
- declare const _default: import("react").MemoExoticComponent<({ value, setValue }: PeriodProps) => import("react/jsx-runtime").JSX.Element>;
6
- export default _default;
@@ -1,17 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { memo } from 'react';
3
- import WheelPicker from './wheel-picker';
4
- const options = [
5
- { value: 'AM', text: 'AM' },
6
- { value: 'PM', text: 'PM' },
7
- ];
8
- const PeriodNative = ({ value, setValue = () => { } }) => {
9
- return (_jsx(WheelPicker, { value: value, options: options, onChange: setValue,
10
- //containerStyle={defaultStyles.container}
11
- itemHeight: 44, decelerationRate: "fast" }));
12
- };
13
- const customComparator = (prev, next) => {
14
- const areEqual = prev.value === next.value && prev.setValue === next.setValue;
15
- return areEqual;
16
- };
17
- export default memo(PeriodNative, customComparator);
@@ -1,6 +0,0 @@
1
- type PeriodProps = {
2
- value: string;
3
- setValue?: (value: any) => void;
4
- };
5
- declare const _default: import("react").MemoExoticComponent<(props: PeriodProps) => import("react/jsx-runtime").JSX.Element>;
6
- export default _default;
@@ -1,10 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { memo } from 'react';
3
- import { Platform } from 'react-native';
4
- import PeriodNative from './period-native';
5
- import PeriodWeb from './period-web';
6
- const PeriodPicker = (props) => {
7
- const Component = Platform.OS === 'web' ? PeriodWeb : PeriodNative;
8
- return _jsx(Component, { ...props });
9
- };
10
- export default memo(PeriodPicker);
@@ -1,6 +0,0 @@
1
- interface PeriodProps {
2
- value: string;
3
- setValue?: (value: any) => void;
4
- }
5
- declare const _default: import("react").MemoExoticComponent<({ value, setValue }: PeriodProps) => import("react/jsx-runtime").JSX.Element>;
6
- export default _default;
@@ -1,21 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { memo } from 'react';
3
- import { Pressable, View } from 'react-native';
4
- import { StyleSheet } from 'react-native-unistyles';
5
- import { BodyText } from '../../BodyText';
6
- const PeriodWeb = ({ value, setValue = () => { } }) => {
7
- return (_jsx(Pressable, { onPress: () => setValue(value == 'AM' ? 'PM' : 'AM'), children: _jsx(View, { style: [styles.period], children: _jsx(BodyText, { children: value }) }) }));
8
- };
9
- const styles = StyleSheet.create({
10
- period: {
11
- width: 65,
12
- height: 44,
13
- alignItems: 'center',
14
- justifyContent: 'center',
15
- },
16
- });
17
- const customComparator = (prev, next) => {
18
- const areEqual = prev.value === next.value && prev.setValue === next.setValue;
19
- return areEqual;
20
- };
21
- export default memo(PeriodWeb, customComparator);
@@ -1,8 +0,0 @@
1
- import { PickerOption } from '../DatePicker.props';
2
- interface WheelProps {
3
- value: number | string;
4
- setValue?: (value: any) => void;
5
- items: PickerOption[];
6
- }
7
- declare const _default: import("react").MemoExoticComponent<({ value, setValue, items }: WheelProps) => import("react/jsx-runtime").JSX.Element>;
8
- export default _default;
@@ -1,19 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { memo } from 'react';
3
- import { Platform } from 'react-native';
4
- import { StyleSheet } from 'react-native-unistyles';
5
- import WheelPicker from './wheel-picker';
6
- const WheelNative = ({ value, setValue = () => { }, items }) => {
7
- return (_jsx(WheelPicker, { value: value, options: items, onChange: setValue, containerStyle: styles.container, itemHeight: 44, decelerationRate: "fast" }));
8
- };
9
- const styles = StyleSheet.create({
10
- container: {
11
- display: 'flex',
12
- ...Platform.select({
13
- web: {
14
- userSelect: 'none',
15
- },
16
- }),
17
- },
18
- });
19
- export default memo(WheelNative);
@@ -1,2 +0,0 @@
1
- import WheelPicker from './wheel-picker';
2
- export default WheelPicker;
@@ -1,2 +0,0 @@
1
- import WheelPicker from './wheel-picker';
2
- export default WheelPicker;
@@ -1,16 +0,0 @@
1
- import React from 'react';
2
- import { Animated, StyleProp, ViewStyle } from 'react-native';
3
- import { PickerOption } from '../../DatePicker.props';
4
- interface ItemProps {
5
- style: StyleProp<ViewStyle>;
6
- option: PickerOption | null;
7
- height: number;
8
- index: number;
9
- currentScrollIndex: Animated.AnimatedAddition<number>;
10
- visibleRest: number;
11
- rotationFunction: (x: number) => number;
12
- opacityFunction: (x: number) => number;
13
- scaleFunction: (x: number) => number;
14
- }
15
- declare const _default: React.NamedExoticComponent<ItemProps>;
16
- export default _default;
@@ -1,97 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import React from 'react';
3
- import { Animated } from 'react-native';
4
- import { BodyText } from '../../../BodyText';
5
- import styles from './wheel-picker.style';
6
- const WheelPickerItem = ({ style, height, option, index, visibleRest, currentScrollIndex, opacityFunction, rotationFunction, scaleFunction, }) => {
7
- const relativeScrollIndex = Animated.subtract(index, currentScrollIndex);
8
- const translateY = relativeScrollIndex.interpolate({
9
- inputRange: (() => {
10
- const range = [0];
11
- for (let i = 1; i <= visibleRest + 1; i++) {
12
- range.unshift(-i);
13
- range.push(i);
14
- }
15
- return range;
16
- })(),
17
- outputRange: (() => {
18
- const range = [0];
19
- for (let i = 1; i <= visibleRest + 1; i++) {
20
- let y = (height / 2) * (1 - Math.sin(Math.PI / 2 - rotationFunction(i)));
21
- for (let j = 1; j < i; j++) {
22
- y += height * (1 - Math.sin(Math.PI / 2 - rotationFunction(j)));
23
- }
24
- range.unshift(y);
25
- range.push(-y);
26
- }
27
- return range;
28
- })(),
29
- });
30
- const opacity = relativeScrollIndex.interpolate({
31
- inputRange: (() => {
32
- const range = [0];
33
- for (let i = 1; i <= visibleRest + 1; i++) {
34
- range.unshift(-i);
35
- range.push(i);
36
- }
37
- return range;
38
- })(),
39
- outputRange: (() => {
40
- const range = [1];
41
- for (let x = 1; x <= visibleRest + 1; x++) {
42
- const y = opacityFunction(x);
43
- range.unshift(y);
44
- range.push(y);
45
- }
46
- return range;
47
- })(),
48
- });
49
- const scale = relativeScrollIndex.interpolate({
50
- inputRange: (() => {
51
- const range = [0];
52
- for (let i = 1; i <= visibleRest + 1; i++) {
53
- range.unshift(-i);
54
- range.push(i);
55
- }
56
- return range;
57
- })(),
58
- outputRange: (() => {
59
- const range = [1.0];
60
- for (let x = 1; x <= visibleRest + 1; x++) {
61
- const y = scaleFunction(x);
62
- range.unshift(y);
63
- range.push(y);
64
- }
65
- return range;
66
- })(),
67
- });
68
- const rotateX = relativeScrollIndex.interpolate({
69
- inputRange: (() => {
70
- const range = [0];
71
- for (let i = 1; i <= visibleRest + 1; i++) {
72
- range.unshift(-i);
73
- range.push(i);
74
- }
75
- return range;
76
- })(),
77
- outputRange: (() => {
78
- const range = ['0deg'];
79
- for (let x = 1; x <= visibleRest + 1; x++) {
80
- const y = rotationFunction(x);
81
- range.unshift(`${y}deg`);
82
- range.push(`${y}deg`);
83
- }
84
- return range;
85
- })(),
86
- });
87
- return (_jsx(Animated.View, { style: [
88
- styles.option,
89
- style,
90
- {
91
- height,
92
- opacity,
93
- transform: [{ translateY }, { rotateX }, { scale }],
94
- },
95
- ], children: _jsx(BodyText, { children: option?.text }) }));
96
- };
97
- export default React.memo(WheelPickerItem);
@@ -1,21 +0,0 @@
1
- import React from 'react';
2
- import { FlatListProps, StyleProp, ViewProps, ViewStyle } from 'react-native';
3
- import { PickerOption } from '../../DatePicker.props';
4
- interface Props {
5
- value: number | string;
6
- options: PickerOption[];
7
- onChange: (index: number | string) => void;
8
- selectedIndicatorStyle?: StyleProp<ViewStyle>;
9
- itemStyle?: ViewStyle;
10
- itemHeight?: number;
11
- containerStyle?: ViewStyle;
12
- containerProps?: Omit<ViewProps, 'style'>;
13
- scaleFunction?: (x: number) => number;
14
- rotationFunction?: (x: number) => number;
15
- opacityFunction?: (x: number) => number;
16
- visibleRest?: number;
17
- decelerationRate?: 'normal' | 'fast' | number;
18
- flatListProps?: Omit<FlatListProps<PickerOption | null>, 'data' | 'renderItem'>;
19
- }
20
- declare const _default: React.NamedExoticComponent<Props>;
21
- export default _default;
@@ -1,88 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { memo, useEffect, useMemo, useRef, useState } from 'react';
3
- import { Animated, Platform, View, } from 'react-native';
4
- import WheelPickerItem from './wheel-picker-item';
5
- import styles from './wheel-picker.style';
6
- const WheelPicker = ({ value, options, onChange, selectedIndicatorStyle = {}, containerStyle = {}, itemStyle = {}, itemHeight = 40, scaleFunction = (x) => 1.0 ** x, rotationFunction = (x) => 1 - Math.pow(1 / 2, x), opacityFunction = (x) => Math.pow(1 / 3, x), visibleRest = 2, decelerationRate = 'normal', containerProps = {}, flatListProps = {}, }) => {
7
- const momentumStarted = useRef(false);
8
- const selectedIndex = options.findIndex(item => item.value === value);
9
- const flatListRef = useRef(null);
10
- const [scrollY] = useState(new Animated.Value(selectedIndex * itemHeight));
11
- const containerHeight = (1 + visibleRest * 2) * itemHeight;
12
- const paddedOptions = useMemo(() => {
13
- const array = [...options];
14
- for (let i = 0; i < visibleRest; i++) {
15
- array.unshift(null);
16
- array.push(null);
17
- }
18
- return array;
19
- }, [options, visibleRest]);
20
- const offsets = useMemo(() => [...Array(paddedOptions.length)].map((_, i) => i * itemHeight), [paddedOptions, itemHeight]);
21
- const currentScrollIndex = useMemo(() => Animated.add(Animated.divide(scrollY, itemHeight), visibleRest), [visibleRest, scrollY, itemHeight]);
22
- const handleScrollEnd = (event) => {
23
- const offsetY = Math.min(itemHeight * (options.length - 1), Math.max(event.nativeEvent.contentOffset.y, 0));
24
- let index = Math.floor(offsetY / itemHeight);
25
- const remainder = offsetY % itemHeight;
26
- if (remainder > itemHeight / 2) {
27
- index++;
28
- }
29
- if (index !== selectedIndex) {
30
- onChange(options[index]?.value || 0);
31
- }
32
- };
33
- const handleMomentumScrollBegin = () => {
34
- momentumStarted.current = true;
35
- };
36
- const handleMomentumScrollEnd = (event) => {
37
- momentumStarted.current = false;
38
- handleScrollEnd(event);
39
- };
40
- const handleScrollEndDrag = (event) => {
41
- // Capture the offset value immediately
42
- const offsetY = event.nativeEvent.contentOffset?.y;
43
- // We'll start a short timer to see if momentum scroll begins
44
- setTimeout(() => {
45
- // If momentum scroll hasn't started within the timeout,
46
- // then it was a slow scroll that won't trigger momentum
47
- if (!momentumStarted.current && offsetY !== undefined) {
48
- // Create a synthetic event with just the data we need
49
- const syntheticEvent = {
50
- nativeEvent: {
51
- contentOffset: { y: offsetY },
52
- },
53
- };
54
- handleScrollEnd(syntheticEvent);
55
- }
56
- }, 50);
57
- };
58
- useEffect(() => {
59
- if (selectedIndex < 0 || selectedIndex >= options.length) {
60
- throw new Error(`Selected index ${selectedIndex} is out of bounds [0, ${options.length - 1}]`);
61
- }
62
- }, [selectedIndex, options]);
63
- /**
64
- * If selectedIndex is changed from outside (not via onChange) we need to scroll to the specified index.
65
- * This ensures that what the user sees as selected in the picker always corresponds to the value state.
66
- */
67
- useEffect(() => {
68
- flatListRef.current?.scrollToIndex({
69
- index: selectedIndex,
70
- animated: Platform.OS === 'ios',
71
- });
72
- }, [selectedIndex, itemHeight]);
73
- return (_jsxs(View, { style: [styles.container, { height: containerHeight }, containerStyle], ...containerProps, children: [_jsx(View, { style: [
74
- styles.selectedIndicator,
75
- selectedIndicatorStyle,
76
- {
77
- transform: [{ translateY: -itemHeight / 2 }],
78
- height: itemHeight,
79
- },
80
- ] }), _jsx(Animated.FlatList, { ...flatListProps, ref: flatListRef, nestedScrollEnabled: true, style: styles.scrollView, showsVerticalScrollIndicator: false, onScroll: Animated.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], {
81
- useNativeDriver: true,
82
- }), onScrollEndDrag: handleScrollEndDrag, onMomentumScrollBegin: handleMomentumScrollBegin, onMomentumScrollEnd: handleMomentumScrollEnd, snapToOffsets: offsets, decelerationRate: decelerationRate, initialScrollIndex: selectedIndex, getItemLayout: (_, index) => ({
83
- length: itemHeight,
84
- offset: itemHeight * index,
85
- index,
86
- }), data: paddedOptions, keyExtractor: (item, index) => item ? `${item.value}-${item.text}-${index}` : `null-${index}`, renderItem: ({ item: option, index }) => (_jsx(WheelPickerItem, { index: index, option: option, style: itemStyle, height: itemHeight, currentScrollIndex: currentScrollIndex, scaleFunction: scaleFunction, rotationFunction: rotationFunction, opacityFunction: opacityFunction, visibleRest: visibleRest }, `option-${index}`)) })] }));
87
- };
88
- export default memo(WheelPicker);
@@ -1,23 +0,0 @@
1
- declare const _default: {
2
- container: {
3
- position: "relative";
4
- };
5
- selectedIndicator: {
6
- position: "absolute";
7
- width: "100%";
8
- top: "50%";
9
- };
10
- scrollView: {
11
- overflow: "hidden";
12
- flex: number;
13
- };
14
- option: {
15
- alignItems: "center";
16
- justifyContent: "center";
17
- paddingHorizontal: number;
18
- zIndex: number;
19
- };
20
- } & {
21
- useVariants: (variants: never) => void;
22
- };
23
- export default _default;
@@ -1,21 +0,0 @@
1
- import { StyleSheet } from 'react-native-unistyles';
2
- export default StyleSheet.create({
3
- container: {
4
- position: 'relative',
5
- },
6
- selectedIndicator: {
7
- position: 'absolute',
8
- width: '100%',
9
- top: '50%',
10
- },
11
- scrollView: {
12
- overflow: 'hidden',
13
- flex: 1,
14
- },
15
- option: {
16
- alignItems: 'center',
17
- justifyContent: 'center',
18
- paddingHorizontal: 16,
19
- zIndex: 100,
20
- },
21
- });
@@ -1,8 +0,0 @@
1
- import { PickerOption } from '../DatePicker.props';
2
- interface WheelProps {
3
- value: number | string;
4
- setValue?: (value: any) => void;
5
- items: PickerOption[];
6
- }
7
- declare const _default: import("react").MemoExoticComponent<({ value, setValue, items }: WheelProps) => import("react/jsx-runtime").JSX.Element>;
8
- export default _default;
@@ -1,146 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { memo, useMemo, useRef } from 'react';
3
- import { Animated, PanResponder, Platform, View } from 'react-native';
4
- import { StyleSheet } from 'react-native-unistyles';
5
- import { isEqual } from '../../../utils';
6
- import { BodyText } from '../../BodyText';
7
- import { CONTAINER_HEIGHT } from '../enums';
8
- import { sin } from './animated-math';
9
- const ITEM_HEIGHT = 44;
10
- const WheelWeb = ({ value, setValue = () => { }, items }) => {
11
- const displayCount = 5;
12
- const translateY = useRef(new Animated.Value(0)).current;
13
- const renderCount = displayCount * 2 < items.length ? displayCount * 8 : displayCount * 2 - 1;
14
- const circular = items.length >= displayCount;
15
- const height = 140;
16
- const radius = height / 2;
17
- const valueIndex = useMemo(() => {
18
- return Math.max(0, items.findIndex(item => item.value === value));
19
- }, [items, value]);
20
- const panResponder = useMemo(() => {
21
- return PanResponder.create({
22
- onMoveShouldSetPanResponder: () => true,
23
- onStartShouldSetPanResponderCapture: () => true,
24
- onPanResponderGrant: () => {
25
- translateY.setValue(0);
26
- },
27
- onPanResponderMove: (evt, gestureState) => {
28
- translateY.setValue(gestureState.dy);
29
- evt.stopPropagation();
30
- },
31
- onPanResponderRelease: (_, gestureState) => {
32
- translateY.extractOffset();
33
- let newValueIndex = valueIndex - Math.round(gestureState.dy / ((radius * 2) / displayCount));
34
- if (circular) {
35
- newValueIndex = (newValueIndex + items.length) % items.length;
36
- }
37
- else {
38
- if (newValueIndex < 0) {
39
- newValueIndex = 0;
40
- }
41
- else if (newValueIndex >= items.length) {
42
- newValueIndex = items.length - 1;
43
- }
44
- }
45
- const newValue = items[newValueIndex];
46
- if (newValue?.value === value) {
47
- translateY.setOffset(0);
48
- translateY.setValue(0);
49
- }
50
- else if (newValue?.value) {
51
- setValue(newValue.value);
52
- }
53
- else if (items[0]?.value) {
54
- setValue(items[0].value);
55
- }
56
- },
57
- });
58
- }, [circular, displayCount, radius, setValue, value, valueIndex, items, translateY]);
59
- const displayValues = useMemo(() => {
60
- const centerIndex = Math.floor(renderCount / 2);
61
- return Array.from({ length: renderCount }, (_, index) => {
62
- let targetIndex = valueIndex + index - centerIndex;
63
- if (circular) {
64
- targetIndex = ((targetIndex % items.length) + items.length) % items.length;
65
- }
66
- else {
67
- targetIndex = Math.max(0, Math.min(targetIndex, items.length - 1));
68
- }
69
- return items[targetIndex] || items[0];
70
- });
71
- }, [renderCount, valueIndex, items, circular]);
72
- const animatedAngles = useMemo(() => {
73
- //translateY.setValue(0);
74
- translateY.setOffset(0);
75
- const currentIndex = displayValues.findIndex(item => item?.value === value);
76
- return displayValues && displayValues.length > 0
77
- ? displayValues.map((_, index) => translateY
78
- .interpolate({
79
- inputRange: [-radius, radius],
80
- outputRange: [
81
- -radius + ((radius * 2) / displayCount) * (index - currentIndex),
82
- radius + ((radius * 2) / displayCount) * (index - currentIndex),
83
- ],
84
- extrapolate: 'extend',
85
- })
86
- .interpolate({
87
- inputRange: [-radius, radius],
88
- outputRange: [-Math.PI / 2, Math.PI / 2],
89
- extrapolate: 'clamp',
90
- }))
91
- : [];
92
- }, [displayValues, radius, value, displayCount, translateY]);
93
- return (_jsxs(View, { style: [styles.container], ...panResponder.panHandlers, children: [_jsx(View, { style: [
94
- styles.selectedIndicator,
95
- {
96
- transform: [{ translateY: -ITEM_HEIGHT / 2 }],
97
- height: ITEM_HEIGHT,
98
- },
99
- ] }), displayValues?.map((displayValue, index) => {
100
- const animatedAngle = animatedAngles[index];
101
- return (_jsx(Animated.View, { style: {
102
- position: 'absolute',
103
- height: ITEM_HEIGHT - 10,
104
- transform: animatedAngle
105
- ? [
106
- {
107
- translateY: Animated.multiply(radius, sin(animatedAngle)),
108
- },
109
- {
110
- rotateX: animatedAngle.interpolate({
111
- inputRange: [-Math.PI / 2, Math.PI / 2],
112
- outputRange: ['-89deg', '89deg'],
113
- extrapolate: 'clamp',
114
- }),
115
- },
116
- ]
117
- : [],
118
- opacity: displayValue?.value !== value ? 0.3 : 1,
119
- }, children: _jsx(BodyText, { children: displayValue?.text }) }, `${displayValue?.text}-${index}`));
120
- })] }));
121
- };
122
- const styles = StyleSheet.create({
123
- container: {
124
- minWidth: 30,
125
- overflow: 'hidden',
126
- alignItems: 'center',
127
- justifyContent: 'center',
128
- height: CONTAINER_HEIGHT / 2,
129
- ...Platform.select({
130
- web: {
131
- cursor: 'pointer',
132
- userSelect: 'none',
133
- },
134
- }),
135
- },
136
- selectedIndicator: {
137
- position: 'absolute',
138
- width: '100%',
139
- top: '50%',
140
- },
141
- });
142
- const customComparator = (prev, next) => {
143
- const areEqual = prev.value === next.value && prev.setValue === next.setValue && isEqual(prev.items, next.items);
144
- return areEqual;
145
- };
146
- export default memo(WheelWeb, customComparator);
@@ -1,8 +0,0 @@
1
- import { PickerOption } from '../DatePicker.props';
2
- type WheelProps = {
3
- value: number | string;
4
- setValue?: (value: any) => void;
5
- items: PickerOption[];
6
- };
7
- declare const _default: import("react").MemoExoticComponent<(props: WheelProps) => import("react/jsx-runtime").JSX.Element>;
8
- export default _default;
@@ -1,10 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { memo } from 'react';
3
- import { Platform } from 'react-native';
4
- import WheelNative from './wheel-native';
5
- import WheelWeb from './wheel-web';
6
- const Wheel = (props) => {
7
- const Component = Platform.OS === 'web' ? WheelWeb : WheelNative;
8
- return _jsx(Component, { ...props });
9
- };
10
- export default memo(Wheel);