@utilitywarehouse/hearth-react-native 0.10.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.
Files changed (132) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/CHANGELOG.md +18 -0
  4. package/build/components/Avatar/Avatar.d.ts +6 -0
  5. package/build/components/Avatar/Avatar.js +80 -0
  6. package/build/components/Avatar/Avatar.props.d.ts +28 -0
  7. package/build/components/Avatar/Avatar.props.js +1 -0
  8. package/build/components/Avatar/index.d.ts +2 -0
  9. package/build/components/Avatar/index.js +1 -0
  10. package/build/components/Banner/Banner.context.d.ts +7 -0
  11. package/build/components/Banner/Banner.context.js +8 -0
  12. package/build/components/Banner/Banner.js +10 -40
  13. package/build/components/Banner/Banner.props.d.ts +3 -5
  14. package/build/components/Banner/BannerIllustration.d.ts +4 -0
  15. package/build/components/Banner/BannerIllustration.js +53 -0
  16. package/build/components/Banner/BannerImage.d.ts +4 -0
  17. package/build/components/Banner/BannerImage.js +53 -0
  18. package/build/components/Banner/index.d.ts +2 -0
  19. package/build/components/Banner/index.js +2 -0
  20. package/build/components/Card/CardAction/CardAction.props.d.ts +2 -3
  21. package/build/components/Card/CardAction/CardActionRoot.js +1 -2
  22. package/build/components/Checkbox/Checkbox.js +1 -2
  23. package/build/components/Checkbox/Checkbox.props.d.ts +3 -3
  24. package/build/components/Checkbox/CheckboxImage.d.ts +2 -1
  25. package/build/components/Checkbox/CheckboxImage.js +8 -1
  26. package/build/components/DateInput/DateInput.d.ts +6 -0
  27. package/build/components/DateInput/DateInput.js +19 -0
  28. package/build/components/DateInput/DateInput.props.d.ts +79 -0
  29. package/build/components/DateInput/DateInput.props.js +1 -0
  30. package/build/components/DateInput/DateInputSegment.d.ts +20 -0
  31. package/build/components/DateInput/DateInputSegment.js +31 -0
  32. package/build/components/DateInput/index.d.ts +2 -0
  33. package/build/components/DateInput/index.js +1 -0
  34. package/build/components/ExpandableCard/ExpandableCard.props.d.ts +1 -2
  35. package/build/components/ExpandableCard/ExpandableCardTrigger.props.d.ts +4 -5
  36. package/build/components/ExpandableCard/ExpandableCardTriggerRoot.js +1 -14
  37. package/build/components/HighlightBanner/HighlightBanner.js +2 -6
  38. package/build/components/HighlightBanner/HighlightBanner.props.d.ts +2 -3
  39. package/build/components/HighlightBanner/HighlightBannerImage.d.ts +4 -0
  40. package/build/components/HighlightBanner/HighlightBannerImage.js +18 -0
  41. package/build/components/HighlightBanner/index.d.ts +1 -0
  42. package/build/components/HighlightBanner/index.js +1 -0
  43. package/build/components/Input/Input.d.ts +5 -7
  44. package/build/components/Input/Input.js +11 -4
  45. package/build/components/Input/InputField.d.ts +4 -7
  46. package/build/components/Input/InputField.js +6 -5
  47. package/build/components/List/ListItem/ListItem.props.d.ts +2 -2
  48. package/build/components/List/ListItem/ListItemRoot.js +1 -2
  49. package/build/components/Modal/Modal.js +2 -6
  50. package/build/components/Modal/Modal.props.d.ts +3 -2
  51. package/build/components/Modal/Modal.web.js +2 -6
  52. package/build/components/Modal/ModalImage.d.ts +4 -0
  53. package/build/components/Modal/ModalImage.js +18 -0
  54. package/build/components/Modal/index.d.ts +1 -0
  55. package/build/components/Modal/index.js +1 -0
  56. package/build/components/Radio/Radio.js +1 -2
  57. package/build/components/Radio/Radio.props.d.ts +3 -3
  58. package/build/components/Radio/RadioImage.d.ts +2 -1
  59. package/build/components/Radio/RadioImage.js +8 -1
  60. package/build/components/index.d.ts +2 -0
  61. package/build/components/index.js +2 -0
  62. package/build/utils/getInitials.d.ts +1 -0
  63. package/build/utils/getInitials.js +8 -0
  64. package/build/utils/index.d.ts +2 -0
  65. package/build/utils/index.js +2 -0
  66. package/build/utils/isThemedImageProps.d.ts +4 -0
  67. package/build/utils/isThemedImageProps.js +4 -0
  68. package/docs/components/AllComponents.web.tsx +18 -1
  69. package/package.json +2 -2
  70. package/src/components/Avatar/Avatar.docs.mdx +105 -0
  71. package/src/components/Avatar/Avatar.props.ts +31 -0
  72. package/src/components/Avatar/Avatar.stories.tsx +77 -0
  73. package/src/components/Avatar/Avatar.tsx +136 -0
  74. package/src/components/Avatar/index.ts +2 -0
  75. package/src/components/Banner/Banner.context.ts +11 -0
  76. package/src/components/Banner/Banner.docs.mdx +55 -37
  77. package/src/components/Banner/Banner.props.ts +3 -5
  78. package/src/components/Banner/Banner.stories.tsx +86 -57
  79. package/src/components/Banner/Banner.tsx +24 -67
  80. package/src/components/Banner/BannerIllustration.tsx +63 -0
  81. package/src/components/Banner/BannerImage.tsx +63 -0
  82. package/src/components/Banner/index.ts +2 -0
  83. package/src/components/Card/Card.docs.mdx +4 -4
  84. package/src/components/Card/CardAction/CardAction.props.ts +2 -3
  85. package/src/components/Card/CardAction/CardAction.stories.tsx +4 -3
  86. package/src/components/Card/CardAction/CardActionRoot.tsx +4 -5
  87. package/src/components/Checkbox/Checkbox.docs.mdx +23 -4
  88. package/src/components/Checkbox/Checkbox.props.ts +3 -3
  89. package/src/components/Checkbox/Checkbox.stories.tsx +14 -8
  90. package/src/components/Checkbox/Checkbox.tsx +1 -2
  91. package/src/components/Checkbox/CheckboxImage.tsx +8 -3
  92. package/src/components/DateInput/DateInput.docs.mdx +163 -0
  93. package/src/components/DateInput/DateInput.props.ts +80 -0
  94. package/src/components/DateInput/DateInput.stories.tsx +269 -0
  95. package/src/components/DateInput/DateInput.tsx +117 -0
  96. package/src/components/DateInput/DateInputSegment.tsx +83 -0
  97. package/src/components/DateInput/index.ts +2 -0
  98. package/src/components/ExpandableCard/ExpandableCard.docs.mdx +2 -2
  99. package/src/components/ExpandableCard/ExpandableCard.props.ts +1 -2
  100. package/src/components/ExpandableCard/ExpandableCard.stories.tsx +3 -3
  101. package/src/components/ExpandableCard/ExpandableCardTrigger.props.ts +4 -5
  102. package/src/components/ExpandableCard/ExpandableCardTriggerRoot.tsx +2 -17
  103. package/src/components/HighlightBanner/HighlightBanner.docs.mdx +73 -42
  104. package/src/components/HighlightBanner/HighlightBanner.props.ts +2 -3
  105. package/src/components/HighlightBanner/HighlightBanner.stories.tsx +85 -60
  106. package/src/components/HighlightBanner/HighlightBanner.tsx +3 -10
  107. package/src/components/HighlightBanner/HighlightBannerImage.tsx +20 -0
  108. package/src/components/HighlightBanner/index.ts +1 -0
  109. package/src/components/Input/Input.stories.tsx +76 -3
  110. package/src/components/Input/Input.tsx +110 -98
  111. package/src/components/Input/InputField.tsx +27 -26
  112. package/src/components/List/List.docs.mdx +15 -9
  113. package/src/components/List/List.stories.tsx +2 -2
  114. package/src/components/List/ListItem/ListItem.props.ts +2 -2
  115. package/src/components/List/ListItem/ListItemRoot.tsx +2 -3
  116. package/src/components/Modal/Modal.docs.mdx +16 -4
  117. package/src/components/Modal/Modal.props.ts +3 -2
  118. package/src/components/Modal/Modal.stories.tsx +2 -5
  119. package/src/components/Modal/Modal.tsx +2 -6
  120. package/src/components/Modal/Modal.web.tsx +2 -6
  121. package/src/components/Modal/ModalImage.tsx +20 -0
  122. package/src/components/Modal/index.ts +1 -0
  123. package/src/components/PillGroup/PillGroup.stories.tsx +1 -1
  124. package/src/components/Radio/Radio.docs.mdx +21 -8
  125. package/src/components/Radio/Radio.props.ts +3 -3
  126. package/src/components/Radio/Radio.stories.tsx +15 -11
  127. package/src/components/Radio/Radio.tsx +1 -2
  128. package/src/components/Radio/RadioImage.tsx +8 -3
  129. package/src/components/index.ts +2 -0
  130. package/src/utils/getInitials.ts +7 -0
  131. package/src/utils/index.ts +2 -0
  132. package/src/utils/isThemedImageProps.ts +8 -0
@@ -0,0 +1,20 @@
1
+ import type { DateInputProps } from './DateInput.props';
2
+ interface DateInputSegmentProps {
3
+ label: string;
4
+ placeholder?: string;
5
+ value?: string;
6
+ onChange?: (text: string) => void;
7
+ onFocus?: DateInputProps['onDayFocus'];
8
+ onBlur?: DateInputProps['onDayBlur'];
9
+ disabled?: boolean;
10
+ required?: boolean;
11
+ validationStatus?: DateInputProps['validationStatus'];
12
+ maxLength?: number;
13
+ readonly?: boolean;
14
+ testID?: string;
15
+ }
16
+ declare const DateInputSegment: {
17
+ ({ label, placeholder, value, onChange, onFocus, onBlur, disabled, validationStatus, maxLength, readonly, testID, }: DateInputSegmentProps): import("react/jsx-runtime").JSX.Element;
18
+ displayName: string;
19
+ };
20
+ export default DateInputSegment;
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { View } from 'react-native';
3
+ import { StyleSheet } from 'react-native-unistyles';
4
+ import { BodyText } from '../BodyText';
5
+ import { Input } from '../Input';
6
+ const DateInputSegment = ({ label, placeholder, value, onChange, onFocus, onBlur, disabled, validationStatus, maxLength, readonly, testID, }) => {
7
+ styles.useVariants({ disabled });
8
+ return (_jsxs(View, { style: styles.container, children: [_jsx(BodyText, { size: "md", style: styles.label, children: label }), _jsx(Input, { value: value, onChangeText: onChange, onFocus: onFocus, onBlur: onBlur, placeholder: disabled ? undefined : placeholder, keyboardType: "number-pad", maxLength: maxLength, testID: testID, accessibilityLabel: label, disabled: disabled, validationStatus: validationStatus, readonly: readonly, style: styles.input })] }));
9
+ };
10
+ DateInputSegment.displayName = 'DateInputSegment';
11
+ const styles = StyleSheet.create(theme => ({
12
+ container: {
13
+ flex: 1,
14
+ gap: theme.components.input.gap,
15
+ maxWidth: 96,
16
+ },
17
+ label: {
18
+ variants: {
19
+ disabled: {
20
+ true: {
21
+ opacity: theme.opacity.disabled,
22
+ },
23
+ },
24
+ },
25
+ },
26
+ input: {
27
+ flex: 1,
28
+ maxWidth: 96,
29
+ },
30
+ }));
31
+ export default DateInputSegment;
@@ -0,0 +1,2 @@
1
+ export { default as DateInput } from './DateInput';
2
+ export type { DateInputProps } from './DateInput.props';
@@ -0,0 +1 @@
1
+ export { default as DateInput } from './DateInput';
@@ -1,5 +1,4 @@
1
1
  import type { ComponentType, ReactNode } from 'react';
2
- import type BadgeProps from '../Badge/Badge.props';
3
2
  import type CardProps from '../Card/Card.props';
4
3
  export interface ExpandableCardProps extends Omit<CardProps, 'children'> {
5
4
  /**
@@ -29,7 +28,7 @@ export interface ExpandableCardProps extends Omit<CardProps, 'children'> {
29
28
  /**
30
29
  * Badge to display
31
30
  */
32
- badge?: BadgeProps;
31
+ badge?: ReactNode;
33
32
  /**
34
33
  * Badge position
35
34
  * @default 'bottom'
@@ -1,6 +1,5 @@
1
- import type { ComponentType } from 'react';
1
+ import type { ComponentType, ReactNode } from 'react';
2
2
  import type { PressableProps } from 'react-native';
3
- import type BadgeProps from '../Badge/Badge.props';
4
3
  export interface ExpandableCardTriggerProps extends Omit<PressableProps, 'children'> {
5
4
  /**
6
5
  * The main heading text
@@ -17,11 +16,11 @@ export interface ExpandableCardTriggerProps extends Omit<PressableProps, 'childr
17
16
  /**
18
17
  * Content to display on the left side (e.g., icon, avatar)
19
18
  */
20
- leadingContent?: React.ReactNode;
19
+ leadingContent?: ReactNode;
21
20
  /**
22
21
  * Optional badge to display
23
22
  */
24
- badge?: BadgeProps;
23
+ badge?: ReactNode;
25
24
  /**
26
25
  * Position of the badge relative to the heading
27
26
  * @default 'bottom'
@@ -39,6 +38,6 @@ export interface ExpandableCardTriggerProps extends Omit<PressableProps, 'childr
39
38
  * Whether the trigger is disabled
40
39
  */
41
40
  disabled?: boolean;
42
- children?: React.ReactNode;
41
+ children?: ReactNode;
43
42
  }
44
43
  export default ExpandableCardTriggerProps;
@@ -2,7 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { ChevronDownSmallIcon, ChevronUpSmallIcon, } from '@utilitywarehouse/hearth-react-native-icons';
3
3
  import { Pressable } 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 ExpandableCardContent from './ExpandableCardContent';
8
7
  import ExpandableCardHelperText from './ExpandableCardHelperText';
@@ -27,19 +26,7 @@ const ExpandableCardTriggerRoot = ({ heading, helperText, leadingIcon, leadingCo
27
26
  }
28
27
  return null;
29
28
  };
30
- const renderTopBadge = () => {
31
- if (badgePosition === 'top' && badge) {
32
- return _jsx(Badge, { ...badge });
33
- }
34
- return null;
35
- };
36
- const renderBottomBadge = () => {
37
- if (badgePosition === 'bottom' && badge) {
38
- return _jsx(Badge, { ...badge });
39
- }
40
- return null;
41
- };
42
- const renderDefaultContent = () => (_jsxs(_Fragment, { children: [renderLeadingContent(), _jsxs(ExpandableCardContent, { children: [renderTopBadge(), _jsx(ExpandableCardText, { children: heading }), helperText && _jsx(ExpandableCardHelperText, { children: helperText }), renderBottomBadge()] }), numericValue && (_jsx(DetailText, { size: "lg", style: styles.numericValue, children: numericValue })), _jsx(ExpandableCardTrailingContent, { style: styles.chevron, children: _jsx(ExpandableCardTrailingIcon, { as: isExpanded ? ChevronUpSmallIcon : ChevronDownSmallIcon }) })] }));
29
+ const renderDefaultContent = () => (_jsxs(_Fragment, { children: [renderLeadingContent(), _jsxs(ExpandableCardContent, { children: [badgePosition === 'top' ? badge : null, _jsx(ExpandableCardText, { children: heading }), helperText && _jsx(ExpandableCardHelperText, { children: helperText }), badgePosition === 'bottom' ? badge : null] }), numericValue && (_jsx(DetailText, { size: "lg", style: styles.numericValue, children: numericValue })), _jsx(ExpandableCardTrailingContent, { style: styles.chevron, children: _jsx(ExpandableCardTrailingIcon, { as: isExpanded ? ChevronUpSmallIcon : ChevronDownSmallIcon }) })] }));
43
30
  return (_jsx(Pressable, { ...props, testID: testID, style: [styles.container, props.style], disabled: disabled, accessibilityRole: "button", accessibilityState: { expanded: isExpanded, disabled }, accessibilityLabel: `${heading}${helperText ? `, ${helperText}` : ''}`, children: children || renderDefaultContent() }));
44
31
  };
45
32
  ExpandableCardTriggerRoot.displayName = 'ExpandableCardTriggerRoot';
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Image, View } from 'react-native';
2
+ import { View } from 'react-native';
3
3
  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
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 })] })] }) }));
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: image }), _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 => ({
@@ -62,10 +62,6 @@ const styles = StyleSheet.create(theme => ({
62
62
  width: '100%',
63
63
  height,
64
64
  }),
65
- image: {
66
- width: '100%',
67
- height: '100%',
68
- },
69
65
  footer: {
70
66
  padding: theme.components.banner.highlight.padding,
71
67
  gap: theme.components.banner.highlight.content.gap,
@@ -1,11 +1,10 @@
1
- import { ReactElement } from 'react';
2
- import { ImageProps } from 'react-native';
1
+ import { ReactElement, ReactNode } from 'react';
3
2
  import CardProps from '../Card/Card.props';
4
3
  interface HighlightBannerProps extends Omit<CardProps, 'noPadding' | 'variant' | 'space' | 'gap' | 'rowGap' | 'columnGap' | 'flexDirection' | 'flexWrap' | 'alignItems' | 'justifyContent' | 'colorScheme'> {
5
4
  heading?: string;
6
5
  headingColor?: 'pig' | 'energy' | 'broadband' | 'mobile' | 'insurance' | 'cashback' | 'highlight';
7
6
  variant?: 'emphasis' | 'subtle';
8
- image?: ImageProps;
7
+ image?: ReactNode;
9
8
  imageContainerHeight?: number;
10
9
  description?: string;
11
10
  link?: ReactElement;
@@ -0,0 +1,4 @@
1
+ import { ImageProps } from 'react-native';
2
+ import { ThemedImageProps } from '../ThemedImage';
3
+ declare const HighlightBannerImage: (props: ImageProps | ThemedImageProps) => import("react/jsx-runtime").JSX.Element;
4
+ export default HighlightBannerImage;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Image } from 'react-native';
3
+ import { StyleSheet } from 'react-native-unistyles';
4
+ import { isThemedImageProps } from '../../utils';
5
+ import { ThemedImage } from '../ThemedImage';
6
+ const HighlightBannerImage = (props) => {
7
+ if (isThemedImageProps(props)) {
8
+ return _jsx(ThemedImage, { ...props, style: [styles.image, props.style] });
9
+ }
10
+ return _jsx(Image, { resizeMode: "cover", ...props, style: [styles.image, props.style] });
11
+ };
12
+ const styles = StyleSheet.create({
13
+ image: {
14
+ width: '100%',
15
+ height: '100%',
16
+ },
17
+ });
18
+ export default HighlightBannerImage;
@@ -1,2 +1,3 @@
1
1
  export { default as HighlightBanner } from './HighlightBanner';
2
2
  export type { default as HighlightBannerProps } from './HighlightBanner.props';
3
+ export { default as HighlightBannerImage } from './HighlightBannerImage';
@@ -1 +1,2 @@
1
1
  export { default as HighlightBanner } from './HighlightBanner';
2
+ export { default as HighlightBannerImage } from './HighlightBannerImage';
@@ -1,4 +1,5 @@
1
1
  import { ComponentType } from 'react';
2
+ import { TextInput } from 'react-native';
2
3
  import type InputProps from './Input.props';
3
4
  export declare const InputComponent: import("@gluestack-ui/input/lib/typescript/types").IInputComponentType<InputProps & {
4
5
  states?: {
@@ -10,20 +11,17 @@ export declare const InputComponent: import("@gluestack-ui/input/lib/typescript/
10
11
  as?: ComponentType;
11
12
  }, import("react-native").ViewProps, import("react-native").TextInputProps & {
12
13
  inBottomSheet?: boolean;
13
- }>;
14
+ } & import("react").RefAttributes<TextInput>>;
14
15
  export declare const InputSlot: import("react").ForwardRefExoticComponent<import("react").RefAttributes<import("react-native").ViewProps> & import("react-native").ViewProps & import("@gluestack-ui/input/lib/typescript/types").IInputSlotProps>;
15
16
  export declare const InputField: import("react").ForwardRefExoticComponent<import("react").RefAttributes<import("react-native").TextInputProps & {
16
17
  inBottomSheet?: boolean;
17
- }> & import("react-native").TextInputProps & {
18
+ } & import("react").RefAttributes<TextInput>> & Omit<import("react-native").TextInputProps & {
18
19
  inBottomSheet?: boolean;
19
- } & import("@gluestack-ui/input/lib/typescript/types").IInputProps>;
20
+ } & import("react").RefAttributes<TextInput>, "ref"> & import("@gluestack-ui/input/lib/typescript/types").IInputProps>;
20
21
  export declare const InputIcon: import("react").ForwardRefExoticComponent<import("react").RefAttributes<import("..").IconProps & {
21
22
  as?: ComponentType;
22
23
  }> & import("..").IconProps & {
23
24
  as?: ComponentType;
24
25
  }>;
25
- declare const Input: {
26
- ({ validationStatus, children, disabled, focused, readonly, leadingIcon, trailingIcon, type, showPasswordToggle, onClear, format, loading, clearable, required, inBottomSheet, ...props }: InputProps): import("react/jsx-runtime").JSX.Element;
27
- displayName: string;
28
- };
26
+ declare const Input: import("react").ForwardRefExoticComponent<InputProps & import("react").RefAttributes<TextInput>>;
29
27
  export default Input;
@@ -1,6 +1,6 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createInput } from '@gluestack-ui/input';
3
- import { useState } from 'react';
3
+ import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
4
4
  import { CloseSmallIcon, EyeOffSmallIcon, EyeSmallIcon, SearchMediumIcon, } from '@utilitywarehouse/hearth-react-native-icons';
5
5
  import { useTheme } from '../../hooks';
6
6
  import { useFormFieldContext } from '../FormField';
@@ -19,13 +19,16 @@ export const InputComponent = createInput({
19
19
  export const InputSlot = InputComponent.Slot;
20
20
  export const InputField = InputComponent.Input;
21
21
  export const InputIcon = InputComponent.Icon;
22
- const Input = ({ validationStatus = 'initial', children, disabled, focused, readonly, leadingIcon, trailingIcon, type, showPasswordToggle = true, onClear, format, loading, clearable = false, required, inBottomSheet = false, ...props }) => {
22
+ const Input = forwardRef(({ validationStatus = 'initial', children, disabled, focused, readonly, leadingIcon, trailingIcon, type, showPasswordToggle = true, onClear, format, loading, clearable = false, required, inBottomSheet = false, ...props }, ref) => {
23
23
  const formFieldContext = useFormFieldContext();
24
24
  const { disabled: formFieldDisabled } = formFieldContext;
25
25
  const validationStatusFromContext = formFieldContext?.validationStatus ?? validationStatus;
26
26
  const isRequired = formFieldContext?.required ?? required;
27
27
  const [fieldType, setFieldType] = useState(type === 'password' ? 'password' : 'text');
28
28
  const { color } = useTheme();
29
+ const inputRef = useRef(null);
30
+ // Expose TextInput methods to parent components
31
+ useImperativeHandle(ref, () => inputRef.current, []);
29
32
  const shouldShowPasswordToggle = type === 'password' && showPasswordToggle;
30
33
  const shouldShowClear = clearable && !!props?.value;
31
34
  const toggleFieldType = () => {
@@ -43,7 +46,11 @@ const Input = ({ validationStatus = 'initial', children, disabled, focused, read
43
46
  }
44
47
  return undefined;
45
48
  })();
46
- return (_jsx(InputComponent, { ...(children ? props : {}), validationStatus: validationStatusFromContext, isInvalid: validationStatusFromContext === 'invalid', isReadOnly: readonly, isDisabled: formFieldDisabled ?? disabled, isFocused: focused, type: type, isRequired: isRequired, children: children ? (_jsx(_Fragment, { children: children })) : (_jsxs(_Fragment, { children: [!!leadingIconComponent && (_jsx(InputSlot, { children: _jsx(InputIcon, { as: leadingIconComponent }) })), _jsx(InputField, { type: fieldType, inputMode: getInputMode, inBottomSheet: inBottomSheet, ...props }), shouldShowClear && (_jsx(InputSlot, { children: _jsx(UnstyledIconButton, { onPress: onClear, icon: CloseSmallIcon }) })), loading && (_jsx(InputSlot, { children: _jsx(Spinner, { size: "xs", color: color.icon.primary }) })), shouldShowPasswordToggle && (_jsx(InputSlot, { children: _jsx(UnstyledIconButton, { onPress: toggleFieldType, icon: fieldType === 'password' ? EyeSmallIcon : EyeOffSmallIcon }) })), !!trailingIcon && (_jsx(InputSlot, { children: _jsx(InputIcon, { as: trailingIcon }) }))] })) }));
47
- };
49
+ return (_jsx(InputComponent, { ...(children ? props : {}), validationStatus: validationStatusFromContext, isInvalid: validationStatusFromContext === 'invalid', isReadOnly: readonly, isDisabled: formFieldDisabled ?? disabled, isFocused: focused, type: type, isRequired: isRequired, children: children ? (_jsx(_Fragment, { children: children })) : (_jsxs(_Fragment, { children: [!!leadingIconComponent && (_jsx(InputSlot, { children: _jsx(InputIcon, { as: leadingIconComponent }) })), _jsx(InputField
50
+ // @ts-expect-error - ref forwarding issue
51
+ , {
52
+ // @ts-expect-error - ref forwarding issue
53
+ ref: inputRef, type: fieldType, inputMode: getInputMode, inBottomSheet: inBottomSheet, ...props }), shouldShowClear && (_jsx(InputSlot, { children: _jsx(UnstyledIconButton, { onPress: onClear, icon: CloseSmallIcon }) })), loading && (_jsx(InputSlot, { children: _jsx(Spinner, { size: "xs", color: color.icon.primary }) })), shouldShowPasswordToggle && (_jsx(InputSlot, { children: _jsx(UnstyledIconButton, { onPress: toggleFieldType, icon: fieldType === 'password' ? EyeSmallIcon : EyeOffSmallIcon }) })), !!trailingIcon && (_jsx(InputSlot, { children: _jsx(InputIcon, { as: trailingIcon }) }))] })) }));
54
+ });
48
55
  Input.displayName = 'Input';
49
56
  export default Input;
@@ -1,8 +1,5 @@
1
- import { TextInputProps } from 'react-native';
2
- declare const InputField: {
3
- ({ style, inBottomSheet, ...props }: TextInputProps & {
4
- inBottomSheet?: boolean;
5
- }): import("react/jsx-runtime").JSX.Element;
6
- displayName: string;
7
- };
1
+ import { TextInput as RNTextInput, TextInputProps } from 'react-native';
2
+ declare const InputField: import("react").ForwardRefExoticComponent<TextInputProps & {
3
+ inBottomSheet?: boolean;
4
+ } & import("react").RefAttributes<RNTextInput>>;
8
5
  export default InputField;
@@ -1,20 +1,21 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { BottomSheetTextInput } from '@gorhom/bottom-sheet';
3
+ import { forwardRef } from 'react';
3
4
  import { TextInput as RNTextInput } from 'react-native';
4
5
  import { StyleSheet } from 'react-native-unistyles';
5
6
  import { useTheme } from '../../hooks';
6
7
  import { useInputContext } from './Input.context';
7
- const InputField = ({ style, inBottomSheet = false, ...props }) => {
8
+ const InputField = forwardRef(({ style, inBottomSheet = false, ...props }, ref) => {
8
9
  const { disabled, focused = false, type } = useInputContext();
9
10
  styles.useVariants({ focused, type });
10
11
  const { color } = useTheme();
11
12
  if (inBottomSheet) {
12
13
  return (
13
- // @ts-expect-error - BottomSheetTextInput type issue
14
- _jsx(BottomSheetTextInput, { placeholderTextColor: color.text.secondary, selectionColor: color.purple[700], cursorColor: color.purple[700], verticalAlign: "middle", "aria-disabled": disabled, ...props, style: [styles.input, style] }));
14
+ // @ts-expect-error - BottomSheetTextInput has incompatible event types with TextInput
15
+ _jsx(BottomSheetTextInput, { ref: ref, placeholderTextColor: color.text.secondary, selectionColor: color.surface.brand.default, cursorColor: color.surface.brand.default, verticalAlign: "middle", "aria-disabled": disabled, ...props, style: [styles.input, style] }));
15
16
  }
16
- return (_jsx(RNTextInput, { placeholderTextColor: color.text.secondary, selectionColor: color.purple[700], cursorColor: color.purple[700], verticalAlign: "middle", "aria-disabled": disabled, ...props, style: [styles.input, style] }));
17
- };
17
+ return (_jsx(RNTextInput, { ref: ref, placeholderTextColor: color.text.secondary, selectionColor: color.surface.brand.default, cursorColor: color.surface.brand.default, verticalAlign: "middle", "aria-disabled": disabled, ...props, style: [styles.input, style] }));
18
+ });
18
19
  InputField.displayName = 'InputField';
19
20
  const styles = StyleSheet.create(theme => ({
20
21
  input: {
@@ -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
  interface ListItemBaseProps extends Omit<PressableProps, 'children'> {
4
4
  loading?: boolean;
5
5
  disabled?: boolean;
@@ -23,7 +23,7 @@ export interface ListItemWithoutChildren extends ListItemBaseProps {
23
23
  leadingContent?: ViewProps['children'];
24
24
  trailingContent?: ViewProps['children'];
25
25
  numericValue?: string | number;
26
- badge?: BadgeProps;
26
+ badge?: ReactNode;
27
27
  badgePosition?: 'top' | 'bottom';
28
28
  }
29
29
  type ListItemProps = ListItemWithChildren | ListItemWithoutChildren;
@@ -3,7 +3,6 @@ import { ChevronRightSmallIcon } from '@utilitywarehouse/hearth-react-native-ico
3
3
  import { useMemo } from 'react';
4
4
  import { Pressable } from 'react-native';
5
5
  import { StyleSheet } from 'react-native-unistyles';
6
- import { Badge } from '../../Badge';
7
6
  import { DetailText } from '../../DetailText';
8
7
  import { Skeleton } from '../../Skeleton';
9
8
  import { useListContext } from '../List.context';
@@ -53,7 +52,7 @@ const ListItemRoot = ({ heading, helperText, leadingContent, trailingContent, di
53
52
  if (loading || listContext?.loading) {
54
53
  return (_jsxs(Pressable, { ...props, testID: loadingTestID, style: [styles.container, props.style], disabled: isDisabled, children: [leadingContent ? _jsx(Skeleton, { width: 24, height: 24 }) : null, _jsxs(ListItemContent, { children: [_jsx(Skeleton, { width: "80%", height: 20 }), _jsx(Skeleton, { width: "100%", height: 16 })] }), onPress || trailingContent ? _jsx(Skeleton, { width: 24, height: 24 }) : null] }));
55
54
  }
56
- return (_jsx(ListItemContext.Provider, { value: value, children: _jsx(Pressable, { ...props, testID: testID, style: [styles.container, props.style], disabled: isDisabled, accessibilityRole: onPress ? 'button' : undefined, children: children ? (children) : (_jsxs(_Fragment, { children: [leadingContent ? (_jsx(ListItemLeadingContent, { children: leadingContent })) : null, _jsxs(ListItemContent, { children: [badgePosition === 'top' && badge ? _jsx(Badge, { ...badge }) : null, _jsx(ListItemText, { children: heading }), helperText ? _jsx(ListItemHelperText, { children: helperText }) : null, badgePosition === 'bottom' && badge ? _jsx(Badge, { ...badge }) : null] }), !!numericValue && _jsx(DetailText, { size: "lg", children: numericValue }), trailingContent ? (_jsx(ListItemTrailingContent, { children: trailingContent })) : onPress ? (_jsx(ListItemTrailingContent, { style: styles.centeredTrailingIcon, children: _jsx(ListItemTrailingIcon, { as: ChevronRightSmallIcon }) })) : null] })) }) }));
55
+ return (_jsx(ListItemContext.Provider, { value: value, children: _jsx(Pressable, { ...props, testID: testID, style: [styles.container, props.style], disabled: isDisabled, accessibilityRole: onPress ? 'button' : undefined, children: children ? (children) : (_jsxs(_Fragment, { children: [leadingContent ? (_jsx(ListItemLeadingContent, { children: leadingContent })) : null, _jsxs(ListItemContent, { children: [badgePosition === 'top' && badge ? badge : null, _jsx(ListItemText, { children: heading }), helperText ? _jsx(ListItemHelperText, { children: helperText }) : null, badgePosition === 'bottom' && badge ? badge : null] }), !!numericValue && _jsx(DetailText, { size: "lg", children: numericValue }), trailingContent ? (_jsx(ListItemTrailingContent, { children: trailingContent })) : onPress ? (_jsx(ListItemTrailingContent, { style: styles.centeredTrailingIcon, children: _jsx(ListItemTrailingIcon, { as: ChevronRightSmallIcon }) })) : null] })) }) }));
57
56
  };
58
57
  ListItemRoot.displayName = 'ListItemRoot';
59
58
  const styles = StyleSheet.create(theme => ({
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { CloseMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
3
3
  import { useCallback, useEffect, useImperativeHandle, useRef } from 'react';
4
- import { AccessibilityInfo, Image, Platform, View, findNodeHandle } from 'react-native';
4
+ import { AccessibilityInfo, Platform, View, findNodeHandle } from 'react-native';
5
5
  import Animated, { Easing, useAnimatedStyle, useSharedValue, withDelay, withTiming, } from 'react-native-reanimated';
6
6
  import { StyleSheet } from 'react-native-unistyles';
7
7
  import { useTheme } from '../../hooks';
@@ -98,7 +98,7 @@ const Modal = ({ ref, children, heading, description, showCloseButton = true, pr
98
98
  }
99
99
  };
100
100
  styles.useVariants({ loading });
101
- 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: "Loading..." })] })) : (_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: [_jsx(Image, { style: styles.image, ...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
+ 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: "Loading..." })] })) : (_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] })] })) }));
102
102
  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 }) })] })) : (_jsxs(BottomSheetModal, { ref: bottomSheetModalRef, enableDynamicSizing: true, snapPoints: image || fullscreen ? ['90%'] : props.snapPoints, showHandle: typeof loading !== 'undefined' && loading ? false : props.showHandle, accessible: false, style: styles.modal, ...props, onChange: handleChange, children: [loading ? _jsx(View, { style: styles.loadingTop }) : null, _jsx(BottomSheetScrollView, { contentContainerStyle: styles.container, ref: scrollViewRef, children: content })] }));
103
103
  };
104
104
  const styles = StyleSheet.create((theme, rt) => ({
@@ -124,10 +124,6 @@ const styles = StyleSheet.create((theme, rt) => ({
124
124
  flex: 1,
125
125
  gap: theme.components.modal.content.gap,
126
126
  },
127
- image: {
128
- width: 260,
129
- height: 260,
130
- },
131
127
  imageContainer: {
132
128
  alignItems: 'center',
133
129
  flex: 1,
@@ -1,10 +1,11 @@
1
- import { ImageProps, ViewProps } from 'react-native';
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
  interface ModalProps extends Omit<BottomSheetProps, 'children'> {
6
7
  loading?: boolean;
7
- image?: ImageProps;
8
+ image?: ReactNode;
8
9
  showCloseButton?: boolean;
9
10
  heading?: string;
10
11
  description?: string;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { CloseMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
3
3
  import { useCallback, useEffect, useImperativeHandle, useRef } from 'react';
4
- import { AccessibilityInfo, Image, Platform, View, findNodeHandle } from 'react-native';
4
+ import { AccessibilityInfo, Platform, View, findNodeHandle } from 'react-native';
5
5
  import Animated, { Easing, useAnimatedStyle, useSharedValue, withDelay, withTiming, } from 'react-native-reanimated';
6
6
  import { StyleSheet } from 'react-native-unistyles';
7
7
  import { useTheme } from '../../hooks';
@@ -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: "Loading..." })] })) : (_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: [_jsx(Image, { style: styles.image, ...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] })] })) }));
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: "Loading..." })] })) : (_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) => ({
@@ -113,10 +113,6 @@ const styles = StyleSheet.create((theme, rt) => ({
113
113
  flex: 1,
114
114
  gap: theme.components.modal.content.gap,
115
115
  },
116
- image: {
117
- width: 260,
118
- height: 260,
119
- },
120
116
  imageContainer: {
121
117
  alignItems: 'center',
122
118
  justifyContent: 'center',
@@ -0,0 +1,4 @@
1
+ import { ImageProps } from 'react-native';
2
+ import { ThemedImageProps } from '../ThemedImage';
3
+ declare const ModalImage: (props: ImageProps | ThemedImageProps) => import("react/jsx-runtime").JSX.Element;
4
+ export default ModalImage;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Image } from 'react-native';
3
+ import { StyleSheet } from 'react-native-unistyles';
4
+ import { isThemedImageProps } from '../../utils';
5
+ import { ThemedImage } from '../ThemedImage';
6
+ const ModalImage = (props) => {
7
+ if (isThemedImageProps(props)) {
8
+ return _jsx(ThemedImage, { ...props, style: [styles.image, props.style] });
9
+ }
10
+ return _jsx(Image, { resizeMode: "cover", ...props, style: [styles.image, props.style] });
11
+ };
12
+ const styles = StyleSheet.create({
13
+ image: {
14
+ width: 260,
15
+ height: 260,
16
+ },
17
+ });
18
+ export default ModalImage;
@@ -1,2 +1,3 @@
1
1
  export { default as Modal } from './Modal';
2
2
  export type { default as ModalProps } from './Modal.props';
3
+ export { default as ModalImage } from './ModalImage';
@@ -1 +1,2 @@
1
1
  export { default as Modal } from './Modal';
2
+ export { default as ModalImage } from './ModalImage';
@@ -8,7 +8,6 @@ import StyledRadio from './RadioRoot';
8
8
  import { useFormFieldContext } from '../FormField';
9
9
  import { Helper } from '../Helper';
10
10
  import { useRadioGroupContext } from './RadioGroup.context';
11
- import RadioImage from './RadioImage';
12
11
  import RadioTextContent from './RadioTextContent';
13
12
  import RadioTileRoot from './RadioTileRoot';
14
13
  const RadioComponent = createRadio({
@@ -31,7 +30,7 @@ const Radio = ({ children, label, disabled, helperIcon, helperText, invalidText,
31
30
  const { validationStatus: groupValidationStatus, type: groupType } = useRadioGroupContext();
32
31
  const validationStatus = fieldValidationStatus ?? groupValidationStatus ?? validation ?? 'initial';
33
32
  const radioType = groupType ?? type;
34
- const radioChildren = children ? (children) : (_jsxs(_Fragment, { children: [_jsx(RadioIndicator, { children: _jsx(RadioIcon, {}) }), image ? _jsx(RadioImage, { ...image }) : null, _jsxs(RadioTextContent, { children: [!!label && _jsx(RadioLabel, { children: label }), !!helperText && _jsx(Helper, { disabled: disabled, icon: helperIcon, text: helperText }), validationStatus === 'invalid' && !!invalidText && (_jsx(Helper, { showIcon: showValidationIcon, disabled: disabled, validationStatus: "invalid", text: invalidText })), validationStatus === 'valid' && !!validText && (_jsx(Helper, { disabled: disabled, showIcon: showValidationIcon, validationStatus: "valid", text: validText }))] })] }));
33
+ const radioChildren = children ? (children) : (_jsxs(_Fragment, { children: [_jsx(RadioIndicator, { children: _jsx(RadioIcon, {}) }), image ? image : null, _jsxs(RadioTextContent, { children: [!!label && _jsx(RadioLabel, { children: label }), !!helperText && _jsx(Helper, { disabled: disabled, icon: helperIcon, text: helperText }), validationStatus === 'invalid' && !!invalidText && (_jsx(Helper, { showIcon: showValidationIcon, disabled: disabled, validationStatus: "invalid", text: invalidText })), validationStatus === 'valid' && !!validText && (_jsx(Helper, { disabled: disabled, showIcon: showValidationIcon, validationStatus: "valid", text: validText }))] })] }));
35
34
  return (_jsx(RadioComponent, { ...props, isDisabled: disabled, children: radioType === 'tile' ? _jsx(RadioTileRoot, { children: radioChildren }) : radioChildren }));
36
35
  };
37
36
  const RadioTile = ({ type = 'tile', ...props }) => _jsx(Radio, { ...props, type: type });
@@ -1,5 +1,5 @@
1
- import type { ComponentType } from 'react';
2
- import type { ImageProps, PressableProps, ViewProps } from 'react-native';
1
+ import type { ComponentType, ReactNode } from 'react';
2
+ import type { PressableProps, ViewProps } from 'react-native';
3
3
  interface RadioBaseProps extends Omit<PressableProps, 'children'> {
4
4
  value: string;
5
5
  onChange?: (isSelected: boolean) => void;
@@ -25,7 +25,7 @@ interface RadioWithoutChildrenProps extends RadioBaseProps {
25
25
  invalidText?: string;
26
26
  validText?: string;
27
27
  showValidationIcon?: boolean;
28
- image?: ImageProps;
28
+ image?: ReactNode;
29
29
  }
30
30
  type RadioProps = RadioWithChildrenProps | RadioWithoutChildrenProps;
31
31
  export default RadioProps;
@@ -1,6 +1,7 @@
1
1
  import { ImageProps } from 'react-native';
2
+ import { ThemedImageProps } from '../ThemedImage';
2
3
  declare const RadioImage: {
3
- ({ source, style, ...props }: ImageProps): import("react/jsx-runtime").JSX.Element;
4
+ ({ ...props }: ImageProps | ThemedImageProps): import("react/jsx-runtime").JSX.Element;
4
5
  displayName: string;
5
6
  };
6
7
  export default RadioImage;
@@ -1,5 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Image } from 'react-native';
3
- const RadioImage = ({ source, style, ...props }) => (_jsx(Image, { source: source, style: style, ...props }));
3
+ import { isThemedImageProps } from '../../utils';
4
+ import { ThemedImage } from '../ThemedImage';
5
+ const RadioImage = ({ ...props }) => {
6
+ if (isThemedImageProps(props)) {
7
+ return _jsx(ThemedImage, { ...props });
8
+ }
9
+ return _jsx(Image, { ...props });
10
+ };
4
11
  RadioImage.displayName = 'RadioImage';
5
12
  export default RadioImage;
@@ -1,5 +1,6 @@
1
1
  export * from './Accordion';
2
2
  export * from './Alert';
3
+ export * from './Avatar';
3
4
  export * from './Badge';
4
5
  export * from './Banner';
5
6
  export * from './BodyText';
@@ -12,6 +13,7 @@ export * from './Center';
12
13
  export * from './Checkbox';
13
14
  export * from './Container';
14
15
  export * from './CurrencyInput';
16
+ export * from './DateInput';
15
17
  export * from './DatePicker';
16
18
  export * from './DatePickerInput';
17
19
  export * from './DescriptionList';
@@ -1,6 +1,7 @@
1
1
  // Custom
2
2
  export * from './Accordion';
3
3
  export * from './Alert';
4
+ export * from './Avatar';
4
5
  export * from './Badge';
5
6
  export * from './Banner';
6
7
  export * from './BodyText';
@@ -13,6 +14,7 @@ export * from './Center';
13
14
  export * from './Checkbox';
14
15
  export * from './Container';
15
16
  export * from './CurrencyInput';
17
+ export * from './DateInput';
16
18
  export * from './DatePicker';
17
19
  export * from './DatePickerInput';
18
20
  export * from './DescriptionList';
@@ -0,0 +1 @@
1
+ export declare function getInitials(name?: string): string | undefined;
@@ -0,0 +1,8 @@
1
+ export function getInitials(name) {
2
+ if (!name)
3
+ return undefined;
4
+ const regex = new RegExp(/(\p{L}{1})\p{L}+/gu);
5
+ const names = [...name.matchAll(regex)];
6
+ const initials = (names.shift()?.[1] || '') + (names.pop()?.[1] || '');
7
+ return initials.toUpperCase();
8
+ }
@@ -1,8 +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
7
  export { default as isEqual } from './isEqual';
8
+ export { default as isThemedImageProps } from './isThemedImageProps';
7
9
  export * from './styleUtils';
8
10
  export * from './themeValueHelpers';