@utilitywarehouse/hearth-react-native 0.11.0 → 0.12.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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +10 -0
- package/build/components/Banner/Banner.context.d.ts +7 -0
- package/build/components/Banner/Banner.context.js +8 -0
- package/build/components/Banner/Banner.js +10 -40
- package/build/components/Banner/Banner.props.d.ts +3 -5
- package/build/components/Banner/BannerIllustration.d.ts +4 -0
- package/build/components/Banner/BannerIllustration.js +53 -0
- package/build/components/Banner/BannerImage.d.ts +4 -0
- package/build/components/Banner/BannerImage.js +53 -0
- package/build/components/Banner/index.d.ts +2 -0
- package/build/components/Banner/index.js +2 -0
- package/build/components/Card/CardAction/CardAction.props.d.ts +2 -3
- package/build/components/Card/CardAction/CardActionRoot.js +1 -2
- package/build/components/Checkbox/Checkbox.js +1 -2
- package/build/components/Checkbox/Checkbox.props.d.ts +3 -3
- package/build/components/Checkbox/CheckboxImage.d.ts +2 -1
- package/build/components/Checkbox/CheckboxImage.js +8 -1
- package/build/components/ExpandableCard/ExpandableCard.props.d.ts +1 -2
- package/build/components/ExpandableCard/ExpandableCardTrigger.props.d.ts +4 -5
- package/build/components/ExpandableCard/ExpandableCardTriggerRoot.js +1 -14
- package/build/components/HighlightBanner/HighlightBanner.js +2 -6
- package/build/components/HighlightBanner/HighlightBanner.props.d.ts +2 -3
- package/build/components/HighlightBanner/HighlightBannerImage.d.ts +4 -0
- package/build/components/HighlightBanner/HighlightBannerImage.js +18 -0
- package/build/components/HighlightBanner/index.d.ts +1 -0
- package/build/components/HighlightBanner/index.js +1 -0
- package/build/components/Input/Input.d.ts +5 -7
- package/build/components/Input/Input.js +11 -4
- package/build/components/Input/InputField.d.ts +4 -7
- package/build/components/Input/InputField.js +6 -5
- package/build/components/List/ListItem/ListItem.props.d.ts +2 -2
- package/build/components/List/ListItem/ListItemRoot.js +1 -2
- package/build/components/Modal/Modal.js +2 -6
- package/build/components/Modal/Modal.props.d.ts +3 -2
- package/build/components/Modal/Modal.web.js +2 -6
- package/build/components/Modal/ModalImage.d.ts +4 -0
- package/build/components/Modal/ModalImage.js +18 -0
- package/build/components/Modal/index.d.ts +1 -0
- package/build/components/Modal/index.js +1 -0
- package/build/components/Radio/Radio.js +1 -2
- package/build/components/Radio/Radio.props.d.ts +3 -3
- package/build/components/Radio/RadioImage.d.ts +2 -1
- package/build/components/Radio/RadioImage.js +8 -1
- package/build/utils/index.d.ts +2 -1
- package/build/utils/index.js +2 -1
- package/build/utils/isThemedImageProps.d.ts +4 -0
- package/build/utils/isThemedImageProps.js +4 -0
- package/package.json +2 -2
- package/src/components/Banner/Banner.context.ts +11 -0
- package/src/components/Banner/Banner.docs.mdx +55 -37
- package/src/components/Banner/Banner.props.ts +3 -5
- package/src/components/Banner/Banner.stories.tsx +86 -57
- package/src/components/Banner/Banner.tsx +24 -67
- package/src/components/Banner/BannerIllustration.tsx +63 -0
- package/src/components/Banner/BannerImage.tsx +63 -0
- package/src/components/Banner/index.ts +2 -0
- package/src/components/Card/Card.docs.mdx +4 -4
- package/src/components/Card/CardAction/CardAction.props.ts +2 -3
- package/src/components/Card/CardAction/CardAction.stories.tsx +4 -3
- package/src/components/Card/CardAction/CardActionRoot.tsx +4 -5
- package/src/components/Checkbox/Checkbox.docs.mdx +23 -4
- package/src/components/Checkbox/Checkbox.props.ts +3 -3
- package/src/components/Checkbox/Checkbox.stories.tsx +14 -8
- package/src/components/Checkbox/Checkbox.tsx +1 -2
- package/src/components/Checkbox/CheckboxImage.tsx +8 -3
- package/src/components/ExpandableCard/ExpandableCard.docs.mdx +2 -2
- package/src/components/ExpandableCard/ExpandableCard.props.ts +1 -2
- package/src/components/ExpandableCard/ExpandableCard.stories.tsx +3 -3
- package/src/components/ExpandableCard/ExpandableCardTrigger.props.ts +4 -5
- package/src/components/ExpandableCard/ExpandableCardTriggerRoot.tsx +2 -17
- package/src/components/HighlightBanner/HighlightBanner.docs.mdx +73 -42
- package/src/components/HighlightBanner/HighlightBanner.props.ts +2 -3
- package/src/components/HighlightBanner/HighlightBanner.stories.tsx +85 -60
- package/src/components/HighlightBanner/HighlightBanner.tsx +3 -10
- package/src/components/HighlightBanner/HighlightBannerImage.tsx +20 -0
- package/src/components/HighlightBanner/index.ts +1 -0
- package/src/components/Input/Input.stories.tsx +76 -3
- package/src/components/Input/Input.tsx +110 -98
- package/src/components/Input/InputField.tsx +27 -26
- package/src/components/List/List.docs.mdx +15 -9
- package/src/components/List/List.stories.tsx +2 -2
- package/src/components/List/ListItem/ListItem.props.ts +2 -2
- package/src/components/List/ListItem/ListItemRoot.tsx +2 -3
- package/src/components/Modal/Modal.docs.mdx +16 -4
- package/src/components/Modal/Modal.props.ts +3 -2
- package/src/components/Modal/Modal.stories.tsx +2 -5
- package/src/components/Modal/Modal.tsx +2 -6
- package/src/components/Modal/Modal.web.tsx +2 -6
- package/src/components/Modal/ModalImage.tsx +20 -0
- package/src/components/Modal/index.ts +1 -0
- package/src/components/PillGroup/PillGroup.stories.tsx +1 -1
- package/src/components/Radio/Radio.docs.mdx +21 -8
- package/src/components/Radio/Radio.props.ts +3 -3
- package/src/components/Radio/Radio.stories.tsx +15 -11
- package/src/components/Radio/Radio.tsx +1 -2
- package/src/components/Radio/RadioImage.tsx +8 -3
- package/src/utils/index.ts +2 -1
- package/src/utils/isThemedImageProps.ts +8 -0
|
@@ -1,25 +1,38 @@
|
|
|
1
1
|
import { BottomSheetTextInput } from '@gorhom/bottom-sheet';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
2
3
|
import { TextInput as RNTextInput, TextInputProps } from 'react-native';
|
|
3
4
|
import { StyleSheet } from 'react-native-unistyles';
|
|
4
5
|
import { useTheme } from '../../hooks';
|
|
5
6
|
import { useInputContext } from './Input.context';
|
|
6
7
|
|
|
7
|
-
const InputField = (
|
|
8
|
-
style,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
const InputField = forwardRef<RNTextInput, TextInputProps & { inBottomSheet?: boolean }>(
|
|
9
|
+
({ style, inBottomSheet = false, ...props }, ref) => {
|
|
10
|
+
const { disabled, focused = false, type } = useInputContext();
|
|
11
|
+
styles.useVariants({ focused, type });
|
|
12
|
+
const { color } = useTheme();
|
|
13
|
+
|
|
14
|
+
if (inBottomSheet) {
|
|
15
|
+
return (
|
|
16
|
+
// @ts-expect-error - BottomSheetTextInput has incompatible event types with TextInput
|
|
17
|
+
<BottomSheetTextInput
|
|
18
|
+
ref={ref as any}
|
|
19
|
+
placeholderTextColor={color.text.secondary}
|
|
20
|
+
selectionColor={color.surface.brand.default}
|
|
21
|
+
cursorColor={color.surface.brand.default}
|
|
22
|
+
verticalAlign="middle"
|
|
23
|
+
aria-disabled={disabled}
|
|
24
|
+
{...props}
|
|
25
|
+
style={[styles.input, style]}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
15
29
|
|
|
16
|
-
if (inBottomSheet) {
|
|
17
30
|
return (
|
|
18
|
-
|
|
19
|
-
|
|
31
|
+
<RNTextInput
|
|
32
|
+
ref={ref}
|
|
20
33
|
placeholderTextColor={color.text.secondary}
|
|
21
|
-
selectionColor={color.
|
|
22
|
-
cursorColor={color.
|
|
34
|
+
selectionColor={color.surface.brand.default}
|
|
35
|
+
cursorColor={color.surface.brand.default}
|
|
23
36
|
verticalAlign="middle"
|
|
24
37
|
aria-disabled={disabled}
|
|
25
38
|
{...props}
|
|
@@ -27,19 +40,7 @@ const InputField = ({
|
|
|
27
40
|
/>
|
|
28
41
|
);
|
|
29
42
|
}
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<RNTextInput
|
|
33
|
-
placeholderTextColor={color.text.secondary}
|
|
34
|
-
selectionColor={color.purple[700]}
|
|
35
|
-
cursorColor={color.purple[700]}
|
|
36
|
-
verticalAlign="middle"
|
|
37
|
-
aria-disabled={disabled}
|
|
38
|
-
{...props}
|
|
39
|
-
style={[styles.input, style]}
|
|
40
|
-
/>
|
|
41
|
-
);
|
|
42
|
-
};
|
|
43
|
+
);
|
|
43
44
|
|
|
44
45
|
InputField.displayName = 'InputField';
|
|
45
46
|
|
|
@@ -4,18 +4,20 @@ import {
|
|
|
4
4
|
ChevronRightSmallIcon,
|
|
5
5
|
ElectricityMediumIcon,
|
|
6
6
|
GasMediumIcon,
|
|
7
|
-
|
|
8
|
-
// HomeMediumIcon,
|
|
7
|
+
HomeMediumIcon,
|
|
9
8
|
PaymentMediumIcon,
|
|
10
9
|
UserMediumIcon,
|
|
11
10
|
} from '@utilitywarehouse/hearth-react-native-icons';
|
|
12
11
|
import {
|
|
13
12
|
Badge,
|
|
14
13
|
BadgeText,
|
|
14
|
+
BodyText,
|
|
15
15
|
Box,
|
|
16
16
|
FlatList,
|
|
17
17
|
Image,
|
|
18
|
+
Link,
|
|
18
19
|
List,
|
|
20
|
+
ListAction,
|
|
19
21
|
ListItem,
|
|
20
22
|
ListItemContent,
|
|
21
23
|
ListItemHelperText,
|
|
@@ -26,9 +28,6 @@ import {
|
|
|
26
28
|
ListItemTrailingIcon,
|
|
27
29
|
SectionHeader,
|
|
28
30
|
Switch,
|
|
29
|
-
Link,
|
|
30
|
-
ListAction,
|
|
31
|
-
BodyText,
|
|
32
31
|
} from '../../';
|
|
33
32
|
import { BackToTopButton, BadgeList, UsageWrap, ViewFigmaButton } from '../../../docs/components';
|
|
34
33
|
import * as Stories from './List.stories';
|
|
@@ -116,7 +115,7 @@ const MyComponent = () => (
|
|
|
116
115
|
| variant | `'subtle' \| 'emphasis'` | | The variant style of the list item. |
|
|
117
116
|
| disabled | `boolean` | `false` | Whether to disable the list item. |
|
|
118
117
|
| loading | `boolean` | `false` | Whether to show the list item in loading state. |
|
|
119
|
-
| badge | `
|
|
118
|
+
| badge | `ReactNode` | | The badge component to display in the list item. |
|
|
120
119
|
| badgePosition | `'top' \| 'bottom'` | `bottom` | Position of the badge in the list item. |
|
|
121
120
|
| numericValue | `string \| number` | | A numeric value to display on the right side of the item. |
|
|
122
121
|
|
|
@@ -197,7 +196,14 @@ parts like `ListItemLeadingContent`, `ListItemContent`, and `ListItemTrailingCon
|
|
|
197
196
|
<Canvas of={Stories.WithBadge} />
|
|
198
197
|
|
|
199
198
|
```tsx
|
|
200
|
-
import {
|
|
199
|
+
import {
|
|
200
|
+
List,
|
|
201
|
+
ListItem,
|
|
202
|
+
IconContainer,
|
|
203
|
+
Flex,
|
|
204
|
+
Box,
|
|
205
|
+
Badge,
|
|
206
|
+
} from '@utilitywarehouse/hearth-react-native';
|
|
201
207
|
|
|
202
208
|
import { ElectricityMediumIcon, GasMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
|
|
203
209
|
|
|
@@ -211,7 +217,7 @@ const BadgeList = () => {
|
|
|
211
217
|
leadingContent={
|
|
212
218
|
<IconContainer icon={ElectricityMediumIcon} size="md" variant="emphasis" color="energy" />
|
|
213
219
|
}
|
|
214
|
-
badge={
|
|
220
|
+
badge={<Badge text="Text" />}
|
|
215
221
|
/>
|
|
216
222
|
<ListItem
|
|
217
223
|
heading="Gas"
|
|
@@ -220,7 +226,7 @@ const BadgeList = () => {
|
|
|
220
226
|
leadingContent={
|
|
221
227
|
<IconContainer icon={GasMediumIcon} size="md" variant="emphasis" color="energy" />
|
|
222
228
|
}
|
|
223
|
-
badge={
|
|
229
|
+
badge={<Badge text="Smart Meter" />}
|
|
224
230
|
/>
|
|
225
231
|
</List>
|
|
226
232
|
);
|
|
@@ -126,7 +126,7 @@ export const WithBadge: Story = {
|
|
|
126
126
|
leadingContent={
|
|
127
127
|
<IconContainer icon={ElectricityMediumIcon} size="md" variant="emphasis" color="energy" />
|
|
128
128
|
}
|
|
129
|
-
badge={
|
|
129
|
+
badge={<Badge text="Text" />}
|
|
130
130
|
/>
|
|
131
131
|
<ListItem
|
|
132
132
|
heading="Gas"
|
|
@@ -135,7 +135,7 @@ export const WithBadge: Story = {
|
|
|
135
135
|
leadingContent={
|
|
136
136
|
<IconContainer icon={GasMediumIcon} size="md" variant="emphasis" color="energy" />
|
|
137
137
|
}
|
|
138
|
-
badge={
|
|
138
|
+
badge={<Badge text="Smart Meter" />}
|
|
139
139
|
/>
|
|
140
140
|
</List>
|
|
141
141
|
),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
import type { PressableProps, ViewProps } from 'react-native';
|
|
2
|
-
import BadgeProps from '../../Badge/Badge.props';
|
|
3
3
|
|
|
4
4
|
interface ListItemBaseProps extends Omit<PressableProps, 'children'> {
|
|
5
5
|
loading?: boolean;
|
|
@@ -26,7 +26,7 @@ export interface ListItemWithoutChildren extends ListItemBaseProps {
|
|
|
26
26
|
leadingContent?: ViewProps['children'];
|
|
27
27
|
trailingContent?: ViewProps['children'];
|
|
28
28
|
numericValue?: string | number;
|
|
29
|
-
badge?:
|
|
29
|
+
badge?: ReactNode;
|
|
30
30
|
badgePosition?: 'top' | 'bottom';
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -2,7 +2,6 @@ import { ChevronRightSmallIcon } from '@utilitywarehouse/hearth-react-native-ico
|
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
3
|
import { Pressable, ViewStyle } from 'react-native';
|
|
4
4
|
import { StyleSheet } from 'react-native-unistyles';
|
|
5
|
-
import { Badge } from '../../Badge';
|
|
6
5
|
import { DetailText } from '../../DetailText';
|
|
7
6
|
import { Skeleton } from '../../Skeleton';
|
|
8
7
|
import { useListContext } from '../List.context';
|
|
@@ -106,10 +105,10 @@ const ListItemRoot = ({
|
|
|
106
105
|
<ListItemLeadingContent>{leadingContent}</ListItemLeadingContent>
|
|
107
106
|
) : null}
|
|
108
107
|
<ListItemContent>
|
|
109
|
-
{badgePosition === 'top' && badge ?
|
|
108
|
+
{badgePosition === 'top' && badge ? badge : null}
|
|
110
109
|
<ListItemText>{heading}</ListItemText>
|
|
111
110
|
{helperText ? <ListItemHelperText>{helperText}</ListItemHelperText> : null}
|
|
112
|
-
{badgePosition === 'bottom' && badge ?
|
|
111
|
+
{badgePosition === 'bottom' && badge ? badge : null}
|
|
113
112
|
</ListItemContent>
|
|
114
113
|
{!!numericValue && <DetailText size="lg">{numericValue}</DetailText>}
|
|
115
114
|
{trailingContent ? (
|
|
@@ -108,6 +108,19 @@ The Modal component extends the `BottomSheetModal` component and accepts all of
|
|
|
108
108
|
| `fullscreen` | `boolean` | Whether the modal should take up the full screen height | `false` |
|
|
109
109
|
| `inNavModal` | `boolean` | Renders the modal correctly when used inside a navigation modal | `false` |
|
|
110
110
|
|
|
111
|
+
### `ModalImage` Props
|
|
112
|
+
|
|
113
|
+
The `ModalImage` component can be used to display an image within the Modal. It accepts the following props:
|
|
114
|
+
|
|
115
|
+
| Property | Type | Description |
|
|
116
|
+
| --------- | --------------------- | ------------------------------------------------------------------------ |
|
|
117
|
+
| `source` | `ImageSourcePropType` | The source of the image to display |
|
|
118
|
+
| `light` | `ImageSourcePropType` | The source of the image to display in light mode (use instead of source) |
|
|
119
|
+
| `dark` | `ImageSourcePropType` | The source of the image to display in dark mode (use instead of source) |
|
|
120
|
+
| `...rest` | `ImageProps` | Additional props to pass to the underlying Image component |
|
|
121
|
+
|
|
122
|
+
For more details about the ThemedImage component used internally, refer to the [`ThemedImage` documentation](/docs/utility-components-themed-image--docs).
|
|
123
|
+
|
|
111
124
|
## Features
|
|
112
125
|
|
|
113
126
|
### Automatic Layout Management
|
|
@@ -269,6 +282,8 @@ Use the `image` prop to display an image-centric modal with centered content:
|
|
|
269
282
|
<Canvas of={Stories.WithImage} />
|
|
270
283
|
|
|
271
284
|
```tsx
|
|
285
|
+
import { Modal, ModalImage, Button } from '@utilitywarehouse/hearth-react-native';
|
|
286
|
+
|
|
272
287
|
const ImageModal = () => {
|
|
273
288
|
const modalRef = useRef<BottomSheetModal>(null);
|
|
274
289
|
|
|
@@ -282,10 +297,7 @@ const ImageModal = () => {
|
|
|
282
297
|
description="Thanks for joining our community"
|
|
283
298
|
primaryButtonText="Get Started"
|
|
284
299
|
secondaryButtonText="Maybe Later"
|
|
285
|
-
image={{
|
|
286
|
-
source: require('./path/to/image.png'),
|
|
287
|
-
resizeMode: 'contain',
|
|
288
|
-
}}
|
|
300
|
+
image={<ModalImage source={require('./path/to/image.png')} resizeMode="contain" />}
|
|
289
301
|
onPressPrimaryButton={() => modalRef.current?.dismiss()}
|
|
290
302
|
onPressSecondaryButton={() => modalRef.current?.dismiss()}
|
|
291
303
|
/>
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ViewProps } from 'react-native';
|
|
2
3
|
import { BottomSheetProps } from '../BottomSheet';
|
|
3
4
|
import { ButtonWithoutChildrenProps } from '../Button/Button.props';
|
|
4
5
|
import { UnstyledIconButtonProps } from '../UnstyledIconButton';
|
|
5
6
|
|
|
6
7
|
interface ModalProps extends Omit<BottomSheetProps, 'children'> {
|
|
7
8
|
loading?: boolean;
|
|
8
|
-
image?:
|
|
9
|
+
image?: ReactNode;
|
|
9
10
|
showCloseButton?: boolean;
|
|
10
11
|
heading?: string;
|
|
11
12
|
description?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
2
|
import { useRef } from 'react';
|
|
3
3
|
import { ImageSourcePropType, Platform, View } from 'react-native';
|
|
4
|
-
import { Modal } from '.';
|
|
4
|
+
import { Modal, ModalImage } from '.';
|
|
5
5
|
import pigs from '../../../docs/assets/pigs.png';
|
|
6
6
|
import { ViewWrap } from '../../../docs/components';
|
|
7
7
|
import { BodyText } from '../BodyText';
|
|
@@ -117,10 +117,7 @@ export const WithImage = () => {
|
|
|
117
117
|
secondaryButtonText="Cancel"
|
|
118
118
|
onPressSecondaryButton={closeModal}
|
|
119
119
|
index={1}
|
|
120
|
-
image={{
|
|
121
|
-
source: pigs as ImageSourcePropType,
|
|
122
|
-
resizeMode: 'contain',
|
|
123
|
-
}}
|
|
120
|
+
image={<ModalImage source={pigs as ImageSourcePropType} resizeMode="contain" />}
|
|
124
121
|
/>
|
|
125
122
|
</ViewWrap>
|
|
126
123
|
</View>
|
|
@@ -2,7 +2,7 @@ import { BottomSheetScrollViewMethods, SNAP_POINT_TYPE } from '@gorhom/bottom-sh
|
|
|
2
2
|
import { BottomSheetModalMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
|
|
3
3
|
import { CloseMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
|
|
4
4
|
import { useCallback, useEffect, useImperativeHandle, useRef } from 'react';
|
|
5
|
-
import { AccessibilityInfo,
|
|
5
|
+
import { AccessibilityInfo, Platform, View, findNodeHandle } from 'react-native';
|
|
6
6
|
import Animated, {
|
|
7
7
|
Easing,
|
|
8
8
|
useAnimatedStyle,
|
|
@@ -200,7 +200,7 @@ const Modal = ({
|
|
|
200
200
|
</View>
|
|
201
201
|
{image ? (
|
|
202
202
|
<View style={styles.imageContainer}>
|
|
203
|
-
|
|
203
|
+
{image}
|
|
204
204
|
<View style={styles.textContent}>
|
|
205
205
|
{heading ? (
|
|
206
206
|
<Heading size="lg" textAlign="center" accessible>
|
|
@@ -296,10 +296,6 @@ const styles = StyleSheet.create((theme, rt) => ({
|
|
|
296
296
|
flex: 1,
|
|
297
297
|
gap: theme.components.modal.content.gap,
|
|
298
298
|
},
|
|
299
|
-
image: {
|
|
300
|
-
width: 260,
|
|
301
|
-
height: 260,
|
|
302
|
-
},
|
|
303
299
|
imageContainer: {
|
|
304
300
|
alignItems: 'center',
|
|
305
301
|
flex: 1,
|
|
@@ -2,7 +2,7 @@ import { BottomSheetScrollViewMethods, SNAP_POINT_TYPE } from '@gorhom/bottom-sh
|
|
|
2
2
|
import { BottomSheetModalMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
|
|
3
3
|
import { CloseMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
|
|
4
4
|
import { useCallback, useEffect, useImperativeHandle, useRef } from 'react';
|
|
5
|
-
import { AccessibilityInfo,
|
|
5
|
+
import { AccessibilityInfo, Platform, View, findNodeHandle } from 'react-native';
|
|
6
6
|
import Animated, {
|
|
7
7
|
Easing,
|
|
8
8
|
useAnimatedStyle,
|
|
@@ -197,7 +197,7 @@ const Modal = ({
|
|
|
197
197
|
</View>
|
|
198
198
|
{image ? (
|
|
199
199
|
<View style={styles.imageContainer}>
|
|
200
|
-
|
|
200
|
+
{image}
|
|
201
201
|
<View style={styles.textContent}>
|
|
202
202
|
{heading ? (
|
|
203
203
|
<Heading size="lg" textAlign="center" accessible>
|
|
@@ -281,10 +281,6 @@ const styles = StyleSheet.create((theme, rt) => ({
|
|
|
281
281
|
flex: 1,
|
|
282
282
|
gap: theme.components.modal.content.gap,
|
|
283
283
|
},
|
|
284
|
-
image: {
|
|
285
|
-
width: 260,
|
|
286
|
-
height: 260,
|
|
287
|
-
},
|
|
288
284
|
imageContainer: {
|
|
289
285
|
alignItems: 'center',
|
|
290
286
|
justifyContent: 'center',
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Image, ImageProps } from 'react-native';
|
|
2
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
3
|
+
import { isThemedImageProps } from '../../utils';
|
|
4
|
+
import { ThemedImage, ThemedImageProps } from '../ThemedImage';
|
|
5
|
+
|
|
6
|
+
const ModalImage = (props: ImageProps | ThemedImageProps) => {
|
|
7
|
+
if (isThemedImageProps(props)) {
|
|
8
|
+
return <ThemedImage {...props} style={[styles.image, props.style]} />;
|
|
9
|
+
}
|
|
10
|
+
return <Image resizeMode="cover" {...props} style={[styles.image, props.style]} />;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const styles = StyleSheet.create({
|
|
14
|
+
image: {
|
|
15
|
+
width: 260,
|
|
16
|
+
height: 260,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export default ModalImage;
|
|
@@ -142,7 +142,7 @@ export const Multiple: Story = {
|
|
|
142
142
|
return (
|
|
143
143
|
<Flex space="lg" direction="column" align="center" style={{ maxWidth: 400 }}>
|
|
144
144
|
<PillGroup wrap={true} multiple value={selectedCategories} onChange={v => setSelectedCategories(v as string[])}>
|
|
145
|
-
<Pill value="
|
|
145
|
+
<Pill value="unread" label="Unread" />
|
|
146
146
|
<Pill value="new" label="New" icon={HeartMediumIcon} />
|
|
147
147
|
<Pill value="favourites" label="My favourites" icon={HeartMediumIcon} />
|
|
148
148
|
<Pill value="read" label="Read" />
|
|
@@ -104,7 +104,7 @@ const MyComponent = () => {
|
|
|
104
104
|
| `validText` | `string` | - | The valid text to be displayed below the radio. |
|
|
105
105
|
| `showValidationIcon` | `boolean` | `true` | Whether to show the validation icon. |
|
|
106
106
|
| `type` | `'default' \| 'tile'` | `default` | The type of the radio. |
|
|
107
|
-
| `image` | `
|
|
107
|
+
| `image` | `ReactNode` | - | The image to be displayed next to the label. |
|
|
108
108
|
|
|
109
109
|
## Components
|
|
110
110
|
|
|
@@ -150,6 +150,15 @@ Contains all Group related layout style props and actions. It inherits all the p
|
|
|
150
150
|
|
|
151
151
|
### `RadioImage`
|
|
152
152
|
|
|
153
|
+
| Property | Type | Description |
|
|
154
|
+
| --------- | --------------------- | ------------------------------------------------------------------------ |
|
|
155
|
+
| `source` | `ImageSourcePropType` | The source of the image to display |
|
|
156
|
+
| `light` | `ImageSourcePropType` | The source of the image to display in light mode (use instead of source) |
|
|
157
|
+
| `dark` | `ImageSourcePropType` | The source of the image to display in dark mode (use instead of source) |
|
|
158
|
+
| `...rest` | `ImageProps` | Additional props to pass to the underlying Image component |
|
|
159
|
+
|
|
160
|
+
For more details about the ThemedImage component used internally, refer to the [`ThemedImage` documentation](/docs/utility-components-themed-image--docs).
|
|
161
|
+
|
|
153
162
|
Contains all Image related layout style props and actions. It inherits all the properties of React Native's [Image component](https://reactnative.dev/docs/image).
|
|
154
163
|
|
|
155
164
|
## Variants
|
|
@@ -261,9 +270,9 @@ The `RadioImage` component is used to display an image next to the radio button.
|
|
|
261
270
|
<Canvas of={Stories.WithImage} />
|
|
262
271
|
|
|
263
272
|
```tsx
|
|
264
|
-
import { Radio, RadioGroup } from '@utilitywarehouse/native-ui';
|
|
273
|
+
import { Radio, RadioGroup, RadioImage } from '@utilitywarehouse/native-ui';
|
|
265
274
|
import visaLogo from './visa-logo.png';
|
|
266
|
-
import
|
|
275
|
+
import mastercardLogo from './mastercard-logo.png';
|
|
267
276
|
|
|
268
277
|
const MyComponent = () => {
|
|
269
278
|
const [value, setValue] = React.useState('Option 1');
|
|
@@ -273,16 +282,20 @@ const MyComponent = () => {
|
|
|
273
282
|
value="visa"
|
|
274
283
|
aria-label="Visa"
|
|
275
284
|
label="Visa"
|
|
276
|
-
image={
|
|
285
|
+
image={
|
|
286
|
+
<RadioImage source={visaLogo} style={{ width: 40, height: 24, resizeMode: 'contain' }} />
|
|
287
|
+
}
|
|
277
288
|
/>
|
|
278
289
|
<Radio
|
|
279
290
|
value="mastercard"
|
|
280
291
|
aria-label="Mastercard"
|
|
281
292
|
label="Mastercard"
|
|
282
|
-
image={
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
293
|
+
image={
|
|
294
|
+
<RadioImage
|
|
295
|
+
source={mastercardLogo}
|
|
296
|
+
style={{ width: 40, height: 24, resizeMode: 'contain' }}
|
|
297
|
+
/>
|
|
298
|
+
}
|
|
286
299
|
/>
|
|
287
300
|
</RadioGroup>
|
|
288
301
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ComponentType } from 'react';
|
|
2
|
-
import type {
|
|
1
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
+
import type { PressableProps, ViewProps } from 'react-native';
|
|
3
3
|
|
|
4
4
|
interface RadioBaseProps extends Omit<PressableProps, 'children'> {
|
|
5
5
|
value: string;
|
|
@@ -28,7 +28,7 @@ interface RadioWithoutChildrenProps extends RadioBaseProps {
|
|
|
28
28
|
invalidText?: string;
|
|
29
29
|
validText?: string;
|
|
30
30
|
showValidationIcon?: boolean;
|
|
31
|
-
image?:
|
|
31
|
+
image?: ReactNode;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
type RadioProps = RadioWithChildrenProps | RadioWithoutChildrenProps;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { ImageSourcePropType } from 'react-native';
|
|
4
|
-
import { Radio, RadioGroup } from '.';
|
|
4
|
+
import { Radio, RadioGroup, RadioImage } from '.';
|
|
5
5
|
import bankLogo from '../../../docs/assets/bank-logo.png';
|
|
6
6
|
import bankLogo1 from '../../../docs/assets/bank-logo1.png';
|
|
7
7
|
import { VariantTitle } from '../../../docs/components';
|
|
@@ -106,11 +106,13 @@ export const WithImage: Story = {
|
|
|
106
106
|
{...args}
|
|
107
107
|
label="Visa"
|
|
108
108
|
value="Option 1"
|
|
109
|
-
image={
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
image={
|
|
110
|
+
<RadioImage
|
|
111
|
+
source={bankLogo1 as ImageSourcePropType}
|
|
112
|
+
style={{ width: 48, height: 32 }}
|
|
113
|
+
resizeMode="cover"
|
|
114
|
+
/>
|
|
115
|
+
}
|
|
114
116
|
/>
|
|
115
117
|
<Radio
|
|
116
118
|
aria-label="Label 2"
|
|
@@ -121,11 +123,13 @@ export const WithImage: Story = {
|
|
|
121
123
|
{...args}
|
|
122
124
|
label="Mastercard"
|
|
123
125
|
value="Option 2"
|
|
124
|
-
image={
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
image={
|
|
127
|
+
<RadioImage
|
|
128
|
+
source={bankLogo as ImageSourcePropType}
|
|
129
|
+
style={{ width: 48, height: 32 }}
|
|
130
|
+
resizeMode="cover"
|
|
131
|
+
/>
|
|
132
|
+
}
|
|
129
133
|
/>
|
|
130
134
|
</RadioGroup>
|
|
131
135
|
),
|
|
@@ -9,7 +9,6 @@ import StyledRadio from './RadioRoot';
|
|
|
9
9
|
import { useFormFieldContext } from '../FormField';
|
|
10
10
|
import { Helper } from '../Helper';
|
|
11
11
|
import { useRadioGroupContext } from './RadioGroup.context';
|
|
12
|
-
import RadioImage from './RadioImage';
|
|
13
12
|
import RadioTextContent from './RadioTextContent';
|
|
14
13
|
import RadioTileRoot from './RadioTileRoot';
|
|
15
14
|
|
|
@@ -57,7 +56,7 @@ const Radio = ({
|
|
|
57
56
|
<RadioIndicator>
|
|
58
57
|
<RadioIcon />
|
|
59
58
|
</RadioIndicator>
|
|
60
|
-
{image ?
|
|
59
|
+
{image ? image : null}
|
|
61
60
|
<RadioTextContent>
|
|
62
61
|
{!!label && <RadioLabel>{label}</RadioLabel>}
|
|
63
62
|
{!!helperText && <Helper disabled={disabled} icon={helperIcon} text={helperText} />}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { Image, ImageProps } from 'react-native';
|
|
2
|
+
import { isThemedImageProps } from '../../utils';
|
|
3
|
+
import { ThemedImage, ThemedImageProps } from '../ThemedImage';
|
|
2
4
|
|
|
3
|
-
const RadioImage = ({
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
const RadioImage = ({ ...props }: ImageProps | ThemedImageProps) => {
|
|
6
|
+
if (isThemedImageProps(props)) {
|
|
7
|
+
return <ThemedImage {...props} />;
|
|
8
|
+
}
|
|
9
|
+
return <Image {...props} />;
|
|
10
|
+
};
|
|
6
11
|
|
|
7
12
|
RadioImage.displayName = 'RadioImage';
|
|
8
13
|
|
package/src/utils/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export { default as coloursAsArray, extractLightColorValues } from './coloursAsArray';
|
|
2
2
|
export { default as formatThousands } from './formatThousands';
|
|
3
3
|
export { default as getFlattenedColorValue } from './getFlattenedColorValue';
|
|
4
|
+
export { getInitials } from './getInitials';
|
|
4
5
|
export { default as getStyleValue } from './getStyleValue';
|
|
5
6
|
export { default as hexWithOpacity } from './hexWithOpacity';
|
|
6
|
-
export { getInitials } from './getInitials';
|
|
7
7
|
export { default as isEqual } from './isEqual';
|
|
8
|
+
export { default as isThemedImageProps } from './isThemedImageProps';
|
|
8
9
|
export * from './styleUtils';
|
|
9
10
|
export * from './themeValueHelpers';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ImageProps } from 'react-native';
|
|
2
|
+
import { ThemedImageProps } from 'src/components';
|
|
3
|
+
|
|
4
|
+
const isThemedImageProps = (props: ThemedImageProps | ImageProps): props is ThemedImageProps => {
|
|
5
|
+
return 'light' in props && 'dark' in props;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default isThemedImageProps;
|