@idealyst/components 1.2.30 → 1.2.32
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/package.json +4 -4
- package/plugin/web.js +2 -0
- package/src/ActivityIndicator/ActivityIndicator.native.tsx +1 -0
- package/src/ActivityIndicator/ActivityIndicator.styles.tsx +1 -5
- package/src/ActivityIndicator/ActivityIndicator.web.tsx +15 -28
- package/src/Alert/Alert.native.tsx +2 -2
- package/src/Alert/Alert.styles.tsx +88 -63
- package/src/Alert/Alert.web.tsx +26 -27
- package/src/Chip/Chip.styles.tsx +124 -142
- package/src/IconButton/IconButton.native.tsx +219 -0
- package/src/IconButton/IconButton.styles.tsx +127 -0
- package/src/IconButton/IconButton.web.tsx +198 -0
- package/src/IconButton/index.native.ts +5 -0
- package/src/IconButton/index.ts +5 -0
- package/src/IconButton/index.web.ts +5 -0
- package/src/IconButton/types.ts +84 -0
- package/src/Skeleton/Skeleton.web.tsx +1 -1
- package/src/Switch/Switch.styles.tsx +23 -6
- package/src/Switch/Switch.web.tsx +7 -9
- package/src/View/View.styles.tsx +1 -0
- package/src/View/View.web.tsx +7 -1
- package/src/examples/ActivityIndicatorExamples.tsx +177 -0
- package/src/examples/SwitchExamples.tsx +24 -24
- package/src/examples/index.ts +1 -0
- package/src/extensions/types.ts +12 -0
- package/src/index.native.ts +4 -0
- package/src/index.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idealyst/components",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.32",
|
|
4
4
|
"description": "Shared component library for React and React Native",
|
|
5
5
|
"documentation": "https://github.com/IdealystIO/idealyst-framework/tree/main/packages/components#readme",
|
|
6
6
|
"readme": "README.md",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"publish:npm": "npm publish"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@idealyst/theme": "^1.2.
|
|
59
|
+
"@idealyst/theme": "^1.2.32",
|
|
60
60
|
"@mdi/js": ">=7.0.0",
|
|
61
61
|
"@mdi/react": ">=1.0.0",
|
|
62
62
|
"@react-native-vector-icons/common": ">=12.0.0",
|
|
@@ -106,8 +106,8 @@
|
|
|
106
106
|
}
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
|
-
"@idealyst/theme": "^1.2.
|
|
110
|
-
"@idealyst/tooling": "^1.2.
|
|
109
|
+
"@idealyst/theme": "^1.2.32",
|
|
110
|
+
"@idealyst/tooling": "^1.2.30",
|
|
111
111
|
"@mdi/react": "^1.6.1",
|
|
112
112
|
"@types/react": "^19.1.0",
|
|
113
113
|
"react": "^19.1.0",
|
package/plugin/web.js
CHANGED
|
@@ -248,6 +248,8 @@ module.exports = function ({ types: t }, options = {}) {
|
|
|
248
248
|
'Alert': ['icon'],
|
|
249
249
|
'Chip': ['icon', 'deleteIcon'],
|
|
250
250
|
'Input': ['leftIcon', 'rightIcon'],
|
|
251
|
+
'TextInput': ['leftIcon', 'rightIcon'],
|
|
252
|
+
'IconButton': ['icon'],
|
|
251
253
|
};
|
|
252
254
|
|
|
253
255
|
const iconProps = iconPropMap[componentName];
|
|
@@ -22,10 +22,10 @@ export type ActivityIndicatorDynamicProps = {
|
|
|
22
22
|
*/
|
|
23
23
|
export const activityIndicatorStyles = defineStyle('ActivityIndicator', (theme: Theme) => ({
|
|
24
24
|
container: (_props: ActivityIndicatorDynamicProps) => ({
|
|
25
|
+
display: 'flex' as const,
|
|
25
26
|
alignItems: 'center' as const,
|
|
26
27
|
justifyContent: 'center' as const,
|
|
27
28
|
variants: {
|
|
28
|
-
// $iterator expands for each activityIndicator size
|
|
29
29
|
size: {
|
|
30
30
|
width: theme.sizes.$activityIndicator.size,
|
|
31
31
|
height: theme.sizes.$activityIndicator.size,
|
|
@@ -46,10 +46,6 @@ export const activityIndicatorStyles = defineStyle('ActivityIndicator', (theme:
|
|
|
46
46
|
height: theme.sizes.$activityIndicator.size,
|
|
47
47
|
borderWidth: theme.sizes.$activityIndicator.borderWidth,
|
|
48
48
|
},
|
|
49
|
-
animating: {
|
|
50
|
-
true: {},
|
|
51
|
-
false: {},
|
|
52
|
-
},
|
|
53
49
|
intent: {
|
|
54
50
|
color: theme.$intents.primary,
|
|
55
51
|
_web: {
|
|
@@ -42,8 +42,9 @@ const ActivityIndicator = forwardRef<IdealystElement, ActivityIndicatorProps>(({
|
|
|
42
42
|
|
|
43
43
|
// Apply variants using the correct Unistyles 3.0 pattern
|
|
44
44
|
activityIndicatorStyles.useVariants({
|
|
45
|
-
size:
|
|
45
|
+
size: size,
|
|
46
46
|
animating,
|
|
47
|
+
intent,
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
// Don't render if not animating and hidesWhenStopped is true
|
|
@@ -51,35 +52,21 @@ const ActivityIndicator = forwardRef<IdealystElement, ActivityIndicatorProps>(({
|
|
|
51
52
|
return null;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
//
|
|
55
|
-
const
|
|
56
|
-
(activityIndicatorStyles.container as any)({}),
|
|
57
|
-
customSize && {
|
|
58
|
-
width: customSize,
|
|
59
|
-
height: customSize,
|
|
60
|
-
},
|
|
61
|
-
style,
|
|
62
|
-
];
|
|
55
|
+
// Dynamic props for style functions
|
|
56
|
+
const dynamicProps = { size: sizeVariant, animating, intent };
|
|
63
57
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
height: customSize,
|
|
71
|
-
borderWidth: Math.max(2, customSize / 10),
|
|
72
|
-
} : {},
|
|
73
|
-
color ? { borderTopColor: color, borderRightColor: color } : {},
|
|
74
|
-
// Add inline CSS animation
|
|
75
|
-
{
|
|
76
|
-
animation: animating ? 'spin 1s linear infinite' : undefined,
|
|
77
|
-
},
|
|
78
|
-
];
|
|
58
|
+
// Use getWebProps - same pattern as Alert
|
|
59
|
+
const containerProps = getWebProps([
|
|
60
|
+
(activityIndicatorStyles.container as any)(dynamicProps),
|
|
61
|
+
customSize && { width: customSize, height: customSize },
|
|
62
|
+
style,
|
|
63
|
+
]);
|
|
79
64
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
65
|
+
const spinnerProps = getWebProps([
|
|
66
|
+
(activityIndicatorStyles.spinner as any)(dynamicProps),
|
|
67
|
+
customSize && { width: customSize, height: customSize, borderWidth: Math.max(2, customSize / 10) },
|
|
68
|
+
color && { borderTopColor: color, borderRightColor: color },
|
|
69
|
+
]);
|
|
83
70
|
|
|
84
71
|
const mergedRef = useMergeRefs(ref, containerProps.ref);
|
|
85
72
|
|
|
@@ -32,8 +32,8 @@ const Alert = forwardRef<IdealystElement, AlertProps>(({
|
|
|
32
32
|
testID,
|
|
33
33
|
id,
|
|
34
34
|
}, ref) => {
|
|
35
|
-
// Apply variants for size
|
|
36
|
-
alertStyles.useVariants({ size });
|
|
35
|
+
// Apply variants for size, intent, and type
|
|
36
|
+
alertStyles.useVariants({ size, intent, type });
|
|
37
37
|
|
|
38
38
|
// Call all styles as functions to get theme-reactive styles
|
|
39
39
|
const dynamicProps = { intent, type, size };
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Alert styles using defineStyle with
|
|
2
|
+
* Alert styles using defineStyle with variant expansion.
|
|
3
|
+
*
|
|
4
|
+
* Alert has compound logic between type+intent that's handled via compoundVariants.
|
|
5
|
+
* The $intents iterator in compoundVariants expands for all intent values.
|
|
3
6
|
*/
|
|
4
7
|
import { StyleSheet } from 'react-native-unistyles';
|
|
5
8
|
import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
|
|
@@ -20,10 +23,10 @@ export type AlertDynamicProps = {
|
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
/**
|
|
23
|
-
* Alert styles with
|
|
26
|
+
* Alert styles with variant expansion for size/intent/type.
|
|
24
27
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
28
|
+
* The intent variant is expanded via $intents iterator.
|
|
29
|
+
* CompoundVariants handle type+intent combinations for colors.
|
|
27
30
|
*/
|
|
28
31
|
export const alertStyles = defineStyle('Alert', (theme: Theme) => ({
|
|
29
32
|
container: (_props: AlertDynamicProps) => ({
|
|
@@ -33,26 +36,33 @@ export const alertStyles = defineStyle('Alert', (theme: Theme) => ({
|
|
|
33
36
|
borderWidth: 1,
|
|
34
37
|
borderStyle: 'solid' as const,
|
|
35
38
|
variants: {
|
|
36
|
-
type: {
|
|
37
|
-
filled: {
|
|
38
|
-
backgroundColor: theme.$intents.primary,
|
|
39
|
-
borderColor: theme.$intents.primary,
|
|
40
|
-
},
|
|
41
|
-
outlined: {
|
|
42
|
-
backgroundColor: 'transparent',
|
|
43
|
-
borderColor: theme.$intents.primary,
|
|
44
|
-
},
|
|
45
|
-
soft: {
|
|
46
|
-
backgroundColor: theme.$intents.light,
|
|
47
|
-
borderColor: theme.$intents.light,
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
39
|
size: {
|
|
51
40
|
gap: theme.sizes.$alert.gap,
|
|
52
41
|
padding: theme.sizes.$alert.padding,
|
|
53
42
|
borderRadius: theme.sizes.$alert.borderRadius,
|
|
54
43
|
},
|
|
44
|
+
// Intent variant - expands to primary, success, danger, etc.
|
|
45
|
+
intent: {
|
|
46
|
+
// Base styles per intent (overridden by type+intent compoundVariants)
|
|
47
|
+
backgroundColor: theme.$intents.primary,
|
|
48
|
+
borderColor: theme.$intents.primary,
|
|
49
|
+
},
|
|
50
|
+
type: {
|
|
51
|
+
filled: {},
|
|
52
|
+
outlined: {
|
|
53
|
+
backgroundColor: 'transparent',
|
|
54
|
+
},
|
|
55
|
+
soft: {},
|
|
56
|
+
},
|
|
55
57
|
},
|
|
58
|
+
compoundVariants: [
|
|
59
|
+
// filled: use intent primary for bg and border
|
|
60
|
+
{ type: 'filled', styles: { backgroundColor: theme.$intents.primary, borderColor: theme.$intents.primary } },
|
|
61
|
+
// outlined: transparent bg, intent primary for border
|
|
62
|
+
{ type: 'outlined', styles: { backgroundColor: 'transparent', borderColor: theme.$intents.primary } },
|
|
63
|
+
// soft: intent light for bg and border
|
|
64
|
+
{ type: 'soft', styles: { backgroundColor: theme.$intents.light, borderColor: theme.$intents.light } },
|
|
65
|
+
],
|
|
56
66
|
}),
|
|
57
67
|
|
|
58
68
|
iconContainer: (_props: AlertDynamicProps) => ({
|
|
@@ -63,63 +73,75 @@ export const alertStyles = defineStyle('Alert', (theme: Theme) => ({
|
|
|
63
73
|
flexShrink: 0,
|
|
64
74
|
marginTop: 2,
|
|
65
75
|
variants: {
|
|
66
|
-
type: {
|
|
67
|
-
filled: {
|
|
68
|
-
color: theme.$intents.contrast,
|
|
69
|
-
},
|
|
70
|
-
outlined: {
|
|
71
|
-
color: theme.$intents.primary,
|
|
72
|
-
},
|
|
73
|
-
soft: {
|
|
74
|
-
color: theme.$intents.primary,
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
76
|
size: {
|
|
78
77
|
width: theme.sizes.$alert.iconSize,
|
|
79
78
|
height: theme.sizes.$alert.iconSize,
|
|
80
79
|
},
|
|
80
|
+
intent: {
|
|
81
|
+
color: theme.$intents.primary,
|
|
82
|
+
},
|
|
83
|
+
type: {
|
|
84
|
+
filled: {},
|
|
85
|
+
outlined: {},
|
|
86
|
+
soft: {},
|
|
87
|
+
},
|
|
81
88
|
},
|
|
89
|
+
compoundVariants: [
|
|
90
|
+
// filled: contrast color for icon
|
|
91
|
+
{ type: 'filled', styles: { color: theme.$intents.contrast } },
|
|
92
|
+
// outlined/soft: primary color for icon
|
|
93
|
+
{ type: 'outlined', styles: { color: theme.$intents.primary } },
|
|
94
|
+
{ type: 'soft', styles: { color: theme.$intents.primary } },
|
|
95
|
+
],
|
|
82
96
|
}),
|
|
83
97
|
|
|
84
98
|
title: (_props: AlertDynamicProps) => ({
|
|
85
99
|
fontWeight: '600' as const,
|
|
86
100
|
variants: {
|
|
87
|
-
type: {
|
|
88
|
-
filled: {
|
|
89
|
-
color: theme.$intents.contrast,
|
|
90
|
-
},
|
|
91
|
-
outlined: {
|
|
92
|
-
color: theme.$intents.primary,
|
|
93
|
-
},
|
|
94
|
-
soft: {
|
|
95
|
-
color: theme.$intents.primary,
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
101
|
size: {
|
|
99
102
|
fontSize: theme.sizes.$alert.titleFontSize,
|
|
100
103
|
lineHeight: theme.sizes.$alert.titleLineHeight,
|
|
101
104
|
},
|
|
105
|
+
intent: {
|
|
106
|
+
color: theme.$intents.primary,
|
|
107
|
+
},
|
|
108
|
+
type: {
|
|
109
|
+
filled: {},
|
|
110
|
+
outlined: {},
|
|
111
|
+
soft: {},
|
|
112
|
+
},
|
|
102
113
|
},
|
|
114
|
+
compoundVariants: [
|
|
115
|
+
// filled: contrast color for title
|
|
116
|
+
{ type: 'filled', styles: { color: theme.$intents.contrast } },
|
|
117
|
+
// outlined/soft: primary color for title
|
|
118
|
+
{ type: 'outlined', styles: { color: theme.$intents.primary } },
|
|
119
|
+
{ type: 'soft', styles: { color: theme.$intents.primary } },
|
|
120
|
+
],
|
|
103
121
|
}),
|
|
104
122
|
|
|
105
123
|
message: (_props: AlertDynamicProps) => ({
|
|
106
124
|
variants: {
|
|
107
|
-
type: {
|
|
108
|
-
filled: {
|
|
109
|
-
color: theme.$intents.contrast,
|
|
110
|
-
},
|
|
111
|
-
outlined: {
|
|
112
|
-
color: theme.colors.text.primary,
|
|
113
|
-
},
|
|
114
|
-
soft: {
|
|
115
|
-
color: theme.colors.text.primary,
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
125
|
size: {
|
|
119
126
|
fontSize: theme.sizes.$alert.messageFontSize,
|
|
120
127
|
lineHeight: theme.sizes.$alert.messageLineHeight,
|
|
121
128
|
},
|
|
129
|
+
intent: {
|
|
130
|
+
color: theme.colors.text.primary,
|
|
131
|
+
},
|
|
132
|
+
type: {
|
|
133
|
+
filled: {},
|
|
134
|
+
outlined: {},
|
|
135
|
+
soft: {},
|
|
136
|
+
},
|
|
122
137
|
},
|
|
138
|
+
compoundVariants: [
|
|
139
|
+
// filled: contrast color for message
|
|
140
|
+
{ type: 'filled', styles: { color: theme.$intents.contrast } },
|
|
141
|
+
// outlined/soft: use default text color (set in intent variant)
|
|
142
|
+
{ type: 'outlined', styles: { color: theme.colors.text.primary } },
|
|
143
|
+
{ type: 'soft', styles: { color: theme.colors.text.primary } },
|
|
144
|
+
],
|
|
123
145
|
}),
|
|
124
146
|
|
|
125
147
|
content: (_props: AlertDynamicProps) => ({
|
|
@@ -128,7 +150,6 @@ export const alertStyles = defineStyle('Alert', (theme: Theme) => ({
|
|
|
128
150
|
flexDirection: 'column' as const,
|
|
129
151
|
variants: {
|
|
130
152
|
size: {
|
|
131
|
-
// Gap is half of the main gap
|
|
132
153
|
gap: theme.sizes.$alert.gap,
|
|
133
154
|
},
|
|
134
155
|
},
|
|
@@ -177,22 +198,26 @@ export const alertStyles = defineStyle('Alert', (theme: Theme) => ({
|
|
|
177
198
|
alignItems: 'center' as const,
|
|
178
199
|
justifyContent: 'center' as const,
|
|
179
200
|
variants: {
|
|
180
|
-
type: {
|
|
181
|
-
filled: {
|
|
182
|
-
color: theme.$intents.contrast,
|
|
183
|
-
},
|
|
184
|
-
outlined: {
|
|
185
|
-
color: theme.$intents.primary,
|
|
186
|
-
},
|
|
187
|
-
soft: {
|
|
188
|
-
color: theme.$intents.primary,
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
201
|
size: {
|
|
192
202
|
width: theme.sizes.$alert.closeIconSize,
|
|
193
203
|
height: theme.sizes.$alert.closeIconSize,
|
|
194
204
|
},
|
|
205
|
+
intent: {
|
|
206
|
+
color: theme.$intents.primary,
|
|
207
|
+
},
|
|
208
|
+
type: {
|
|
209
|
+
filled: {},
|
|
210
|
+
outlined: {},
|
|
211
|
+
soft: {},
|
|
212
|
+
},
|
|
195
213
|
},
|
|
214
|
+
compoundVariants: [
|
|
215
|
+
// filled: contrast color for close icon
|
|
216
|
+
{ type: 'filled', styles: { color: theme.$intents.contrast } },
|
|
217
|
+
// outlined/soft: primary color for close icon
|
|
218
|
+
{ type: 'outlined', styles: { color: theme.$intents.primary } },
|
|
219
|
+
{ type: 'soft', styles: { color: theme.$intents.primary } },
|
|
220
|
+
],
|
|
196
221
|
}),
|
|
197
222
|
}));
|
|
198
223
|
|
package/src/Alert/Alert.web.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isValidElement, forwardRef } from 'react';
|
|
1
|
+
import { isValidElement, forwardRef, ElementType, useMemo } from 'react';
|
|
2
2
|
import { getWebProps } from 'react-native-unistyles/web';
|
|
3
3
|
import { alertStyles } from './Alert.styles';
|
|
4
4
|
import type { AlertProps } from './types';
|
|
@@ -8,13 +8,13 @@ import useMergeRefs from '../hooks/useMergeRefs';
|
|
|
8
8
|
import type { IdealystElement } from '../utils/refTypes';
|
|
9
9
|
|
|
10
10
|
// Default icons for each intent
|
|
11
|
-
const defaultIcons: Record<string,
|
|
12
|
-
primary:
|
|
13
|
-
success:
|
|
14
|
-
error:
|
|
15
|
-
warning:
|
|
16
|
-
info:
|
|
17
|
-
neutral:
|
|
11
|
+
const defaultIcons: Record<string, React.ComponentType<any>> = {
|
|
12
|
+
primary: (props: any) => <IconSvg {...props} name="information" aria-label="information" />,
|
|
13
|
+
success: (props: any) => <IconSvg {...props} name="check-circle" aria-label="check-circle" />,
|
|
14
|
+
error: (props: any) => <IconSvg {...props} name="alert-circle" aria-label="alert-circle" />,
|
|
15
|
+
warning: (props: any) => <IconSvg {...props} name="alert" aria-label="alert" />,
|
|
16
|
+
info: (props: any) => <IconSvg {...props} name="information" aria-label="information" />,
|
|
17
|
+
neutral: (props: any) => <IconSvg {...props} name="record-circle" aria-label="record-circle" />,
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -37,8 +37,8 @@ const Alert = forwardRef<IdealystElement, AlertProps>(({
|
|
|
37
37
|
testID,
|
|
38
38
|
id,
|
|
39
39
|
}, ref) => {
|
|
40
|
-
// Apply variants for size
|
|
41
|
-
alertStyles.useVariants({ size });
|
|
40
|
+
// Apply variants for size, intent, and type
|
|
41
|
+
alertStyles.useVariants({ size, intent, type });
|
|
42
42
|
|
|
43
43
|
// Compute dynamic styles with intent, type, and size
|
|
44
44
|
const dynamicProps = { intent, type, size };
|
|
@@ -51,26 +51,25 @@ const Alert = forwardRef<IdealystElement, AlertProps>(({
|
|
|
51
51
|
const closeButtonProps = getWebProps([(alertStyles.closeButton as any)(dynamicProps)]);
|
|
52
52
|
const closeIconProps = getWebProps([(alertStyles.closeIcon as any)(dynamicProps)]);
|
|
53
53
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
const Icon = useMemo(() => {
|
|
55
|
+
if (!showIcon) return null;
|
|
56
|
+
if (!icon) {
|
|
57
|
+
const Element = defaultIcons[intent];
|
|
58
|
+
if (Element) {
|
|
59
|
+
return <Element {...iconContainerProps} />;
|
|
60
|
+
}
|
|
61
|
+
return null
|
|
62
|
+
} else if (typeof icon === 'string') {
|
|
63
|
+
return <IconSvg
|
|
64
|
+
name={icon}
|
|
64
65
|
{...iconContainerProps}
|
|
65
|
-
aria-label={
|
|
66
|
+
aria-label={icon}
|
|
66
67
|
/>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return iconProp;
|
|
68
|
+
} else if (isValidElement(icon)) {
|
|
69
|
+
return icon;
|
|
70
70
|
}
|
|
71
|
-
|
|
72
71
|
return null;
|
|
73
|
-
};
|
|
72
|
+
}, [icon, showIcon, intent]);
|
|
74
73
|
|
|
75
74
|
const mergedRef = useMergeRefs(ref, containerProps.ref);
|
|
76
75
|
|
|
@@ -82,7 +81,7 @@ const Alert = forwardRef<IdealystElement, AlertProps>(({
|
|
|
82
81
|
data-testid={testID}
|
|
83
82
|
role="alert"
|
|
84
83
|
>
|
|
85
|
-
{
|
|
84
|
+
{Icon}
|
|
86
85
|
|
|
87
86
|
<div {...contentProps}>
|
|
88
87
|
{title && (
|