@utilitywarehouse/hearth-react-native 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/preview.tsx +1 -0
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +16 -16
- package/CHANGELOG.md +74 -2
- package/build/components/Menu/Menu.d.ts +1 -1
- package/build/components/Menu/Menu.js +2 -2
- package/build/components/Menu/Menu.props.d.ts +2 -6
- package/build/components/Modal/Modal.d.ts +1 -1
- package/build/components/Modal/Modal.js +2 -2
- package/build/components/Modal/Modal.props.d.ts +1 -0
- package/build/components/Modal/Modal.web.d.ts +1 -1
- package/build/components/Modal/Modal.web.js +2 -2
- package/build/components/Select/Select.d.ts +1 -1
- package/build/components/Select/Select.js +9 -10
- package/build/components/Select/Select.props.d.ts +16 -0
- package/build/components/Toast/ToastItem.js +3 -1
- package/docs/changelog.mdx +687 -0
- package/package.json +6 -6
- package/scripts/copyChangelog.js +50 -0
- package/src/components/Checkbox/CheckboxGroup.figma.tsx +21 -1
- package/src/components/Menu/Menu.docs.mdx +8 -5
- package/src/components/Menu/Menu.figma.tsx +27 -27
- package/src/components/Menu/Menu.props.ts +2 -6
- package/src/components/Menu/Menu.tsx +3 -6
- package/src/components/Menu/MenuItem.figma.tsx +26 -18
- package/src/components/Modal/Modal.docs.mdx +22 -21
- package/src/components/Modal/Modal.figma.tsx +58 -47
- package/src/components/Modal/Modal.props.ts +1 -0
- package/src/components/Modal/Modal.stories.tsx +4 -0
- package/src/components/Modal/Modal.tsx +2 -1
- package/src/components/Modal/Modal.web.tsx +2 -1
- package/src/components/PillGroup/Pill.figma.tsx +4 -17
- package/src/components/PillGroup/PillGroup.figma.tsx +8 -9
- package/src/components/ProgressStepper/ProgressStep.figma.tsx +4 -15
- package/src/components/ProgressStepper/ProgressStepper.figma.tsx +9 -16
- package/src/components/Radio/Radio.figma.tsx +35 -22
- package/src/components/Radio/RadioGroup.figma.tsx +69 -41
- package/src/components/Radio/RadioTile.figma.tsx +34 -0
- package/src/components/RadioCard/RadioCard.figma.tsx +24 -0
- package/src/components/SectionHeader/SectionHeader.figma.tsx +31 -25
- package/src/components/Select/Select.docs.mdx +76 -28
- package/src/components/Select/Select.figma.tsx +44 -43
- package/src/components/Select/Select.props.ts +16 -0
- package/src/components/Select/Select.tsx +42 -35
- package/src/components/Select/SelectOption.figma.tsx +3 -21
- package/src/components/Spinner/Spinner.figma.tsx +12 -25
- package/src/components/Switch/Switch.figma.tsx +2 -23
- package/src/components/Tabs/Tab.figma.tsx +21 -0
- package/src/components/Tabs/Tabs.figma.tsx +18 -27
- package/src/components/Textarea/Textarea.figma.tsx +64 -0
- package/src/components/Toast/ToastItem.tsx +3 -1
- package/src/components/ToggleButtonCard/ToggleButtonCard.figma.tsx +24 -0
- package/src/components/VerificationInput/VerificationInput.figma.tsx +53 -0
- package/src/components/Radio/RadioTileRoot.figma.tsx +0 -31
package/.storybook/preview.tsx
CHANGED
package/.turbo/turbo-build.log
CHANGED
package/.turbo/turbo-lint.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @utilitywarehouse/hearth-react-native@0.
|
|
2
|
+
> @utilitywarehouse/hearth-react-native@0.20.0 lint /home/runner/work/hearth/hearth/packages/react-native
|
|
3
3
|
> TIMING=1 eslint .
|
|
4
4
|
|
|
5
5
|
|
|
@@ -31,11 +31,11 @@
|
|
|
31
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
32
|
|
|
33
33
|
/home/runner/work/hearth/hearth/packages/react-native/src/components/Modal/Modal.tsx
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
73: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
|
+
269:5 warning React Hook useCallback has a missing dependency: 'footer'. Either include it or remove the dependency array react-hooks/exhaustive-deps
|
|
36
36
|
|
|
37
37
|
/home/runner/work/hearth/hearth/packages/react-native/src/components/Modal/Modal.web.tsx
|
|
38
|
-
|
|
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
39
|
|
|
40
40
|
/home/runner/work/hearth/hearth/packages/react-native/src/components/PillGroup/PillGroup.tsx
|
|
41
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
|
|
@@ -58,15 +58,15 @@
|
|
|
58
58
|
|
|
59
59
|
✖ 25 problems (0 errors, 25 warnings)
|
|
60
60
|
|
|
61
|
-
Rule
|
|
62
|
-
|
|
63
|
-
@typescript-eslint/no-unused-vars
|
|
64
|
-
react-hooks/exhaustive-deps
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
no-
|
|
70
|
-
no-
|
|
71
|
-
|
|
72
|
-
|
|
61
|
+
Rule | Time (ms) | Relative
|
|
62
|
+
:-----------------------------------------|----------:|--------:
|
|
63
|
+
@typescript-eslint/no-unused-vars | 1584.824 | 64.0%
|
|
64
|
+
react-hooks/exhaustive-deps | 101.118 | 4.1%
|
|
65
|
+
no-global-assign | 70.605 | 2.8%
|
|
66
|
+
react-hooks/rules-of-hooks | 63.862 | 2.6%
|
|
67
|
+
no-misleading-character-class | 49.106 | 2.0%
|
|
68
|
+
@typescript-eslint/ban-ts-comment | 38.021 | 1.5%
|
|
69
|
+
no-unexpected-multiline | 35.859 | 1.4%
|
|
70
|
+
no-loss-of-precision | 32.618 | 1.3%
|
|
71
|
+
@typescript-eslint/triple-slash-reference | 29.048 | 1.2%
|
|
72
|
+
no-useless-escape | 27.538 | 1.1%
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,77 @@
|
|
|
1
1
|
# @utilitywarehouse/hearth-react-native
|
|
2
2
|
|
|
3
|
+
## 0.20.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#898](https://github.com/utilitywarehouse/hearth/pull/898) [`d32a188`](https://github.com/utilitywarehouse/hearth/commit/d32a18840c04222b7b1348133137dc5e56745fe3) Thanks [@jordmccord](https://github.com/jordmccord)! - 🌟 [FEATURE]: Add validation and helper text props to `Select` component
|
|
8
|
+
|
|
9
|
+
The `Select` component now supports built-in validation messages and helper text through new props: `invalidText`, `validText`, `helperText`, and `helperIcon`. This provides a more integrated validation experience without needing to wrap the component in FormField.
|
|
10
|
+
|
|
11
|
+
**Components affected**:
|
|
12
|
+
- `Select`
|
|
13
|
+
|
|
14
|
+
**Developer changes**:
|
|
15
|
+
|
|
16
|
+
You can now add helper text and validation messages directly to Select:
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { Select } from '@utilitywarehouse/hearth-react-native';
|
|
20
|
+
|
|
21
|
+
<Select
|
|
22
|
+
label="Choose an option"
|
|
23
|
+
placeholder="Select an option"
|
|
24
|
+
helperText="This is some helper text for the select component."
|
|
25
|
+
validationStatus="invalid"
|
|
26
|
+
invalidText="Please select a valid option"
|
|
27
|
+
options={[
|
|
28
|
+
{ label: 'Option 1', value: '1' },
|
|
29
|
+
{ label: 'Option 2', value: '2' },
|
|
30
|
+
{ label: 'Option 3', value: '3' },
|
|
31
|
+
]}
|
|
32
|
+
value={value}
|
|
33
|
+
onValueChange={setValue}
|
|
34
|
+
/>;
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The component now also supports a `labelVariant` prop to control label styling:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
<Select
|
|
41
|
+
label="Choose an option"
|
|
42
|
+
labelVariant="heading"
|
|
43
|
+
// ... other props
|
|
44
|
+
/>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
These new props work seamlessly alongside the existing FormField wrapper if you prefer that approach. No changes are required to existing Select implementations.
|
|
48
|
+
|
|
49
|
+
## 0.19.1
|
|
50
|
+
|
|
51
|
+
### Patch Changes
|
|
52
|
+
|
|
53
|
+
- [#886](https://github.com/utilitywarehouse/hearth/pull/886) [`7a948de`](https://github.com/utilitywarehouse/hearth/commit/7a948dea0d15ce7ca34e4d405e86984213c96196) Thanks [@jordmccord](https://github.com/jordmccord)! - 💅 [ENHANCEMENT]: Add `loadingHeading` prop to `Modal` component
|
|
54
|
+
|
|
55
|
+
The `Modal` component now supports a `loadingHeading` prop to customise the heading text displayed during loading states. If not provided, it defaults to 'Loading...'.
|
|
56
|
+
|
|
57
|
+
**Components affected**:
|
|
58
|
+
- `Modal`
|
|
59
|
+
|
|
60
|
+
**Developer changes**:
|
|
61
|
+
|
|
62
|
+
No changes required. To customise the loading heading text, use the new `loadingHeading` prop:
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
<Modal
|
|
66
|
+
loading={isLoading}
|
|
67
|
+
loadingHeading="Processing your request..."
|
|
68
|
+
heading="Confirm Action"
|
|
69
|
+
description="Please wait while we process your request"
|
|
70
|
+
/>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- [#888](https://github.com/utilitywarehouse/hearth/pull/888) [`9b3e172`](https://github.com/utilitywarehouse/hearth/commit/9b3e172f9964026f4f3ba140731432ac63550256) Thanks [@jordmccord](https://github.com/jordmccord)! - 🐛 [FIX]: Align `Toast` icon and dismiss button to the top
|
|
74
|
+
|
|
3
75
|
## 0.19.0
|
|
4
76
|
|
|
5
77
|
### Minor Changes
|
|
@@ -117,7 +189,7 @@
|
|
|
117
189
|
|
|
118
190
|
**Developer changes**:
|
|
119
191
|
|
|
120
|
-
You can now
|
|
192
|
+
You can now customise `IconButton` colors for service-specific branding:
|
|
121
193
|
|
|
122
194
|
```tsx
|
|
123
195
|
import { IconButton } from '@utilitywarehouse/hearth-react-native';
|
|
@@ -138,7 +210,7 @@
|
|
|
138
210
|
- `activeBackgroundColor` - Sets the background color when pressed or in an active state
|
|
139
211
|
- `shadowColor` - Sets the shadow/elevation color
|
|
140
212
|
|
|
141
|
-
These overrides work alongside the existing `variant` and `colorScheme` props, allowing you to maintain structural styling while
|
|
213
|
+
These overrides work alongside the existing `variant` and `colorScheme` props, allowing you to maintain structural styling while customising colors for specific branding requirements.
|
|
142
214
|
|
|
143
215
|
### Patch Changes
|
|
144
216
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type MenuProps from './Menu.props';
|
|
2
2
|
import type { MenuMethods } from './Menu.props';
|
|
3
|
-
declare const Menu: import("react").ForwardRefExoticComponent<MenuProps & import("react").RefAttributes<MenuMethods>>;
|
|
3
|
+
declare const Menu: import("react").ForwardRefExoticComponent<Omit<MenuProps, "ref"> & import("react").RefAttributes<MenuMethods>>;
|
|
4
4
|
export default Menu;
|
|
@@ -4,7 +4,7 @@ import { StyleSheet } from 'react-native-unistyles';
|
|
|
4
4
|
import { BodyText } from '../BodyText';
|
|
5
5
|
import { BottomSheetModal, BottomSheetScrollView } from '../BottomSheet';
|
|
6
6
|
import { MenuContext } from './Menu.context';
|
|
7
|
-
const Menu = forwardRef(({ heading, children,
|
|
7
|
+
const Menu = forwardRef(({ heading, children, ...props }, ref) => {
|
|
8
8
|
const bottomSheetModalRef = useRef(null);
|
|
9
9
|
useImperativeHandle(ref, () => ({
|
|
10
10
|
present: () => bottomSheetModalRef.current?.present(),
|
|
@@ -14,7 +14,7 @@ const Menu = forwardRef(({ heading, children, bottomSheetProps }, ref) => {
|
|
|
14
14
|
bottomSheetModalRef.current?.dismiss();
|
|
15
15
|
}, []);
|
|
16
16
|
const contextValue = useMemo(() => ({ close: handleClose }), [handleClose]);
|
|
17
|
-
return (_jsx(BottomSheetModal, { ref: bottomSheetModalRef, ...
|
|
17
|
+
return (_jsx(BottomSheetModal, { ref: bottomSheetModalRef, ...props, children: _jsx(BottomSheetScrollView, { contentContainerStyle: styles.container, children: _jsxs(MenuContext.Provider, { value: contextValue, children: [heading && (_jsx(BodyText, { size: "md", weight: "semibold", children: heading })), children] }) }) }));
|
|
18
18
|
});
|
|
19
19
|
Menu.displayName = 'Menu';
|
|
20
20
|
const styles = StyleSheet.create(theme => ({
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { BottomSheetModalProps } from '@gorhom/bottom-sheet';
|
|
2
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import { BottomSheetProps } from '../BottomSheet';
|
|
3
3
|
export interface MenuMethods {
|
|
4
4
|
present: () => void;
|
|
5
5
|
dismiss: () => void;
|
|
6
6
|
}
|
|
7
|
-
export interface MenuProps {
|
|
7
|
+
export interface MenuProps extends BottomSheetProps {
|
|
8
8
|
/**
|
|
9
9
|
* Heading text displayed at the top of the menu
|
|
10
10
|
*/
|
|
@@ -13,9 +13,5 @@ export interface MenuProps {
|
|
|
13
13
|
* Menu items to display
|
|
14
14
|
*/
|
|
15
15
|
children: ReactNode;
|
|
16
|
-
/**
|
|
17
|
-
* Optional bottom sheet modal props to customise the menu behavior
|
|
18
|
-
*/
|
|
19
|
-
bottomSheetProps?: Partial<BottomSheetModalProps>;
|
|
20
16
|
}
|
|
21
17
|
export default MenuProps;
|
|
@@ -3,5 +3,5 @@ import ModalProps from './Modal.props';
|
|
|
3
3
|
type Modal<T = any> = BottomSheetModalMethods<T> & {
|
|
4
4
|
triggerCloseAnimation?: () => void;
|
|
5
5
|
};
|
|
6
|
-
declare const Modal: ({ ref, children, heading, description, showCloseButton, primaryButtonText, secondaryButtonText, onPressPrimaryButton, onPressCloseButton, onPressSecondaryButton, closeOnPrimaryButtonPress, closeOnSecondaryButtonPress, loading, fullscreen, image, primaryButtonProps, secondaryButtonProps, closeButtonProps, inNavModal, stickyFooter, ...props }: ModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
declare const Modal: ({ ref, children, heading, description, showCloseButton, primaryButtonText, secondaryButtonText, onPressPrimaryButton, onPressCloseButton, onPressSecondaryButton, closeOnPrimaryButtonPress, closeOnSecondaryButtonPress, loading, loadingHeading, fullscreen, image, primaryButtonProps, secondaryButtonProps, closeButtonProps, inNavModal, stickyFooter, ...props }: ModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
7
|
export default Modal;
|
|
@@ -13,7 +13,7 @@ import { Button } from '../Button';
|
|
|
13
13
|
import { Heading } from '../Heading';
|
|
14
14
|
import { Spinner } from '../Spinner';
|
|
15
15
|
import { UnstyledIconButton } from '../UnstyledIconButton';
|
|
16
|
-
const Modal = ({ ref, children, heading, description, showCloseButton = true, primaryButtonText, secondaryButtonText, onPressPrimaryButton, onPressCloseButton, onPressSecondaryButton, closeOnPrimaryButtonPress = true, closeOnSecondaryButtonPress = true, loading, fullscreen = false, image, primaryButtonProps, secondaryButtonProps, closeButtonProps, inNavModal = false, stickyFooter = true, ...props }) => {
|
|
16
|
+
const Modal = ({ ref, children, heading, description, showCloseButton = true, primaryButtonText, secondaryButtonText, onPressPrimaryButton, onPressCloseButton, onPressSecondaryButton, closeOnPrimaryButtonPress = true, closeOnSecondaryButtonPress = true, loading, loadingHeading = 'Loading...', fullscreen = false, image, primaryButtonProps, secondaryButtonProps, closeButtonProps, inNavModal = false, stickyFooter = true, ...props }) => {
|
|
17
17
|
const bottomSheetModalRef = useRef(null);
|
|
18
18
|
const viewRef = useRef(null);
|
|
19
19
|
const scrollViewRef = useRef(null);
|
|
@@ -107,7 +107,7 @@ const Modal = ({ ref, children, heading, description, showCloseButton = true, pr
|
|
|
107
107
|
showHandle: props.showHandle,
|
|
108
108
|
});
|
|
109
109
|
const footer = (_jsxs(View, { style: styles.footer, children: [onPressPrimaryButton && primaryButtonText ? (_jsx(Button, { onPress: handlePrimaryButtonPress, text: primaryButtonText, ...primaryButtonProps, variant: primaryButtonProps?.variant ?? 'solid', colorScheme: primaryButtonProps?.colorScheme ?? 'highlight' })) : null, onPressSecondaryButton && secondaryButtonText ? (_jsx(Button, { onPress: handleSecondaryButtonPress, text: secondaryButtonText, ...secondaryButtonProps, variant: secondaryButtonProps?.variant ?? 'outline', colorScheme: secondaryButtonProps?.colorScheme ?? 'functional' })) : null] }));
|
|
110
|
-
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" }), _jsx(Heading, { size: "lg", textAlign: "center", children:
|
|
110
|
+
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" }), _jsx(Heading, { size: "lg", textAlign: "center", 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, children: heading })) : null, description && !image ? _jsx(BodyText, { accessible: true, children: description }) : null] }), showCloseButton ? (_jsx(UnstyledIconButton, { icon: CloseMediumIcon, onPress: handleCloseButtonPress, accessibilityLabel: "Close modal", ...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, children: heading })) : null, description ? (_jsx(BodyText, { textAlign: "center", accessible: true, children: description })) : null] })] })) : null, children, !stickyFooter && !noButtons ? footer : null] })) }));
|
|
111
111
|
const renderFooter = useCallback((props) => (_jsx(BottomSheetFooter, { ...props, children: _jsx(View, { style: styles.footerWrap, children: footer }) })), [
|
|
112
112
|
onPressPrimaryButton,
|
|
113
113
|
primaryButtonText,
|
|
@@ -3,5 +3,5 @@ import ModalProps from './Modal.props';
|
|
|
3
3
|
type Modal<T = any> = BottomSheetModalMethods<T> & {
|
|
4
4
|
triggerCloseAnimation?: () => void;
|
|
5
5
|
};
|
|
6
|
-
declare const Modal: ({ ref, children, heading, description, showCloseButton, primaryButtonText, secondaryButtonText, onPressPrimaryButton, onPressCloseButton, onPressSecondaryButton, closeOnPrimaryButtonPress, closeOnSecondaryButtonPress, loading, image, primaryButtonProps, secondaryButtonProps, closeButtonProps, inNavModal, ...props }: ModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
declare const Modal: ({ ref, children, heading, description, showCloseButton, primaryButtonText, secondaryButtonText, onPressPrimaryButton, onPressCloseButton, onPressSecondaryButton, closeOnPrimaryButtonPress, closeOnSecondaryButtonPress, loading, loadingHeading, image, primaryButtonProps, secondaryButtonProps, closeButtonProps, inNavModal, ...props }: ModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
7
|
export default Modal;
|
|
@@ -12,7 +12,7 @@ import { Button } from '../Button';
|
|
|
12
12
|
import { Heading } from '../Heading';
|
|
13
13
|
import { Spinner } from '../Spinner';
|
|
14
14
|
import { UnstyledIconButton } from '../UnstyledIconButton';
|
|
15
|
-
const Modal = ({ ref, children, heading, description, showCloseButton = true, primaryButtonText, secondaryButtonText, onPressPrimaryButton, onPressCloseButton, onPressSecondaryButton, closeOnPrimaryButtonPress = true, closeOnSecondaryButtonPress = true, loading, image, primaryButtonProps, secondaryButtonProps, closeButtonProps, inNavModal = false, ...props }) => {
|
|
15
|
+
const Modal = ({ ref, children, heading, description, showCloseButton = true, primaryButtonText, secondaryButtonText, onPressPrimaryButton, onPressCloseButton, onPressSecondaryButton, closeOnPrimaryButtonPress = true, closeOnSecondaryButtonPress = true, loading, loadingHeading = 'Loading...', image, primaryButtonProps, secondaryButtonProps, closeButtonProps, inNavModal = false, ...props }) => {
|
|
16
16
|
const bottomSheetModalRef = useRef(null);
|
|
17
17
|
const viewRef = useRef(null);
|
|
18
18
|
const scrollViewRef = useRef(null);
|
|
@@ -97,7 +97,7 @@ const Modal = ({ ref, children, heading, description, showCloseButton = true, pr
|
|
|
97
97
|
bottomSheetModalRef.current?.dismiss();
|
|
98
98
|
}
|
|
99
99
|
};
|
|
100
|
-
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" }), _jsx(Heading, { size: "lg", textAlign: "center", children:
|
|
100
|
+
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" }), _jsx(Heading, { size: "lg", textAlign: "center", 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, children: heading })) : null, description && !image ? _jsx(BodyText, { accessible: true, children: description }) : null] }), showCloseButton ? (_jsx(UnstyledIconButton, { icon: CloseMediumIcon, onPress: handleCloseButtonPress, accessibilityLabel: "Close modal", ...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, children: heading })) : null, description ? (_jsx(BodyText, { textAlign: "center", accessible: true, children: description })) : null] })] })) : null, children, _jsxs(View, { style: styles.footer, children: [onPressPrimaryButton && primaryButtonText ? (_jsx(Button, { onPress: handlePrimaryButtonPress, text: primaryButtonText, ...primaryButtonProps, variant: primaryButtonProps?.variant ?? 'solid', colorScheme: primaryButtonProps?.colorScheme ?? 'highlight' })) : null, onPressSecondaryButton && secondaryButtonText ? (_jsx(Button, { onPress: handleSecondaryButtonPress, text: secondaryButtonText, ...secondaryButtonProps, variant: secondaryButtonProps?.variant ?? 'outline', colorScheme: secondaryButtonProps?.colorScheme ?? 'functional' })) : null] })] })) }));
|
|
101
101
|
return inNavModal ? (_jsxs(View, { style: { flex: 1, backgroundColor: theme.color.background.primary }, children: [Platform.OS === 'android' ? (_jsx(Animated.View, { style: [styles.androidContainer, animatedBackgroundStyle], children: _jsx(Animated.View, { style: [styles.pretendContent, animatedPretendContentStyle] }) })) : null, _jsx(Animated.View, { style: [styles.inNavModalContainer, Platform.OS === 'android' && animatedInNavModalStyle], children: _jsx(View, { style: styles.inNavModalContent, children: content }) })] })) : (_jsx(BottomSheetModal, { ref: bottomSheetModalRef, enableDynamicSizing: true, snapPoints: image ? ['90%'] : props.snapPoints, showHandle: typeof loading !== 'undefined' && loading ? false : props.showHandle, accessible: false, ...props, onChange: handleChange, children: _jsx(BottomSheetScrollView, { contentContainerStyle: styles.container, ref: scrollViewRef, children: content }) }));
|
|
102
102
|
};
|
|
103
103
|
const styles = StyleSheet.create((theme, rt) => ({
|
|
@@ -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, required, children, bottomSheetProps, menuHeading, readonly, emptyText, listProps, searchable, searchPlaceholder, ...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;
|
|
@@ -6,13 +6,12 @@ import { StyleSheet } from 'react-native-unistyles';
|
|
|
6
6
|
import { BodyText } from '../BodyText';
|
|
7
7
|
import { BottomSheetFlatList, BottomSheetModal, BottomSheetScrollView, BottomSheetView, } from '../BottomSheet';
|
|
8
8
|
import { DetailText } from '../DetailText';
|
|
9
|
-
import { useFormFieldContext } from '../FormField';
|
|
9
|
+
import { FormField, useFormFieldContext } from '../FormField';
|
|
10
10
|
import { Icon } from '../Icon';
|
|
11
11
|
import { Input } from '../Input';
|
|
12
|
-
import { Label } from '../Label';
|
|
13
12
|
import { SelectContext } from './Select.context';
|
|
14
13
|
import SelectOption from './SelectOption';
|
|
15
|
-
const Select = ({ options = [], value, onValueChange, label, labelVariant = 'body', placeholder = 'Select an option', disabled = false, leadingIcon: LeadingIcon, validationStatus = 'initial', required = true, children, bottomSheetProps, menuHeading, readonly = false, emptyText = 'No options available', listProps, searchable = false, searchPlaceholder = 'Search', ...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 }) => {
|
|
16
15
|
const formFieldContext = useFormFieldContext();
|
|
17
16
|
const validationStatusFromContext = formFieldContext?.validationStatus ?? validationStatus;
|
|
18
17
|
const isRequired = formFieldContext?.required ?? required;
|
|
@@ -67,13 +66,13 @@ const Select = ({ options = [], value, onValueChange, label, labelVariant = 'bod
|
|
|
67
66
|
}, []);
|
|
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: [
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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 }) => [
|
|
70
|
+
styles.selectContainer,
|
|
71
|
+
styles.pressedContainer(pressed || isOpen),
|
|
72
|
+
], children: [!!LeadingIcon && (_jsx(View, { children: (() => {
|
|
73
|
+
const IconAny = Icon;
|
|
74
|
+
return _jsx(IconAny, { as: LeadingIcon, style: styles.icon });
|
|
75
|
+
})() })), _jsx(View, { style: styles.optionContainer, children: _jsx(BodyText, { numberOfLines: 1, style: styles.placeholderText, children: selectedOption?.label || selectedLabel || placeholder }) }), _jsx(View, { children: _jsx(Icon, { as: ExpandSmallIcon, style: styles.icon }) })] }) }), _jsx(BottomSheetModal, { ref: bottomSheetModalRef, snapPoints: ['25%', '40%', '80%'], onChange: handleClose, enableDynamicSizing: false, ...bottomSheetProps, children: _jsxs(SelectContext.Provider, { value: {
|
|
77
76
|
selectedValue: value,
|
|
78
77
|
onValueChange,
|
|
79
78
|
close: closeBottomSheet,
|
|
@@ -50,6 +50,22 @@ interface SelectProps extends ViewProps {
|
|
|
50
50
|
* @default 'body'.
|
|
51
51
|
*/
|
|
52
52
|
labelVariant?: 'heading' | 'body';
|
|
53
|
+
/**
|
|
54
|
+
* Helper text to show below the select
|
|
55
|
+
*/
|
|
56
|
+
helperText?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Optional icon to display alongside the helper text
|
|
59
|
+
*/
|
|
60
|
+
helperIcon?: React.ComponentType;
|
|
61
|
+
/**
|
|
62
|
+
* Text to display when validationStatus is 'invalid'
|
|
63
|
+
*/
|
|
64
|
+
invalidText?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Text to display when validationStatus is 'valid'
|
|
67
|
+
*/
|
|
68
|
+
validText?: string;
|
|
53
69
|
/**
|
|
54
70
|
* Placeholder text to show when no value is selected
|
|
55
71
|
*/
|
|
@@ -109,7 +109,8 @@ const styles = StyleSheet.create(theme => ({
|
|
|
109
109
|
width: 24,
|
|
110
110
|
height: 24,
|
|
111
111
|
justifyContent: 'center',
|
|
112
|
-
|
|
112
|
+
alignSelf: 'flex-start',
|
|
113
|
+
alignItems: 'flex-start',
|
|
113
114
|
flexShrink: 0,
|
|
114
115
|
},
|
|
115
116
|
icon: {
|
|
@@ -125,6 +126,7 @@ const styles = StyleSheet.create(theme => ({
|
|
|
125
126
|
text: { flexShrink: 1 },
|
|
126
127
|
actions: {
|
|
127
128
|
flexShrink: 0,
|
|
129
|
+
alignSelf: 'flex-start',
|
|
128
130
|
},
|
|
129
131
|
}));
|
|
130
132
|
export default ToastItem;
|