@xetwa/design-system 1.0.2

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 (168) hide show
  1. package/.github/workflows/publish.yml +30 -0
  2. package/.storybook/main.ts +17 -0
  3. package/.storybook/preview.tsx +65 -0
  4. package/eslint.config.js +22 -0
  5. package/index.html +13 -0
  6. package/package.json +55 -0
  7. package/public/favicon.svg +1 -0
  8. package/public/icons.svg +24 -0
  9. package/src/App.css +184 -0
  10. package/src/App.tsx +122 -0
  11. package/src/BordasSombras.mdx +343 -0
  12. package/src/Colors.mdx +393 -0
  13. package/src/GrelhaLayout.mdx +375 -0
  14. package/src/Icons.mdx +42 -0
  15. package/src/MovimentoBreakpoints.mdx +379 -0
  16. package/src/Spacing.mdx +231 -0
  17. package/src/Typography.mdx +321 -0
  18. package/src/assets/Mascots/vava/estaticos/vava-acenar.svg +3 -0
  19. package/src/assets/Mascots/vava/estaticos/vava-acertou.svg +3 -0
  20. package/src/assets/Mascots/vava/estaticos/vava-celebrar.svg +3 -0
  21. package/src/assets/Mascots/vava/estaticos/vava-com-autocolantes.svg +3 -0
  22. package/src/assets/Mascots/vava/estaticos/vava-dormir.svg +3 -0
  23. package/src/assets/Mascots/vava/estaticos/vava-errou.svg +3 -0
  24. package/src/assets/Mascots/vava/estaticos/vava-feliz.svg +3 -0
  25. package/src/assets/Mascots/vava/estaticos/vava-neutra.svg +3 -0
  26. package/src/assets/Mascots/vava/estaticos/vava-original.svg +3 -0
  27. package/src/assets/Mascots/vava/estaticos/vava-pensar.svg +3 -0
  28. package/src/assets/Mascots/vava/estaticos/vava-surpresa.svg +3 -0
  29. package/src/assets/Mascots/yaya/avatar/yaya-avatar-falar.svg +7 -0
  30. package/src/assets/Mascots/yaya/avatar/yaya-avatar-feliz.svg +7 -0
  31. package/src/assets/Mascots/yaya/avatar/yaya-avatar-transparente.svg +6 -0
  32. package/src/assets/Mascots/yaya/estaticos/yaya-acertou.svg +13 -0
  33. package/src/assets/Mascots/yaya/estaticos/yaya-celebrar.svg +13 -0
  34. package/src/assets/Mascots/yaya/estaticos/yaya-dormir.svg +13 -0
  35. package/src/assets/Mascots/yaya/estaticos/yaya-errou.svg +13 -0
  36. package/src/assets/Mascots/yaya/estaticos/yaya-falar.svg +13 -0
  37. package/src/assets/Mascots/yaya/estaticos/yaya-feliz.svg +13 -0
  38. package/src/assets/Mascots/yaya/estaticos/yaya-neutra.svg +13 -0
  39. package/src/assets/Mascots/yaya/estaticos/yaya-pensar.svg +13 -0
  40. package/src/assets/Mascots/yaya/estaticos/yaya-surpresa.svg +13 -0
  41. package/src/assets/hero.png +0 -0
  42. package/src/assets/react.svg +1 -0
  43. package/src/assets/vite.svg +1 -0
  44. package/src/components/Buttons/BackButton/BackButton.stories.tsx +86 -0
  45. package/src/components/Buttons/BackButton/BackButton.tsx +107 -0
  46. package/src/components/Buttons/FabButton/FabButton.stories.tsx +74 -0
  47. package/src/components/Buttons/FabButton/FabButton.tsx +161 -0
  48. package/src/components/Buttons/IconButton/IconButton.stories.tsx +99 -0
  49. package/src/components/Buttons/IconButton/IconButton.tsx +189 -0
  50. package/src/components/Buttons/JourneyButton/JourneyButton.stories.tsx +80 -0
  51. package/src/components/Buttons/JourneyButton/JourneyButton.tsx +194 -0
  52. package/src/components/Buttons/MainButton/MainButton.stories.tsx +144 -0
  53. package/src/components/Buttons/MainButton/MainButton.tsx +258 -0
  54. package/src/components/Buttons/WordChip/WordChip.stories.tsx +84 -0
  55. package/src/components/Buttons/WordChip/WordChip.tsx +157 -0
  56. package/src/components/Buttons/WordChip/index.ts +1 -0
  57. package/src/components/Cards/AnswerOptionCard/AnswerOptionCard.stories.tsx +181 -0
  58. package/src/components/Cards/AnswerOptionCard/AnswerOptionCard.tsx +201 -0
  59. package/src/components/Cards/BaseCard/BaseCard.stories.tsx +148 -0
  60. package/src/components/Cards/BaseCard/BaseCard.tsx +181 -0
  61. package/src/components/Cards/BoardingPassCard/BoardingPassCard.stories.tsx +205 -0
  62. package/src/components/Cards/BoardingPassCard/BoardingPassCard.tsx +384 -0
  63. package/src/components/Cards/BoardingPassCard/FlightIcon.tsx +21 -0
  64. package/src/components/Cards/BoardingPassCard/FlightIcon.web.tsx +18 -0
  65. package/src/components/Cards/CountryCard/CountryCard.stories.tsx +97 -0
  66. package/src/components/Cards/CountryCard/CountryCard.tsx +185 -0
  67. package/src/components/Cards/LevelProgressCard/LevelProgressCard.stories.tsx +61 -0
  68. package/src/components/Cards/LevelProgressCard/LevelProgressCard.tsx +143 -0
  69. package/src/components/Cards/ModuleCard/ModuleCard.stories.tsx +108 -0
  70. package/src/components/Cards/ModuleCard/ModuleCard.tsx +304 -0
  71. package/src/components/Cards/ModuleCompletionCard/ModuleCompletionCard.stories.tsx +53 -0
  72. package/src/components/Cards/ModuleCompletionCard/ModuleCompletionCard.tsx +167 -0
  73. package/src/components/Cards/Passport/PassportCover.tsx +114 -0
  74. package/src/components/Cards/Passport/PassportIDPage.tsx +217 -0
  75. package/src/components/Cards/Passport/PassportStampPage.tsx +253 -0
  76. package/src/components/Cards/Passport/PassportViewer.stories.tsx +95 -0
  77. package/src/components/Cards/Passport/PassportViewer.tsx +328 -0
  78. package/src/components/Cards/PlanCard/PlanCard.stories.tsx +159 -0
  79. package/src/components/Cards/PlanCard/PlanCard.tsx +317 -0
  80. package/src/components/Cards/PricingCard/PricingCard.stories.tsx +83 -0
  81. package/src/components/Cards/PricingCard/PricingCard.tsx +144 -0
  82. package/src/components/Cards/SelectionCard/SelectionCard.stories.tsx +77 -0
  83. package/src/components/Cards/SelectionCard/SelectionCard.tsx +111 -0
  84. package/src/components/Cards/TeacherCard/TeacherCard.stories.tsx +126 -0
  85. package/src/components/Cards/TeacherCard/TeacherCard.tsx +236 -0
  86. package/src/components/Charts/WeeklyProgressChart/WeeklyProgressChart.stories.tsx +89 -0
  87. package/src/components/Charts/WeeklyProgressChart/WeeklyProgressChart.tsx +179 -0
  88. package/src/components/Charts/WeeklyProgressChart/index.ts +1 -0
  89. package/src/components/DataDisplay/Avatar/Avatar.stories.tsx +85 -0
  90. package/src/components/DataDisplay/Avatar/Avatar.tsx +118 -0
  91. package/src/components/DataDisplay/Avatar/index.ts +1 -0
  92. package/src/components/DataDisplay/Badge/Badge.stories.tsx +62 -0
  93. package/src/components/DataDisplay/Badge/Badge.tsx +146 -0
  94. package/src/components/DataDisplay/Flag/Flag.stories.tsx +98 -0
  95. package/src/components/DataDisplay/Flag/Flag.tsx +347 -0
  96. package/src/components/DataDisplay/Flag/Flag.web.tsx +334 -0
  97. package/src/components/DataDisplay/InstructionBubble/InstructionBubble.stories.tsx +80 -0
  98. package/src/components/DataDisplay/InstructionBubble/InstructionBubble.tsx +86 -0
  99. package/src/components/DataDisplay/LevelBadge/LevelBadge.stories.tsx +99 -0
  100. package/src/components/DataDisplay/LevelBadge/LevelBadge.tsx +118 -0
  101. package/src/components/DataDisplay/ProgressBar/ProgressBar.stories.tsx +95 -0
  102. package/src/components/DataDisplay/ProgressBar/ProgressBar.tsx +117 -0
  103. package/src/components/DataDisplay/StatBadge/StatBadge.stories.tsx +82 -0
  104. package/src/components/DataDisplay/StatBadge/StatBadge.tsx +135 -0
  105. package/src/components/DataDisplay/StatBadge/index.ts +1 -0
  106. package/src/components/DataDisplay/Tag/Tag.stories.tsx +63 -0
  107. package/src/components/DataDisplay/Tag/Tag.tsx +148 -0
  108. package/src/components/Feedback/FeedbackBottomSheet/FeedbackBottomSheet.stories.tsx +74 -0
  109. package/src/components/Feedback/FeedbackBottomSheet/FeedbackBottomSheet.tsx +200 -0
  110. package/src/components/Forms/Checkbox/Checkbox.stories.tsx +60 -0
  111. package/src/components/Forms/Checkbox/Checkbox.tsx +127 -0
  112. package/src/components/Forms/Checkbox/index.ts +1 -0
  113. package/src/components/Forms/DaySelector/DaySelector.stories.tsx +62 -0
  114. package/src/components/Forms/DaySelector/DaySelector.tsx +133 -0
  115. package/src/components/Forms/Radio/Radio.stories.tsx +61 -0
  116. package/src/components/Forms/Radio/Radio.tsx +141 -0
  117. package/src/components/Forms/Radio/index.ts +1 -0
  118. package/src/components/Forms/SegmentedToggle/SegmentedToggle.stories.tsx +67 -0
  119. package/src/components/Forms/SegmentedToggle/SegmentedToggle.tsx +150 -0
  120. package/src/components/Forms/SegmentedToggle/index.ts +1 -0
  121. package/src/components/Forms/Select/Select.stories.tsx +59 -0
  122. package/src/components/Forms/Select/Select.tsx +255 -0
  123. package/src/components/Forms/Select/index.ts +1 -0
  124. package/src/components/Forms/Switch/Switch.stories.tsx +57 -0
  125. package/src/components/Forms/Switch/Switch.tsx +120 -0
  126. package/src/components/Forms/Switch/index.ts +1 -0
  127. package/src/components/Forms/TimeSlot/TimeSlot.stories.tsx +62 -0
  128. package/src/components/Forms/TimeSlot/TimeSlot.tsx +116 -0
  129. package/src/components/Headers/CountryHeader/CountryHeader.stories.tsx +114 -0
  130. package/src/components/Headers/CountryHeader/CountryHeader.tsx +147 -0
  131. package/src/components/Headers/ProfileHeader/ProfileHeader.stories.tsx +141 -0
  132. package/src/components/Headers/ProfileHeader/ProfileHeader.tsx +233 -0
  133. package/src/components/Inputs/FillInTheBlank/FillInTheBlank.stories.tsx +333 -0
  134. package/src/components/Inputs/FillInTheBlank/FillInTheBlank.tsx +287 -0
  135. package/src/components/Inputs/FillInTheBlank/index.ts +1 -0
  136. package/src/components/Inputs/TextInput/TextInput.stories.tsx +103 -0
  137. package/src/components/Inputs/TextInput/TextInput.tsx +187 -0
  138. package/src/components/Mascots/Vava/Vava.stories.tsx +114 -0
  139. package/src/components/Mascots/Vava/Vava.tsx +276 -0
  140. package/src/components/Mascots/Yaya/Yaya.stories.tsx +98 -0
  141. package/src/components/Mascots/Yaya/Yaya.tsx +233 -0
  142. package/src/components/Navigation/BottomTabBar/BottomTabBar.stories.tsx +68 -0
  143. package/src/components/Navigation/BottomTabBar/BottomTabBar.tsx +85 -0
  144. package/src/components/Navigation/BottomTabBar/BottomTabBarItem.tsx +68 -0
  145. package/src/components/Navigation/BottomTabBar/index.ts +2 -0
  146. package/src/components/Navigation/PaginationDots/PaginationDots.stories.tsx +62 -0
  147. package/src/components/Navigation/PaginationDots/PaginationDots.tsx +81 -0
  148. package/src/components/Navigation/PaginationDots/index.ts +1 -0
  149. package/src/components/Navigation/ProgressMap/ProgressMap.stories.tsx +116 -0
  150. package/src/components/Navigation/ProgressMap/ProgressMap.tsx +827 -0
  151. package/src/components/Navigation/WorldProgressMap/WorldProgressMap.stories.tsx +169 -0
  152. package/src/components/Navigation/WorldProgressMap/WorldProgressMap.tsx +790 -0
  153. package/src/components/Typography/Typography.stories.tsx +127 -0
  154. package/src/components/Typography/Typography.tsx +53 -0
  155. package/src/hooks/useResponsive.ts +41 -0
  156. package/src/hooks/useTheme.ts +32 -0
  157. package/src/index.css +355 -0
  158. package/src/index.ts +28 -0
  159. package/src/main.tsx +10 -0
  160. package/src/mocks/codegenNativeComponent.ts +5 -0
  161. package/src/styles/countryThemes.ts +79 -0
  162. package/src/styles/theme.ts +297 -0
  163. package/src/utils/iconMap.ts +23 -0
  164. package/tsconfig.app.json +25 -0
  165. package/tsconfig.json +7 -0
  166. package/tsconfig.node.json +24 -0
  167. package/vite.config.ts +51 -0
  168. package/vitest.shims.d.ts +1 -0
@@ -0,0 +1,81 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { View, StyleSheet, Animated, Easing } from 'react-native';
3
+ import type { ViewStyle } from 'react-native';
4
+ import { theme } from '../../../styles/theme';
5
+ import { useResponsive } from '../../../hooks/useResponsive';
6
+
7
+ /**
8
+ * Componente de navegação em forma de pontos (Dots).
9
+ * Usado em carrosséis, onboarding ou para indicar a página atual.
10
+ */
11
+ export interface PaginationDotsProps {
12
+ /** O número total de páginas/pontos. */
13
+ totalPages: number;
14
+ /** A página atual (base 0). */
15
+ currentPage: number;
16
+ /** Cor customizada dos pontos inativos (opcional). */
17
+ inactiveColor?: string;
18
+ /** Cor customizada do ponto ativo (opcional). */
19
+ activeColor?: string;
20
+ style?: ViewStyle | ViewStyle[];
21
+ }
22
+
23
+ interface DotProps {
24
+ isActive: boolean;
25
+ }
26
+
27
+ const Dot = ({ isActive }: DotProps) => {
28
+ const { scale } = useResponsive();
29
+
30
+ // Animação da largura: Inativo (6px) -> Ativo (20px)
31
+ const widthAnim = useRef(new Animated.Value(isActive ? scale(20) : scale(6))).current;
32
+
33
+ useEffect(() => {
34
+ Animated.timing(widthAnim, {
35
+ toValue: isActive ? scale(20) : scale(6),
36
+ duration: 250,
37
+ easing: Easing.bezier(0.175, 0.885, 0.32, 1.275), // Efeito "ease-bounce" semelhante ao CSS
38
+ useNativeDriver: false, // Animating width requires useNativeDriver: false
39
+ }).start();
40
+ }, [isActive, widthAnim, scale]);
41
+
42
+ return (
43
+ <Animated.View
44
+ style={[
45
+ styles.dot,
46
+ {
47
+ width: widthAnim,
48
+ height: scale(6),
49
+ borderRadius: scale(3),
50
+ backgroundColor: isActive ? theme.colors.primary : theme.colors.brown[100],
51
+ },
52
+ ]}
53
+ />
54
+ );
55
+ };
56
+
57
+ export const PaginationDots = ({ totalPages, currentPage, style }: PaginationDotsProps) => {
58
+ const { scale } = useResponsive();
59
+
60
+ // Garantir que não crasha caso passem steps negativos
61
+ const safeCurrentStep = Math.max(0, Math.min(currentPage, totalPages - 1));
62
+
63
+ return (
64
+ <View style={[styles.container, { gap: scale(7), marginBottom: scale(24) }, style]}>
65
+ {Array.from({ length: totalPages }).map((_, index) => (
66
+ <Dot key={index} isActive={index === safeCurrentStep} />
67
+ ))}
68
+ </View>
69
+ );
70
+ };
71
+
72
+ const styles = StyleSheet.create({
73
+ container: {
74
+ flexDirection: 'row',
75
+ justifyContent: 'center',
76
+ alignItems: 'center',
77
+ },
78
+ dot: {
79
+ // Definido via styles dinâmicos, mas as bases podem ficar aqui
80
+ },
81
+ });
@@ -0,0 +1 @@
1
+ export * from './PaginationDots';
@@ -0,0 +1,116 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { View, Alert, Platform } from 'react-native';
3
+ import { ProgressMap } from './ProgressMap';
4
+ import type { MapStation } from './ProgressMap';
5
+
6
+ const meta = {
7
+ title: 'Components/Navigation/ProgressMap',
8
+ component: ProgressMap,
9
+ parameters: {
10
+ layout: 'fullscreen',
11
+ docs: {
12
+ description: {
13
+ component:
14
+ 'O **ProgressMap** é um componente premium para a Home Screen que renderiza um mapa de progresso interativo e rolável. Apresenta ilhas/continentes SVG, rotas pontilhadas, bandeiras circulares com indicador de paragem e um painel inferior de continuação.',
15
+ },
16
+ },
17
+ },
18
+ tags: ['autodocs'],
19
+ argTypes: {
20
+ size: {
21
+ control: 'select',
22
+ options: ['sm', 'md', 'lg'],
23
+ },
24
+ activeStationId: {
25
+ control: 'number',
26
+ },
27
+ },
28
+ decorators: [
29
+ (Story) => (
30
+ <View style={{ flex: 1, height: 750, backgroundColor: '#efe2d6', justifyContent: 'center', alignItems: 'center' }}>
31
+ <View style={{ width: '100%', height: '100%', maxWidth: 500, borderLeftWidth: 1, borderRightWidth: 1, borderColor: '#efe2d6' }}>
32
+ <Story />
33
+ </View>
34
+ </View>
35
+ ),
36
+ ],
37
+ } satisfies Meta<any>;
38
+
39
+ export default meta;
40
+ type Story = StoryObj<any>;
41
+
42
+ // 8 Stops: Rota da Francofonia
43
+ const baseStations: MapStation[] = [
44
+ { id: 1, label: 'Paris', levelCode: 'A1', countryCode: 'FR', status: 'visited' },
45
+ { id: 2, label: 'Bruxelles', levelCode: 'A2', countryCode: 'BE', status: 'visited' },
46
+ { id: 3, label: 'Genève', levelCode: 'A2', countryCode: 'CH', status: 'visited' },
47
+ { id: 4, label: 'Montréal', levelCode: 'B1', countryCode: 'CA', status: 'visited' },
48
+ { id: 5, label: 'Dakar', levelCode: 'B2', countryCode: 'SN', status: 'current' },
49
+ { id: 6, label: 'Abidjan', levelCode: 'B2', countryCode: 'CI', status: 'locked' },
50
+ { id: 7, label: 'Yaoundé', levelCode: 'C1', countryCode: 'CM', status: 'locked' },
51
+ { id: 8, label: 'Antananarivo', levelCode: 'C1', countryCode: 'MG', status: 'locked' },
52
+ ];
53
+
54
+ export const Default: Story = {
55
+ name: 'Rota da Francofonia (8 Paragens)',
56
+ args: {
57
+ title: 'A ROTA DA FRANCOFONIA',
58
+ stations: baseStations,
59
+ activeStationId: 5,
60
+ size: 'md',
61
+ onStationPress: (station: any) => {
62
+ if (Platform.OS === 'web') {
63
+ console.log('Estação selecionada:', station.label);
64
+ } else {
65
+ Alert.alert('Estação selecionada', station.label);
66
+ }
67
+ },
68
+ onContinuePress: (station: any) => {
69
+ if (Platform.OS === 'web') {
70
+ console.log('A continuar viagem de:', station.label);
71
+ } else {
72
+ Alert.alert('Viagem', `A continuar de ${station.label}`);
73
+ }
74
+ },
75
+ onBackPress: () => {
76
+ console.log('Retroceder');
77
+ },
78
+ onFlightPress: () => {
79
+ console.log('Abrir Voo');
80
+ },
81
+ },
82
+ };
83
+
84
+ // Long winding route of 15 stops
85
+ const longStations: MapStation[] = [
86
+ { id: 1, label: 'Paris', levelCode: 'A1', countryCode: 'FR', status: 'visited' },
87
+ { id: 2, label: 'Bruxelles', levelCode: 'A1', countryCode: 'BE', status: 'visited' },
88
+ { id: 3, label: 'Luxembourg', levelCode: 'A2', countryCode: 'LU', status: 'visited' },
89
+ { id: 4, label: 'Monaco', levelCode: 'A2', countryCode: 'MC', status: 'visited' },
90
+ { id: 5, label: 'Genève', levelCode: 'A2', countryCode: 'CH', status: 'visited' },
91
+ { id: 6, label: 'Montréal', levelCode: 'B1', countryCode: 'CA', status: 'visited' },
92
+ { id: 7, label: 'Aosta', levelCode: 'B1', countryCode: 'FR', status: 'visited' }, // Fallback flag FR
93
+ { id: 8, label: 'Bamako', levelCode: 'B1', countryCode: 'ML', status: 'visited' },
94
+ { id: 9, label: 'Dakar', levelCode: 'B2', countryCode: 'SN', status: 'current' },
95
+ { id: 10, label: 'Abidjan', levelCode: 'B2', countryCode: 'CI', status: 'locked' },
96
+ { id: 11, label: 'Ouagadougou', levelCode: 'B2', countryCode: 'BF', status: 'locked' },
97
+ { id: 12, label: 'Niamey', levelCode: 'C1', countryCode: 'NE', status: 'locked' },
98
+ { id: 13, label: 'N\'Djamena', levelCode: 'C1', countryCode: 'TD', status: 'locked' },
99
+ { id: 14, label: 'Libreville', levelCode: 'C1', countryCode: 'GA', status: 'locked' },
100
+ { id: 15, label: 'Antananarivo', levelCode: 'C1', countryCode: 'MG', status: 'locked' },
101
+ ];
102
+
103
+ export const LongJourney: Story = {
104
+ name: 'Longa Viagem (15 Paragens)',
105
+ args: {
106
+ title: 'EXPEDIÇÃO TRANSAFRICANA',
107
+ subtitle: '15 paragens · A1 → C1',
108
+ stations: longStations,
109
+ activeStationId: 9,
110
+ size: 'md',
111
+ onStationPress: (station: any) => console.log('Station pressed:', station),
112
+ onContinuePress: (station: any) => console.log('Continue pressed from:', station),
113
+ onBackPress: () => console.log('Back pressed'),
114
+ onFlightPress: () => console.log('Flight pressed'),
115
+ },
116
+ };