rn-vs-lb 1.0.61 → 1.0.63
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/components/Chat/InputMessage.stories.tsx +7 -0
- package/components/Chat/InputMessage.tsx +27 -6
- package/components/Gallery/AiAgentGallery.pure.tsx +138 -0
- package/components/Gallery/AiAgentGallery.stories.tsx +75 -0
- package/components/Gallery/index.ts +1 -0
- package/components/UI/StepProgress.stories.tsx +61 -0
- package/components/UI/StepProgress.tsx +153 -0
- package/components/UI/index.ts +1 -0
- package/components/index.ts +1 -0
- package/package.json +1 -1
|
@@ -22,6 +22,7 @@ const meta: Meta<Props> = {
|
|
|
22
22
|
argTypes: {
|
|
23
23
|
onAttachPress: { control: false },
|
|
24
24
|
onMaxImagesExceeded: { control: false },
|
|
25
|
+
enableImageAttachment: { control: 'boolean' },
|
|
25
26
|
},
|
|
26
27
|
};
|
|
27
28
|
export default meta;
|
|
@@ -89,6 +90,12 @@ Default.args = {
|
|
|
89
90
|
maxImages: 1,
|
|
90
91
|
};
|
|
91
92
|
|
|
93
|
+
export const AttachmentsDisabled = Template.bind({});
|
|
94
|
+
AttachmentsDisabled.args = {
|
|
95
|
+
placeholder: 'No attachments allowed',
|
|
96
|
+
enableImageAttachment: false,
|
|
97
|
+
};
|
|
98
|
+
|
|
92
99
|
export const WithAttachments = Template.bind({});
|
|
93
100
|
WithAttachments.args = {
|
|
94
101
|
placeholder: 'Attach up to 2 images',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { FC, useCallback, useRef, useState } from 'react';
|
|
1
|
+
import React, { FC, useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { View, StyleSheet, TextInput, TouchableOpacity, Text, Image, ScrollView, ActivityIndicator } from 'react-native';
|
|
3
3
|
import { Ionicons } from '@expo/vector-icons';
|
|
4
4
|
import { ThemeType, useTheme } from '../../theme';
|
|
@@ -22,6 +22,7 @@ interface InputMessageProps {
|
|
|
22
22
|
maxImages?: number; // по умолчанию 1
|
|
23
23
|
onAttachPress?: () => Promise<ImageAsset[] | void>; // родитель сам открывает пикер и вернёт выбранные
|
|
24
24
|
onMaxImagesExceeded?: (max: number) => void;
|
|
25
|
+
enableImageAttachment?: boolean;
|
|
25
26
|
|
|
26
27
|
// Индикатор отправки (можно не передавать — тогда управляем внутри)
|
|
27
28
|
sendingControlled?: boolean;
|
|
@@ -47,6 +48,7 @@ export const InputMessage: FC<InputMessageProps> = ({
|
|
|
47
48
|
maxImages = 1,
|
|
48
49
|
onAttachPress,
|
|
49
50
|
onMaxImagesExceeded,
|
|
51
|
+
enableImageAttachment = true,
|
|
50
52
|
|
|
51
53
|
sendingControlled,
|
|
52
54
|
isSending: isSendingProp,
|
|
@@ -64,6 +66,13 @@ export const InputMessage: FC<InputMessageProps> = ({
|
|
|
64
66
|
const [isSendingLocal, setIsSendingLocal] = useState(false);
|
|
65
67
|
|
|
66
68
|
const isSending = sendingControlled ? !!isSendingProp : isSendingLocal;
|
|
69
|
+
const attachmentsAllowed = enableImageAttachment;
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (!attachmentsAllowed && images.length > 0) {
|
|
73
|
+
setImages([]);
|
|
74
|
+
}
|
|
75
|
+
}, [attachmentsAllowed, images.length]);
|
|
67
76
|
|
|
68
77
|
// Собственный дебаунс без lodash
|
|
69
78
|
const stopTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
@@ -74,7 +83,7 @@ export const InputMessage: FC<InputMessageProps> = ({
|
|
|
74
83
|
}, [onTyping, onStopTyping]);
|
|
75
84
|
|
|
76
85
|
const handleAttachPress = useCallback(async () => {
|
|
77
|
-
if (!onAttachPress) return;
|
|
86
|
+
if (!attachmentsAllowed || !onAttachPress) return;
|
|
78
87
|
const selected = (await onAttachPress()) || [];
|
|
79
88
|
if (!selected.length) return;
|
|
80
89
|
|
|
@@ -165,7 +174,12 @@ export const InputMessage: FC<InputMessageProps> = ({
|
|
|
165
174
|
)}
|
|
166
175
|
|
|
167
176
|
{/* Поле ввода + кнопки */}
|
|
168
|
-
<View
|
|
177
|
+
<View
|
|
178
|
+
style={[
|
|
179
|
+
styles.inputContainer,
|
|
180
|
+
attachmentsAllowed ? styles.inputContainerWithAttach : styles.inputContainerWithoutAttach,
|
|
181
|
+
]}
|
|
182
|
+
>
|
|
169
183
|
<TextInput
|
|
170
184
|
multiline
|
|
171
185
|
placeholder={placeholder}
|
|
@@ -183,9 +197,11 @@ export const InputMessage: FC<InputMessageProps> = ({
|
|
|
183
197
|
onContentSizeChange={(e) => setInputHeight(e.nativeEvent.contentSize.height)}
|
|
184
198
|
/>
|
|
185
199
|
|
|
186
|
-
|
|
187
|
-
<
|
|
188
|
-
|
|
200
|
+
{attachmentsAllowed && (
|
|
201
|
+
<TouchableOpacity style={styles.attachButton} onPress={handleAttachPress}>
|
|
202
|
+
<Ionicons name="image-outline" size={22} color={theme.primary} />
|
|
203
|
+
</TouchableOpacity>
|
|
204
|
+
)}
|
|
189
205
|
|
|
190
206
|
<TouchableOpacity style={styles.sendButton} onPress={handleSubmit} disabled={isSending}>
|
|
191
207
|
{isSending ? (
|
|
@@ -208,8 +224,13 @@ export const getStyles = (theme: ThemeType) =>
|
|
|
208
224
|
borderTopWidth: 1,
|
|
209
225
|
borderTopColor: theme.border,
|
|
210
226
|
paddingRight: 45,
|
|
227
|
+
},
|
|
228
|
+
inputContainerWithAttach: {
|
|
211
229
|
paddingLeft: 45,
|
|
212
230
|
},
|
|
231
|
+
inputContainerWithoutAttach: {
|
|
232
|
+
paddingLeft: 12,
|
|
233
|
+
},
|
|
213
234
|
replyContainer: {
|
|
214
235
|
backgroundColor: theme.background,
|
|
215
236
|
padding: 6,
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import React, { memo, useMemo } from "react";
|
|
2
|
+
import { ActivityIndicator, Image, Pressable, StyleSheet, Text, View } from "react-native";
|
|
3
|
+
import { useTheme, ThemeType, SizesType, TypographytType } from "../../theme";
|
|
4
|
+
import { GalleryModal } from "../Modals";
|
|
5
|
+
|
|
6
|
+
export type AiAgentGalleryViewProps = {
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
photos: string[];
|
|
9
|
+
galleryColumns: number;
|
|
10
|
+
galleryItemSize: number;
|
|
11
|
+
|
|
12
|
+
visible: boolean;
|
|
13
|
+
initialIndex: number;
|
|
14
|
+
onOpenAt: (index: number) => void;
|
|
15
|
+
onClose: () => void;
|
|
16
|
+
|
|
17
|
+
emptyTest: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const AiAgentGalleryView = memo(
|
|
21
|
+
({
|
|
22
|
+
isLoading,
|
|
23
|
+
photos,
|
|
24
|
+
galleryColumns,
|
|
25
|
+
galleryItemSize,
|
|
26
|
+
visible,
|
|
27
|
+
initialIndex,
|
|
28
|
+
onOpenAt,
|
|
29
|
+
onClose,
|
|
30
|
+
emptyTest,
|
|
31
|
+
}: AiAgentGalleryViewProps) => {
|
|
32
|
+
const { theme, sizes, typography } = useTheme();
|
|
33
|
+
const isDark = (theme as any)?.isDark ?? false;
|
|
34
|
+
|
|
35
|
+
const styles = useMemo(() => getStyles(theme, sizes, typography, isDark), [
|
|
36
|
+
theme,
|
|
37
|
+
sizes,
|
|
38
|
+
typography,
|
|
39
|
+
isDark,
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
if (isLoading) {
|
|
43
|
+
return (
|
|
44
|
+
<View style={styles.galleryWrapper}>
|
|
45
|
+
<ActivityIndicator />
|
|
46
|
+
</View>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!photos.length) {
|
|
51
|
+
return (
|
|
52
|
+
<View style={styles.galleryWrapper}>
|
|
53
|
+
<View style={styles.emptyState}>
|
|
54
|
+
<Text style={styles.emptyText}>{emptyTest}</Text>
|
|
55
|
+
</View>
|
|
56
|
+
</View>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<View style={styles.galleryWrapper}>
|
|
62
|
+
<View style={styles.galleryGrid}>
|
|
63
|
+
{photos.map((photo, i) => {
|
|
64
|
+
const isLastInRow = (i + 1) % galleryColumns === 0;
|
|
65
|
+
return (
|
|
66
|
+
<Pressable
|
|
67
|
+
key={`${photo}-${i}`}
|
|
68
|
+
onPress={() => onOpenAt(i)}
|
|
69
|
+
android_ripple={{ color: "#00000022" }}
|
|
70
|
+
style={[
|
|
71
|
+
styles.galleryImage,
|
|
72
|
+
isLastInRow && styles.galleryImageLast,
|
|
73
|
+
{ width: galleryItemSize, height: galleryItemSize },
|
|
74
|
+
]}
|
|
75
|
+
>
|
|
76
|
+
<Image
|
|
77
|
+
source={{ uri: photo }}
|
|
78
|
+
style={{
|
|
79
|
+
width: "100%",
|
|
80
|
+
height: "100%",
|
|
81
|
+
borderRadius: styles.galleryImage.borderRadius,
|
|
82
|
+
}}
|
|
83
|
+
/>
|
|
84
|
+
</Pressable>
|
|
85
|
+
);
|
|
86
|
+
})}
|
|
87
|
+
</View>
|
|
88
|
+
|
|
89
|
+
<GalleryModal
|
|
90
|
+
visible={visible}
|
|
91
|
+
images={photos}
|
|
92
|
+
initialIndex={initialIndex}
|
|
93
|
+
onRequestClose={onClose}
|
|
94
|
+
/>
|
|
95
|
+
</View>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
AiAgentGalleryView.displayName = "AiAgentGalleryView";
|
|
101
|
+
|
|
102
|
+
const getStyles = (
|
|
103
|
+
theme: ThemeType,
|
|
104
|
+
sizes: SizesType,
|
|
105
|
+
typography: TypographytType,
|
|
106
|
+
isDark: boolean
|
|
107
|
+
) =>
|
|
108
|
+
StyleSheet.create({
|
|
109
|
+
galleryWrapper: {
|
|
110
|
+
paddingHorizontal: sizes.md as number,
|
|
111
|
+
paddingVertical: sizes.xl as number,
|
|
112
|
+
},
|
|
113
|
+
galleryGrid: {
|
|
114
|
+
flexDirection: "row",
|
|
115
|
+
flexWrap: "wrap",
|
|
116
|
+
},
|
|
117
|
+
galleryImage: {
|
|
118
|
+
borderRadius: 18,
|
|
119
|
+
backgroundColor: theme.backgroundSecond,
|
|
120
|
+
marginRight: sizes.sm as number,
|
|
121
|
+
marginBottom: sizes.sm as number,
|
|
122
|
+
},
|
|
123
|
+
galleryImageLast: {
|
|
124
|
+
marginRight: 0,
|
|
125
|
+
},
|
|
126
|
+
emptyState: {
|
|
127
|
+
alignItems: "center",
|
|
128
|
+
justifyContent: "center",
|
|
129
|
+
paddingVertical: sizes.lg as number,
|
|
130
|
+
},
|
|
131
|
+
emptyText: {
|
|
132
|
+
...(typography.bodySm as object),
|
|
133
|
+
color: theme.greyText,
|
|
134
|
+
textAlign: "center",
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
export default AiAgentGalleryView;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Meta, StoryFn } from '@storybook/react';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
import { ThemeProvider } from '../../theme';
|
|
5
|
+
import { AiAgentGalleryView } from './AiAgentGallery.pure';
|
|
6
|
+
|
|
7
|
+
type Props = React.ComponentProps<typeof AiAgentGalleryView>;
|
|
8
|
+
|
|
9
|
+
const meta: Meta<Props> = {
|
|
10
|
+
title: 'Gallery/AiAgentGallery',
|
|
11
|
+
component: AiAgentGalleryView,
|
|
12
|
+
decorators: [
|
|
13
|
+
(Story) => (
|
|
14
|
+
<ThemeProvider>
|
|
15
|
+
<View style={{ paddingVertical: 24 }}>
|
|
16
|
+
<Story />
|
|
17
|
+
</View>
|
|
18
|
+
</ThemeProvider>
|
|
19
|
+
),
|
|
20
|
+
],
|
|
21
|
+
args: {
|
|
22
|
+
galleryColumns: 3,
|
|
23
|
+
galleryItemSize: 108,
|
|
24
|
+
emptyTest: 'No generated images yet. Try creating one with your AI agent!',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default meta;
|
|
29
|
+
|
|
30
|
+
const Template: StoryFn<Props> = ({
|
|
31
|
+
onOpenAt: _onOpenAt,
|
|
32
|
+
onClose: _onClose,
|
|
33
|
+
visible: _visible,
|
|
34
|
+
initialIndex: _initialIndex,
|
|
35
|
+
...rest
|
|
36
|
+
}) => {
|
|
37
|
+
const [visible, setVisible] = useState(false);
|
|
38
|
+
const [initialIndex, setInitialIndex] = useState(0);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<AiAgentGalleryView
|
|
42
|
+
{...rest}
|
|
43
|
+
visible={visible}
|
|
44
|
+
initialIndex={initialIndex}
|
|
45
|
+
onOpenAt={(index) => {
|
|
46
|
+
setInitialIndex(index);
|
|
47
|
+
setVisible(true);
|
|
48
|
+
}}
|
|
49
|
+
onClose={() => setVisible(false)}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const Default = Template.bind({});
|
|
55
|
+
Default.args = {
|
|
56
|
+
isLoading: false,
|
|
57
|
+
photos: [
|
|
58
|
+
'https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=600&q=60',
|
|
59
|
+
'https://images.unsplash.com/photo-1498050108023-c5249f4df085?auto=format&fit=crop&w=600&q=60',
|
|
60
|
+
'https://images.unsplash.com/photo-1521572163474-6864f9cf17ab?auto=format&fit=crop&w=600&q=60',
|
|
61
|
+
'https://images.unsplash.com/photo-1545239351-1141bd82e8a6?auto=format&fit=crop&w=600&q=60',
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const Loading = Template.bind({});
|
|
66
|
+
Loading.args = {
|
|
67
|
+
isLoading: true,
|
|
68
|
+
photos: [],
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const Empty = Template.bind({});
|
|
72
|
+
Empty.args = {
|
|
73
|
+
isLoading: false,
|
|
74
|
+
photos: [],
|
|
75
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./AiAgentGallery.pure"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Meta, StoryFn } from '@storybook/react';
|
|
3
|
+
import { View, Alert } from 'react-native';
|
|
4
|
+
import { ThemeProvider } from '../../theme';
|
|
5
|
+
import { StepProgress } from './StepProgress';
|
|
6
|
+
|
|
7
|
+
type Props = React.ComponentProps<typeof StepProgress>;
|
|
8
|
+
|
|
9
|
+
const meta: Meta<Props> = {
|
|
10
|
+
title: 'UI/StepProgress',
|
|
11
|
+
component: StepProgress,
|
|
12
|
+
decorators: [
|
|
13
|
+
(Story) => (
|
|
14
|
+
<ThemeProvider>
|
|
15
|
+
<View style={{ padding: 24 }}>
|
|
16
|
+
<Story />
|
|
17
|
+
</View>
|
|
18
|
+
</ThemeProvider>
|
|
19
|
+
),
|
|
20
|
+
],
|
|
21
|
+
args: {
|
|
22
|
+
steps: [
|
|
23
|
+
{ title: 'Briefing', description: 'Share context and goals for your agent.' },
|
|
24
|
+
{ title: 'Generation', description: 'The agent drafts a tailored solution.' },
|
|
25
|
+
{ title: 'Review', description: 'Assess the output and give feedback.' },
|
|
26
|
+
{ title: 'Launch', description: 'Publish or deploy your agent deliverable.' },
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default meta;
|
|
32
|
+
|
|
33
|
+
const Template: StoryFn<Props> = (args) => <StepProgress {...args} />;
|
|
34
|
+
|
|
35
|
+
export const Default = Template.bind({});
|
|
36
|
+
Default.args = {
|
|
37
|
+
activeStep: 1,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const FirstStep = Template.bind({});
|
|
41
|
+
FirstStep.args = {
|
|
42
|
+
activeStep: 0,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const WithClickableSteps: StoryFn<Props> = (args) => {
|
|
46
|
+
const [activeStep, setActiveStep] = useState(args.activeStep ?? 2);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<StepProgress
|
|
50
|
+
{...args}
|
|
51
|
+
activeStep={activeStep}
|
|
52
|
+
onStepPress={(index) => {
|
|
53
|
+
Alert.alert('Step selected', args.steps?.[index]?.title ?? `Step ${index + 1}`);
|
|
54
|
+
setActiveStep(index);
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
WithClickableSteps.args = {
|
|
60
|
+
activeStep: 2,
|
|
61
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
|
3
|
+
import { ThemeType, TypographytType, SizesType, useTheme } from "rn-vs-lb/theme";
|
|
4
|
+
|
|
5
|
+
interface StepProgressProps {
|
|
6
|
+
steps: { title: string; description?: string }[];
|
|
7
|
+
activeStep: number;
|
|
8
|
+
onStepPress?: (index: number) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const StepProgress: React.FC<StepProgressProps> = ({ steps, activeStep, onStepPress }) => {
|
|
12
|
+
const { theme, typography, sizes } = useTheme();
|
|
13
|
+
|
|
14
|
+
const styles = useMemo(
|
|
15
|
+
() => createStyles({ theme, typography, sizes }),
|
|
16
|
+
[theme, typography, sizes],
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const currentDescription = steps[activeStep]?.description ?? "";
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<View style={styles.container}>
|
|
23
|
+
<View style={styles.stepsRow}>
|
|
24
|
+
{steps.map((step, index) => {
|
|
25
|
+
const isActive = index === activeStep;
|
|
26
|
+
const isCompleted = index < activeStep;
|
|
27
|
+
const isPressable = typeof onStepPress === "function" && index < activeStep;
|
|
28
|
+
return (
|
|
29
|
+
<TouchableOpacity
|
|
30
|
+
key={step.title ?? index}
|
|
31
|
+
style={[styles.stepItem, isPressable && styles.stepItemPressable]}
|
|
32
|
+
activeOpacity={0.7}
|
|
33
|
+
onPress={isPressable ? () => onStepPress(index) : undefined}
|
|
34
|
+
disabled={!isPressable}
|
|
35
|
+
>
|
|
36
|
+
<View style={styles.stepHeader}>
|
|
37
|
+
<View
|
|
38
|
+
style={[
|
|
39
|
+
styles.circle,
|
|
40
|
+
(isActive || isCompleted) && styles.circleActive,
|
|
41
|
+
]}
|
|
42
|
+
>
|
|
43
|
+
<Text
|
|
44
|
+
style={[
|
|
45
|
+
styles.circleText,
|
|
46
|
+
(isActive || isCompleted) && styles.circleTextActive,
|
|
47
|
+
]}
|
|
48
|
+
>
|
|
49
|
+
{index + 1}
|
|
50
|
+
</Text>
|
|
51
|
+
</View>
|
|
52
|
+
{index < steps.length - 1 ? (
|
|
53
|
+
<View
|
|
54
|
+
style={[
|
|
55
|
+
styles.connector,
|
|
56
|
+
(isCompleted || (isActive && activeStep === index)) && styles.connectorActive,
|
|
57
|
+
]}
|
|
58
|
+
/>
|
|
59
|
+
) : null}
|
|
60
|
+
</View>
|
|
61
|
+
<Text
|
|
62
|
+
numberOfLines={2}
|
|
63
|
+
style={[styles.stepTitle, isActive && styles.stepTitleActive]}
|
|
64
|
+
>
|
|
65
|
+
{step.title}
|
|
66
|
+
</Text>
|
|
67
|
+
</TouchableOpacity>
|
|
68
|
+
);
|
|
69
|
+
})}
|
|
70
|
+
</View>
|
|
71
|
+
{currentDescription ? (
|
|
72
|
+
<Text style={styles.description}>{currentDescription}</Text>
|
|
73
|
+
) : null}
|
|
74
|
+
</View>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const createStyles = ({
|
|
79
|
+
theme,
|
|
80
|
+
typography,
|
|
81
|
+
sizes,
|
|
82
|
+
}: {
|
|
83
|
+
theme: ThemeType;
|
|
84
|
+
typography: TypographytType;
|
|
85
|
+
sizes: SizesType;
|
|
86
|
+
}) =>
|
|
87
|
+
StyleSheet.create({
|
|
88
|
+
container: {
|
|
89
|
+
marginBottom: sizes.xl as number,
|
|
90
|
+
},
|
|
91
|
+
stepsRow: {
|
|
92
|
+
flexDirection: "row",
|
|
93
|
+
alignItems: "center",
|
|
94
|
+
justifyContent: "space-between",
|
|
95
|
+
},
|
|
96
|
+
stepItem: {
|
|
97
|
+
flex: 1,
|
|
98
|
+
marginRight: sizes.sm as number,
|
|
99
|
+
},
|
|
100
|
+
stepItemPressable: {
|
|
101
|
+
opacity: 0.9,
|
|
102
|
+
},
|
|
103
|
+
stepHeader: {
|
|
104
|
+
flexDirection: "row",
|
|
105
|
+
alignItems: "center",
|
|
106
|
+
marginBottom: sizes.xs as number,
|
|
107
|
+
},
|
|
108
|
+
circle: {
|
|
109
|
+
width: 36,
|
|
110
|
+
height: 36,
|
|
111
|
+
borderRadius: 18,
|
|
112
|
+
borderWidth: 2,
|
|
113
|
+
borderColor: theme.border,
|
|
114
|
+
alignItems: "center",
|
|
115
|
+
justifyContent: "center",
|
|
116
|
+
backgroundColor: theme.white,
|
|
117
|
+
},
|
|
118
|
+
circleActive: {
|
|
119
|
+
borderColor: theme.primary,
|
|
120
|
+
backgroundColor: theme.primary,
|
|
121
|
+
},
|
|
122
|
+
circleText: {
|
|
123
|
+
...typography.bodyXs,
|
|
124
|
+
color: theme.text,
|
|
125
|
+
fontWeight: "600",
|
|
126
|
+
},
|
|
127
|
+
circleTextActive: {
|
|
128
|
+
color: theme.white,
|
|
129
|
+
},
|
|
130
|
+
connector: {
|
|
131
|
+
flex: 1,
|
|
132
|
+
height: 2,
|
|
133
|
+
marginLeft: sizes.xs as number,
|
|
134
|
+
backgroundColor: theme.border,
|
|
135
|
+
},
|
|
136
|
+
connectorActive: {
|
|
137
|
+
backgroundColor: theme.primary,
|
|
138
|
+
},
|
|
139
|
+
stepTitle: {
|
|
140
|
+
...typography.bodyXs,
|
|
141
|
+
color: theme.greyText,
|
|
142
|
+
},
|
|
143
|
+
stepTitleActive: {
|
|
144
|
+
color: theme.text,
|
|
145
|
+
fontWeight: "600",
|
|
146
|
+
},
|
|
147
|
+
description: {
|
|
148
|
+
marginTop: sizes.sm as number,
|
|
149
|
+
...typography.bodySm,
|
|
150
|
+
color: theme.greyText,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
|
package/components/UI/index.ts
CHANGED
package/components/index.ts
CHANGED