@utilitywarehouse/hearth-react-native 0.16.2 → 0.18.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 +174 -0
- package/build/components/BodyText/BodyText.js +2 -2
- 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/IconButton/IconButton.props.d.ts +19 -0
- package/build/components/IconButton/IconButtonRoot.d.ts +1 -1
- package/build/components/IconButton/IconButtonRoot.js +43 -2
- 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/ListItemHelperText.d.ts +1 -1
- package/build/components/List/ListItem/ListItemHelperText.js +2 -2
- package/build/components/List/ListItem/ListItemRoot.js +12 -4
- package/build/utils/isThemedImageProps.d.ts +1 -1
- package/package.json +2 -2
- package/src/components/BodyText/BodyText.tsx +2 -2
- 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.docs.mdx +91 -9
- package/src/components/IconButton/IconButton.figma.tsx +20 -30
- package/src/components/IconButton/IconButton.props.ts +19 -0
- package/src/components/IconButton/IconButton.stories.tsx +56 -0
- package/src/components/IconButton/IconButtonRoot.tsx +54 -1
- 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/ListItemHelperText.tsx +2 -2
- 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
|
@@ -1,104 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ReactNode, useMemo } from 'react';
|
|
2
2
|
import { GestureResponderEvent, Pressable, ViewStyle } from 'react-native';
|
|
3
3
|
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 CardActions from './CardActions';
|
|
7
8
|
import CardContent from './CardContent';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
};
|
|
73
|
-
|
|
74
|
-
// Helper that recursively collects onPress or other defined handlers from descendants
|
|
75
|
-
const collectChildActionHandlers = (
|
|
76
|
-
children: React.ReactNode
|
|
77
|
-
): Array<(e: GestureResponderEvent) => void> =>
|
|
78
|
-
React.Children.toArray(children).reduce(
|
|
79
|
-
(handlers, child) => {
|
|
80
|
-
if (React.isValidElement(child)) {
|
|
81
|
-
const childProps = child.props as any;
|
|
82
|
-
// @ts-expect-error - type
|
|
83
|
-
if (child.type.displayName === 'CardPressHandler') {
|
|
84
|
-
const actionChildren = React.Children.toArray(childProps.children);
|
|
85
|
-
const handlerToInherit = childProps['handlerToInherit'] || 'onPress';
|
|
86
|
-
const firstChild = actionChildren[0];
|
|
87
|
-
if (
|
|
88
|
-
React.isValidElement(firstChild) &&
|
|
89
|
-
typeof (firstChild.props as any)[handlerToInherit] === 'function'
|
|
90
|
-
) {
|
|
91
|
-
handlers.push((firstChild.props as any)[handlerToInherit]);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (childProps.children) {
|
|
95
|
-
handlers.push(...collectChildActionHandlers(childProps.children));
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return handlers;
|
|
99
|
-
},
|
|
100
|
-
[] as Array<(e: GestureResponderEvent) => void>
|
|
101
|
-
);
|
|
9
|
+
import {
|
|
10
|
+
checkForComponentType,
|
|
11
|
+
collectChildActionHandlers,
|
|
12
|
+
extractCardActions,
|
|
13
|
+
filterChildren,
|
|
14
|
+
hasOnlyPotentialActions,
|
|
15
|
+
} from './helpers';
|
|
102
16
|
|
|
103
17
|
const Card = ({
|
|
104
18
|
children,
|
|
@@ -116,8 +30,8 @@ const Card = ({
|
|
|
116
30
|
}: CardProps & { states?: { active?: boolean; disabled?: boolean } }) => {
|
|
117
31
|
const { active } = states || { active: false };
|
|
118
32
|
const childActionHandlers = collectChildActionHandlers(children as ReactNode);
|
|
119
|
-
const hasActions = checkForComponentType(children as ReactNode,
|
|
120
|
-
const hasContent = checkForComponentType(children as ReactNode,
|
|
33
|
+
const hasActions = checkForComponentType(children as ReactNode, CardActions);
|
|
34
|
+
const hasContent = checkForComponentType(children as ReactNode, CardContent);
|
|
121
35
|
// Extract style props using our custom hook
|
|
122
36
|
const { computedStyles, remainingProps } = useStyleProps(rest);
|
|
123
37
|
|
|
@@ -132,19 +46,9 @@ const Card = ({
|
|
|
132
46
|
const inheritChildAction = childActionHandlers.length > 0;
|
|
133
47
|
const showPressed = inheritChildAction || !!onPress;
|
|
134
48
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
// Check if there's any content besides CardActions
|
|
139
|
-
const hasOnlyActions =
|
|
140
|
-
hasActions &&
|
|
141
|
-
!hasContent &&
|
|
142
|
-
React.Children.toArray(filteredChildren).filter(child => child != null).length === 0;
|
|
143
|
-
|
|
144
|
-
const filteredCardActions =
|
|
145
|
-
!hasContent && hasActions
|
|
146
|
-
? extractChildren(children as ReactNode, 'CardAction', hasOnlyActions)
|
|
147
|
-
: null;
|
|
49
|
+
// Check if all children are action groups (CardActions)
|
|
50
|
+
const potentiallyOnlyActions = hasOnlyPotentialActions(children as ReactNode, CardActions);
|
|
51
|
+
const hasOnlyActions = potentiallyOnlyActions && !hasContent;
|
|
148
52
|
|
|
149
53
|
const context = useMemo(
|
|
150
54
|
() => ({
|
|
@@ -162,38 +66,30 @@ const Card = ({
|
|
|
162
66
|
styles.useVariants({
|
|
163
67
|
variant,
|
|
164
68
|
colorScheme,
|
|
165
|
-
noPadding: noPadding || hasActions || hasContent,
|
|
69
|
+
noPadding: noPadding || hasActions || hasContent || hasOnlyActions,
|
|
166
70
|
active,
|
|
167
71
|
showPressed,
|
|
168
72
|
disabled,
|
|
169
|
-
space: hasActions || hasContent ? 'none' : space,
|
|
73
|
+
space: hasActions || hasContent || hasOnlyActions ? 'none' : space,
|
|
170
74
|
shadowColor,
|
|
171
75
|
});
|
|
172
76
|
|
|
173
77
|
const renderChildren = () => {
|
|
174
|
-
//
|
|
175
|
-
if (hasContent || !hasActions) {
|
|
78
|
+
// Explicit CardContent used - render as-is or Card has only actions (or potential action wrappers) - render children directly
|
|
79
|
+
if (hasContent || hasOnlyActions || !hasActions) {
|
|
176
80
|
return children as ReactNode;
|
|
177
81
|
}
|
|
178
82
|
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return filteredCardActions as ReactNode;
|
|
183
|
-
}
|
|
83
|
+
// Has both actions and other content - wrap non-action content and render actions separately
|
|
84
|
+
const filteredNonActionChildren = filterChildren(children as ReactNode, CardActions);
|
|
85
|
+
const cardActions = extractCardActions(children as ReactNode, CardActions);
|
|
184
86
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
</>
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Fallback
|
|
196
|
-
return children as ReactNode;
|
|
87
|
+
return (
|
|
88
|
+
<>
|
|
89
|
+
<CardContent>{filteredNonActionChildren as ReactNode}</CardContent>
|
|
90
|
+
{cardActions}
|
|
91
|
+
</>
|
|
92
|
+
);
|
|
197
93
|
};
|
|
198
94
|
|
|
199
95
|
return (
|
|
@@ -298,7 +194,6 @@ const styles = StyleSheet.create(theme => ({
|
|
|
298
194
|
},
|
|
299
195
|
},
|
|
300
196
|
},
|
|
301
|
-
|
|
302
197
|
active: {
|
|
303
198
|
true: {},
|
|
304
199
|
},
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { GestureResponderEvent } from 'react-native';
|
|
3
|
+
|
|
4
|
+
const getInheritableHandler = (
|
|
5
|
+
child: React.ReactNode,
|
|
6
|
+
handlerToInherit: string
|
|
7
|
+
): ((e: GestureResponderEvent) => void) | null => {
|
|
8
|
+
if (!React.isValidElement(child)) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const childProps = child.props as any;
|
|
13
|
+
const isDisabled = !!childProps.disabled || !!childProps.loading;
|
|
14
|
+
if (isDisabled || typeof childProps[handlerToInherit] !== 'function') {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return childProps[handlerToInherit];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Helper to check if children contain specific component types
|
|
22
|
+
export const checkForComponentType = (
|
|
23
|
+
children: React.ReactNode,
|
|
24
|
+
componentType: React.ComponentType<any>
|
|
25
|
+
): boolean => {
|
|
26
|
+
return React.Children.toArray(children).some(child => {
|
|
27
|
+
if (React.isValidElement(child)) {
|
|
28
|
+
if (child.type === componentType) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
const childProps = child.props as any;
|
|
32
|
+
if (childProps.children) {
|
|
33
|
+
return checkForComponentType(childProps.children, componentType);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Check if a component has "content" in its children (not just actions)
|
|
41
|
+
export const hasContentInChildren = (
|
|
42
|
+
child: React.ReactNode,
|
|
43
|
+
actionType: React.ComponentType<any>
|
|
44
|
+
): boolean => {
|
|
45
|
+
if (!React.isValidElement(child)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const childProps = child.props as any;
|
|
50
|
+
if (!childProps?.children) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Check if children contain anything other than the action type
|
|
55
|
+
const childrenArray = React.Children.toArray(childProps.children);
|
|
56
|
+
return childrenArray.some(c => {
|
|
57
|
+
if (!React.isValidElement(c)) {
|
|
58
|
+
// Text, numbers, etc - this is content
|
|
59
|
+
return c != null;
|
|
60
|
+
}
|
|
61
|
+
return c.type !== actionType;
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Check if all children are CardActions groups
|
|
66
|
+
export const hasOnlyPotentialActions = (
|
|
67
|
+
children: React.ReactNode,
|
|
68
|
+
actionType: React.ComponentType<any>
|
|
69
|
+
): boolean => {
|
|
70
|
+
const childArray = React.Children.toArray(children);
|
|
71
|
+
if (childArray.length === 0) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let hasActionCandidate = false;
|
|
76
|
+
|
|
77
|
+
for (const child of childArray) {
|
|
78
|
+
if (!React.isValidElement(child)) {
|
|
79
|
+
if (child != null) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (child.type === actionType) {
|
|
86
|
+
hasActionCandidate = true;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (checkForComponentType(child, actionType)) {
|
|
91
|
+
hasActionCandidate = true;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (typeof child.type === 'string') {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (hasContentInChildren(child, actionType)) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return hasActionCandidate || checkForComponentType(children, actionType);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Helper to filter out specific component types from children
|
|
110
|
+
export const filterChildren = (
|
|
111
|
+
children: React.ReactNode,
|
|
112
|
+
excludeComponentType: React.ComponentType<any>
|
|
113
|
+
): React.ReactNode => {
|
|
114
|
+
return React.Children.map(children, child => {
|
|
115
|
+
if (React.isValidElement(child)) {
|
|
116
|
+
if (child.type === excludeComponentType) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Check if this child contains the excludeComponentType
|
|
121
|
+
if (checkForComponentType(child, excludeComponentType)) {
|
|
122
|
+
return null; // This child or its descendants contain the action
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const childProps = child.props as any;
|
|
126
|
+
if (childProps.children) {
|
|
127
|
+
const filteredChildren = filterChildren(childProps.children, excludeComponentType);
|
|
128
|
+
// Only preserve wrapper if it has non-null children
|
|
129
|
+
const hasContent = React.Children.toArray(filteredChildren).some(c => c != null);
|
|
130
|
+
if (!hasContent) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
return React.cloneElement(child, {
|
|
134
|
+
...childProps,
|
|
135
|
+
children: filteredChildren,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return child;
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// Helper to extract only CardActions (preserving wrapper components)
|
|
144
|
+
export const extractCardActions = (
|
|
145
|
+
children: React.ReactNode,
|
|
146
|
+
actionType: React.ComponentType<any>
|
|
147
|
+
): React.ReactNode => {
|
|
148
|
+
const recursiveExtract = (children: React.ReactNode): React.ReactNode => {
|
|
149
|
+
return React.Children.map(children, child => {
|
|
150
|
+
if (!React.isValidElement(child)) return null;
|
|
151
|
+
|
|
152
|
+
// Direct action
|
|
153
|
+
if (child.type === actionType) {
|
|
154
|
+
return child;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// If this child contains a CardActions wrapper in its tree, keep it
|
|
158
|
+
if (checkForComponentType(child, actionType) && !hasContentInChildren(child, actionType)) {
|
|
159
|
+
return child;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return null;
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
return recursiveExtract(children);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Helper that recursively collects onPress or other defined handlers from descendants
|
|
170
|
+
export const collectChildActionHandlers = (
|
|
171
|
+
children: React.ReactNode
|
|
172
|
+
): Array<(e: GestureResponderEvent) => void> =>
|
|
173
|
+
React.Children.toArray(children).reduce(
|
|
174
|
+
(handlers, child) => {
|
|
175
|
+
if (React.isValidElement(child)) {
|
|
176
|
+
const childProps = child.props as any;
|
|
177
|
+
// Check using displayName as CardPressHandler might not be directly importable
|
|
178
|
+
// @ts-expect-error - type
|
|
179
|
+
if (child.type?.displayName === 'CardPressHandler') {
|
|
180
|
+
const actionChildren = React.Children.toArray(childProps.children);
|
|
181
|
+
const handlerToInherit = childProps['handlerToInherit'] || 'onPress';
|
|
182
|
+
const firstChild = actionChildren[0];
|
|
183
|
+
const handler = getInheritableHandler(firstChild, handlerToInherit);
|
|
184
|
+
if (handler) {
|
|
185
|
+
handlers.push(handler);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (childProps.children) {
|
|
189
|
+
handlers.push(...collectChildActionHandlers(childProps.children));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return handlers;
|
|
193
|
+
},
|
|
194
|
+
[] as Array<(e: GestureResponderEvent) => void>
|
|
195
|
+
);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { default as Card } from './Card';
|
|
2
2
|
export { useCardContext } from './Card.context';
|
|
3
3
|
export * from './CardAction';
|
|
4
|
+
export { default as CardActions } from './CardActions';
|
|
5
|
+
export { default as CardContent } from './CardContent';
|
|
4
6
|
export { default as CardPressHandler } from './CardPressHandler';
|
|
5
7
|
export { useCardPressHandlerContext } from './CardPressHandler.context';
|
|
@@ -1,54 +1,49 @@
|
|
|
1
|
-
import
|
|
2
|
-
import ExpandableCard from
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* -- This file was auto-generated by Code Connect --
|
|
7
|
-
* `props` includes a mapping from your code props to Figma properties.
|
|
8
|
-
* You should check this is correct, and update the `example` function
|
|
9
|
-
* to return the code example you'd like to see in Figma
|
|
10
|
-
*/
|
|
1
|
+
import figma from '@figma/code-connect';
|
|
2
|
+
import { ExpandableCard } from '../';
|
|
3
|
+
import { IconContainer } from '../IconContainer';
|
|
11
4
|
|
|
12
5
|
figma.connect(
|
|
13
6
|
ExpandableCard,
|
|
14
|
-
|
|
7
|
+
'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?node-id=7222%3A5935',
|
|
15
8
|
{
|
|
16
9
|
props: {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
expanded: figma.boolean('Expand?'),
|
|
11
|
+
heading: figma.string('Heading'),
|
|
12
|
+
helperText: figma.string('Helper text'),
|
|
13
|
+
leadingContent: figma.boolean('Leading content?', {
|
|
14
|
+
true: figma.nestedProps('Leading content', {
|
|
15
|
+
variant: figma.enum('Variant', {
|
|
16
|
+
Icon: figma.instance('Icon-24'),
|
|
17
|
+
'Icon Container': <IconContainer icon={figma.instance('Icon-24')} />,
|
|
18
|
+
}),
|
|
19
|
+
}),
|
|
24
20
|
}),
|
|
25
|
-
disabled: figma.enum(
|
|
21
|
+
disabled: figma.enum('State', {
|
|
26
22
|
Active: true,
|
|
27
23
|
}),
|
|
28
|
-
collapsable: figma.boolean(
|
|
29
|
-
focusable: figma.enum(
|
|
24
|
+
collapsable: figma.boolean('Expand?'),
|
|
25
|
+
focusable: figma.enum('State', {
|
|
30
26
|
Focus: true,
|
|
31
27
|
}),
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// "leadingContent": figma.boolean('Leading content?'),
|
|
40
|
-
// "badge": figma.boolean('Badge?')
|
|
28
|
+
content: figma.instance('Custom content'),
|
|
29
|
+
numericalValue: figma.boolean('Numerical value?', {
|
|
30
|
+
true: figma.string('Numerical value'),
|
|
31
|
+
}),
|
|
32
|
+
badge: figma.boolean('Badge?', {
|
|
33
|
+
true: figma.instance('Badge'),
|
|
34
|
+
}),
|
|
41
35
|
},
|
|
42
|
-
example:
|
|
36
|
+
example: props => (
|
|
43
37
|
<ExpandableCard
|
|
44
38
|
expanded={props.expanded}
|
|
45
39
|
heading={props.heading}
|
|
46
40
|
helperText={props.helperText}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
leadingContent={props.leadingContent?.variant}
|
|
42
|
+
numericValue={props.numericalValue}
|
|
43
|
+
badge={props.badge}
|
|
44
|
+
>
|
|
45
|
+
{props.content}
|
|
46
|
+
</ExpandableCard>
|
|
52
47
|
),
|
|
53
|
-
}
|
|
54
|
-
)
|
|
48
|
+
}
|
|
49
|
+
);
|
|
@@ -1,23 +1,40 @@
|
|
|
1
|
-
import
|
|
2
|
-
import ExpandableCardGroup from
|
|
3
|
-
import figma from "@figma/code-connect"
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* -- This file was auto-generated by Code Connect --
|
|
7
|
-
* None of your props could be automatically mapped to Figma properties.
|
|
8
|
-
* You should update the `props` object to include a mapping from your
|
|
9
|
-
* code props to Figma properties, and update the `example` function to
|
|
10
|
-
* return the code example you'd like to see in Figma
|
|
11
|
-
*/
|
|
1
|
+
import figma from '@figma/code-connect';
|
|
2
|
+
import { ExpandableCardGroup } from '../';
|
|
12
3
|
|
|
13
4
|
figma.connect(
|
|
14
5
|
ExpandableCardGroup,
|
|
15
|
-
|
|
6
|
+
'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=7222-7221&m=dev',
|
|
16
7
|
{
|
|
17
8
|
props: {
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
sectionHeader: figma.boolean('Section header?', {
|
|
10
|
+
true: figma.nestedProps('Section Header', {
|
|
11
|
+
heading: figma.string('Heading'),
|
|
12
|
+
helperText: figma.boolean('Helper text?', {
|
|
13
|
+
true: figma.string('Helper text'),
|
|
14
|
+
}),
|
|
15
|
+
trailingContent: figma.boolean('Trailing content?', {
|
|
16
|
+
true: figma.nestedProps('Trailing content', {
|
|
17
|
+
headerTrailingContent: figma.instance('Variant'),
|
|
18
|
+
}),
|
|
19
|
+
}),
|
|
20
|
+
invalidText: figma.enum('State', {
|
|
21
|
+
Invalid: figma.nestedProps('Validation Text', {
|
|
22
|
+
invalidText: figma.string('Text'),
|
|
23
|
+
}),
|
|
24
|
+
}),
|
|
25
|
+
}),
|
|
26
|
+
}),
|
|
27
|
+
cards: figma.children('Expandable Card'),
|
|
20
28
|
},
|
|
21
|
-
example:
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
example: props => (
|
|
30
|
+
<ExpandableCardGroup
|
|
31
|
+
heading={props.sectionHeader?.heading}
|
|
32
|
+
helperText={props.sectionHeader?.helperText}
|
|
33
|
+
headerTrailingContent={props.sectionHeader?.trailingContent?.headerTrailingContent}
|
|
34
|
+
invalidText={props.sectionHeader?.invalidText?.invalidText}
|
|
35
|
+
>
|
|
36
|
+
{props.cards}
|
|
37
|
+
</ExpandableCardGroup>
|
|
38
|
+
),
|
|
39
|
+
}
|
|
40
|
+
);
|
|
@@ -26,6 +26,11 @@ export interface ExpandableCardGroupProps extends ViewProps {
|
|
|
26
26
|
* Test ID for testing
|
|
27
27
|
*/
|
|
28
28
|
testID?: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Validation text displayed below the helper text when in an invalid state
|
|
32
|
+
*/
|
|
33
|
+
invalidText?: string;
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
export default ExpandableCardGroupProps;
|
|
@@ -10,6 +10,7 @@ const ExpandableCardGroup = ({
|
|
|
10
10
|
children,
|
|
11
11
|
style,
|
|
12
12
|
testID = 'expandable-card-group',
|
|
13
|
+
invalidText,
|
|
13
14
|
...props
|
|
14
15
|
}: ExpandableCardGroupProps) => {
|
|
15
16
|
return (
|
|
@@ -19,6 +20,7 @@ const ExpandableCardGroup = ({
|
|
|
19
20
|
heading={heading}
|
|
20
21
|
helperText={helperText}
|
|
21
22
|
trailingContent={headerTrailingContent}
|
|
23
|
+
invalidText={invalidText}
|
|
22
24
|
/>
|
|
23
25
|
) : null}
|
|
24
26
|
<View style={styles.cardsContainer}>{children}</View>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import figma from '@figma/code-connect';
|
|
2
|
+
import { HighlightBanner, Image } from '..';
|
|
3
|
+
|
|
4
|
+
figma.connect(
|
|
5
|
+
HighlightBanner,
|
|
6
|
+
'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=8306-4665&t=3uUSBVdxldgG5uz3-4',
|
|
7
|
+
{
|
|
8
|
+
props: {
|
|
9
|
+
heading: figma.string('Heading'),
|
|
10
|
+
description: figma.string('Description'),
|
|
11
|
+
image: figma.boolean('Image?', {
|
|
12
|
+
true: <Image source={{ uri: '' }} />,
|
|
13
|
+
}),
|
|
14
|
+
headingColor: figma.enum('Heading color', {
|
|
15
|
+
Highlight: 'highlight',
|
|
16
|
+
Pig: 'pig',
|
|
17
|
+
Energy: 'energy',
|
|
18
|
+
Broadband: 'broadband',
|
|
19
|
+
Insurance: 'insurance',
|
|
20
|
+
Cashback: 'cashback',
|
|
21
|
+
Mobile: 'mobile',
|
|
22
|
+
}),
|
|
23
|
+
link: figma.boolean('Link?', {
|
|
24
|
+
true: figma.children('Link'),
|
|
25
|
+
}),
|
|
26
|
+
button: figma.boolean('Button?', {
|
|
27
|
+
true: figma.children('Button'),
|
|
28
|
+
}),
|
|
29
|
+
},
|
|
30
|
+
example: props => {
|
|
31
|
+
return (
|
|
32
|
+
// HighlightBanner doesn't need to be wrapped in a Card
|
|
33
|
+
// it's a standalone component in code please see the HighlightBanner docs
|
|
34
|
+
// https://hearth.prod.uw.systems/react-native/?path=/docs/components-highlightbanner--docs
|
|
35
|
+
<HighlightBanner
|
|
36
|
+
heading={props.heading}
|
|
37
|
+
description={props.description}
|
|
38
|
+
image={props.image}
|
|
39
|
+
headingColor={props.headingColor}
|
|
40
|
+
link={props.link}
|
|
41
|
+
button={props.button}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
);
|