@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.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +14 -14
- package/CHANGELOG.md +132 -0
- package/build/components/Card/CardAction/CardActionRoot.js +12 -2
- package/build/components/Card/CardActions.context.d.ts +6 -0
- package/build/components/Card/CardActions.context.js +5 -0
- package/build/components/Card/CardActions.d.ts +7 -0
- package/build/components/Card/CardActions.js +29 -0
- package/build/components/Card/CardRoot.js +16 -104
- package/build/components/Card/helpers.d.ts +8 -0
- package/build/components/Card/helpers.js +146 -0
- package/build/components/Card/index.d.ts +2 -0
- package/build/components/Card/index.js +2 -0
- package/build/components/ExpandableCard/ExpandableCardGroup.d.ts +1 -1
- package/build/components/ExpandableCard/ExpandableCardGroup.js +2 -2
- package/build/components/ExpandableCard/ExpandableCardGroup.props.d.ts +4 -0
- package/build/components/Input/Input.js +4 -3
- package/build/components/Input/Input.props.d.ts +9 -0
- package/build/components/List/List.context.d.ts +4 -2
- package/build/components/List/List.context.js +0 -2
- package/build/components/List/List.d.ts +1 -1
- package/build/components/List/List.js +25 -38
- package/build/components/List/List.props.d.ts +1 -0
- package/build/components/List/ListAction/ListAction.js +24 -7
- package/build/components/List/ListAction/ListAction.props.d.ts +1 -0
- package/build/components/List/ListItem/ListItemRoot.js +12 -4
- package/build/utils/isThemedImageProps.d.ts +1 -1
- package/package.json +3 -3
- package/src/components/Card/Card.docs.mdx +224 -66
- package/src/components/Card/Card.stories.tsx +29 -25
- package/src/components/Card/CardAction/CardAction.stories.tsx +239 -93
- package/src/components/Card/CardAction/CardActionRoot.tsx +15 -2
- package/src/components/Card/CardActions.context.ts +12 -0
- package/src/components/Card/CardActions.tsx +40 -0
- package/src/components/Card/CardRoot.tsx +27 -132
- package/src/components/Card/helpers.tsx +195 -0
- package/src/components/Card/index.ts +2 -0
- package/src/components/ExpandableCard/ExpandableCard.figma.tsx +33 -38
- package/src/components/ExpandableCard/ExpandableCardGroup.figma.tsx +34 -17
- package/src/components/ExpandableCard/ExpandableCardGroup.props.ts +5 -0
- package/src/components/ExpandableCard/ExpandableCardGroup.tsx +2 -0
- package/src/components/HighlightBanner/HighlightBanner.figma.tsx +46 -0
- package/src/components/IconButton/IconButton.figma.tsx +20 -30
- package/src/components/IconContainer/IconContainer.figma.tsx +7 -13
- package/src/components/IndicatorIconButton/IndicatorIconButton.figma.tsx +16 -0
- package/src/components/Input/Input.docs.mdx +55 -15
- package/src/components/Input/Input.figma.tsx +106 -40
- package/src/components/Input/Input.props.ts +9 -0
- package/src/components/Input/Input.tsx +21 -0
- package/src/components/Link/Link.figma.tsx +31 -38
- package/src/components/List/List.context.ts +2 -4
- package/src/components/List/List.docs.mdx +10 -5
- package/src/components/List/List.figma.tsx +42 -28
- package/src/components/List/List.props.ts +1 -0
- package/src/components/List/List.stories.tsx +43 -0
- package/src/components/List/List.tsx +38 -51
- package/src/components/List/ListAction/ListAction.figma.tsx +5 -13
- package/src/components/List/ListAction/ListAction.props.ts +1 -0
- package/src/components/List/ListAction/ListAction.tsx +40 -10
- package/src/components/List/ListItem/ListItem.figma.tsx +43 -27
- package/src/components/List/ListItem/ListItemRoot.tsx +15 -4
- package/src/utils/isThemedImageProps.ts +1 -1
- 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;
|
|
@@ -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, {
|
|
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
|
|
8
|
-
|
|
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
|
|
49
|
-
|
|
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:
|
|
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 => ({
|
|
@@ -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 {
|
|
4
|
+
import { useId, useLayoutEffect } from 'react';
|
|
5
|
+
import { Pressable, View } from 'react-native';
|
|
5
6
|
import { StyleSheet } from 'react-native-unistyles';
|
|
6
|
-
import {
|
|
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
|
|
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
|
|
43
|
+
isFirstChild,
|
|
34
44
|
container: listContext?.container,
|
|
35
45
|
});
|
|
36
|
-
return (
|
|
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;
|
|
@@ -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
|
|
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
|
|
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
|
|
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 '
|
|
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.
|
|
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-
|
|
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": {
|