@utilitywarehouse/hearth-react-native 0.5.0 → 0.7.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/.storybook/main.ts +33 -7
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +14 -0
- package/build/components/BottomSheet/BottomSheetBackdrop.js +2 -2
- package/build/components/BottomSheet/BottomSheetFlatList.js +2 -2
- package/build/components/BottomSheet/BottomSheetHandle.js +2 -2
- package/build/components/Button/ButtonIcon.js +2 -1
- package/build/components/Button/ButtonRoot.js +2 -6
- package/build/components/Button/ButtonText.js +4 -1
- package/build/components/Card/Card.context.d.ts +7 -0
- package/build/components/Card/CardAction/CardAction.context.d.ts +9 -0
- package/build/components/Card/{CardAction.context.js → CardAction/CardAction.context.js} +7 -1
- package/build/components/Card/CardAction/CardAction.d.ts +18 -0
- package/build/components/Card/CardAction/CardAction.js +7 -0
- package/build/components/Card/CardAction/CardAction.props.d.ts +63 -0
- package/build/components/Card/CardAction/CardAction.props.js +1 -0
- package/build/components/Card/CardAction/CardActionContent.d.ts +6 -0
- package/build/components/Card/CardAction/CardActionContent.js +13 -0
- package/build/components/Card/CardAction/CardActionHelperText.d.ts +6 -0
- package/build/components/Card/CardAction/CardActionHelperText.js +13 -0
- package/build/components/Card/CardAction/CardActionIcon.d.ts +9 -0
- package/build/components/Card/CardAction/CardActionIcon.js +19 -0
- package/build/components/Card/CardAction/CardActionLeadingContent.d.ts +6 -0
- package/build/components/Card/CardAction/CardActionLeadingContent.js +5 -0
- package/build/components/Card/CardAction/CardActionRoot.d.ts +12 -0
- package/build/components/Card/CardAction/CardActionRoot.js +155 -0
- package/build/components/Card/CardAction/CardActionText.d.ts +6 -0
- package/build/components/Card/CardAction/CardActionText.js +9 -0
- package/build/components/Card/CardAction/CardActionTrailingContent.d.ts +6 -0
- package/build/components/Card/CardAction/CardActionTrailingContent.js +5 -0
- package/build/components/Card/CardAction/CardActionTrailingIcon.d.ts +9 -0
- package/build/components/Card/CardAction/CardActionTrailingIcon.js +19 -0
- package/build/components/Card/CardAction/index.d.ts +10 -0
- package/build/components/Card/CardAction/index.js +9 -0
- package/build/components/Card/CardContent.d.ts +6 -0
- package/build/components/Card/CardContent.js +33 -0
- package/build/components/Card/CardPressHandler.context.d.ts +6 -0
- package/build/components/Card/CardPressHandler.context.js +6 -0
- package/build/components/Card/{CardAction.d.ts → CardPressHandler.d.ts} +3 -3
- package/build/components/Card/CardPressHandler.js +13 -0
- package/build/components/Card/CardRoot.js +103 -11
- package/build/components/Card/index.d.ts +3 -2
- package/build/components/Card/index.js +3 -2
- package/build/components/Checkbox/CheckboxIcon.js +2 -1
- package/build/components/Container/Container.d.ts +6 -0
- package/build/components/Container/Container.js +40 -0
- package/build/components/Container/Container.props.d.ts +85 -0
- package/build/components/Container/Container.props.js +1 -0
- package/build/components/Container/index.d.ts +2 -0
- package/build/components/Container/index.js +1 -0
- package/build/components/CurrencyInput/CurrencyInput.js +1 -1
- package/build/components/Helper/HelperIcon.js +2 -1
- package/build/components/Icon/Icon.d.ts +2 -6
- package/build/components/IconButton/IconButtonIcon.js +2 -1
- package/build/components/IconContainer/IconContainer.d.ts +4 -3
- package/build/components/IconContainer/IconContainer.js +3 -3
- package/build/components/Input/InputField.js +4 -2
- package/build/components/Input/InputIcon.js +2 -1
- package/build/components/Link/LinkIcon.js +3 -2
- package/build/components/List/ListAction/ListActionTrailingIcon.js +2 -1
- package/build/components/List/ListItem/ListItemIcon.js +2 -1
- package/build/components/List/ListItem/ListItemTrailingIcon.js +2 -3
- package/build/components/ProgressStepper/ProgressStep.d.ts +1 -1
- package/build/components/ProgressStepper/ProgressStep.js +6 -6
- package/build/components/ProgressStepper/ProgressStepper.props.d.ts +3 -3
- package/build/components/ProgressStepper/index.d.ts +1 -1
- package/build/components/Radio/RadioIcon.js +7 -2
- package/build/components/RadioCard/RadioCardIcon.js +3 -2
- package/build/components/Spinner/Spinner.js +2 -0
- package/build/components/Spinner/Spinner.web.js +2 -0
- package/build/components/Switch/Switch.js +5 -3
- package/build/components/Switch/Switch.web.js +1 -0
- package/build/components/Tabs/TabsList.js +6 -1
- package/build/components/Textarea/TextareaField.js +1 -1
- package/build/components/ThemedImage/ThemedImage.d.ts +12 -0
- package/build/components/ThemedImage/ThemedImage.js +27 -0
- package/build/components/ThemedImage/ThemedImage.props.d.ts +13 -0
- package/build/components/ThemedImage/ThemedImage.props.js +1 -0
- package/build/components/ThemedImage/index.d.ts +2 -0
- package/build/components/ThemedImage/index.js +1 -0
- package/build/components/ToggleButton/ToggleButtonIcon.js +2 -1
- package/build/components/ToggleButton/ToggleButtonRoot.js +2 -2
- package/build/components/UnstyledIconButton/UnstyledIconButtonIcon.js +2 -1
- package/build/components/index.d.ts +3 -1
- package/build/components/index.js +3 -1
- package/build/core/index.d.ts +3 -3
- package/build/core/index.js +3 -3
- package/build/core/themes.d.ts +24 -12
- package/build/hooks/useColorMode.d.ts +1 -1
- package/build/hooks/useColorMode.js +7 -8
- package/build/hooks/useStyleProps.js +1 -1
- package/build/tokens/components/dark/banner.d.ts +19 -0
- package/build/tokens/components/dark/banner.js +19 -0
- package/build/tokens/components/dark/card-action.d.ts +11 -0
- package/build/tokens/components/dark/card-action.js +10 -0
- package/build/tokens/components/dark/card-content.d.ts +25 -0
- package/build/tokens/components/dark/card-content.js +24 -0
- package/build/tokens/components/dark/drawer.d.ts +29 -0
- package/build/tokens/components/dark/drawer.js +28 -0
- package/build/tokens/components/dark/illustrations.d.ts +0 -1
- package/build/tokens/components/dark/illustrations.js +0 -1
- package/build/tokens/components/dark/index.d.ts +3 -0
- package/build/tokens/components/dark/index.js +3 -0
- package/build/tokens/components/light/banner.d.ts +19 -0
- package/build/tokens/components/light/banner.js +19 -0
- package/build/tokens/components/light/card-action.d.ts +11 -0
- package/build/tokens/components/light/card-action.js +10 -0
- package/build/tokens/components/light/card-content.d.ts +25 -0
- package/build/tokens/components/light/card-content.js +24 -0
- package/build/tokens/components/light/drawer.d.ts +29 -0
- package/build/tokens/components/light/drawer.js +28 -0
- package/build/tokens/components/light/illustrations.d.ts +0 -1
- package/build/tokens/components/light/illustrations.js +0 -1
- package/build/tokens/components/light/index.d.ts +3 -0
- package/build/tokens/components/light/index.js +3 -0
- package/build/tokens/layout.d.ts +6 -6
- package/build/tokens/layout.js +3 -3
- package/build/tokens/typography.d.ts +6 -0
- package/build/tokens/typography.js +3 -0
- package/docs/components/AllComponents.web.tsx +38 -3
- package/docs/components/NextPrevPage.tsx +5 -5
- package/docs/components/VariantTitle.tsx +17 -7
- package/docs/layout-components.docs.mdx +30 -0
- package/package.json +18 -14
- package/src/components/BottomSheet/BottomSheetBackdrop.tsx +2 -2
- package/src/components/BottomSheet/BottomSheetFlatList.tsx +2 -3
- package/src/components/BottomSheet/BottomSheetHandle.tsx +1 -1
- package/src/components/Button/ButtonIcon.tsx +2 -1
- package/src/components/Button/ButtonRoot.tsx +2 -6
- package/src/components/Button/ButtonText.tsx +4 -1
- package/src/components/Card/Card.context.ts +7 -0
- package/src/components/Card/Card.docs.mdx +212 -14
- package/src/components/Card/Card.stories.tsx +50 -3
- package/src/components/Card/CardAction/CardAction.context.ts +22 -0
- package/src/components/Card/CardAction/CardAction.props.ts +87 -0
- package/src/components/Card/CardAction/CardAction.stories.tsx +265 -0
- package/src/components/Card/CardAction/CardAction.tsx +10 -0
- package/src/components/Card/CardAction/CardActionContent.tsx +20 -0
- package/src/components/Card/CardAction/CardActionHelperText.tsx +21 -0
- package/src/components/Card/CardAction/CardActionIcon.tsx +32 -0
- package/src/components/Card/CardAction/CardActionLeadingContent.tsx +9 -0
- package/src/components/Card/CardAction/CardActionRoot.tsx +258 -0
- package/src/components/Card/CardAction/CardActionText.tsx +17 -0
- package/src/components/Card/CardAction/CardActionTrailingContent.tsx +9 -0
- package/src/components/Card/CardAction/CardActionTrailingIcon.tsx +32 -0
- package/src/components/Card/CardAction/index.ts +10 -0
- package/src/components/Card/CardContent.tsx +40 -0
- package/src/components/Card/CardPressHandler.context.ts +12 -0
- package/src/components/Card/CardPressHandler.tsx +20 -0
- package/src/components/Card/CardRoot.tsx +128 -13
- package/src/components/Card/index.ts +3 -2
- package/src/components/Checkbox/CheckboxIcon.tsx +2 -1
- package/src/components/Container/Container.docs.mdx +168 -0
- package/src/components/Container/Container.props.ts +89 -0
- package/src/components/Container/Container.stories.tsx +274 -0
- package/src/components/Container/Container.tsx +52 -0
- package/src/components/Container/index.tsx +2 -0
- package/src/components/CurrencyInput/CurrencyInput.tsx +1 -1
- package/src/components/Helper/HelperIcon.tsx +2 -1
- package/src/components/Icon/Icon.tsx +4 -3
- package/src/components/IconButton/IconButtonIcon.tsx +2 -1
- package/src/components/IconContainer/IconContainer.tsx +17 -19
- package/src/components/Input/InputField.tsx +2 -1
- package/src/components/Input/InputIcon.tsx +2 -1
- package/src/components/Link/LinkIcon.tsx +3 -2
- package/src/components/List/ListAction/ListActionTrailingIcon.tsx +2 -1
- package/src/components/List/ListItem/ListItemIcon.tsx +2 -1
- package/src/components/List/ListItem/ListItemTrailingIcon.tsx +2 -3
- package/src/components/ProgressStepper/ProgressStep.tsx +8 -8
- package/src/components/ProgressStepper/ProgressStepper.docs.mdx +11 -11
- package/src/components/ProgressStepper/ProgressStepper.props.ts +3 -3
- package/src/components/ProgressStepper/ProgressStepper.stories.tsx +27 -27
- package/src/components/ProgressStepper/index.ts +1 -1
- package/src/components/Radio/RadioIcon.tsx +8 -3
- package/src/components/RadioCard/RadioCardIcon.tsx +4 -3
- package/src/components/Spinner/Spinner.tsx +2 -0
- package/src/components/Spinner/Spinner.web.tsx +2 -0
- package/src/components/Switch/Switch.tsx +10 -5
- package/src/components/Switch/Switch.web.tsx +5 -0
- package/src/components/Tabs/TabsList.tsx +2 -0
- package/src/components/Textarea/TextareaField.tsx +1 -1
- package/src/components/ThemedImage/ThemedImage.docs.mdx +208 -0
- package/src/components/ThemedImage/ThemedImage.props.ts +15 -0
- package/src/components/ThemedImage/ThemedImage.stories.tsx +175 -0
- package/src/components/ThemedImage/ThemedImage.tsx +34 -0
- package/src/components/ThemedImage/index.tsx +2 -0
- package/src/components/ToggleButton/ToggleButtonIcon.tsx +2 -1
- package/src/components/ToggleButton/ToggleButtonRoot.tsx +2 -2
- package/src/components/UnstyledIconButton/UnstyledIconButtonIcon.tsx +2 -1
- package/src/components/index.ts +3 -9
- package/src/core/index.ts +14 -11
- package/src/hooks/useColorMode.ts +9 -12
- package/src/hooks/useStyleProps.ts +1 -1
- package/src/tokens/components/dark/banner.ts +19 -0
- package/src/tokens/components/dark/card-action.ts +11 -0
- package/src/tokens/components/dark/card-content.ts +25 -0
- package/src/tokens/components/dark/drawer.ts +29 -0
- package/src/tokens/components/dark/illustrations.ts +0 -1
- package/src/tokens/components/dark/index.ts +3 -0
- package/src/tokens/components/light/banner.ts +19 -0
- package/src/tokens/components/light/card-action.ts +11 -0
- package/src/tokens/components/light/card-content.ts +25 -0
- package/src/tokens/components/light/drawer.ts +29 -0
- package/src/tokens/components/light/illustrations.ts +0 -1
- package/src/tokens/components/light/index.ts +3 -0
- package/src/tokens/layout.ts +3 -3
- package/src/tokens/typography.ts +3 -0
- package/src/vite-env.d.ts +6 -0
- package/build/components/Card/CardAction.context.d.ts +0 -6
- package/build/components/Card/CardAction.js +0 -13
- package/src/components/Card/CardAction.context.ts +0 -12
- package/src/components/Card/CardAction.tsx +0 -18
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { View, ViewProps } from 'react-native';
|
|
2
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
3
|
+
import { useCardContext } from './Card.context';
|
|
4
|
+
|
|
5
|
+
const CardContent = ({ children, style, ...props }: ViewProps) => {
|
|
6
|
+
const { noPadding, space } = useCardContext();
|
|
7
|
+
styles.useVariants({
|
|
8
|
+
noPadding,
|
|
9
|
+
space,
|
|
10
|
+
});
|
|
11
|
+
return (
|
|
12
|
+
<View style={[styles.container, style]} {...props}>
|
|
13
|
+
{children}
|
|
14
|
+
</View>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
CardContent.displayName = 'CardContent';
|
|
19
|
+
|
|
20
|
+
const styles = StyleSheet.create(theme => ({
|
|
21
|
+
container: {
|
|
22
|
+
variants: {
|
|
23
|
+
space: theme.globalStyle.variants.space,
|
|
24
|
+
noPadding: {
|
|
25
|
+
true: {
|
|
26
|
+
padding: theme.components.card.mobile.paddingNone,
|
|
27
|
+
},
|
|
28
|
+
false: {
|
|
29
|
+
padding: {
|
|
30
|
+
base: theme.components.card.mobile.padding,
|
|
31
|
+
md: theme.components.card.tablet.padding,
|
|
32
|
+
lg: theme.components.card.desktop.padding,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
export default CardContent;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
interface CardPressHandlerContextProps {
|
|
4
|
+
pressed?: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const CardPressHandlerContext = createContext<CardPressHandlerContextProps>({});
|
|
8
|
+
|
|
9
|
+
export const useCardPressHandlerContext = (): CardPressHandlerContextProps => {
|
|
10
|
+
const context = useContext(CardPressHandlerContext);
|
|
11
|
+
return context;
|
|
12
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { PropsWithChildren, useMemo } from 'react';
|
|
2
|
+
import { useCardContext } from './Card.context';
|
|
3
|
+
import { CardPressHandlerContext } from './CardPressHandler.context';
|
|
4
|
+
|
|
5
|
+
const CardPressHandler = ({ children }: PropsWithChildren<{ handlerToInherit?: string }>) => {
|
|
6
|
+
const { pressed } = useCardContext();
|
|
7
|
+
const context = useMemo(
|
|
8
|
+
() => ({
|
|
9
|
+
pressed,
|
|
10
|
+
}),
|
|
11
|
+
[pressed]
|
|
12
|
+
);
|
|
13
|
+
return (
|
|
14
|
+
<CardPressHandlerContext.Provider value={context}>{children}</CardPressHandlerContext.Provider>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
CardPressHandler.displayName = 'CardPressHandler';
|
|
19
|
+
|
|
20
|
+
export default CardPressHandler;
|
|
@@ -4,6 +4,72 @@ import { StyleSheet } from 'react-native-unistyles';
|
|
|
4
4
|
import { useStyleProps } from '../../hooks';
|
|
5
5
|
import { CardContext } from './Card.context';
|
|
6
6
|
import CardProps from './Card.props';
|
|
7
|
+
import CardContent from './CardContent';
|
|
8
|
+
|
|
9
|
+
// Helper to check if children contain specific component types
|
|
10
|
+
const checkForComponentType = (children: React.ReactNode, displayName: string): boolean => {
|
|
11
|
+
return React.Children.toArray(children).some(child => {
|
|
12
|
+
if (React.isValidElement(child)) {
|
|
13
|
+
// @ts-expect-error - type
|
|
14
|
+
if (child.type.displayName === displayName) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
const childProps = child.props as any;
|
|
18
|
+
if (childProps.children) {
|
|
19
|
+
return checkForComponentType(childProps.children, displayName);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Helper to filter out specific component types from children
|
|
27
|
+
const filterChildren = (children: React.ReactNode, excludeDisplayName: string): React.ReactNode => {
|
|
28
|
+
return React.Children.map(children, child => {
|
|
29
|
+
if (React.isValidElement(child)) {
|
|
30
|
+
// @ts-expect-error - type
|
|
31
|
+
if (child.type.displayName === excludeDisplayName) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const childProps = child.props as any;
|
|
35
|
+
if (childProps.children) {
|
|
36
|
+
return React.cloneElement(child, {
|
|
37
|
+
...childProps,
|
|
38
|
+
children: filterChildren(childProps.children, excludeDisplayName),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return child;
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Helper to extract specific component types from children
|
|
47
|
+
const extractChildren = (
|
|
48
|
+
children: React.ReactNode,
|
|
49
|
+
includeDisplayName: string,
|
|
50
|
+
markFirst = false
|
|
51
|
+
): React.ReactNode => {
|
|
52
|
+
let isFirstFound = false;
|
|
53
|
+
return React.Children.map(children, child => {
|
|
54
|
+
if (React.isValidElement(child)) {
|
|
55
|
+
// @ts-expect-error - type
|
|
56
|
+
if (child.type.displayName === includeDisplayName) {
|
|
57
|
+
const isFirst = markFirst && !isFirstFound;
|
|
58
|
+
if (isFirst) {
|
|
59
|
+
isFirstFound = true;
|
|
60
|
+
}
|
|
61
|
+
return markFirst
|
|
62
|
+
? React.cloneElement(child, { ...(child.props || {}), isFirst } as any)
|
|
63
|
+
: child;
|
|
64
|
+
}
|
|
65
|
+
const childProps = child.props as any;
|
|
66
|
+
if (childProps.children) {
|
|
67
|
+
return extractChildren(childProps.children, includeDisplayName, markFirst);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
});
|
|
72
|
+
};
|
|
7
73
|
|
|
8
74
|
// Helper that recursively collects onPress or other defined handlers from descendants
|
|
9
75
|
const collectChildActionHandlers = (
|
|
@@ -14,15 +80,15 @@ const collectChildActionHandlers = (
|
|
|
14
80
|
if (React.isValidElement(child)) {
|
|
15
81
|
const childProps = child.props as any;
|
|
16
82
|
// @ts-expect-error - type
|
|
17
|
-
if (child.type.displayName === '
|
|
83
|
+
if (child.type.displayName === 'CardPressHandler') {
|
|
18
84
|
const actionChildren = React.Children.toArray(childProps.children);
|
|
19
|
-
const
|
|
85
|
+
const handlerToInherit = childProps['handlerToInherit'] || 'onPress';
|
|
20
86
|
const firstChild = actionChildren[0];
|
|
21
87
|
if (
|
|
22
88
|
React.isValidElement(firstChild) &&
|
|
23
|
-
typeof (firstChild.props as any)[
|
|
89
|
+
typeof (firstChild.props as any)[handlerToInherit] === 'function'
|
|
24
90
|
) {
|
|
25
|
-
handlers.push((firstChild.props as any)[
|
|
91
|
+
handlers.push((firstChild.props as any)[handlerToInherit]);
|
|
26
92
|
}
|
|
27
93
|
}
|
|
28
94
|
if (childProps.children) {
|
|
@@ -48,6 +114,8 @@ const Card = ({
|
|
|
48
114
|
}: CardProps & { states?: { active?: boolean; disabled?: boolean } }) => {
|
|
49
115
|
const { active } = states || { active: false };
|
|
50
116
|
const childActionHandlers = collectChildActionHandlers(children as ReactNode);
|
|
117
|
+
const hasActions = checkForComponentType(children as ReactNode, 'CardAction');
|
|
118
|
+
const hasContent = checkForComponentType(children as ReactNode, 'CardContent');
|
|
51
119
|
// Extract style props using our custom hook
|
|
52
120
|
const { computedStyles, remainingProps } = useStyleProps(rest);
|
|
53
121
|
|
|
@@ -62,22 +130,69 @@ const Card = ({
|
|
|
62
130
|
const inheritChildAction = childActionHandlers.length > 0;
|
|
63
131
|
const showPressed = inheritChildAction || !!onPress;
|
|
64
132
|
|
|
133
|
+
const filteredChildren =
|
|
134
|
+
!hasContent && hasActions ? filterChildren(children as ReactNode, 'CardAction') : null;
|
|
135
|
+
|
|
136
|
+
// Check if there's any content besides CardActions
|
|
137
|
+
const hasOnlyActions =
|
|
138
|
+
hasActions &&
|
|
139
|
+
!hasContent &&
|
|
140
|
+
React.Children.toArray(filteredChildren).filter(child => child != null).length === 0;
|
|
141
|
+
|
|
142
|
+
const filteredCardActions =
|
|
143
|
+
!hasContent && hasActions
|
|
144
|
+
? extractChildren(children as ReactNode, 'CardAction', hasOnlyActions)
|
|
145
|
+
: null;
|
|
146
|
+
|
|
147
|
+
const context = useMemo(
|
|
148
|
+
() => ({
|
|
149
|
+
pressed: showPressed && active,
|
|
150
|
+
noPadding,
|
|
151
|
+
hasActions,
|
|
152
|
+
hasContent,
|
|
153
|
+
hasOnlyActions,
|
|
154
|
+
space,
|
|
155
|
+
variant,
|
|
156
|
+
}),
|
|
157
|
+
[showPressed, active, hasActions, hasContent, hasOnlyActions, noPadding, space, variant]
|
|
158
|
+
);
|
|
159
|
+
|
|
65
160
|
styles.useVariants({
|
|
66
161
|
variant,
|
|
67
162
|
colorScheme,
|
|
68
|
-
noPadding,
|
|
163
|
+
noPadding: noPadding || hasActions || hasContent,
|
|
69
164
|
active,
|
|
70
165
|
showPressed,
|
|
71
166
|
disabled,
|
|
72
|
-
space,
|
|
167
|
+
space: hasActions || hasContent ? 'none' : space,
|
|
73
168
|
});
|
|
74
169
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
170
|
+
const renderChildren = () => {
|
|
171
|
+
// Default: render children as-is
|
|
172
|
+
if (hasContent || !hasActions) {
|
|
173
|
+
return children as ReactNode;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Card has actions but no explicit CardContent
|
|
177
|
+
if (hasOnlyActions) {
|
|
178
|
+
// Only CardActions, no other content - render actions directly
|
|
179
|
+
return filteredCardActions as ReactNode;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (filteredChildren) {
|
|
183
|
+
// Has both actions and other content - wrap content and render actions below
|
|
184
|
+
return (
|
|
185
|
+
<>
|
|
186
|
+
<CardContent>{filteredChildren as ReactNode}</CardContent>
|
|
187
|
+
{filteredCardActions as ReactNode}
|
|
188
|
+
</>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Fallback
|
|
193
|
+
return children as ReactNode;
|
|
194
|
+
};
|
|
195
|
+
|
|
81
196
|
return (
|
|
82
197
|
<CardContext.Provider value={context}>
|
|
83
198
|
<Pressable
|
|
@@ -88,7 +203,7 @@ const Card = ({
|
|
|
88
203
|
accessible={showPressed}
|
|
89
204
|
importantForAccessibility={showPressed ? 'yes' : 'no'}
|
|
90
205
|
>
|
|
91
|
-
{
|
|
206
|
+
{renderChildren()}
|
|
92
207
|
</Pressable>
|
|
93
208
|
</CardContext.Provider>
|
|
94
209
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as Card } from './Card';
|
|
2
2
|
export { useCardContext } from './Card.context';
|
|
3
|
-
export
|
|
4
|
-
export { default as
|
|
3
|
+
export * from './CardAction';
|
|
4
|
+
export { default as CardPressHandler } from './CardPressHandler';
|
|
5
|
+
export { useCardPressHandlerContext } from './CardPressHandler.context';
|
|
@@ -11,7 +11,8 @@ const CheckboxIcon = ({ style, ...props }: IconProps) => {
|
|
|
11
11
|
{...props}
|
|
12
12
|
style={
|
|
13
13
|
Platform.OS === 'web'
|
|
14
|
-
?
|
|
14
|
+
? // @ts-expect-error - style prop type issue
|
|
15
|
+
{ ...(styles.icon as StyleProp<ViewStyle>), ...props.style }
|
|
15
16
|
: ([styles.icon as ViewStyle, style] as any)
|
|
16
17
|
}
|
|
17
18
|
/>
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Canvas, Controls, Meta, Primary, Story } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { BodyText, Box, Container } from '../..';
|
|
3
|
+
import { BackToTopButton, UsageWrap, ViewFigmaButton } from '../../../docs/components';
|
|
4
|
+
import * as Stories from './Container.stories';
|
|
5
|
+
|
|
6
|
+
<Meta title="Primitives / Container" />
|
|
7
|
+
|
|
8
|
+
<BackToTopButton />
|
|
9
|
+
|
|
10
|
+
# Container
|
|
11
|
+
|
|
12
|
+
The Container component is a layout primitive that provides consistent spacing and structure using the design system's layout tokens. It automatically applies responsive margin and padding based on the current breakpoint, and supports additional customization through spacing props.
|
|
13
|
+
|
|
14
|
+
- [Playground](#playground)
|
|
15
|
+
- [Usage](#usage)
|
|
16
|
+
- [Basic Usage](#basic-usage)
|
|
17
|
+
- [With Custom Padding](#with-custom-padding)
|
|
18
|
+
- [With Custom Margin](#with-custom-margin)
|
|
19
|
+
- [With Custom Spacing](#with-custom-spacing)
|
|
20
|
+
- [Props](#props)
|
|
21
|
+
- [Design Tokens](#design-tokens)
|
|
22
|
+
|
|
23
|
+
## Playground
|
|
24
|
+
|
|
25
|
+
<Canvas of={Stories.Playground} />
|
|
26
|
+
|
|
27
|
+
<Controls of={Stories.Playground} />
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
### Basic Usage
|
|
32
|
+
|
|
33
|
+
The Container component uses layout tokens automatically for responsive spacing:
|
|
34
|
+
|
|
35
|
+
<UsageWrap>
|
|
36
|
+
<Container backgroundColor="backgroundSecondary">
|
|
37
|
+
<Box bg="blue400" p="200" borderRadius="md">
|
|
38
|
+
<BodyText>Container content</BodyText>
|
|
39
|
+
</Box>
|
|
40
|
+
</Container>
|
|
41
|
+
</UsageWrap>
|
|
42
|
+
|
|
43
|
+
```jsx
|
|
44
|
+
import { Container, Box, BodyText } from '@utilitywarehouse/hearth-react-native';
|
|
45
|
+
|
|
46
|
+
const MyComponent = () => (
|
|
47
|
+
<Container>
|
|
48
|
+
<Box bg="cyan400" p="200" borderRadius="md">
|
|
49
|
+
<BodyText>Container content</BodyText>
|
|
50
|
+
</Box>
|
|
51
|
+
</Container>
|
|
52
|
+
);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### With Custom Padding
|
|
56
|
+
|
|
57
|
+
You can override the default padding with custom values using space tokens:
|
|
58
|
+
|
|
59
|
+
<Canvas of={Stories.WithPadding} />
|
|
60
|
+
|
|
61
|
+
```jsx
|
|
62
|
+
import { Container, Box, BodyText } from '@utilitywarehouse/hearth-react-native';
|
|
63
|
+
|
|
64
|
+
const MyComponent = () => (
|
|
65
|
+
<Container padding="300">
|
|
66
|
+
<Box bg="cyan400" p="200" borderRadius="md">
|
|
67
|
+
<BodyText>Container with padding</BodyText>
|
|
68
|
+
</Box>
|
|
69
|
+
</Container>
|
|
70
|
+
);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### With Custom Margin
|
|
74
|
+
|
|
75
|
+
You can override the default margin with custom values using space tokens:
|
|
76
|
+
|
|
77
|
+
<Canvas of={Stories.WithMargin} />
|
|
78
|
+
|
|
79
|
+
```jsx
|
|
80
|
+
import { Container, Box, BodyText } from '@utilitywarehouse/hearth-react-native';
|
|
81
|
+
|
|
82
|
+
const MyComponent = () => (
|
|
83
|
+
<Container margin="300">
|
|
84
|
+
<Box bg="cyan400" p="200" borderRadius="md">
|
|
85
|
+
<BodyText>Container with margin</BodyText>
|
|
86
|
+
</Box>
|
|
87
|
+
</Container>
|
|
88
|
+
);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### With Custom Spacing
|
|
92
|
+
|
|
93
|
+
The Container component supports a `space` prop for controlling gap between child elements, as well as directional padding and margin props:
|
|
94
|
+
|
|
95
|
+
<Canvas of={Stories.WithCustomSpacing} />
|
|
96
|
+
|
|
97
|
+
```jsx
|
|
98
|
+
import { Container, Box, BodyText } from '@utilitywarehouse/hearth-react-native';
|
|
99
|
+
|
|
100
|
+
const MyComponent = () => (
|
|
101
|
+
<Container space="xl" paddingHorizontal="200" paddingVertical="300">
|
|
102
|
+
<Box bg="cyan400" p="200" borderRadius="md">
|
|
103
|
+
<BodyText>Item 1</BodyText>
|
|
104
|
+
</Box>
|
|
105
|
+
<Box bg="purple400" p="200" borderRadius="md">
|
|
106
|
+
<BodyText>Item 2</BodyText>
|
|
107
|
+
</Box>
|
|
108
|
+
<Box bg="pink400" p="200" borderRadius="md">
|
|
109
|
+
<BodyText>Item 3</BodyText>
|
|
110
|
+
</Box>
|
|
111
|
+
</Container>
|
|
112
|
+
);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Props
|
|
116
|
+
|
|
117
|
+
The Container component supports spacing props similar to the Box component, with both long-form and shorthand syntax:
|
|
118
|
+
|
|
119
|
+
### Spacing Props
|
|
120
|
+
|
|
121
|
+
| Name | Shorthand | Type | Default | Description |
|
|
122
|
+
| ------------------- | --------- | ------------ | ------- | ---------------------------------------- |
|
|
123
|
+
| `padding` | `p` | `SpaceValue` | - | The padding of the container. |
|
|
124
|
+
| `paddingHorizontal` | `px` | `SpaceValue` | - | The horizontal padding of the container. |
|
|
125
|
+
| `paddingVertical` | `py` | `SpaceValue` | - | The vertical padding of the container. |
|
|
126
|
+
| `paddingTop` | `pt` | `SpaceValue` | - | The top padding of the container. |
|
|
127
|
+
| `paddingBottom` | `pb` | `SpaceValue` | - | The bottom padding of the container. |
|
|
128
|
+
| `paddingLeft` | `pl` | `SpaceValue` | - | The left padding of the container. |
|
|
129
|
+
| `paddingRight` | `pr` | `SpaceValue` | - | The right padding of the container. |
|
|
130
|
+
| `margin` | `m` | `SpaceValue` | - | The margin of the container. |
|
|
131
|
+
| `marginHorizontal` | `mx` | `SpaceValue` | - | The horizontal margin of the container. |
|
|
132
|
+
| `marginVertical` | `my` | `SpaceValue` | - | The vertical margin of the container. |
|
|
133
|
+
| `marginTop` | `mt` | `SpaceValue` | - | The top margin of the container. |
|
|
134
|
+
| `marginBottom` | `mb` | `SpaceValue` | - | The bottom margin of the container. |
|
|
135
|
+
| `marginLeft` | `ml` | `SpaceValue` | - | The left margin of the container. |
|
|
136
|
+
| `marginRight` | `mr` | `SpaceValue` | - | The right margin of the container. |
|
|
137
|
+
|
|
138
|
+
## Design Tokens
|
|
139
|
+
|
|
140
|
+
The Container component uses the following layout tokens from the design system:
|
|
141
|
+
|
|
142
|
+
### Mobile (320px - 740px)
|
|
143
|
+
|
|
144
|
+
- **Margin Horizontal**: 16px
|
|
145
|
+
- **Padding Top**: 24px
|
|
146
|
+
- **Padding Bottom**: 32px
|
|
147
|
+
|
|
148
|
+
### Tablet (740px - 992px)
|
|
149
|
+
|
|
150
|
+
- **Margin Horizontal**: 32px
|
|
151
|
+
- **Padding Top**: 24px
|
|
152
|
+
- **Padding Bottom**: 32px
|
|
153
|
+
|
|
154
|
+
### Desktop (992px+)
|
|
155
|
+
|
|
156
|
+
- **Margin Horizontal**: 32px
|
|
157
|
+
- **Padding Top**: 32px
|
|
158
|
+
- **Padding Bottom**: 48px
|
|
159
|
+
|
|
160
|
+
These values are automatically applied based on the current breakpoint. You can override them using the padding and margin props.
|
|
161
|
+
|
|
162
|
+
### Space Tokens
|
|
163
|
+
|
|
164
|
+
For the `padding`, `margin`, and directional spacing props, you can use any of the following space token values:
|
|
165
|
+
|
|
166
|
+
`'0'`, `'25'`, `'50'`, `'75'`, `'100'`, `'150'`, `'175'`, `'200'`, `'250'`, `'300'`, `'350'`, `'400'`, `'500'`, `'600'`, `'700'`, `'800'`, `'900'`, `'1000'`
|
|
167
|
+
|
|
168
|
+
These correspond to pixel values: 0px, 2px, 4px, 6px, 8px, 12px, 14px, 16px, 20px, 24px, 28px, 32px, 40px, 48px, 56px, 64px, 72px, 80px respectively.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ViewProps } from 'react-native';
|
|
2
|
+
import { SpaceValue, SpacingValues } from '../../types';
|
|
3
|
+
|
|
4
|
+
interface ContainerProps extends ViewProps {
|
|
5
|
+
/**
|
|
6
|
+
* The padding of the container.
|
|
7
|
+
*/
|
|
8
|
+
padding?: SpaceValue;
|
|
9
|
+
/**
|
|
10
|
+
* The horizontal padding of the container.
|
|
11
|
+
*/
|
|
12
|
+
paddingHorizontal?: SpaceValue;
|
|
13
|
+
/**
|
|
14
|
+
* The vertical padding of the container.
|
|
15
|
+
*/
|
|
16
|
+
paddingVertical?: SpaceValue;
|
|
17
|
+
/**
|
|
18
|
+
* The top padding of the container.
|
|
19
|
+
*/
|
|
20
|
+
paddingTop?: SpaceValue;
|
|
21
|
+
/**
|
|
22
|
+
* The bottom padding of the container.
|
|
23
|
+
*/
|
|
24
|
+
paddingBottom?: SpaceValue;
|
|
25
|
+
/**
|
|
26
|
+
* The left padding of the container.
|
|
27
|
+
*/
|
|
28
|
+
paddingLeft?: SpaceValue;
|
|
29
|
+
/**
|
|
30
|
+
* The right padding of the container.
|
|
31
|
+
*/
|
|
32
|
+
paddingRight?: SpaceValue;
|
|
33
|
+
/**
|
|
34
|
+
* The margin of the container.
|
|
35
|
+
*/
|
|
36
|
+
margin?: SpaceValue;
|
|
37
|
+
/**
|
|
38
|
+
* The horizontal margin of the container.
|
|
39
|
+
*/
|
|
40
|
+
marginHorizontal?: SpaceValue;
|
|
41
|
+
/**
|
|
42
|
+
* The vertical margin of the container.
|
|
43
|
+
*/
|
|
44
|
+
marginVertical?: SpaceValue;
|
|
45
|
+
/**
|
|
46
|
+
* The top margin of the container.
|
|
47
|
+
*/
|
|
48
|
+
marginTop?: SpaceValue;
|
|
49
|
+
/**
|
|
50
|
+
* The bottom margin of the container.
|
|
51
|
+
*/
|
|
52
|
+
marginBottom?: SpaceValue;
|
|
53
|
+
/**
|
|
54
|
+
* The left margin of the container.
|
|
55
|
+
*/
|
|
56
|
+
marginLeft?: SpaceValue;
|
|
57
|
+
/**
|
|
58
|
+
* The right margin of the container.
|
|
59
|
+
*/
|
|
60
|
+
marginRight?: SpaceValue;
|
|
61
|
+
// Padding
|
|
62
|
+
p?: SpaceValue;
|
|
63
|
+
px?: SpaceValue;
|
|
64
|
+
py?: SpaceValue;
|
|
65
|
+
pt?: SpaceValue;
|
|
66
|
+
pb?: SpaceValue;
|
|
67
|
+
pl?: SpaceValue;
|
|
68
|
+
pr?: SpaceValue;
|
|
69
|
+
// Margin
|
|
70
|
+
m?: SpaceValue;
|
|
71
|
+
mx?: SpaceValue;
|
|
72
|
+
my?: SpaceValue;
|
|
73
|
+
mt?: SpaceValue;
|
|
74
|
+
mb?: SpaceValue;
|
|
75
|
+
ml?: SpaceValue;
|
|
76
|
+
mr?: SpaceValue;
|
|
77
|
+
/**
|
|
78
|
+
* The space between child elements (gap).
|
|
79
|
+
*/
|
|
80
|
+
space?: SpacingValues;
|
|
81
|
+
/**
|
|
82
|
+
* The space between child elements.
|
|
83
|
+
*/
|
|
84
|
+
gap?: SpaceValue;
|
|
85
|
+
backgroundColor?: 'backgroundBrand' | 'backgroundPrimary' | 'backgroundSecondary' | 'transparent';
|
|
86
|
+
bg?: 'backgroundBrand' | 'backgroundPrimary' | 'backgroundSecondary' | 'transparent';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export default ContainerProps;
|