rn-vs-lb 1.0.63 → 1.0.65

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.
Files changed (42) hide show
  1. package/components/Button/DeleteAccountButton.stories.tsx +12 -0
  2. package/components/Button/DeleteAccountButton.tsx +28 -8
  3. package/components/Button/TelegramFeedbackLink.stories.tsx +6 -0
  4. package/components/Button/TelegramFeedbackLink.tsx +12 -4
  5. package/components/Cards/EventCard.stories.tsx +3 -0
  6. package/components/Cards/EventCard.tsx +9 -2
  7. package/components/Chat/InputMessage.stories.tsx +11 -0
  8. package/components/Chat/InputMessage.tsx +5 -3
  9. package/components/Header/HeaderWithImg.stories.tsx +9 -0
  10. package/components/Header/HeaderWithImg.tsx +27 -7
  11. package/components/Modals/GuestAiChatModal.stories.tsx +11 -3
  12. package/components/Modals/GuestAiChatModal.tsx +9 -3
  13. package/components/Modals/ReportModal.stories.tsx +34 -1
  14. package/components/Modals/ReportModal.tsx +23 -24
  15. package/components/Poll/PollCardList.stories.tsx +4 -0
  16. package/components/Poll/PollCardList.tsx +4 -2
  17. package/components/Profile/ProfilePhotoBanner.stories.tsx +10 -1
  18. package/components/Profile/ProfilePhotoBanner.tsx +5 -3
  19. package/components/Specialist/Hero.stories.tsx +1 -0
  20. package/components/Specialist/Hero.tsx +3 -1
  21. package/components/Specialist/ServicesList.stories.tsx +1 -0
  22. package/components/Specialist/ServicesList.tsx +4 -3
  23. package/components/UI/DeletedState.stories.tsx +6 -1
  24. package/components/UI/DeletedState.tsx +12 -3
  25. package/components/UI/DescriptionMore.stories.tsx +2 -0
  26. package/components/UI/DescriptionMore.tsx +13 -3
  27. package/components/UI/EmptyState.stories.tsx +4 -1
  28. package/components/UI/EmptyState.tsx +3 -2
  29. package/components/UI/NoAuth.stories.tsx +3 -0
  30. package/components/UI/NoAuth.tsx +7 -6
  31. package/components/UI/ParticipantItem.stories.tsx +21 -0
  32. package/components/UI/ParticipantItem.tsx +30 -6
  33. package/components/UI/StepProgress.tsx +1 -1
  34. package/components/UI/ThemeSwitcher.stories.tsx +5 -1
  35. package/components/UI/ThemeSwitcher.tsx +7 -2
  36. package/components/UI/UpdateRequiredView.stories.tsx +2 -0
  37. package/components/UI/UpdateRequiredView.tsx +3 -2
  38. package/components/UserCards/Organazer.tsx +3 -2
  39. package/components/UserCards/Organizer.stories.tsx +4 -0
  40. package/components/UserCards/SpecialistCard.stories.tsx +2 -0
  41. package/components/UserCards/SpecialistCard.tsx +3 -2
  42. package/package.json +1 -1
@@ -29,6 +29,7 @@ Default.args = {
29
29
  creatorAvatar: 'https://i.pravatar.cc/150?img=11',
30
30
  votesCount: 42,
31
31
  createdAt: '2 days ago',
32
+ votesLabel: 'votes',
32
33
  };
33
34
 
34
35
  export const WithLongQuestion = Template.bind({});
@@ -39,6 +40,7 @@ WithLongQuestion.args = {
39
40
  creatorAvatar: 'https://i.pravatar.cc/150?img=5',
40
41
  votesCount: 128,
41
42
  createdAt: '5 hours ago',
43
+ votesLabel: 'votes',
42
44
  };
43
45
 
44
46
  export const WithoutDate = Template.bind({});
@@ -48,6 +50,7 @@ WithoutDate.args = {
48
50
  creatorAvatar: 'https://i.pravatar.cc/150?img=24',
49
51
  votesCount: 8,
50
52
  createdAt: null,
53
+ votesLabel: 'votes',
51
54
  };
52
55
 
53
56
  export const MinimalInfo = Template.bind({});
@@ -57,4 +60,5 @@ MinimalInfo.args = {
57
60
  creatorAvatar: 'https://i.pravatar.cc/150?img=36',
58
61
  votesCount: 230,
59
62
  createdAt: 'just now',
63
+ votesLabel: 'votes',
60
64
  };
@@ -9,6 +9,7 @@ interface PollCardProps {
9
9
  votesCount: number;
10
10
  onPress?: () => void;
11
11
  createdAt: string | null;
12
+ votesLabel: string;
12
13
  }
13
14
 
14
15
  const PollCardList: React.FC<PollCardProps> = ({
@@ -17,7 +18,8 @@ const PollCardList: React.FC<PollCardProps> = ({
17
18
  creatorAvatar,
18
19
  votesCount,
19
20
  onPress,
20
- createdAt
21
+ createdAt,
22
+ votesLabel,
21
23
  }) => {
22
24
  const { globalStyleSheet, commonStyles, typography } = useTheme();
23
25
  const styles = getStyles({ commonStyles });
@@ -33,7 +35,7 @@ const PollCardList: React.FC<PollCardProps> = ({
33
35
  </View>
34
36
  <Text style={typography.bodyXs}>{creatorName}</Text>
35
37
  <View style={globalStyleSheet.flexRowCenterBetween}>
36
- <Text style={typography.bodyXs}>{votesCount} votes</Text>
38
+ <Text style={typography.bodyXs}>{votesCount} {votesLabel}</Text>
37
39
  <Text style={typography.bodyXs}>{createdAt}</Text>
38
40
  </View>
39
41
  </View>
@@ -34,11 +34,18 @@ const closeHandler = () => {
34
34
 
35
35
  export const Default = Template.bind({});
36
36
  Default.args = {
37
+ message: 'Upload a photo — it will help others recognize and trust you.',
38
+ buttonText: 'Add Photo',
37
39
  };
38
40
 
39
41
  export const InsideScrollableList: StoryFn = () => (
40
42
  <ScrollView contentContainerStyle={{ gap: 12, padding: 16 }}>
41
- <ProfilePhotoBanner onAddPhoto={addPhotoHandler} onClose={closeHandler} />
43
+ <ProfilePhotoBanner
44
+ onAddPhoto={addPhotoHandler}
45
+ onClose={closeHandler}
46
+ message="Upload a photo — it will help others recognize and trust you."
47
+ buttonText="Add Photo"
48
+ />
42
49
  <View style={{ height: 150, backgroundColor: '#f0f0f0', borderRadius: 12 }} />
43
50
  <View style={{ height: 150, backgroundColor: '#f5f5f5', borderRadius: 12 }} />
44
51
  <View style={{ height: 150, backgroundColor: '#fafafa', borderRadius: 12 }} />
@@ -61,6 +68,8 @@ export const DismissibleBehaviour: StoryFn = () => {
61
68
  closeHandler();
62
69
  setVisible(false);
63
70
  }}
71
+ message="Upload a photo — it will help others recognize and trust you."
72
+ buttonText="Add Photo"
64
73
  />
65
74
  )}
66
75
  <View style={{ height: 160, backgroundColor: '#d9ecff', borderRadius: 16 }} />
@@ -7,21 +7,23 @@ import Button from '../Button/Button';
7
7
  interface Props {
8
8
  onAddPhoto: () => void;
9
9
  onClose: () => void;
10
+ message: string;
11
+ buttonText: string;
10
12
  }
11
13
 
12
- const ProfilePhotoBanner: React.FC<Props> = ({ onAddPhoto, onClose }) => {
14
+ const ProfilePhotoBanner: React.FC<Props> = ({ onAddPhoto, onClose, message, buttonText }) => {
13
15
  const { theme, typography } = useTheme();
14
16
  const styles = getStyles({ theme });
15
17
 
16
18
  return (
17
19
  <View style={styles.container}>
18
20
  <View style={styles.row}>
19
- <Text style={[typography.body, styles.text]}>Upload a photo — it will help others recognize and trust you.</Text>
21
+ <Text style={[typography.body, styles.text]}>{message}</Text>
20
22
  <TouchableOpacity onPress={onClose} style={styles.closeButton}>
21
23
  <Ionicons name="close" size={20} color={theme.text} />
22
24
  </TouchableOpacity>
23
25
  </View>
24
- <Button title="Add Photo" onPress={onAddPhoto} />
26
+ <Button title={buttonText} onPress={onAddPhoto} />
25
27
  </View>
26
28
  );
27
29
  };
@@ -27,6 +27,7 @@ const meta = {
27
27
  profession: 'Makeup Artist',
28
28
  addressLine: '12 Riverside Dr, NYC',
29
29
  showOnMap: true,
30
+ mapLabel: 'On the map',
30
31
  },
31
32
  } satisfies Meta<typeof Hero>;
32
33
 
@@ -15,6 +15,7 @@ export type HeroProps = {
15
15
  onMessage?: () => void;
16
16
  onPressMap?: () => void;
17
17
  socials?: React.ReactNode; // сюда можно передать <SocialIconsRow .../>
18
+ mapLabel: string;
18
19
  };
19
20
 
20
21
  const Hero: React.FC<HeroProps> = ({
@@ -29,6 +30,7 @@ const Hero: React.FC<HeroProps> = ({
29
30
  onMessage,
30
31
  onPressMap,
31
32
  socials,
33
+ mapLabel,
32
34
  }) => {
33
35
  const { theme, globalStyleSheet, typography } = useTheme();
34
36
  const s = getStyles({ theme, globalStyleSheet });
@@ -67,7 +69,7 @@ const Hero: React.FC<HeroProps> = ({
67
69
 
68
70
  {showOnMap && (
69
71
  <TouchableOpacity style={[globalStyleSheet.flexRowCenterEnd, { marginTop: 6 }]} onPress={onPressMap} activeOpacity={0.8}>
70
- <Text style={{ color: theme.primary, fontWeight: '600' }}>On the map</Text>
72
+ <Text style={{ color: theme.primary, fontWeight: '600' }}>{mapLabel}</Text>
71
73
  <Ionicons name="chevron-forward" size={16} color={theme.primary} />
72
74
  </TouchableOpacity>
73
75
  )}
@@ -41,6 +41,7 @@ const meta = {
41
41
  title: 'Services',
42
42
  total: 12,
43
43
  services: SERVICES,
44
+ moreLabel: 'MORE',
44
45
  },
45
46
  } satisfies Meta<typeof ServicesList>;
46
47
 
@@ -14,15 +14,16 @@ export type ServiceItem = {
14
14
  };
15
15
 
16
16
  export type ServicesListProps = {
17
- title?: string;
17
+ title: string;
18
18
  total?: number; // для счетчика справа от заголовка
19
19
  services: ServiceItem[];
20
20
  onPressService?: (item: ServiceItem, index: number) => void;
21
21
  onPressMore?: () => void;
22
22
  style?: ViewStyle;
23
+ moreLabel: string;
23
24
  };
24
25
 
25
- const ServicesList: React.FC<ServicesListProps> = ({ title = 'Services', total, services, onPressService, onPressMore, style }) => {
26
+ const ServicesList: React.FC<ServicesListProps> = ({ title, total, services, onPressService, onPressMore, style, moreLabel }) => {
26
27
  const { theme } = useTheme();
27
28
  const s = getStyles(theme);
28
29
 
@@ -36,7 +37,7 @@ const ServicesList: React.FC<ServicesListProps> = ({ title = 'Services', total,
36
37
  </Text>
37
38
  {!!onPressMore && (
38
39
  <TouchableOpacity onPress={onPressMore}>
39
- <Text style={s.moreLink}>MORE</Text>
40
+ <Text style={s.moreLink}>{moreLabel}</Text>
40
41
  </TouchableOpacity>
41
42
  )}
42
43
  </View>
@@ -16,9 +16,14 @@ const Template: StoryFn<DeletedStateProps> = (args) => <DeletedState {...args} /
16
16
  const goBackHandler = () => {};
17
17
 
18
18
  export const WithoutAction = Template.bind({});
19
- WithoutAction.args = {};
19
+ WithoutAction.args = {
20
+ title: 'Deleted',
21
+ buttonText: 'Go back',
22
+ };
20
23
 
21
24
  export const WithGoBack = Template.bind({});
22
25
  WithGoBack.args = {
23
26
  goBack: goBackHandler,
27
+ title: 'Deleted',
28
+ buttonText: 'Go back',
24
29
  };
@@ -7,9 +7,11 @@ import { Button } from '../Button';
7
7
 
8
8
  type Props = {
9
9
  goBack?: () => void;
10
+ title: string;
11
+ buttonText: string;
10
12
  }
11
13
 
12
- const DeletedState: FC<Props> = ({ goBack }) => {
14
+ const DeletedState: FC<Props> = ({ goBack, title, buttonText }) => {
13
15
  const { theme, commonStyles, typography } = useTheme();
14
16
  const styles = getStyles(theme);
15
17
 
@@ -17,9 +19,16 @@ const DeletedState: FC<Props> = ({ goBack }) => {
17
19
  <View style={[commonStyles.container, styles.container]}>
18
20
  <Ionicons name="file-tray-outline" size={50} color={theme.placeholder} />
19
21
  <Spacer size='xxs' />
20
- <Text style={[typography.titleH6Regular, { color: theme.placeholder }]}>Deleted</Text>
22
+ <Text style={[typography.titleH6Regular, { color: theme.placeholder }]}>{title}</Text>
21
23
  <Spacer size='lg' />
22
- {goBack && <Button onPress={goBack} type='gray-outline' title='Go back' textStyle={[typography.body, { color: theme.greyText }]} />}
24
+ {goBack && (
25
+ <Button
26
+ onPress={goBack}
27
+ type='gray-outline'
28
+ title={buttonText}
29
+ textStyle={[typography.body, { color: theme.greyText }]}
30
+ />
31
+ )}
23
32
  </View>
24
33
  );
25
34
  };
@@ -15,6 +15,8 @@ const meta = {
15
15
  'Passionate about natural looks, skin preparation, and color theory. ' +
16
16
  'Open for travel and on-location work; kit is fully sanitized and cruelty-free.',
17
17
  expanded: false,
18
+ expandedLabel: 'Less',
19
+ collapsedLabel: 'More details',
18
20
  },
19
21
  } satisfies Meta<typeof DescriptionSection>;
20
22
 
@@ -4,14 +4,24 @@ import { useTheme, ThemeType } from '../../theme';
4
4
  import CardContainer from './CardContainer';
5
5
 
6
6
  export type DescriptionSectionProps = {
7
- title?: string;
7
+ title: string;
8
8
  text: string;
9
9
  expanded: boolean;
10
10
  onToggle: () => void;
11
11
  style?: ViewStyle;
12
+ expandedLabel: string;
13
+ collapsedLabel: string;
12
14
  };
13
15
 
14
- const DescriptionSection: React.FC<DescriptionSectionProps> = ({ title = 'Description', text, expanded, onToggle, style }) => {
16
+ const DescriptionSection: React.FC<DescriptionSectionProps> = ({
17
+ title,
18
+ text,
19
+ expanded,
20
+ onToggle,
21
+ style,
22
+ expandedLabel,
23
+ collapsedLabel,
24
+ }) => {
15
25
  const { theme, typography } = useTheme();
16
26
  const s = getStyles(theme);
17
27
 
@@ -23,7 +33,7 @@ const DescriptionSection: React.FC<DescriptionSectionProps> = ({ title = 'Descri
23
33
  {text}
24
34
  </Text>
25
35
  <TouchableOpacity onPress={onToggle}>
26
- <Text style={s.moreLink}>{expanded ? 'Less' : 'More details'}</Text>
36
+ <Text style={s.moreLink}>{expanded ? expandedLabel : collapsedLabel}</Text>
27
37
  </TouchableOpacity>
28
38
  </CardContainer>
29
39
  </View>
@@ -9,6 +9,9 @@ const meta: Meta = {
9
9
 
10
10
  export default meta;
11
11
 
12
- const Template: StoryFn = () => <EmptyState />;
12
+ const Template: StoryFn<React.ComponentProps<typeof EmptyState>> = (args) => <EmptyState {...args} />;
13
13
 
14
14
  export const Default = Template.bind({});
15
+ Default.args = {
16
+ message: 'No Data',
17
+ };
@@ -6,9 +6,10 @@ import { ThemeType, useTheme } from '../../theme';
6
6
 
7
7
  type Props = {
8
8
  reverted?: boolean;
9
+ message: string;
9
10
  }
10
11
 
11
- const EmptyState = () => {
12
+ const EmptyState: React.FC<Props> = ({ message }) => {
12
13
  const { theme, commonStyles, typography } = useTheme();
13
14
  const styles = getStyles(theme);
14
15
 
@@ -16,7 +17,7 @@ const EmptyState = () => {
16
17
  <View style={[commonStyles.container, styles.container]}>
17
18
  <Ionicons name="file-tray-outline" size={50} color={theme.placeholder} />
18
19
  <Spacer size='xxs' />
19
- <Text style={[typography.titleH6Regular, { color: theme.placeholder }]}>No Data</Text>
20
+ <Text style={[typography.titleH6Regular, { color: theme.placeholder }]}>{message}</Text>
20
21
  </View>
21
22
  );
22
23
  };
@@ -18,4 +18,7 @@ const Template: StoryFn<NoAuthProps> = (args) => <NoAuth {...args} />;
18
18
 
19
19
  export const Default = Template.bind({});
20
20
  Default.args = {
21
+ title: 'Welcome!',
22
+ description: 'To continue, please log in to the system.',
23
+ buttonText: 'Log In',
21
24
  };
@@ -7,21 +7,22 @@ import { useTheme } from '../../theme';
7
7
 
8
8
  type NoAuthProps = {
9
9
  onPress: () => void;
10
+ title: string;
11
+ description: string;
12
+ buttonText: string;
10
13
  }
11
14
 
12
- export const NoAuth: FC<NoAuthProps> = ({ onPress }) => {
15
+ export const NoAuth: FC<NoAuthProps> = ({ onPress, title, description, buttonText }) => {
13
16
  const { commonStyles, typography, theme } = useTheme();
14
17
 
15
18
  return (
16
19
  <View style={[commonStyles.container, {backgroundColor: theme.background}]}>
17
- <Text style={typography.titleH3}>Welcome!</Text>
20
+ <Text style={typography.titleH3}>{title}</Text>
18
21
  <Spacer size='xs' />
19
- <Text style={typography.body}>
20
- To continue, please log in to the system.
21
- </Text>
22
+ <Text style={typography.body}>{description}</Text>
22
23
  <Spacer size='lg' />
23
24
  <View style={styles.button}>
24
- <Button title='Log In' onPress={onPress} />
25
+ <Button title={buttonText} onPress={onPress} />
25
26
  </View>
26
27
  </View>
27
28
  );
@@ -32,12 +32,19 @@ PendingParticipant.args = {
32
32
  participant: {
33
33
  _id: 'participant-1',
34
34
  status: 'PENDING',
35
+ name: 'Jane',
36
+ lastname: 'Cooper',
37
+ avatarFile: '',
35
38
  },
36
39
  fullName: 'Jane Cooper',
37
40
  avatarUrl: 'https://i.pravatar.cc/100?img=5',
38
41
  isMe: true,
39
42
  myId: 'host-1',
40
43
  isModerated: true,
44
+ confirmLabel: 'Confirm',
45
+ rejectLabel: 'Reject',
46
+ deleteLabel: 'Delete',
47
+ youLabel: 'you',
41
48
  };
42
49
 
43
50
  export const ConfirmedGuest = Template.bind({});
@@ -45,12 +52,19 @@ ConfirmedGuest.args = {
45
52
  participant: {
46
53
  _id: 'participant-2',
47
54
  status: 'CONFIRMED',
55
+ name: 'Robert',
56
+ lastname: 'Fox',
57
+ avatarFile: '',
48
58
  },
49
59
  fullName: 'Robert Fox',
50
60
  avatarUrl: 'https://i.pravatar.cc/100?img=12',
51
61
  isMe: true,
52
62
  myId: 'participant-2',
53
63
  isModerated: false,
64
+ confirmLabel: 'Confirm',
65
+ rejectLabel: 'Reject',
66
+ deleteLabel: 'Delete',
67
+ youLabel: 'you',
54
68
  };
55
69
 
56
70
  export const ReadOnlyView = Template.bind({});
@@ -58,10 +72,17 @@ ReadOnlyView.args = {
58
72
  participant: {
59
73
  _id: 'participant-3',
60
74
  status: 'REJECTED',
75
+ name: 'Theresa',
76
+ lastname: 'Webb',
77
+ avatarFile: '',
61
78
  },
62
79
  fullName: 'Theresa Webb',
63
80
  avatarUrl: 'https://i.pravatar.cc/100?img=45',
64
81
  isMe: false,
65
82
  myId: 'host-1',
66
83
  isModerated: false,
84
+ confirmLabel: 'Confirm',
85
+ rejectLabel: 'Reject',
86
+ deleteLabel: 'Delete',
87
+ youLabel: 'you',
67
88
  };
@@ -15,11 +15,35 @@ type ParticipantItemProps = {
15
15
  onReject?: (userId: string) => void;
16
16
  onProfilePress: (profileId: string) => void;
17
17
  isModerated: boolean;
18
+ confirmLabel: string;
19
+ rejectLabel: string;
20
+ deleteLabel: string;
21
+ youLabel: string;
22
+ statusLabels?: Partial<Record<NonNullable<EventParticipant['status']>, string>>;
18
23
  };
19
24
 
20
- export const ParticipantItem: FC<ParticipantItemProps> = ({ fullName, avatarUrl, isModerated, participant, isMe, myId, onActionPress, onProfilePress, onConfirm, onReject }) => {
25
+ export const ParticipantItem: FC<ParticipantItemProps> = ({
26
+ fullName,
27
+ avatarUrl,
28
+ isModerated,
29
+ participant,
30
+ isMe,
31
+ myId,
32
+ onActionPress,
33
+ onProfilePress,
34
+ onConfirm,
35
+ onReject,
36
+ confirmLabel,
37
+ rejectLabel,
38
+ deleteLabel,
39
+ youLabel,
40
+ statusLabels,
41
+ }) => {
21
42
  const { globalStyleSheet, theme, sizes, commonStyles, typography } = useTheme();
22
43
  const styles = getStyles({ theme, sizes, commonStyles });
44
+ const statusKey = participant.status as NonNullable<EventParticipant['status']> | undefined;
45
+ const statusText = statusKey ? statusLabels?.[statusKey] ?? participant.status?.toLowerCase() : undefined;
46
+ const statusStyle = statusKey ? (styles as Record<string, typeof styles.status_default>)[`status_${statusKey}`] : undefined;
23
47
 
24
48
  return (
25
49
  <View key={participant._id} style={globalStyleSheet.flexRowCenterBetween}>
@@ -28,19 +52,19 @@ export const ParticipantItem: FC<ParticipantItemProps> = ({ fullName, avatarUrl,
28
52
  <Text style={typography.body}>{fullName}</Text>
29
53
  </TouchableOpacity>
30
54
  <View style={globalStyleSheet.flexRowCenter}>
31
- {participant.status && (
32
- <Text style={[styles.statusText, styles[`status_${participant.status}`] || styles.status_default]}>{participant.status.toLowerCase()}</Text>
55
+ {statusText && (
56
+ <Text style={[styles.statusText, statusStyle ?? styles.status_default]}>{statusText}</Text>
33
57
  )}
34
58
  {isMe && myId !== participant._id && (
35
59
  <ThreeDotsMenu
36
60
  items={[
37
61
  {
38
- label: 'Confirm',
62
+ label: confirmLabel,
39
63
  icon: 'checkmark-outline',
40
64
  onPress: () => onConfirm && onConfirm(participant._id),
41
65
  },
42
66
  {
43
- label: isModerated ? 'Reject' : 'Delete',
67
+ label: isModerated ? rejectLabel : deleteLabel,
44
68
  icon: 'close-outline',
45
69
  colorIcon: theme.red,
46
70
  onPress: () => isModerated ? (onReject && onReject(participant._id)) : onActionPress(participant._id),
@@ -49,7 +73,7 @@ export const ParticipantItem: FC<ParticipantItemProps> = ({ fullName, avatarUrl,
49
73
  />
50
74
 
51
75
  )}
52
- {isMe && myId === participant._id && <Text style={styles.youText}>you</Text>}
76
+ {isMe && myId === participant._id && <Text style={styles.youText}>{youLabel}</Text>}
53
77
  </View>
54
78
  </View>
55
79
  );
@@ -1,6 +1,6 @@
1
1
  import React, { useMemo } from "react";
2
2
  import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
3
- import { ThemeType, TypographytType, SizesType, useTheme } from "rn-vs-lb/theme";
3
+ import { ThemeType, TypographytType, SizesType, useTheme } from "../../theme";
4
4
 
5
5
  interface StepProgressProps {
6
6
  steps: { title: string; description?: string }[];
@@ -17,6 +17,10 @@ const meta: Meta = {
17
17
 
18
18
  export default meta;
19
19
 
20
- const Template: StoryFn = () => <ThemeSwitcher />;
20
+ const Template: StoryFn<React.ComponentProps<typeof ThemeSwitcher>> = (args) => <ThemeSwitcher {...args} />;
21
21
 
22
22
  export const Default = Template.bind({});
23
+ Default.args = {
24
+ lightModeLabel: 'Light Mode',
25
+ darkModeLabel: 'Dark Mode',
26
+ };
@@ -3,7 +3,12 @@ import { View, Text, Switch, StyleSheet } from 'react-native';
3
3
  import { FontAwesome } from '@expo/vector-icons';
4
4
  import { useTheme } from '../../theme';
5
5
 
6
- const ThemeSwitcher: React.FC = () => {
6
+ interface ThemeSwitcherProps {
7
+ lightModeLabel: string;
8
+ darkModeLabel: string;
9
+ }
10
+
11
+ const ThemeSwitcher: React.FC<ThemeSwitcherProps> = ({ lightModeLabel, darkModeLabel }) => {
7
12
  const { theme, toggleTheme, isDark, globalStyleSheet, typography } = useTheme();
8
13
  // th-list puzzle-piece
9
14
  return (
@@ -11,7 +16,7 @@ const ThemeSwitcher: React.FC = () => {
11
16
  <View style={globalStyleSheet.flexRowCenter}>
12
17
  <FontAwesome style={styles.iconContainer} name={"th-list"} size={18} color={theme.text} />
13
18
  <Text style={[typography.titleH6Regular, { color: theme.text }]}>
14
- {isDark ? 'Dark Mode' : 'Light Mode'}
19
+ {isDark ? darkModeLabel : lightModeLabel}
15
20
  </Text>
16
21
  </View>
17
22
  <Switch
@@ -58,6 +58,7 @@ export const Default: Story = {
58
58
  title: 'Необходимо обновление',
59
59
  description:
60
60
  'Для корректной работы приложения установите последнюю версию. Нажмите кнопку ниже, чтобы перейти в магазин.',
61
+ updateButtonText: 'Обновить',
61
62
  },
62
63
  };
63
64
 
@@ -67,5 +68,6 @@ export const Refreshing: Story = {
67
68
  refreshing: true,
68
69
  title: 'Проверка обновлений...',
69
70
  description: 'Подождите, идет проверка доступных обновлений.',
71
+ updateButtonText: 'Обновить',
70
72
  },
71
73
  };
@@ -19,9 +19,10 @@ type Props = {
19
19
  onPressUpdate: () => void;
20
20
  title: string;
21
21
  description: string;
22
+ updateButtonText: string;
22
23
  };
23
24
 
24
- export const UpdateRequiredView = memo(({ anim, refreshing, onRefresh, onPressUpdate, title, description }: Props) => {
25
+ export const UpdateRequiredView = memo(({ anim, refreshing, onRefresh, onPressUpdate, title, description, updateButtonText }: Props) => {
25
26
  const { theme, commonStyles, typography } = useTheme() as any;
26
27
 
27
28
  const ui = {
@@ -51,7 +52,7 @@ export const UpdateRequiredView = memo(({ anim, refreshing, onRefresh, onPressUp
51
52
 
52
53
  <Spacer size="xl" />
53
54
  <View style={styles.button}>
54
- <Button title="Обновить" onPress={onPressUpdate} />
55
+ <Button title={updateButtonText} onPress={onPressUpdate} />
55
56
  </View>
56
57
  </ScrollView>
57
58
  );
@@ -7,9 +7,10 @@ interface OrganizerContainerProps {
7
7
  avatarUri: string;
8
8
  organizerName: string;
9
9
  onPress: () => void;
10
+ roleLabel: string;
10
11
  }
11
12
 
12
- const Organizer: React.FC<OrganizerContainerProps> = ({ avatarUri, organizerName, onPress }) => {
13
+ const Organizer: React.FC<OrganizerContainerProps> = ({ avatarUri, organizerName, onPress, roleLabel }) => {
13
14
  const { globalStyleSheet, sizes, commonStyles, typography } = useTheme();
14
15
  const styles = getStyles({ sizes, commonStyles });
15
16
 
@@ -17,7 +18,7 @@ const Organizer: React.FC<OrganizerContainerProps> = ({ avatarUri, organizerName
17
18
  <TouchableOpacity onPress={onPress} style={globalStyleSheet.flexRowCenter}>
18
19
  <Image source={{ uri: avatarUri }} style={styles.avatar} />
19
20
  <View>
20
- <Text style={typography.body}>Organizer</Text>
21
+ <Text style={typography.body}>{roleLabel}</Text>
21
22
  <Text
22
23
  style={typography.titleH6Regular}
23
24
  numberOfLines={1}
@@ -33,22 +33,26 @@ export const Default = Template.bind({});
33
33
  Default.args = {
34
34
  avatarUri: 'https://i.pravatar.cc/150?img=5',
35
35
  organizerName: 'Maria Antonova',
36
+ roleLabel: 'Organizer',
36
37
  };
37
38
 
38
39
  export const LongName = Template.bind({});
39
40
  LongName.args = {
40
41
  avatarUri: 'https://i.pravatar.cc/150?img=47',
41
42
  organizerName: 'Ассоциация содействия развитию креативных индустрий Белграда',
43
+ roleLabel: 'Organizer',
42
44
  };
43
45
 
44
46
  export const CustomAvatar = Template.bind({});
45
47
  CustomAvatar.args = {
46
48
  avatarUri: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?auto=format&fit=crop&w=200&q=80',
47
49
  organizerName: 'Volunteer Labs',
50
+ roleLabel: 'Organizer',
48
51
  };
49
52
 
50
53
  export const WithoutAvatar = Template.bind({});
51
54
  WithoutAvatar.args = {
52
55
  avatarUri: 'https://via.placeholder.com/80x80.png?text=Org',
53
56
  organizerName: 'Placeholder Collective',
57
+ roleLabel: 'Organizer',
54
58
  };
@@ -59,6 +59,7 @@ Default.args = {
59
59
  services,
60
60
  gallery,
61
61
  link: 'https://images.unsplash.com/',
62
+ actionLabel: 'More',
62
63
  };
63
64
 
64
65
  export const WithoutServices = Template.bind({});
@@ -83,6 +84,7 @@ MinimalInfo.args = {
83
84
  fullName: 'Unknown Specialist',
84
85
  avatarUri: 'https://i.pravatar.cc/150?img=60',
85
86
  link: 'https://images.unsplash.com/',
87
+ actionLabel: 'More',
86
88
  };
87
89
 
88
90
  export const ExtendedServices = Template.bind({});
@@ -13,9 +13,10 @@ interface SpecialistCardProps {
13
13
  gallery?: string[];
14
14
  link: string;
15
15
  onPress: () => void;
16
+ actionLabel: string;
16
17
  }
17
18
 
18
- const SpecialistCard: React.FC<SpecialistCardProps> = ({avatarUri, services, gallery, onPress, link, fullName, profession, city, country }) => {
19
+ const SpecialistCard: React.FC<SpecialistCardProps> = ({avatarUri, services, gallery, onPress, link, fullName, profession, city, country, actionLabel }) => {
19
20
  const { theme, typography } = useTheme() as any;
20
21
  const styles = getStyles(theme);
21
22
 
@@ -52,7 +53,7 @@ const SpecialistCard: React.FC<SpecialistCardProps> = ({avatarUri, services, gal
52
53
  style={styles.bookBtn}
53
54
  activeOpacity={0.85}
54
55
  >
55
- <Text style={styles.bookText}>More</Text>
56
+ <Text style={styles.bookText}>{actionLabel}</Text>
56
57
  </TouchableOpacity>
57
58
  </View>
58
59
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rn-vs-lb",
3
- "version": "1.0.63",
3
+ "version": "1.0.65",
4
4
  "description": "Expo Router + Storybook template ready for npm distribution.",
5
5
  "keywords": [
6
6
  "expo",