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

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 (44) hide show
  1. package/.turbo/turbo-build.log +4 -5
  2. package/.turbo/turbo-lint.log +69 -0
  3. package/build/components/Button/ButtonRoot.js +0 -8
  4. package/build/components/List/List.js +2 -2
  5. package/build/components/Modal/Modal.js +11 -16
  6. package/build/components/Select/Select.d.ts +1 -1
  7. package/build/components/Select/Select.js +4 -5
  8. package/build/components/Select/Select.props.d.ts +0 -4
  9. package/build/components/Select/SelectOption.d.ts +1 -1
  10. package/build/components/Select/SelectOption.js +2 -2
  11. package/build/components/VerificationInput/VerificationInput.js +3 -3
  12. package/package.json +3 -3
  13. package/src/components/Button/Button.stories.tsx +7 -43
  14. package/src/components/Button/ButtonRoot.tsx +0 -8
  15. package/src/components/List/List.tsx +4 -5
  16. package/src/components/Modal/Modal.tsx +16 -31
  17. package/src/components/Select/Select.props.ts +0 -4
  18. package/src/components/Select/Select.tsx +1 -6
  19. package/src/components/Select/SelectOption.tsx +0 -2
  20. package/src/components/VerificationInput/VerificationInput.tsx +0 -3
  21. package/build/components/DatePicker/TimePicker.d.ts +0 -3
  22. package/build/components/DatePicker/TimePicker.js +0 -84
  23. package/build/components/DatePicker/time-picker/animated-math.d.ts +0 -4
  24. package/build/components/DatePicker/time-picker/animated-math.js +0 -19
  25. package/build/components/DatePicker/time-picker/period-native.d.ts +0 -6
  26. package/build/components/DatePicker/time-picker/period-native.js +0 -17
  27. package/build/components/DatePicker/time-picker/period-picker.d.ts +0 -6
  28. package/build/components/DatePicker/time-picker/period-picker.js +0 -10
  29. package/build/components/DatePicker/time-picker/period-web.d.ts +0 -6
  30. package/build/components/DatePicker/time-picker/period-web.js +0 -21
  31. package/build/components/DatePicker/time-picker/wheel-native.d.ts +0 -8
  32. package/build/components/DatePicker/time-picker/wheel-native.js +0 -19
  33. package/build/components/DatePicker/time-picker/wheel-picker/index.d.ts +0 -2
  34. package/build/components/DatePicker/time-picker/wheel-picker/index.js +0 -2
  35. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.d.ts +0 -16
  36. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.js +0 -97
  37. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.d.ts +0 -21
  38. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.js +0 -88
  39. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.d.ts +0 -23
  40. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.js +0 -21
  41. package/build/components/DatePicker/time-picker/wheel-web.d.ts +0 -8
  42. package/build/components/DatePicker/time-picker/wheel-web.js +0 -146
  43. package/build/components/DatePicker/time-picker/wheel.d.ts +0 -8
  44. 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.2 build /home/runner/work/hearth/hearth/packages/react-native
3
+ > tsc
4
+
@@ -0,0 +1,69 @@
1
+
2
+ > @utilitywarehouse/hearth-react-native@0.27.2 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
+ 86: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
+ 313: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 | 1502.050 | 59.5%
61
+ react-hooks/exhaustive-deps | 121.560 | 4.8%
62
+ react-hooks/rules-of-hooks | 110.933 | 4.4%
63
+ no-global-assign | 82.813 | 3.3%
64
+ @typescript-eslint/ban-ts-comment | 53.232 | 2.1%
65
+ @typescript-eslint/triple-slash-reference | 44.665 | 1.8%
66
+ no-unexpected-multiline | 38.719 | 1.5%
67
+ no-misleading-character-class | 38.467 | 1.5%
68
+ no-loss-of-precision | 30.881 | 1.2%
69
+ no-useless-backreference | 26.745 | 1.1%
@@ -108,14 +108,6 @@ const styles = StyleSheet.create(theme => ({
108
108
  paddingHorizontal: 0,
109
109
  },
110
110
  },
111
- {
112
- size: 'md',
113
- paddingNone: true,
114
- variant: 'ghost',
115
- styles: {
116
- paddingHorizontal: 0,
117
- },
118
- },
119
111
  // Variant Color Schemes
120
112
  // Emphasis
121
113
  // Emphasis Yellow
@@ -6,7 +6,7 @@ import { Card } from '../Card';
6
6
  import { SectionHeader } from '../SectionHeader';
7
7
  import { ListContext } from './List.context';
8
8
  const List = ({ children, heading, helperText, headerTrailingContent, invalidText, ...props }) => {
9
- const { loading, disabled, container = 'none', testID, style, ...rest } = props;
9
+ const { loading, disabled, container = 'none' } = props;
10
10
  const orderRef = useRef([]);
11
11
  const [firstItemId, setFirstItemId] = useState(undefined);
12
12
  const containerToCard = {
@@ -35,7 +35,7 @@ const List = ({ children, heading, helperText, headerTrailingContent, invalidTex
35
35
  registerItem,
36
36
  };
37
37
  styles.useVariants({ disabled });
38
- return (_jsx(ListContext.Provider, { value: value, children: _jsxs(View, { ...rest, style: [styles.container, style], children: [heading ? (_jsx(SectionHeader, { heading: heading, helperText: helperText, trailingContent: headerTrailingContent, invalidText: invalidText })) : null, container === 'none' ? (_jsx(View, { testID: testID, children: children })) : (React.Children.count(children) > 0 && (_jsx(Card, { ...containerToCard, noPadding: true, style: styles.card, testID: testID, children: _jsx(_Fragment, { children: children }) })))] }) }));
38
+ return (_jsx(ListContext.Provider, { value: value, children: _jsxs(View, { ...props, style: [styles.container, props.style], children: [heading ? (_jsx(SectionHeader, { heading: heading, helperText: helperText, trailingContent: headerTrailingContent, invalidText: invalidText })) : null, container === 'none' ? (_jsx(View, { children: children })) : (React.Children.count(children) > 0 && (_jsx(Card, { ...containerToCard, noPadding: true, style: styles.card, children: _jsx(_Fragment, { children: children }) })))] }) }));
39
39
  };
40
40
  List.displayName = 'List';
41
41
  const styles = StyleSheet.create(theme => ({
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { BottomSheetFooter, } from '@gorhom/bottom-sheet';
3
3
  import { CloseMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
4
4
  import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
5
- import { AccessibilityInfo, Dimensions, Platform, ScrollView, View, findNodeHandle, } from 'react-native';
5
+ import { AccessibilityInfo, Dimensions, Platform, ScrollView, View, findNodeHandle } from 'react-native';
6
6
  import Animated, { Easing, useAnimatedStyle, useSharedValue, withDelay, withTiming, } from 'react-native-reanimated';
7
7
  import { StyleSheet } from 'react-native-unistyles';
8
8
  import { useTheme } from '../../hooks';
@@ -120,12 +120,7 @@ const Modal = ({ ref, children, heading, description, showCloseButton = true, pr
120
120
  });
121
121
  const footer = (_jsxs(View, { style: styles.footer, children: [onPressPrimaryButton && primaryButtonText ? (_jsx(Button, { onPress: handlePrimaryButtonPress, text: primaryButtonText, inverted: isBrandBackground && inNavModal, ...primaryButtonProps, variant: primaryButtonProps?.variant ?? 'solid', colorScheme: primaryButtonProps?.colorScheme ?? 'highlight' })) : null, onPressSecondaryButton && secondaryButtonText ? (_jsx(Button, { onPress: handleSecondaryButtonPress, text: secondaryButtonText, inverted: isBrandBackground && inNavModal, ...secondaryButtonProps, variant: secondaryButtonProps?.variant ?? 'outline', colorScheme: secondaryButtonProps?.colorScheme ?? 'functional' })) : null] }));
122
122
  const InNavModalContainer = scrollable ? ScrollView : View;
123
- const content = (_jsx(_Fragment, { children: loading ? (_jsxs(View, { style: styles.loadingContainer, accessible: Platform.OS === 'android' ? true : undefined, accessibilityLabel: Platform.OS === 'android' ? 'Loading' : undefined, screenReaderFocusable: true, ref: viewRef, children: [_jsx(Spinner, { size: "lg", color: isBrandBackground && inNavModal ? theme.color.icon.inverted : undefined }), _jsx(Heading, { size: "lg", textAlign: "center", inverted: isBrandBackground && inNavModal, children: loadingHeading })] })) : (_jsxs(View, { style: styles.container, accessible: Platform.OS === 'android' ? true : undefined, accessibilityLabel: Platform.OS === 'android' ? 'Modal content' : undefined, screenReaderFocusable: true, ref: viewRef, children: [_jsxs(View, { style: styles.header, children: [_jsxs(View, { style: styles.headerTextContent, children: [heading && !image ? (_jsx(Heading, { size: "lg", accessible: true, inverted: isBrandBackground && inNavModal, children: heading })) : null, description && !image ? (_jsx(BodyText, { accessible: true, inverted: isBrandBackground && inNavModal, children: description })) : null] }), showCloseButton ? (_jsx(UnstyledIconButton, { icon: CloseMediumIcon, onPress: handleCloseButtonPress, accessibilityLabel: "Close modal", inverted: isBrandBackground && inNavModal, ...closeButtonProps })) : null] }), image ? (_jsxs(View, { style: styles.imageContainer, children: [image, _jsxs(View, { style: styles.textContent, children: [heading ? (_jsx(Heading, { size: "lg", textAlign: "center", accessible: true, inverted: isBrandBackground && inNavModal, children: heading })) : null, description ? (_jsx(BodyText, { textAlign: "center", accessible: true, inverted: isBrandBackground && inNavModal, children: description })) : null] })] })) : null, inNavModal && (_jsxs(InNavModalContainer, { style: {
124
- flex: stickyFooter ? 1 : 0,
125
- ...(scrollable ? { marginHorizontal: -1 } : {}),
126
- }, ...(scrollable ? { contentContainerStyle: { paddingHorizontal: 1 } } : {}), children: [children, !stickyFooter ? (_jsx(View, { style: styles.inNavModalFooterContainer, children: footer })) : null] })), !inNavModal && children, ((!stickyFooter && !inNavModal) || (inNavModal && stickyFooter)) && !noButtons
127
- ? footer
128
- : null] })) }));
123
+ const content = (_jsx(_Fragment, { children: loading ? (_jsxs(View, { style: styles.loadingContainer, accessible: Platform.OS === 'android' ? true : undefined, accessibilityLabel: Platform.OS === 'android' ? 'Loading' : undefined, screenReaderFocusable: true, ref: viewRef, children: [_jsx(Spinner, { size: "lg", color: isBrandBackground && inNavModal ? theme.color.icon.inverted : undefined }), _jsx(Heading, { size: "lg", textAlign: "center", inverted: isBrandBackground && inNavModal, children: loadingHeading })] })) : (_jsxs(View, { style: styles.container, accessible: Platform.OS === 'android' ? true : undefined, accessibilityLabel: Platform.OS === 'android' ? 'Modal content' : undefined, screenReaderFocusable: true, ref: viewRef, children: [_jsxs(View, { style: styles.header, children: [_jsxs(View, { style: styles.headerTextContent, children: [heading && !image ? (_jsx(Heading, { size: "lg", accessible: true, inverted: isBrandBackground && inNavModal, children: heading })) : null, description && !image ? (_jsx(BodyText, { accessible: true, inverted: isBrandBackground && inNavModal, children: description })) : null] }), showCloseButton ? (_jsx(UnstyledIconButton, { icon: CloseMediumIcon, onPress: handleCloseButtonPress, accessibilityLabel: "Close modal", inverted: isBrandBackground && inNavModal, ...closeButtonProps })) : null] }), image ? (_jsxs(View, { style: styles.imageContainer, children: [image, _jsxs(View, { style: styles.textContent, children: [heading ? (_jsx(Heading, { size: "lg", textAlign: "center", accessible: true, inverted: isBrandBackground && inNavModal, children: heading })) : null, description ? (_jsx(BodyText, { textAlign: "center", accessible: true, inverted: isBrandBackground && inNavModal, children: description })) : null] })] })) : null, inNavModal && (_jsxs(InNavModalContainer, { style: { flex: stickyFooter ? 1 : 0 }, children: [children, !stickyFooter ? _jsx(View, { style: styles.inNavModalFooterContainer, children: footer }) : null] })), !inNavModal && children, ((!stickyFooter && !inNavModal) || (inNavModal && stickyFooter)) && !noButtons ? footer : null] })) }));
129
124
  const renderFooter = useCallback((props) => (_jsx(BottomSheetFooter, { ...props, children: _jsx(View, { style: styles.footerWrap, children: footer }) })), [
130
125
  onPressPrimaryButton,
131
126
  primaryButtonText,
@@ -134,7 +129,7 @@ const Modal = ({ ref, children, heading, description, showCloseButton = true, pr
134
129
  primaryButtonProps,
135
130
  secondaryButtonProps,
136
131
  ]);
137
- return inNavModal ? (_jsxs(View, { onLayout: e => {
132
+ return inNavModal ? (_jsxs(View, { onLayout: (e) => {
138
133
  setInNavModalHeight(e.nativeEvent.layout.height);
139
134
  }, style: {
140
135
  flex: 1,
@@ -245,7 +240,7 @@ const styles = StyleSheet.create((theme, rt) => ({
245
240
  borderTopLeftRadius: theme.components.modal.borderRadius,
246
241
  borderTopRightRadius: theme.components.modal.borderRadius,
247
242
  backgroundColor: theme.color.surface.neutral.strong,
248
- paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
243
+ paddingBottom: theme.components.modal.padding + rt.insets.bottom,
249
244
  variants: {
250
245
  background: {
251
246
  primary: {},
@@ -255,22 +250,22 @@ const styles = StyleSheet.create((theme, rt) => ({
255
250
  },
256
251
  fullscreen: {
257
252
  true: {
258
- padding: theme.components.bottomSheet.padding,
253
+ padding: theme.components.modal.padding,
259
254
  paddingTop: rt.insets.top,
260
255
  },
261
256
  false: {
262
- padding: theme.components.bottomSheet.padding,
263
- },
264
- },
257
+ padding: theme.components.modal.padding,
258
+ }
259
+ }
265
260
  },
266
261
  },
267
262
  inNavModalFooterContainer: {
268
- paddingTop: theme.components.bottomSheet.padding,
263
+ paddingTop: theme.components.modal.padding,
269
264
  },
270
265
  androidContainer: {
271
266
  height: rt.insets.top + 18,
272
- paddingLeft: theme.components.bottomSheet.padding,
273
- paddingRight: theme.components.bottomSheet.padding,
267
+ paddingLeft: theme.components.modal.padding,
268
+ paddingRight: theme.components.modal.padding,
274
269
  justifyContent: 'flex-end',
275
270
  },
276
271
  pretendContent: {
@@ -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.2",
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",
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react-native';
1
+ import { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import * as Icons from '@utilitywarehouse/hearth-react-native-icons';
3
3
  import { AddSmallIcon, ChevronRightSmallIcon } from '@utilitywarehouse/hearth-react-native-icons';
4
4
  import { Platform } from 'react-native';
@@ -92,7 +92,7 @@ type Story = StoryObj<typeof meta>;
92
92
 
93
93
  export const Playground: Story = {
94
94
  /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
95
- render: ({ icon: _icon, children: _, ...args }: StoryObj<typeof meta.args>) => {
95
+ render: ({ icon: _icon, children: _, ...args }) => {
96
96
  // @ts-expect-error - This is a playground
97
97
  const icon = _icon === 'none' ? undefined : Icons[_icon];
98
98
  return <Button {...args} icon={icon} />;
@@ -104,7 +104,7 @@ export const Variants: Story = {
104
104
  controls: { exclude: ['variant'] },
105
105
  },
106
106
  /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
107
- render: ({ icon: _icon, children: _, ...args }: StoryObj<typeof meta.args>) => {
107
+ render: ({ icon: _icon, children: _, ...args }) => {
108
108
  // @ts-expect-error - This is a playground
109
109
  const icon = _icon === 'none' ? undefined : Icons[_icon];
110
110
  return (
@@ -123,9 +123,11 @@ export const Variants: Story = {
123
123
  {args.colorScheme !== 'highlight' && (
124
124
  <>
125
125
  <VariantTitle title="Outline" invert={args.inverted}>
126
+ {/* @ts-expect-error - story loop types don't match */}
126
127
  <Button {...args} variant="outline" icon={icon} />
127
128
  </VariantTitle>
128
129
  <VariantTitle title="Ghost" invert={args.inverted}>
130
+ {/* @ts-expect-error - story loop types don't match */}
129
131
  <Button {...args} variant="ghost" icon={icon} />
130
132
  </VariantTitle>
131
133
  </>
@@ -136,44 +138,6 @@ export const Variants: Story = {
136
138
  },
137
139
  };
138
140
 
139
- export const PaddingNone: Story = {
140
- parameters: {
141
- controls: {
142
- include: ['text', 'size', 'inverted', 'icon', 'iconPosition'],
143
- },
144
- },
145
- /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
146
- render: ({ icon: _icon, children: _, ...args }: StoryObj<typeof meta.args>) => {
147
- // @ts-expect-error - This is a playground
148
- const icon = _icon === 'none' ? undefined : Icons[_icon];
149
-
150
- return (
151
- <Flex direction="column" spacing="lg">
152
- <VariantTitle title="Default Padding" invert={args.inverted}>
153
- <Flex direction="row" align="center" spacing="none">
154
- <Box backgroundColor="brand" width="100" height="100" />
155
- <Button
156
- {...args}
157
- colorScheme="functional"
158
- variant="ghost"
159
- icon={icon}
160
- paddingNone={false}
161
- />
162
- <Box backgroundColor="brand" width="100" height="100" />
163
- </Flex>
164
- </VariantTitle>
165
- <VariantTitle title="No Padding (paddingNone)" invert={args.inverted}>
166
- <Flex direction="row" align="center" spacing="none">
167
- <Box backgroundColor="brand" width="100" height="100" />
168
- <Button {...args} colorScheme="functional" variant="ghost" icon={icon} paddingNone />
169
- <Box backgroundColor="brand" width="100" height="100" />
170
- </Flex>
171
- </VariantTitle>
172
- </Flex>
173
- );
174
- },
175
- };
176
-
177
141
  type ColorScheme = ButtonProps['colorScheme'];
178
142
  type Variant = ButtonProps['variant'];
179
143
 
@@ -181,7 +145,7 @@ export const KitchenSink: Story = {
181
145
  parameters: {
182
146
  controls: { include: ['text', 'size', 'inverted'] },
183
147
  },
184
- render: ({ text, inverted, size }: StoryObj<typeof meta.args>) => {
148
+ render: ({ text, inverted, size }) => {
185
149
  const schemes: Array<ColorScheme> = ['highlight', 'destructive', 'affirmative', 'functional'];
186
150
  const variants: Array<Variant> = ['emphasis', 'solid', 'outline', 'ghost'];
187
151
  return (
@@ -210,7 +174,7 @@ export const KitchenSink: Story = {
210
174
  .map(variant => (
211
175
  <Box key={variant} mb="100">
212
176
  <Box mb="100">
213
- <DetailText size="lg" inverted={inverted}>
177
+ <DetailText size="lg" color={inverted ? 'warmWhite50' : 'grey1000'}>
214
178
  {scheme} - {variant}
215
179
  </DetailText>
216
180
  </Box>
@@ -132,14 +132,6 @@ const styles = StyleSheet.create(theme => ({
132
132
  paddingHorizontal: 0,
133
133
  },
134
134
  },
135
- {
136
- size: 'md',
137
- paddingNone: true,
138
- variant: 'ghost',
139
- styles: {
140
- paddingHorizontal: 0,
141
- },
142
- },
143
135
  // Variant Color Schemes
144
136
  // Emphasis
145
137
  // Emphasis Yellow
@@ -14,8 +14,7 @@ const List = ({
14
14
  invalidText,
15
15
  ...props
16
16
  }: ListProps) => {
17
- const { loading, disabled, container = 'none', testID, style, ...rest } = props;
18
-
17
+ const { loading, disabled, container = 'none' } = props;
19
18
  const orderRef = useRef<string[]>([]);
20
19
  const [firstItemId, setFirstItemId] = useState<string | undefined>(undefined);
21
20
  const containerToCard: {
@@ -52,7 +51,7 @@ const List = ({
52
51
  styles.useVariants({ disabled });
53
52
  return (
54
53
  <ListContext.Provider value={value}>
55
- <View {...rest} style={[styles.container, style]}>
54
+ <View {...props} style={[styles.container, props.style]}>
56
55
  {heading ? (
57
56
  <SectionHeader
58
57
  heading={heading}
@@ -62,10 +61,10 @@ const List = ({
62
61
  />
63
62
  ) : null}
64
63
  {container === 'none' ? (
65
- <View testID={testID}>{children}</View>
64
+ <View>{children}</View>
66
65
  ) : (
67
66
  React.Children.count(children) > 0 && (
68
- <Card {...containerToCard} noPadding style={styles.card} testID={testID}>
67
+ <Card {...containerToCard} noPadding style={styles.card}>
69
68
  <>{children}</>
70
69
  </Card>
71
70
  )
@@ -7,14 +7,7 @@ import {
7
7
  import { BottomSheetModalMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
8
8
  import { CloseMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
9
9
  import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
10
- import {
11
- AccessibilityInfo,
12
- Dimensions,
13
- Platform,
14
- ScrollView,
15
- View,
16
- findNodeHandle,
17
- } from 'react-native';
10
+ import { AccessibilityInfo, Dimensions, Platform, ScrollView, View, findNodeHandle } from 'react-native';
18
11
  import Animated, {
19
12
  Easing,
20
13
  useAnimatedStyle,
@@ -299,23 +292,13 @@ const Modal = ({
299
292
  </View>
300
293
  ) : null}
301
294
  {inNavModal && (
302
- <InNavModalContainer
303
- style={{
304
- flex: stickyFooter ? 1 : 0,
305
- ...(scrollable ? { marginHorizontal: -1 } : {}),
306
- }}
307
- {...(scrollable ? { contentContainerStyle: { paddingHorizontal: 1 } } : {})}
308
- >
295
+ <InNavModalContainer style={{ flex: stickyFooter ? 1 : 0 }}>
309
296
  {children}
310
- {!stickyFooter ? (
311
- <View style={styles.inNavModalFooterContainer}>{footer}</View>
312
- ) : null}
297
+ {!stickyFooter ? <View style={styles.inNavModalFooterContainer}>{footer}</View> : null}
313
298
  </InNavModalContainer>
314
299
  )}
315
300
  {!inNavModal && children}
316
- {((!stickyFooter && !inNavModal) || (inNavModal && stickyFooter)) && !noButtons
317
- ? footer
318
- : null}
301
+ {((!stickyFooter && !inNavModal) || (inNavModal && stickyFooter)) && !noButtons ? footer : null}
319
302
  </View>
320
303
  )}
321
304
  </>
@@ -339,7 +322,7 @@ const Modal = ({
339
322
 
340
323
  return inNavModal ? (
341
324
  <View
342
- onLayout={e => {
325
+ onLayout={(e) => {
343
326
  setInNavModalHeight(e.nativeEvent.layout.height);
344
327
  }}
345
328
  style={{
@@ -355,7 +338,9 @@ const Modal = ({
355
338
  <Animated.View
356
339
  style={[styles.inNavModalContainer, Platform.OS === 'android' && animatedInNavModalStyle]}
357
340
  >
358
- <View style={styles.inNavModalContent}>{content}</View>
341
+ <View style={styles.inNavModalContent}>
342
+ {content}
343
+ </View>
359
344
  </Animated.View>
360
345
  </View>
361
346
  ) : (
@@ -486,7 +471,7 @@ const styles = StyleSheet.create((theme, rt) => ({
486
471
  borderTopLeftRadius: theme.components.modal.borderRadius,
487
472
  borderTopRightRadius: theme.components.modal.borderRadius,
488
473
  backgroundColor: theme.color.surface.neutral.strong,
489
- paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
474
+ paddingBottom: theme.components.modal.padding + rt.insets.bottom,
490
475
  variants: {
491
476
  background: {
492
477
  primary: {},
@@ -496,22 +481,22 @@ const styles = StyleSheet.create((theme, rt) => ({
496
481
  },
497
482
  fullscreen: {
498
483
  true: {
499
- padding: theme.components.bottomSheet.padding,
484
+ padding: theme.components.modal.padding,
500
485
  paddingTop: rt.insets.top,
501
486
  },
502
487
  false: {
503
- padding: theme.components.bottomSheet.padding,
504
- },
505
- },
488
+ padding: theme.components.modal.padding,
489
+ }
490
+ }
506
491
  },
507
492
  },
508
493
  inNavModalFooterContainer: {
509
- paddingTop: theme.components.bottomSheet.padding,
494
+ paddingTop: theme.components.modal.padding,
510
495
  },
511
496
  androidContainer: {
512
497
  height: rt.insets.top + 18,
513
- paddingLeft: theme.components.bottomSheet.padding,
514
- paddingRight: theme.components.bottomSheet.padding,
498
+ paddingLeft: theme.components.modal.padding,
499
+ paddingRight: theme.components.modal.padding,
515
500
  justifyContent: 'flex-end',
516
501
  },
517
502
  pretendContent: {
@@ -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
  )}