@utilitywarehouse/hearth-react-native 0.8.0 → 0.8.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 (45) hide show
  1. package/.storybook/preview.tsx +1 -0
  2. package/.turbo/turbo-build.log +1 -1
  3. package/.turbo/turbo-lint.log +1 -1
  4. package/CHANGELOG.md +22 -0
  5. package/build/components/Banner/Banner.js +27 -7
  6. package/build/components/Banner/Banner.props.d.ts +4 -9
  7. package/build/components/Card/Card.props.d.ts +1 -0
  8. package/build/components/Card/CardRoot.d.ts +1 -1
  9. package/build/components/Card/CardRoot.js +28 -1
  10. package/build/components/HighlightBanner/HighlightBanner.js +12 -2
  11. package/build/components/HighlightBanner/HighlightBanner.props.d.ts +1 -1
  12. package/build/components/List/List.js +1 -1
  13. package/build/components/List/ListAction/ListActionTrailingIcon.js +2 -2
  14. package/build/components/RadioCard/RadioCardGroup.context.d.ts +12 -0
  15. package/build/components/RadioCard/RadioCardGroup.context.js +3 -0
  16. package/build/components/RadioCard/RadioCardGroup.js +15 -10
  17. package/build/components/RadioCard/RadioCardLabel.d.ts +1 -1
  18. package/build/components/RadioCard/RadioCardLabel.js +7 -1
  19. package/build/components/RadioCard/RadioCardRoot.js +13 -0
  20. package/build/core/themes.d.ts +40 -0
  21. package/build/core/themes.js +20 -0
  22. package/docs/adding-shadows.mdx +43 -0
  23. package/package.json +3 -3
  24. package/src/components/Banner/Banner.docs.mdx +1 -1
  25. package/src/components/Banner/Banner.props.ts +4 -9
  26. package/src/components/Banner/Banner.stories.tsx +16 -0
  27. package/src/components/Banner/Banner.tsx +46 -31
  28. package/src/components/Card/Card.docs.mdx +20 -1
  29. package/src/components/Card/Card.props.ts +9 -0
  30. package/src/components/Card/Card.stories.tsx +39 -0
  31. package/src/components/Card/CardRoot.tsx +29 -0
  32. package/src/components/Checkbox/CheckboxGroup.stories.tsx +19 -1
  33. package/src/components/HighlightBanner/HighlightBanner.docs.mdx +21 -2
  34. package/src/components/HighlightBanner/HighlightBanner.props.ts +1 -0
  35. package/src/components/HighlightBanner/HighlightBanner.stories.tsx +31 -1
  36. package/src/components/HighlightBanner/HighlightBanner.tsx +16 -4
  37. package/src/components/List/List.tsx +5 -3
  38. package/src/components/List/ListAction/ListActionTrailingIcon.tsx +2 -2
  39. package/src/components/Radio/RadioGroup.stories.tsx +18 -0
  40. package/src/components/RadioCard/RadioCardGroup.context.ts +16 -0
  41. package/src/components/RadioCard/RadioCardGroup.stories.tsx +24 -0
  42. package/src/components/RadioCard/RadioCardGroup.tsx +28 -19
  43. package/src/components/RadioCard/RadioCardLabel.tsx +12 -1
  44. package/src/components/RadioCard/RadioCardRoot.tsx +15 -0
  45. package/src/core/themes.ts +20 -0
@@ -72,6 +72,7 @@ const preview = {
72
72
  'Theme Tokens',
73
73
  'Hooks',
74
74
  'Layout Components',
75
+ 'Guides',
75
76
  'All Components',
76
77
  'Primitives',
77
78
  'Typography',
@@ -1,4 +1,4 @@
1
1
 
2
- > @utilitywarehouse/hearth-react-native@0.8.0 build /home/runner/work/hearth/hearth/packages/react-native
2
+ > @utilitywarehouse/hearth-react-native@0.8.2 build /home/runner/work/hearth/hearth/packages/react-native
3
3
  > tsc
4
4
 
@@ -1,5 +1,5 @@
1
1
 
2
- > @utilitywarehouse/hearth-react-native@0.8.0 lint /home/runner/work/hearth/hearth/packages/react-native
2
+ > @utilitywarehouse/hearth-react-native@0.8.2 lint /home/runner/work/hearth/hearth/packages/react-native
3
3
  > TIMING=1 eslint --max-warnings 0
4
4
 
5
5
  Rule | Time (ms) | Relative
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @utilitywarehouse/hearth-react-native
2
2
 
3
+ ## 0.8.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#652](https://github.com/utilitywarehouse/hearth/pull/652) [`5119703`](https://github.com/utilitywarehouse/hearth/commit/5119703a31f663cc8c0a8bb2c6ba5b10f9bf72d6) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `RadioCard` label wrapping issue
8
+
9
+ - [#648](https://github.com/utilitywarehouse/hearth/pull/648) [`c90ea5c`](https://github.com/utilitywarehouse/hearth/commit/c90ea5ce165f27ccfc9774ec58ac642d02b349d1) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `ListAction` icon size
10
+
11
+ - [#648](https://github.com/utilitywarehouse/hearth/pull/648) [`c90ea5c`](https://github.com/utilitywarehouse/hearth/commit/c90ea5ce165f27ccfc9774ec58ac642d02b349d1) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `Banner` text gap size
12
+
13
+ - [#651](https://github.com/utilitywarehouse/hearth/pull/651) [`4ee77b7`](https://github.com/utilitywarehouse/hearth/commit/4ee77b75e58ac4abbeba375ecb367d8899c7f1a0) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `Banner` image and height issue
14
+
15
+ - [#649](https://github.com/utilitywarehouse/hearth/pull/649) [`7374535`](https://github.com/utilitywarehouse/hearth/commit/737453598ad5e885b35b5fcd2e4c4ccff4910c43) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `List` to only show `Card` container if it has children
16
+
17
+ - [#648](https://github.com/utilitywarehouse/hearth/pull/648) [`c90ea5c`](https://github.com/utilitywarehouse/hearth/commit/c90ea5ce165f27ccfc9774ec58ac642d02b349d1) Thanks [@jordmccord](https://github.com/jordmccord)! - Adds `shadowColor` prop to `Card` and exposes helpers in theme
18
+
19
+ ## 0.8.1
20
+
21
+ ### Patch Changes
22
+
23
+ - [#641](https://github.com/utilitywarehouse/hearth/pull/641) [`251242e`](https://github.com/utilitywarehouse/hearth/commit/251242e218c0b24589c3fb6fb6963b53bda8a367) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `HighlightBanner` when no image is provided
24
+
3
25
  ## 0.8.0
4
26
 
5
27
  ### Minor Changes
@@ -16,10 +16,10 @@ const Banner = ({ icon, iconContainerVariant = 'subtle', iconContainerSize = 'md
16
16
  return (_jsx(IconContainer, { icon: icon, variant: iconContainerVariant, size: iconContainerSize, color: iconContainerColor, style: styles.media }));
17
17
  }
18
18
  if (illustration) {
19
- return (_jsx(ThemedImage, { light: illustration.light, dark: illustration.dark, style: styles.image, accessible: true, accessibilityLabel: heading }));
19
+ return (_jsx(ThemedImage, { ...illustration, resizeMode: "cover", style: [styles.media, styles.imageWrapper, illustration.style] }));
20
20
  }
21
21
  if (image) {
22
- return (_jsx(View, { style: [styles.media, styles.imageWrapper], children: _jsx(ThemedImage, { light: image.light, dark: image.dark, style: styles.image, accessible: true, accessibilityLabel: heading }) }));
22
+ return (_jsx(View, { style: [styles.media, styles.imageWrapper], children: _jsx(ThemedImage, { ...image, style: [styles.image, image.style] }) }));
23
23
  }
24
24
  return null;
25
25
  };
@@ -32,7 +32,7 @@ const Banner = ({ icon, iconContainerVariant = 'subtle', iconContainerSize = 'md
32
32
  }
33
33
  return null;
34
34
  };
35
- const content = (_jsxs(View, { style: styles.container, children: [renderIconOrImage(), _jsxs(View, { style: styles.contentContainer, children: [_jsxs(View, { style: styles.textContainer, children: [_jsx(Heading, { size: "sm", style: styles.heading, textAlign: hasIllustration && direction === 'vertical' ? 'center' : 'left', children: heading }), _jsx(BodyText, { size: "md", style: styles.description, textAlign: hasIllustration && direction === 'vertical' ? 'center' : 'left', children: description }), renderAction()] }), onPress && (_jsx(UnstyledIconButton, { icon: ChevronRightSmallIcon, size: "sm", onPress: onPress, style: styles.chevron })), onClose && (_jsx(UnstyledIconButton, { icon: CloseSmallIcon, size: "sm", onPress: onClose, style: styles.closeButton, accessibilityLabel: "Close banner" }))] })] }));
35
+ const content = (_jsxs(View, { style: styles.container, children: [renderIconOrImage(), _jsxs(View, { style: styles.contentContainer, children: [_jsxs(View, { style: styles.contentTextContainer, children: [_jsxs(View, { style: styles.textContainer, children: [_jsx(Heading, { size: "sm", style: styles.heading, textAlign: hasIllustration && direction === 'vertical' ? 'center' : 'left', children: heading }), _jsx(BodyText, { size: "md", style: styles.description, textAlign: hasIllustration && direction === 'vertical' ? 'center' : 'left', children: description })] }), renderAction()] }), onPress && (_jsx(UnstyledIconButton, { icon: ChevronRightSmallIcon, size: "sm", onPress: onPress, style: styles.chevron })), onClose && (_jsx(UnstyledIconButton, { icon: CloseSmallIcon, size: "sm", onPress: onClose, style: styles.closeButton, accessibilityLabel: "Close banner" }))] })] }));
36
36
  if (onPress) {
37
37
  return (_jsx(Card, { variant: variant, style: [styles.card, style], ...props, children: _jsx(Pressable, { onPress: onPress, accessibilityRole: "button", style: styles.pressable, children: content }) }));
38
38
  }
@@ -92,6 +92,7 @@ const styles = StyleSheet.create(theme => ({
92
92
  },
93
93
  },
94
94
  imageWrapper: {
95
+ flexDirection: 'row',
95
96
  variants: {
96
97
  direction: {
97
98
  horizontal: {},
@@ -103,8 +104,8 @@ const styles = StyleSheet.create(theme => ({
103
104
  },
104
105
  image: {
105
106
  borderRadius: theme.borderRadius.md,
106
- borderWidth: theme.borderWidth[1],
107
107
  borderColor: theme.color.border.strong,
108
+ borderWidth: theme.borderWidth[1],
108
109
  variants: {
109
110
  direction: {
110
111
  horizontal: { width: 160, height: 95 },
@@ -116,15 +117,34 @@ const styles = StyleSheet.create(theme => ({
116
117
  },
117
118
  },
118
119
  contentContainer: {
119
- flex: 1,
120
- flexDirection: 'row',
121
120
  alignItems: 'flex-start',
122
121
  justifyContent: 'space-between',
123
122
  gap: theme.space.lg,
123
+ variants: {
124
+ direction: {
125
+ horizontal: {
126
+ flex: 1,
127
+ flexDirection: 'row',
128
+ },
129
+ vertical: {
130
+ flexDirection: 'column',
131
+ },
132
+ },
133
+ },
124
134
  },
125
135
  textContainer: {
126
- flex: 1,
136
+ gap: theme.space.sm,
137
+ },
138
+ contentTextContainer: {
127
139
  gap: theme.space.lg,
140
+ variants: {
141
+ direction: {
142
+ horizontal: {
143
+ flex: 1,
144
+ },
145
+ vertical: {},
146
+ },
147
+ },
128
148
  },
129
149
  heading: {
130
150
  compoundVariants: [
@@ -1,6 +1,7 @@
1
1
  import type { ComponentType, ReactElement } from 'react';
2
- import type { ImageSourcePropType } from 'react-native';
2
+ import { ImageProps } from 'react-native';
3
3
  import type CardProps from '../Card/Card.props';
4
+ import { ThemedImageProps } from '../ThemedImage';
4
5
  export type BannerDirection = 'horizontal' | 'vertical';
5
6
  export interface BannerProps extends Omit<CardProps, 'noPadding' | 'variant' | 'colorScheme' | 'space' | 'gap' | 'rowGap' | 'columnGap' | 'flexDirection' | 'flexWrap' | 'alignItems' | 'justifyContent'> {
6
7
  /**
@@ -27,18 +28,12 @@ export interface BannerProps extends Omit<CardProps, 'noPadding' | 'variant' | '
27
28
  * Illustration to display in the banner
28
29
  * Mutually exclusive with icon and image
29
30
  */
30
- illustration?: {
31
- light: ImageSourcePropType | ReactElement | ComponentType;
32
- dark: ImageSourcePropType | ReactElement | ComponentType;
33
- };
31
+ illustration?: ThemedImageProps & ImageProps;
34
32
  /**
35
33
  * Image to display in the banner
36
34
  * Mutually exclusive with icon and illustration
37
35
  */
38
- image?: {
39
- light: ImageSourcePropType | ReactElement | ComponentType;
40
- dark: ImageSourcePropType | ReactElement | ComponentType;
41
- };
36
+ image?: ThemedImageProps & ImageProps;
42
37
  /**
43
38
  * Heading text
44
39
  */
@@ -3,6 +3,7 @@ import { SpaceValue, SpacingValues } from '../../types';
3
3
  interface CardProps extends PressableProps {
4
4
  variant?: 'emphasis' | 'subtle';
5
5
  colorScheme?: 'neutralStrong' | 'neutralSubtle' | 'brand' | 'energy' | 'broadband' | 'mobile' | 'insurance' | 'cashback' | 'pig';
6
+ shadowColor?: 'functional' | 'brand' | 'energy' | 'broadband' | 'mobile' | 'insurance' | 'cashback' | 'pig';
6
7
  noPadding?: boolean;
7
8
  disabled?: boolean;
8
9
  space?: SpacingValues;
@@ -1,6 +1,6 @@
1
1
  import CardProps from './Card.props';
2
2
  declare const Card: {
3
- ({ children, variant, colorScheme, noPadding, style, states, space, disabled, onPress, ...rest }: CardProps & {
3
+ ({ children, variant, colorScheme, shadowColor, noPadding, style, states, space, disabled, onPress, ...rest }: CardProps & {
4
4
  states?: {
5
5
  active?: boolean;
6
6
  disabled?: boolean;
@@ -83,7 +83,7 @@ const collectChildActionHandlers = (children) => React.Children.toArray(children
83
83
  }
84
84
  return handlers;
85
85
  }, []);
86
- const Card = ({ children, variant = 'subtle', colorScheme = 'neutralStrong', noPadding = false, style, states, space, disabled = false, onPress, ...rest }) => {
86
+ const Card = ({ children, variant = 'subtle', colorScheme = 'neutralStrong', shadowColor, noPadding = false, style, states, space, disabled = false, onPress, ...rest }) => {
87
87
  const { active } = states || { active: false };
88
88
  const childActionHandlers = collectChildActionHandlers(children);
89
89
  const hasActions = checkForComponentType(children, 'CardAction');
@@ -123,6 +123,7 @@ const Card = ({ children, variant = 'subtle', colorScheme = 'neutralStrong', noP
123
123
  showPressed,
124
124
  disabled,
125
125
  space: hasActions || hasContent ? 'none' : space,
126
+ shadowColor,
126
127
  });
127
128
  const renderChildren = () => {
128
129
  // Default: render children as-is
@@ -190,6 +191,32 @@ const styles = StyleSheet.create(theme => ({
190
191
  borderWidth: theme.components.card.brand.borderWidth,
191
192
  },
192
193
  },
194
+ shadowColor: {
195
+ functional: {
196
+ boxShadow: theme.helpers.shadow.functional,
197
+ },
198
+ brand: {
199
+ boxShadow: theme.helpers.shadow.brand,
200
+ },
201
+ energy: {
202
+ boxShadow: theme.helpers.shadow.energy,
203
+ },
204
+ broadband: {
205
+ boxShadow: theme.helpers.shadow.broadband,
206
+ },
207
+ mobile: {
208
+ boxShadow: theme.helpers.shadow.mobile,
209
+ },
210
+ insurance: {
211
+ boxShadow: theme.helpers.shadow.insurance,
212
+ },
213
+ cashback: {
214
+ boxShadow: theme.helpers.shadow.cashback,
215
+ },
216
+ pig: {
217
+ boxShadow: theme.helpers.shadow.pig,
218
+ },
219
+ },
193
220
  noPadding: {
194
221
  true: {
195
222
  padding: theme.components.card.mobile.paddingNone,
@@ -4,8 +4,8 @@ import { StyleSheet } from 'react-native-unistyles';
4
4
  import { BodyText } from '../BodyText';
5
5
  import { Card } from '../Card';
6
6
  const HighlightBanner = ({ heading, headingColor, image, imageContainerHeight, description, link, button, variant = 'emphasis', style, ...props }) => {
7
- styles.useVariants({ headingColor, variant });
8
- return (_jsx(Card, { variant: variant, noPadding: true, style: style, ...props, children: _jsxs(View, { style: [styles.container], children: [_jsx(View, { style: [styles.header], children: _jsx(BodyText, { size: "md", textAlign: "center", weight: "semibold", children: heading }) }), _jsx(View, { style: styles.imageContainer(imageContainerHeight), children: _jsx(Image, { resizeMode: "cover", ...image, style: [styles.image, image?.style] }) }), _jsxs(View, { style: styles.footer, children: [_jsx(BodyText, { size: "md", textAlign: "center", children: description }), link && _jsx(View, { style: styles.linkContainer, children: link }), button && _jsx(View, { style: styles.buttonContainer, children: button })] })] }) }));
7
+ styles.useVariants({ headingColor, variant, hasImage: Boolean(image) });
8
+ return (_jsx(Card, { variant: variant, noPadding: true, style: style, ...props, children: _jsxs(View, { style: [styles.container], children: [_jsx(View, { style: [styles.header], children: _jsx(BodyText, { size: "md", textAlign: "center", weight: "semibold", children: heading }) }), !!image && (_jsx(View, { style: styles.imageContainer(imageContainerHeight), children: _jsx(Image, { resizeMode: "cover", ...image, style: [styles.image, image?.style] }) })), _jsxs(View, { style: styles.footer, children: [_jsx(BodyText, { size: "md", textAlign: "center", children: description }), link && _jsx(View, { style: styles.linkContainer, children: link }), button && _jsx(View, { style: styles.buttonContainer, children: button })] })] }) }));
9
9
  };
10
10
  HighlightBanner.displayName = 'HighlightBanner';
11
11
  const styles = StyleSheet.create(theme => ({
@@ -51,6 +51,11 @@ const styles = StyleSheet.create(theme => ({
51
51
  borderColor: theme.color.border.subtle,
52
52
  },
53
53
  },
54
+ hasImage: {
55
+ false: {
56
+ borderBottomWidth: 0,
57
+ },
58
+ },
54
59
  },
55
60
  },
56
61
  imageContainer: (height = 200) => ({
@@ -74,6 +79,11 @@ const styles = StyleSheet.create(theme => ({
74
79
  borderColor: theme.color.border.subtle,
75
80
  },
76
81
  },
82
+ hasImage: {
83
+ true: {
84
+ flex: 1,
85
+ },
86
+ },
77
87
  },
78
88
  },
79
89
  linkContainer: {
@@ -1,7 +1,7 @@
1
1
  import { ReactElement } from 'react';
2
2
  import { ImageProps } from 'react-native';
3
3
  import CardProps from '../Card/Card.props';
4
- interface HighlightBannerProps extends Omit<CardProps, 'noPadding' | 'variant' | 'space' | 'gap' | 'rowGap' | 'columnGap' | 'flexDirection' | 'flexWrap' | 'alignItems' | 'justifyContent'> {
4
+ interface HighlightBannerProps extends Omit<CardProps, 'noPadding' | 'variant' | 'space' | 'gap' | 'rowGap' | 'columnGap' | 'flexDirection' | 'flexWrap' | 'alignItems' | 'justifyContent' | 'colorScheme'> {
5
5
  heading?: string;
6
6
  headingColor?: 'pig' | 'energy' | 'broadband' | 'mobile' | 'insurance' | 'cashback' | 'highlight';
7
7
  variant?: 'emphasis' | 'subtle';
@@ -44,7 +44,7 @@ const List = ({ children, heading, helperText, headerTrailingContent, ...props }
44
44
  const updatedChildren = markFirstListItem(children);
45
45
  const value = useMemo(() => ({ loading, disabled, container }), [loading, disabled, container]);
46
46
  styles.useVariants({ disabled });
47
- 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 })) : null, container === 'none' ? (_jsx(View, { children: updatedChildren })) : (_jsx(Card, { ...containerToCard, noPadding: true, style: styles.card, children: _jsx(_Fragment, { children: updatedChildren }) }))] }) }));
47
+ 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 })) : null, container === 'none' ? (_jsx(View, { children: updatedChildren })) : (React.Children.count(updatedChildren) > 0 && (_jsx(Card, { ...containerToCard, noPadding: true, style: styles.card, children: _jsx(_Fragment, { children: updatedChildren }) })))] }) }));
48
48
  };
49
49
  List.displayName = 'List';
50
50
  const styles = StyleSheet.create(theme => ({
@@ -12,8 +12,8 @@ ListActionTrailingIcon.displayName = 'ListActionTrailingIcon';
12
12
  const styles = StyleSheet.create(theme => ({
13
13
  icon: {
14
14
  color: theme.color.icon.primary,
15
- width: 24,
16
- height: 24,
15
+ minWidth: 20,
16
+ minHeight: 20,
17
17
  },
18
18
  }));
19
19
  export default ListActionTrailingIcon;
@@ -0,0 +1,12 @@
1
+ export declare const RadioCardGroupContext: import("react").Context<{
2
+ flexDirection?: "row" | "column" | "row-reverse" | "column-reverse";
3
+ flexWrap?: "nowrap" | "wrap" | "wrap-reverse";
4
+ justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";
5
+ alignItems?: "flex-start" | "flex-end" | "center" | "stretch" | "baseline";
6
+ }>;
7
+ export declare const useRadioCardGroupContext: () => {
8
+ flexDirection?: "row" | "column" | "row-reverse" | "column-reverse";
9
+ flexWrap?: "nowrap" | "wrap" | "wrap-reverse";
10
+ justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";
11
+ alignItems?: "flex-start" | "flex-end" | "center" | "stretch" | "baseline";
12
+ };
@@ -0,0 +1,3 @@
1
+ import { createContext, useContext } from 'react';
2
+ export const RadioCardGroupContext = createContext({});
3
+ export const useRadioCardGroupContext = () => useContext(RadioCardGroupContext);
@@ -1,18 +1,23 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
2
3
  import { View } from 'react-native';
3
4
  import { StyleSheet } from 'react-native-unistyles';
4
5
  import { Grid } from '../Grid';
6
+ import { RadioCardGroupContext } from './RadioCardGroup.context';
5
7
  const RadioCardGroup = ({ children, gap = '200', style, flexDirection = 'row', flexWrap, justifyContent, alignItems, columns, ...props }) => {
6
- return columns ? (_jsx(Grid, { ...props, gap: gap, columns: columns, style: style, children: children })) : (_jsx(View, { ...props, style: [
7
- styles.containerGap(gap),
8
- {
9
- flexDirection,
10
- flexWrap,
11
- justifyContent,
12
- alignItems,
13
- },
14
- style,
15
- ], children: children }));
8
+ const context = useMemo(() => {
9
+ return { flexDirection, flexWrap, justifyContent, alignItems };
10
+ }, [flexDirection, flexWrap, justifyContent, alignItems]);
11
+ return columns ? (_jsx(RadioCardGroupContext.Provider, { value: context, children: _jsx(Grid, { ...props, gap: gap, columns: columns, style: style, children: children }) })) : (_jsx(RadioCardGroupContext.Provider, { value: context, children: _jsx(View, { ...props, style: [
12
+ styles.containerGap(gap),
13
+ {
14
+ flexDirection,
15
+ flexWrap,
16
+ justifyContent,
17
+ alignItems,
18
+ },
19
+ style,
20
+ ], children: children }) }));
16
21
  };
17
22
  const styles = StyleSheet.create(theme => ({
18
23
  containerGap: (gap) => ({
@@ -1,6 +1,6 @@
1
1
  import LabelProps from '../Label/Label.props';
2
2
  declare const RadioCardLabel: {
3
- ({ children, ...props }: LabelProps): import("react/jsx-runtime").JSX.Element;
3
+ ({ children, style, ...props }: LabelProps): import("react/jsx-runtime").JSX.Element;
4
4
  displayName: string;
5
5
  };
6
6
  export default RadioCardLabel;
@@ -1,5 +1,11 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { StyleSheet } from 'react-native-unistyles';
2
3
  import { Label } from '../Label';
3
- const RadioCardLabel = ({ children, ...props }) => _jsx(Label, { ...props, children: children });
4
+ const RadioCardLabel = ({ children, style, ...props }) => (_jsx(Label, { ...props, style: [styles.label, style], children: children }));
5
+ const styles = StyleSheet.create({
6
+ label: {
7
+ flexShrink: 1,
8
+ },
9
+ });
4
10
  RadioCardLabel.displayName = 'RadioCardLabel';
5
11
  export default RadioCardLabel;
@@ -3,14 +3,17 @@ import { useMemo } from 'react';
3
3
  import { StyleSheet } from 'react-native-unistyles';
4
4
  import { Pressable } from 'react-native';
5
5
  import { RadioCardContext } from './RadioCard.context';
6
+ import { useRadioCardGroupContext } from './RadioCardGroup.context';
6
7
  const RadioCardRoot = ({ children, style, states, ...props }) => {
7
8
  const { checked, active } = states ?? {};
9
+ const { flexDirection } = useRadioCardGroupContext() ?? {};
8
10
  const value = useMemo(() => ({
9
11
  checked,
10
12
  active,
11
13
  }), [checked, active]);
12
14
  styles.useVariants({
13
15
  selected: checked,
16
+ flexDirection,
14
17
  });
15
18
  return (_jsx(RadioCardContext.Provider, { value: value, children: _jsx(Pressable, { ...props, style: [styles.container, style], children: children }) }));
16
19
  };
@@ -37,6 +40,16 @@ const styles = StyleSheet.create(theme => ({
37
40
  margin: -theme.components.card.selectable.borderWidthSelected / 2,
38
41
  },
39
42
  },
43
+ flexDirection: {
44
+ row: {},
45
+ column: {
46
+ width: '100%',
47
+ },
48
+ 'row-reverse': {},
49
+ 'column-reverse': {
50
+ width: '100%',
51
+ },
52
+ },
40
53
  },
41
54
  _web: {
42
55
  '_focus-visible': {
@@ -2,6 +2,16 @@ import { DimensionValue } from 'react-native';
2
2
  import { components } from '../tokens';
3
3
  export declare const lightTheme: {
4
4
  readonly helpers: {
5
+ shadow: {
6
+ functional: string;
7
+ brand: string;
8
+ energy: string;
9
+ broadband: string;
10
+ mobile: string;
11
+ insurance: string;
12
+ cashback: string;
13
+ pig: string;
14
+ };
5
15
  focusVisible: {
6
16
  outlineStyle: string;
7
17
  outlineWidth: number;
@@ -1352,6 +1362,16 @@ export declare const lightTheme: {
1352
1362
  };
1353
1363
  export declare const darkTheme: {
1354
1364
  readonly helpers: {
1365
+ shadow: {
1366
+ functional: string;
1367
+ brand: string;
1368
+ energy: string;
1369
+ broadband: string;
1370
+ mobile: string;
1371
+ insurance: string;
1372
+ cashback: string;
1373
+ pig: string;
1374
+ };
1355
1375
  focusVisible: {
1356
1376
  outlineStyle: string;
1357
1377
  outlineWidth: number;
@@ -2714,6 +2734,16 @@ export declare const darkTheme: {
2714
2734
  export declare const themes: {
2715
2735
  readonly light: {
2716
2736
  readonly helpers: {
2737
+ shadow: {
2738
+ functional: string;
2739
+ brand: string;
2740
+ energy: string;
2741
+ broadband: string;
2742
+ mobile: string;
2743
+ insurance: string;
2744
+ cashback: string;
2745
+ pig: string;
2746
+ };
2717
2747
  focusVisible: {
2718
2748
  outlineStyle: string;
2719
2749
  outlineWidth: number;
@@ -4064,6 +4094,16 @@ export declare const themes: {
4064
4094
  };
4065
4095
  readonly dark: {
4066
4096
  readonly helpers: {
4097
+ shadow: {
4098
+ functional: string;
4099
+ brand: string;
4100
+ energy: string;
4101
+ broadband: string;
4102
+ mobile: string;
4103
+ insurance: string;
4104
+ cashback: string;
4105
+ pig: string;
4106
+ };
4067
4107
  focusVisible: {
4068
4108
  outlineStyle: string;
4069
4109
  outlineWidth: number;
@@ -254,6 +254,16 @@ const shared = {
254
254
  };
255
255
  const lightHelpers = {
256
256
  ...shared.helpers,
257
+ shadow: {
258
+ functional: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.default}`,
259
+ brand: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.brand}`,
260
+ energy: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.energy}`,
261
+ broadband: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.broadband}`,
262
+ mobile: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.mobile}`,
263
+ insurance: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.insurance}`,
264
+ cashback: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.cashback}`,
265
+ pig: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.pig}`,
266
+ },
257
267
  focusVisible: {
258
268
  outlineStyle: 'solid',
259
269
  outlineWidth: 2,
@@ -286,6 +296,16 @@ export const lightTheme = {
286
296
  };
287
297
  const darkHelpers = {
288
298
  ...shared.helpers,
299
+ shadow: {
300
+ functional: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.default}`,
301
+ brand: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.brand}`,
302
+ energy: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.energy}`,
303
+ broadband: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.broadband}`,
304
+ mobile: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.mobile}`,
305
+ insurance: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.insurance}`,
306
+ cashback: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.cashback}`,
307
+ pig: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.pig}`,
308
+ },
289
309
  focusVisible: {
290
310
  outlineStyle: 'solid',
291
311
  outlineWidth: 2,
@@ -0,0 +1,43 @@
1
+ import { Meta } from '@storybook/addon-docs/blocks';
2
+ import { BackToTopButton, NextPrevPage } from './components';
3
+
4
+ <Meta title="Guides / Adding Shadows" />
5
+ <BackToTopButton />
6
+
7
+ # Adding Shadows
8
+
9
+ You can add shadows to your components in Hearth React Native using the Unistyles styling system. Shadows help create depth and visual hierarchy in your UI.
10
+
11
+ - [Using Predefined Shadows](#using-predefined-shadows)
12
+ - [Components with Shadow Props](#components-with-shadow-props)
13
+
14
+ ## Using Predefined Shadows
15
+
16
+ Hearth provides a set of predefined shadow styles that you can easily apply to your components. These shadows are defined in the theme and can be accessed via the `theme.helpers.shadow` object.
17
+
18
+ ```tsx
19
+ import { View } from 'react-native';
20
+ import { StyleSheet, Input } from '@utilitywarehouse/hearth-react-native';
21
+
22
+ const styles = StyleSheet.create(theme => ({
23
+ input: {
24
+ boxShadow: theme.helpers.shadow.functional, // Apply a predefined shadow
25
+ },
26
+ }));
27
+
28
+ const MyComponent = () => (
29
+ <View>
30
+ <Input placeholder="Input with shadow" style={styles.input} />
31
+ </View>
32
+ );
33
+ ```
34
+
35
+ ## Components with Shadow Props
36
+
37
+ Some Hearth components, like `Card`, allow you to specify shadow colors directly via props. You can use the `shadowColor` prop to set the shadow color based on the theme.
38
+
39
+ ```tsx
40
+ import { Card } from '@utilitywarehouse/hearth-react-native';
41
+
42
+ const MyComponent = () => <Card shadowColor="brand">{/* Card content */}</Card>;
43
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilitywarehouse/hearth-react-native",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Utility Warehouse React Native UI library",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -57,8 +57,8 @@
57
57
  "vite-plugin-svgr": "^4.5.0",
58
58
  "vitest": "^3.2.4",
59
59
  "@utilitywarehouse/hearth-fonts": "^0.0.4",
60
- "@utilitywarehouse/hearth-react-icons": "^0.7.2",
61
- "@utilitywarehouse/hearth-react-native-icons": "^0.7.2",
60
+ "@utilitywarehouse/hearth-react-icons": "^0.7.3",
61
+ "@utilitywarehouse/hearth-react-native-icons": "^0.7.3",
62
62
  "@utilitywarehouse/hearth-svg-assets": "^0.2.0",
63
63
  "@utilitywarehouse/hearth-tokens": "^0.1.3"
64
64
  },
@@ -24,7 +24,7 @@ The `Banner` component is a versatile card-based component for displaying inform
24
24
  - [With Link](#with-link)
25
25
  - [Pressable](#pressable)
26
26
  - [With Close Button](#with-close-button)
27
- - [Vertical Layout](#vertical-layout)
27
+ - [Vertical Layout](#vertical-layout-1)
28
28
  - [Color Schemes](#color-schemes)
29
29
  - [Complex Examples](#complex-examples)
30
30
 
@@ -1,6 +1,7 @@
1
1
  import type { ComponentType, ReactElement } from 'react';
2
- import type { ImageSourcePropType } from 'react-native';
2
+ import { ImageProps } from 'react-native';
3
3
  import type CardProps from '../Card/Card.props';
4
+ import { ThemedImageProps } from '../ThemedImage';
4
5
 
5
6
  export type BannerDirection = 'horizontal' | 'vertical';
6
7
 
@@ -50,18 +51,12 @@ export interface BannerProps
50
51
  * Illustration to display in the banner
51
52
  * Mutually exclusive with icon and image
52
53
  */
53
- illustration?: {
54
- light: ImageSourcePropType | ReactElement | ComponentType;
55
- dark: ImageSourcePropType | ReactElement | ComponentType;
56
- };
54
+ illustration?: ThemedImageProps & ImageProps;
57
55
  /**
58
56
  * Image to display in the banner
59
57
  * Mutually exclusive with icon and illustration
60
58
  */
61
- image?: {
62
- light: ImageSourcePropType | ReactElement | ComponentType;
63
- dark: ImageSourcePropType | ReactElement | ComponentType;
64
- };
59
+ image?: ThemedImageProps & ImageProps;
65
60
  /**
66
61
  * Heading text
67
62
  */