@utilitywarehouse/hearth-react-native 0.16.2 → 0.17.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 (63) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-lint.log +14 -14
  3. package/CHANGELOG.md +132 -0
  4. package/build/components/Card/CardAction/CardActionRoot.js +12 -2
  5. package/build/components/Card/CardActions.context.d.ts +6 -0
  6. package/build/components/Card/CardActions.context.js +5 -0
  7. package/build/components/Card/CardActions.d.ts +7 -0
  8. package/build/components/Card/CardActions.js +29 -0
  9. package/build/components/Card/CardRoot.js +16 -104
  10. package/build/components/Card/helpers.d.ts +8 -0
  11. package/build/components/Card/helpers.js +146 -0
  12. package/build/components/Card/index.d.ts +2 -0
  13. package/build/components/Card/index.js +2 -0
  14. package/build/components/ExpandableCard/ExpandableCardGroup.d.ts +1 -1
  15. package/build/components/ExpandableCard/ExpandableCardGroup.js +2 -2
  16. package/build/components/ExpandableCard/ExpandableCardGroup.props.d.ts +4 -0
  17. package/build/components/Input/Input.js +4 -3
  18. package/build/components/Input/Input.props.d.ts +9 -0
  19. package/build/components/List/List.context.d.ts +4 -2
  20. package/build/components/List/List.context.js +0 -2
  21. package/build/components/List/List.d.ts +1 -1
  22. package/build/components/List/List.js +25 -38
  23. package/build/components/List/List.props.d.ts +1 -0
  24. package/build/components/List/ListAction/ListAction.js +24 -7
  25. package/build/components/List/ListAction/ListAction.props.d.ts +1 -0
  26. package/build/components/List/ListItem/ListItemRoot.js +12 -4
  27. package/build/utils/isThemedImageProps.d.ts +1 -1
  28. package/package.json +3 -3
  29. package/src/components/Card/Card.docs.mdx +224 -66
  30. package/src/components/Card/Card.stories.tsx +29 -25
  31. package/src/components/Card/CardAction/CardAction.stories.tsx +239 -93
  32. package/src/components/Card/CardAction/CardActionRoot.tsx +15 -2
  33. package/src/components/Card/CardActions.context.ts +12 -0
  34. package/src/components/Card/CardActions.tsx +40 -0
  35. package/src/components/Card/CardRoot.tsx +27 -132
  36. package/src/components/Card/helpers.tsx +195 -0
  37. package/src/components/Card/index.ts +2 -0
  38. package/src/components/ExpandableCard/ExpandableCard.figma.tsx +33 -38
  39. package/src/components/ExpandableCard/ExpandableCardGroup.figma.tsx +34 -17
  40. package/src/components/ExpandableCard/ExpandableCardGroup.props.ts +5 -0
  41. package/src/components/ExpandableCard/ExpandableCardGroup.tsx +2 -0
  42. package/src/components/HighlightBanner/HighlightBanner.figma.tsx +46 -0
  43. package/src/components/IconButton/IconButton.figma.tsx +20 -30
  44. package/src/components/IconContainer/IconContainer.figma.tsx +7 -13
  45. package/src/components/IndicatorIconButton/IndicatorIconButton.figma.tsx +16 -0
  46. package/src/components/Input/Input.docs.mdx +55 -15
  47. package/src/components/Input/Input.figma.tsx +106 -40
  48. package/src/components/Input/Input.props.ts +9 -0
  49. package/src/components/Input/Input.tsx +21 -0
  50. package/src/components/Link/Link.figma.tsx +31 -38
  51. package/src/components/List/List.context.ts +2 -4
  52. package/src/components/List/List.docs.mdx +10 -5
  53. package/src/components/List/List.figma.tsx +42 -28
  54. package/src/components/List/List.props.ts +1 -0
  55. package/src/components/List/List.stories.tsx +43 -0
  56. package/src/components/List/List.tsx +38 -51
  57. package/src/components/List/ListAction/ListAction.figma.tsx +5 -13
  58. package/src/components/List/ListAction/ListAction.props.ts +1 -0
  59. package/src/components/List/ListAction/ListAction.tsx +40 -10
  60. package/src/components/List/ListItem/ListItem.figma.tsx +43 -27
  61. package/src/components/List/ListItem/ListItemRoot.tsx +15 -4
  62. package/src/utils/isThemedImageProps.ts +1 -1
  63. package/src/components/InlineLink/InlineLink.figma.tsx +0 -33
@@ -3,6 +3,7 @@ import { createInput } from '@gluestack-ui/input';
3
3
  import { forwardRef, useEffect, 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
+ import { BodyText } from '../BodyText';
6
7
  import { FormField, useFormFieldContext } from '../FormField';
7
8
  import { Spinner } from '../Spinner';
8
9
  import { UnstyledIconButton } from '../UnstyledIconButton';
@@ -19,7 +20,7 @@ export const InputComponent = createInput({
19
20
  export const InputSlot = InputComponent.Slot;
20
21
  export const InputField = InputComponent.Input;
21
22
  export const InputIcon = InputComponent.Icon;
22
- const Input = forwardRef(({ validationStatus = 'initial', children, disabled, focused, readonly, leadingIcon, trailingIcon, type, showPasswordToggle = true, onClear, loading, clearable = false, required = true, inBottomSheet = false, style, label, labelVariant, helperText, helperIcon, validText, invalidText, ...props }, ref) => {
23
+ const Input = forwardRef(({ validationStatus = 'initial', children, disabled, focused, readonly, leadingIcon, trailingIcon, type, showPasswordToggle = true, onClear, loading, clearable = false, required = true, inBottomSheet = false, style, label, labelVariant, helperText, helperIcon, validText, invalidText, prefix, suffix, ...props }, ref) => {
23
24
  const formFieldContext = useFormFieldContext();
24
25
  const inputLabel = label ?? formFieldContext?.label;
25
26
  const inputHelperText = helperText ?? formFieldContext?.helperText;
@@ -84,11 +85,11 @@ const Input = forwardRef(({ validationStatus = 'initial', children, disabled, fo
84
85
  }
85
86
  return accessibilityHint || props.accessibilityHint;
86
87
  };
87
- return (_jsx(FormField, { label: label, labelVariant: labelVariant, helperText: helperText, helperIcon: helperIcon, validText: validText, invalidText: invalidText, required: required, validationStatus: validationStatus, disabled: disabled, readonly: readonly, accessibilityHandledByChildren: true, children: _jsx(InputComponent, { ...(children ? props : {}), validationStatus: inputValidationStatus, isInvalid: inputValidationStatus === 'invalid', isReadOnly: inputReadonly, isDisabled: inputDisabled, isFocused: focused, type: type, isRequired: inputRequired, style: style, children: children ? (_jsx(_Fragment, { children: children })) : (_jsxs(_Fragment, { children: [!!leadingIconComponent && (_jsx(InputSlot, { children: _jsx(InputIcon, { as: leadingIconComponent }) })), _jsx(InputField
88
+ return (_jsx(FormField, { label: label, labelVariant: labelVariant, helperText: helperText, helperIcon: helperIcon, validText: validText, invalidText: invalidText, required: required, validationStatus: validationStatus, disabled: disabled, readonly: readonly, accessibilityHandledByChildren: true, children: _jsx(InputComponent, { ...(children ? props : {}), validationStatus: inputValidationStatus, isInvalid: inputValidationStatus === 'invalid', isReadOnly: inputReadonly, isDisabled: inputDisabled, isFocused: focused, type: type, isRequired: inputRequired, style: style, children: children ? (_jsx(_Fragment, { children: children })) : (_jsxs(_Fragment, { children: [!!leadingIconComponent && (_jsx(InputSlot, { children: _jsx(InputIcon, { as: leadingIconComponent }) })), !!prefix && (_jsx(InputSlot, { children: typeof prefix === 'string' || typeof prefix === 'number' ? (_jsx(BodyText, { children: prefix })) : (prefix) })), _jsx(InputField
88
89
  // @ts-expect-error - ref forwarding issue
89
90
  , {
90
91
  // @ts-expect-error - ref forwarding issue
91
- ref: inputRef, type: fieldType, inputMode: getInputMode, inBottomSheet: inBottomSheet, ...props, "aria-label": getAccessibilityLabel(), accessibilityHint: getAccessibilityHint() }), 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 }) }))] })) }) }));
92
+ ref: inputRef, type: fieldType, inputMode: getInputMode, inBottomSheet: inBottomSheet, ...props, "aria-label": getAccessibilityLabel(), accessibilityHint: getAccessibilityHint() }), 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 }) })), !!suffix && (_jsx(InputSlot, { children: typeof suffix === 'string' || typeof suffix === 'number' ? (_jsx(BodyText, { children: suffix })) : (suffix) })), !!trailingIcon && (_jsx(InputSlot, { children: _jsx(InputIcon, { as: trailingIcon }) }))] })) }) }));
92
93
  });
93
94
  Input.displayName = 'Input';
94
95
  export default Input;
@@ -1,4 +1,5 @@
1
1
  import type { ComponentType } from 'react';
2
+ import React from 'react';
2
3
  import type { TextInputProps, ViewProps } from 'react-native';
3
4
  export interface InputBaseProps {
4
5
  /**
@@ -43,12 +44,16 @@ export interface InputWithChildrenProps extends InputBaseProps, ViewProps {
43
44
  onClear?: never;
44
45
  leadingIcon?: never;
45
46
  trailingIcon?: never;
47
+ prefix?: never;
48
+ suffix?: never;
46
49
  }
47
50
  interface InputWithoutChildrenBaseProps extends InputBaseProps, Omit<TextInputProps, 'children'> {
48
51
  children?: never;
49
52
  leadingIcon?: ComponentType;
50
53
  trailingIcon?: ComponentType;
51
54
  required?: boolean;
55
+ prefix?: string | number | React.ReactNode;
56
+ suffix?: string | number | React.ReactNode;
52
57
  }
53
58
  interface TextInputSpecificProps extends InputWithoutChildrenBaseProps {
54
59
  type?: 'text';
@@ -65,6 +70,8 @@ interface PasswordInputSpecificProps extends InputWithoutChildrenBaseProps {
65
70
  loading?: never;
66
71
  clearable?: never;
67
72
  onClear?: never;
73
+ prefix?: never;
74
+ suffix?: never;
68
75
  }
69
76
  interface SearchInputSpecificProps extends InputWithoutChildrenBaseProps {
70
77
  type: 'search';
@@ -73,6 +80,8 @@ interface SearchInputSpecificProps extends InputWithoutChildrenBaseProps {
73
80
  onClear?: () => void;
74
81
  showPasswordToggle?: never;
75
82
  format?: never;
83
+ prefix?: never;
84
+ suffix?: never;
76
85
  }
77
86
  export type InputWithoutChildrenProps = TextInputSpecificProps | PasswordInputSpecificProps | SearchInputSpecificProps;
78
87
  /**
@@ -3,11 +3,13 @@ export declare const ListContext: import("react").Context<{
3
3
  loading?: ListProps["loading"];
4
4
  disabled?: ListProps["disabled"];
5
5
  container?: ListProps["container"];
6
+ firstItemId?: string;
7
+ registerItem?: (id: string) => () => void;
6
8
  }>;
7
9
  export declare const useListContext: () => {
8
10
  loading?: ListProps["loading"];
9
11
  disabled?: ListProps["disabled"];
10
12
  container?: ListProps["container"];
13
+ firstItemId?: string;
14
+ registerItem?: (id: string) => () => void;
11
15
  };
12
- export declare const ListFirstItemContext: import("react").Context<boolean>;
13
- export declare const useListFirstItemContext: () => boolean;
@@ -4,5 +4,3 @@ export const useListContext = () => {
4
4
  const context = useContext(ListContext);
5
5
  return context;
6
6
  };
7
- export const ListFirstItemContext = createContext(false);
8
- export const useListFirstItemContext = () => useContext(ListFirstItemContext);
@@ -1,6 +1,6 @@
1
1
  import type ListProps from './List.props';
2
2
  declare const List: {
3
- ({ children, heading, helperText, headerTrailingContent, ...props }: ListProps): import("react/jsx-runtime").JSX.Element;
3
+ ({ children, heading, helperText, headerTrailingContent, invalidText, ...props }: ListProps): import("react/jsx-runtime").JSX.Element;
4
4
  displayName: string;
5
5
  };
6
6
  export default List;
@@ -1,54 +1,41 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useMemo } from 'react';
2
+ import React, { useCallback, useRef, useState } from 'react';
3
3
  import { View } from 'react-native';
4
4
  import { StyleSheet } from 'react-native-unistyles';
5
5
  import { Card } from '../Card';
6
6
  import { SectionHeader } from '../SectionHeader';
7
- import { ListContext, ListFirstItemContext } from './List.context';
8
- import { ListAction } from './ListAction';
9
- import { ListItem } from './ListItem';
10
- const markFirstListItem = (children) => {
11
- let found = false;
12
- const recursiveClone = (children) => {
13
- return React.Children.map(children, (child) => {
14
- if (!React.isValidElement(child))
15
- return child;
16
- // Check if the current element is the ListItem or ListAction and hasn't been marked yet
17
- if (!found) {
18
- if (child.type === ListItem || child.type === ListAction) {
19
- found = true;
20
- return (_jsx(ListFirstItemContext.Provider, { value: true, children: child }));
21
- }
22
- // If the child has nested children, process them recursively
23
- if (React.isValidElement(child) &&
24
- child.props &&
25
- typeof child.props === 'object' &&
26
- child.props !== null &&
27
- 'children' in child.props &&
28
- child.props.children) {
29
- const clonedChildren = recursiveClone(child.props.children);
30
- return React.cloneElement(child, { children: clonedChildren });
31
- }
32
- found = true;
33
- return _jsx(ListFirstItemContext.Provider, { value: true, children: child });
34
- }
35
- return child;
36
- });
37
- };
38
- return recursiveClone(children);
39
- };
40
- const List = ({ children, heading, helperText, headerTrailingContent, ...props }) => {
7
+ import { ListContext } from './List.context';
8
+ const List = ({ children, heading, helperText, headerTrailingContent, invalidText, ...props }) => {
41
9
  const { loading, disabled, container = 'none' } = props;
10
+ const orderRef = useRef([]);
11
+ const [firstItemId, setFirstItemId] = useState(undefined);
42
12
  const containerToCard = {
43
13
  variant: container === 'subtleWhite' || container === 'subtleWarmWhite' ? 'subtle' : 'emphasis',
44
14
  colorScheme: container === 'subtleWhite' || container === 'emphasisWhite'
45
15
  ? 'neutralStrong'
46
16
  : 'neutralSubtle',
47
17
  };
48
- const updatedChildren = markFirstListItem(children);
49
- const value = useMemo(() => ({ loading, disabled, container }), [loading, disabled, container]);
18
+ const registerItem = useCallback((id) => {
19
+ if (!orderRef.current.includes(id)) {
20
+ orderRef.current.push(id);
21
+ }
22
+ const nextFirst = orderRef.current[0];
23
+ setFirstItemId(prev => (prev === nextFirst ? prev : nextFirst));
24
+ return () => {
25
+ orderRef.current = orderRef.current.filter(currentId => currentId !== id);
26
+ const nextFirst = orderRef.current[0];
27
+ setFirstItemId(prev => (prev === nextFirst ? prev : nextFirst));
28
+ };
29
+ }, []);
30
+ const value = {
31
+ loading,
32
+ disabled,
33
+ container,
34
+ firstItemId,
35
+ registerItem,
36
+ };
50
37
  styles.useVariants({ disabled });
51
- 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 }) })))] }) }));
38
+ return (_jsx(ListContext.Provider, { value: value, children: _jsxs(View, { ...props, style: [styles.container, props.style], children: [heading ? (_jsx(SectionHeader, { heading: heading, helperText: helperText, trailingContent: headerTrailingContent, invalidText: invalidText })) : null, container === 'none' ? (_jsx(View, { children: children })) : (React.Children.count(children) > 0 && (_jsx(Card, { ...containerToCard, noPadding: true, style: styles.card, children: _jsx(_Fragment, { children: children }) })))] }) }));
52
39
  };
53
40
  List.displayName = 'List';
54
41
  const styles = StyleSheet.create(theme => ({
@@ -6,5 +6,6 @@ interface ListProps extends ViewProps {
6
6
  headerTrailingContent?: React.ReactNode;
7
7
  disabled?: boolean;
8
8
  loading?: boolean;
9
+ invalidText?: string;
9
10
  }
10
11
  export default ListProps;
@@ -1,17 +1,19 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { createPressable } from '@gluestack-ui/pressable';
3
3
  import { ChevronRightSmallIcon } from '@utilitywarehouse/hearth-react-native-icons';
4
- import { Pressable } from 'react-native';
4
+ import { useId, useLayoutEffect } from 'react';
5
+ import { Pressable, View } from 'react-native';
5
6
  import { StyleSheet } from 'react-native-unistyles';
6
- import { useListContext, useListFirstItemContext } from '../List.context';
7
+ import { Skeleton } from '../../Skeleton';
8
+ import { useListContext } from '../List.context';
7
9
  import ListActionContent from './ListActionContent';
8
10
  import ListActionText from './ListActionText';
9
11
  import ListActionTrailingContent from './ListActionTrailingContent';
10
12
  import ListActionTrailingIcon from './ListActionTrailingIcon';
11
- const ListActionRoot = ({ heading, disabled, variant = 'subtle', ...props }) => {
13
+ const ListActionRoot = ({ heading, disabled, variant = 'subtle', loading, ...props }) => {
12
14
  const { onPress } = props;
13
15
  const listContext = useListContext();
14
- const isFirstContext = useListFirstItemContext();
16
+ const { registerItem, firstItemId } = listContext;
15
17
  const { active } = props.states || { active: false };
16
18
  const getListContainer = () => {
17
19
  if (listContext?.container?.includes('subtle')) {
@@ -24,16 +26,24 @@ const ListActionRoot = ({ heading, disabled, variant = 'subtle', ...props }) =>
24
26
  };
25
27
  const isDisabled = disabled || listContext?.disabled || false;
26
28
  const listItemVariant = getListContainer() || variant;
29
+ const actionId = useId();
30
+ useLayoutEffect(() => {
31
+ if (!registerItem) {
32
+ return;
33
+ }
34
+ return registerItem(actionId);
35
+ }, [actionId, registerItem]);
36
+ const isFirstChild = firstItemId === actionId;
27
37
  const testID = props.testID || 'list-action';
28
38
  styles.useVariants({
29
39
  variant: listItemVariant,
30
40
  disabled: isDisabled,
31
41
  active,
32
42
  showDisabled: !listContext?.disabled && disabled,
33
- isFirstChild: isFirstContext,
43
+ isFirstChild,
34
44
  container: listContext?.container,
35
45
  });
36
- return (_jsxs(Pressable, { ...props, testID: testID, style: [styles.container, props.style], disabled: isDisabled || !onPress, children: [_jsx(ListActionContent, { children: _jsx(ListActionText, { children: heading }) }), _jsx(ListActionTrailingContent, { style: styles.centeredTrailingIcon, children: _jsx(ListActionTrailingIcon, { as: ChevronRightSmallIcon }) })] }));
46
+ return (_jsx(Pressable, { ...props, testID: testID, style: [styles.container, props.style], disabled: isDisabled || !onPress, children: loading ? (_jsxs(View, { style: styles.loadingWrap, children: [_jsx(Skeleton, { style: { flex: 1, maxWidth: 166 }, width: "auto", height: 24, borderRadius: "sm" }), _jsx(Skeleton, { width: 24, height: 24, borderRadius: "sm" })] })) : (_jsxs(_Fragment, { children: [_jsx(ListActionContent, { children: _jsx(ListActionText, { children: heading }) }), _jsx(ListActionTrailingContent, { style: styles.centeredTrailingIcon, children: _jsx(ListActionTrailingIcon, { as: ChevronRightSmallIcon }) })] })) }));
37
47
  };
38
48
  const ListAction = createPressable({
39
49
  Root: ListActionRoot,
@@ -100,5 +110,12 @@ const styles = StyleSheet.create(theme => ({
100
110
  centeredTrailingIcon: {
101
111
  justifyContent: 'center',
102
112
  },
113
+ loadingWrap: {
114
+ flexDirection: 'row',
115
+ justifyContent: 'space-between',
116
+ alignItems: 'center',
117
+ width: '100%',
118
+ gap: theme.space['200'],
119
+ },
103
120
  }));
104
121
  export default ListAction;
@@ -2,6 +2,7 @@ import type { PressableProps } from 'react-native';
2
2
  interface ListActionProps extends Omit<PressableProps, 'children'> {
3
3
  heading: string;
4
4
  disabled?: boolean;
5
+ loading?: boolean;
5
6
  variant?: 'subtle' | 'emphasis';
6
7
  }
7
8
  export default ListActionProps;
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { ChevronRightSmallIcon } from '@utilitywarehouse/hearth-react-native-icons';
3
- import { useMemo } from 'react';
3
+ import { useId, useLayoutEffect, useMemo } from 'react';
4
4
  import { Pressable } from 'react-native';
5
5
  import { StyleSheet } from 'react-native-unistyles';
6
6
  import { DetailText } from '../../DetailText';
7
7
  import { Skeleton } from '../../Skeleton';
8
- import { useListContext, useListFirstItemContext } from '../List.context';
8
+ import { useListContext } from '../List.context';
9
9
  import { ListItemContext } from './ListItem.context';
10
10
  import ListItemContent from './ListItemContent';
11
11
  import ListItemHeading from './ListItemHeading';
@@ -16,8 +16,16 @@ import ListItemTrailingIcon from './ListItemTrailingIcon';
16
16
  const ListItemRoot = ({ heading, helperText, leadingContent, trailingContent, disabled, loading, children, states, variant = 'subtle', badge, badgePosition = 'bottom', numericValue, truncateHeading = false, truncateHelperText = false, ...props }) => {
17
17
  const { onPress } = props;
18
18
  const listContext = useListContext();
19
- const isFirstContext = useListFirstItemContext();
19
+ const { registerItem, firstItemId } = listContext;
20
20
  const { active } = states || { active: false };
21
+ const itemId = useId();
22
+ useLayoutEffect(() => {
23
+ if (!registerItem) {
24
+ return;
25
+ }
26
+ return registerItem(itemId);
27
+ }, [itemId, registerItem]);
28
+ const isFirstChild = firstItemId === itemId;
21
29
  const getListContainer = () => {
22
30
  if (listContext?.container?.includes('subtle')) {
23
31
  return 'subtle';
@@ -39,7 +47,7 @@ const ListItemRoot = ({ heading, helperText, leadingContent, trailingContent, di
39
47
  active,
40
48
  disabled: isDisabled || isLoading,
41
49
  showDisabled: !listContext.disabled && disabled,
42
- isFirstChild: isFirstContext,
50
+ isFirstChild,
43
51
  container: listContext?.container,
44
52
  });
45
53
  const value = useMemo(() => {
@@ -1,4 +1,4 @@
1
1
  import { ImageProps } from 'react-native';
2
- import { ThemedImageProps } from 'src/components';
2
+ import { ThemedImageProps } from '../components';
3
3
  declare const isThemedImageProps: (props: ThemedImageProps | ImageProps) => props is ThemedImageProps;
4
4
  export default isThemedImageProps;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilitywarehouse/hearth-react-native",
3
- "version": "0.16.2",
3
+ "version": "0.17.0",
4
4
  "description": "Utility Warehouse React Native UI library",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -55,10 +55,10 @@
55
55
  "vite": "^7.1.3",
56
56
  "vite-plugin-svgr": "^4.5.0",
57
57
  "vitest": "^3.2.4",
58
- "@utilitywarehouse/hearth-react-icons": "^0.7.4",
58
+ "@utilitywarehouse/hearth-fonts": "^0.0.4",
59
59
  "@utilitywarehouse/hearth-react-native-icons": "^0.7.4",
60
+ "@utilitywarehouse/hearth-react-icons": "^0.7.4",
60
61
  "@utilitywarehouse/hearth-svg-assets": "^0.3.0",
61
- "@utilitywarehouse/hearth-fonts": "^0.0.4",
62
62
  "@utilitywarehouse/hearth-tokens": "^0.2.2"
63
63
  },
64
64
  "peerDependencies": {