react-native-elearn-ui 0.1.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.
Files changed (100) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +37 -0
  3. package/lib/module/components/Button.js +82 -0
  4. package/lib/module/components/Button.js.map +1 -0
  5. package/lib/module/components/Card.js +49 -0
  6. package/lib/module/components/Card.js.map +1 -0
  7. package/lib/module/components/CircularProgress.js +80 -0
  8. package/lib/module/components/CircularProgress.js.map +1 -0
  9. package/lib/module/components/Icon.js +268 -0
  10. package/lib/module/components/Icon.js.map +1 -0
  11. package/lib/module/components/ProgressBar.js +39 -0
  12. package/lib/module/components/ProgressBar.js.map +1 -0
  13. package/lib/module/components/Typography.js +102 -0
  14. package/lib/module/components/Typography.js.map +1 -0
  15. package/lib/module/components/index.js +10 -0
  16. package/lib/module/components/index.js.map +1 -0
  17. package/lib/module/context/ElearnConfigContext.js +76 -0
  18. package/lib/module/context/ElearnConfigContext.js.map +1 -0
  19. package/lib/module/context/ThemeContext.js +45 -0
  20. package/lib/module/context/ThemeContext.js.map +1 -0
  21. package/lib/module/index.js +13 -0
  22. package/lib/module/index.js.map +1 -0
  23. package/lib/module/multiply.js +6 -0
  24. package/lib/module/multiply.js.map +1 -0
  25. package/lib/module/package.json +1 -0
  26. package/lib/module/screens/HomeScreen.js +330 -0
  27. package/lib/module/screens/HomeScreen.js.map +1 -0
  28. package/lib/module/screens/QbankScreen.js +200 -0
  29. package/lib/module/screens/QbankScreen.js.map +1 -0
  30. package/lib/module/screens/QuestionScreen.js +383 -0
  31. package/lib/module/screens/QuestionScreen.js.map +1 -0
  32. package/lib/module/screens/QuizStartScreen.js +230 -0
  33. package/lib/module/screens/QuizStartScreen.js.map +1 -0
  34. package/lib/module/screens/ResultScreen.js +318 -0
  35. package/lib/module/screens/ResultScreen.js.map +1 -0
  36. package/lib/module/screens/TopicListScreen.js +222 -0
  37. package/lib/module/screens/TopicListScreen.js.map +1 -0
  38. package/lib/module/screens/index.js +9 -0
  39. package/lib/module/screens/index.js.map +1 -0
  40. package/lib/module/types/index.js +2 -0
  41. package/lib/module/types/index.js.map +1 -0
  42. package/lib/typescript/package.json +1 -0
  43. package/lib/typescript/src/components/Button.d.ts +14 -0
  44. package/lib/typescript/src/components/Button.d.ts.map +1 -0
  45. package/lib/typescript/src/components/Card.d.ts +12 -0
  46. package/lib/typescript/src/components/Card.d.ts.map +1 -0
  47. package/lib/typescript/src/components/CircularProgress.d.ts +15 -0
  48. package/lib/typescript/src/components/CircularProgress.d.ts.map +1 -0
  49. package/lib/typescript/src/components/Icon.d.ts +11 -0
  50. package/lib/typescript/src/components/Icon.d.ts.map +1 -0
  51. package/lib/typescript/src/components/ProgressBar.d.ts +11 -0
  52. package/lib/typescript/src/components/ProgressBar.d.ts.map +1 -0
  53. package/lib/typescript/src/components/Typography.d.ts +12 -0
  54. package/lib/typescript/src/components/Typography.d.ts.map +1 -0
  55. package/lib/typescript/src/components/index.d.ts +9 -0
  56. package/lib/typescript/src/components/index.d.ts.map +1 -0
  57. package/lib/typescript/src/context/ElearnConfigContext.d.ts +22 -0
  58. package/lib/typescript/src/context/ElearnConfigContext.d.ts.map +1 -0
  59. package/lib/typescript/src/context/ThemeContext.d.ts +11 -0
  60. package/lib/typescript/src/context/ThemeContext.d.ts.map +1 -0
  61. package/lib/typescript/src/index.d.ts +6 -0
  62. package/lib/typescript/src/index.d.ts.map +1 -0
  63. package/lib/typescript/src/multiply.d.ts +2 -0
  64. package/lib/typescript/src/multiply.d.ts.map +1 -0
  65. package/lib/typescript/src/screens/HomeScreen.d.ts +3 -0
  66. package/lib/typescript/src/screens/HomeScreen.d.ts.map +1 -0
  67. package/lib/typescript/src/screens/QbankScreen.d.ts +3 -0
  68. package/lib/typescript/src/screens/QbankScreen.d.ts.map +1 -0
  69. package/lib/typescript/src/screens/QuestionScreen.d.ts +11 -0
  70. package/lib/typescript/src/screens/QuestionScreen.d.ts.map +1 -0
  71. package/lib/typescript/src/screens/QuizStartScreen.d.ts +10 -0
  72. package/lib/typescript/src/screens/QuizStartScreen.d.ts.map +1 -0
  73. package/lib/typescript/src/screens/ResultScreen.d.ts +11 -0
  74. package/lib/typescript/src/screens/ResultScreen.d.ts.map +1 -0
  75. package/lib/typescript/src/screens/TopicListScreen.d.ts +9 -0
  76. package/lib/typescript/src/screens/TopicListScreen.d.ts.map +1 -0
  77. package/lib/typescript/src/screens/index.d.ts +7 -0
  78. package/lib/typescript/src/screens/index.d.ts.map +1 -0
  79. package/lib/typescript/src/types/index.d.ts +107 -0
  80. package/lib/typescript/src/types/index.d.ts.map +1 -0
  81. package/package.json +121 -0
  82. package/src/components/Button.tsx +101 -0
  83. package/src/components/Card.tsx +57 -0
  84. package/src/components/CircularProgress.tsx +93 -0
  85. package/src/components/Icon.tsx +338 -0
  86. package/src/components/ProgressBar.tsx +47 -0
  87. package/src/components/Typography.tsx +112 -0
  88. package/src/components/index.ts +8 -0
  89. package/src/context/ElearnConfigContext.tsx +90 -0
  90. package/src/context/ThemeContext.tsx +37 -0
  91. package/src/index.tsx +33 -0
  92. package/src/multiply.tsx +3 -0
  93. package/src/screens/HomeScreen.tsx +291 -0
  94. package/src/screens/QbankScreen.tsx +176 -0
  95. package/src/screens/QuestionScreen.tsx +402 -0
  96. package/src/screens/QuizStartScreen.tsx +215 -0
  97. package/src/screens/ResultScreen.tsx +303 -0
  98. package/src/screens/TopicListScreen.tsx +200 -0
  99. package/src/screens/index.ts +6 -0
  100. package/src/types/index.ts +122 -0
@@ -0,0 +1,107 @@
1
+ export interface ThemeConfig {
2
+ primary: string;
3
+ secondary: string;
4
+ success: string;
5
+ danger: string;
6
+ warning: string;
7
+ background: string;
8
+ cardBackground: string;
9
+ textPrimary: string;
10
+ textSecondary: string;
11
+ textInverse: string;
12
+ border: string;
13
+ fontRegular?: string;
14
+ fontMedium?: string;
15
+ fontBold?: string;
16
+ }
17
+ export interface StringsConfig {
18
+ homeHeaderTitle?: string;
19
+ homeHeaderSubtitle?: string;
20
+ dailyQuizTitle?: string;
21
+ dailyQuizSubtitle?: string;
22
+ dailyQuizProgressLabel?: string;
23
+ trackQuickLabel?: string;
24
+ subjectsTitle?: string;
25
+ popularTopicsTitle?: string;
26
+ qbankTitle?: string;
27
+ qbankSubtitle?: string;
28
+ topicsLabel?: string;
29
+ questionsCountLabel?: string;
30
+ startQuizButton?: string;
31
+ topicsAndItemsLabel?: string;
32
+ infoTitle?: string;
33
+ questionLabel?: string;
34
+ explanationLabel?: string;
35
+ nextButtonLabel?: string;
36
+ submitButtonLabel?: string;
37
+ correctAnswerLabel?: string;
38
+ incorrectAnswerLabel?: string;
39
+ resultsTitle?: string;
40
+ resultsSubtitle?: string;
41
+ accuracyLabel?: string;
42
+ timeSpentLabel?: string;
43
+ correctAnswersCountLabel?: string;
44
+ reviewAnswersButton?: string;
45
+ goHomeButton?: string;
46
+ scorecardTitle?: string;
47
+ }
48
+ export interface Question {
49
+ id: string;
50
+ text: string;
51
+ imageUrl?: string;
52
+ options: string[];
53
+ correctOptionIndex: number;
54
+ explanation: string;
55
+ }
56
+ export interface Topic {
57
+ id: string;
58
+ title: string;
59
+ totalQuestions: number;
60
+ completedQuestions: number;
61
+ progress: number;
62
+ questions?: Question[];
63
+ }
64
+ export interface Course {
65
+ id: string;
66
+ title: string;
67
+ description?: string;
68
+ iconName?: string;
69
+ progress: number;
70
+ totalQuestions: number;
71
+ completedQuestions: number;
72
+ topics: Topic[];
73
+ }
74
+ export interface DailyQuizConfig {
75
+ id: string;
76
+ title: string;
77
+ description: string;
78
+ questionsCount: number;
79
+ progressPercentage: number;
80
+ questions: Question[];
81
+ }
82
+ export interface ElearnConfig {
83
+ theme?: Partial<ThemeConfig>;
84
+ strings?: Partial<StringsConfig>;
85
+ courses?: Course[];
86
+ dailyQuiz?: DailyQuizConfig;
87
+ }
88
+ export interface ElearnCallbacks {
89
+ onStartQuiz?: (quizId: string, questions: Question[], title: string) => void;
90
+ onSelectCourse?: (course: Course) => void;
91
+ onSelectTopic?: (course: Course, topic: Topic) => void;
92
+ onFinishQuiz?: (quizId: string, results: QuizResults) => void;
93
+ onBackToDashboard?: () => void;
94
+ }
95
+ export interface QuizResults {
96
+ quizId: string;
97
+ totalQuestions: number;
98
+ correctCount: number;
99
+ wrongCount: number;
100
+ skippedCount: number;
101
+ accuracy: number;
102
+ timeSpentSeconds: number;
103
+ userAnswers: {
104
+ [questionId: string]: number;
105
+ };
106
+ }
107
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/types/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,121 @@
1
+ {
2
+ "name": "react-native-elearn-ui",
3
+ "version": "0.1.0",
4
+ "description": "Enterprise E-Learning UI library for React Native",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "react-native-elearn-ui-source": "./src/index.tsx",
10
+ "types": "./lib/typescript/src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "src",
17
+ "lib",
18
+ "android",
19
+ "ios",
20
+ "cpp",
21
+ "*.podspec",
22
+ "react-native.config.js",
23
+ "!ios/build",
24
+ "!android/build",
25
+ "!android/gradle",
26
+ "!android/gradlew",
27
+ "!android/gradlew.bat",
28
+ "!android/local.properties",
29
+ "!**/__tests__",
30
+ "!**/__fixtures__",
31
+ "!**/__mocks__",
32
+ "!**/.*"
33
+ ],
34
+ "scripts": {
35
+ "example": "yarn workspace react-native-elearn-ui-example",
36
+ "clean": "del-cli lib",
37
+ "prepare": "bob build",
38
+ "typecheck": "tsc",
39
+ "lint": "eslint \"**/*.{js,ts,tsx}\""
40
+ },
41
+ "keywords": [
42
+ "react-native",
43
+ "ios",
44
+ "android"
45
+ ],
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/harveedesigns/e_learn_pack.git"
49
+ },
50
+ "author": "Antigravity <antigravity@google.com> (https://github.com/harveedesigns)",
51
+ "license": "MIT",
52
+ "bugs": {
53
+ "url": "https://github.com/harveedesigns/e_learn_pack/issues"
54
+ },
55
+ "homepage": "https://github.com/harveedesigns/e_learn_pack#readme",
56
+ "publishConfig": {
57
+ "registry": "https://registry.npmjs.org/"
58
+ },
59
+ "devDependencies": {
60
+ "@eslint/compat": "^2.1.0",
61
+ "@eslint/eslintrc": "^3.3.5",
62
+ "@eslint/js": "^10.0.1",
63
+ "@react-native/babel-preset": "0.85.0",
64
+ "@react-native/eslint-config": "0.85.0",
65
+ "@types/react": "^19.2.0",
66
+ "del-cli": "^7.0.0",
67
+ "eslint": "^9.39.4",
68
+ "eslint-config-prettier": "^10.1.8",
69
+ "eslint-plugin-ft-flow": "^3.0.11",
70
+ "eslint-plugin-prettier": "^5.5.6",
71
+ "prettier": "^3.8.3",
72
+ "react": "19.2.0",
73
+ "react-native": "0.83.6",
74
+ "react-native-builder-bob": "^0.43.0",
75
+ "react-native-svg": "*",
76
+ "turbo": "^2.9.16",
77
+ "typescript": "^6.0.3"
78
+ },
79
+ "peerDependencies": {
80
+ "react": "*",
81
+ "react-native": "*",
82
+ "react-native-svg": "*"
83
+ },
84
+ "workspaces": [
85
+ "example"
86
+ ],
87
+ "packageManager": "yarn@4.11.0",
88
+ "react-native-builder-bob": {
89
+ "source": "src",
90
+ "output": "lib",
91
+ "targets": [
92
+ [
93
+ "module",
94
+ {
95
+ "esm": true
96
+ }
97
+ ],
98
+ [
99
+ "typescript",
100
+ {
101
+ "project": "tsconfig.build.json"
102
+ }
103
+ ]
104
+ ]
105
+ },
106
+ "prettier": {
107
+ "quoteProps": "consistent",
108
+ "singleQuote": true,
109
+ "tabWidth": 2,
110
+ "trailingComma": "es5",
111
+ "useTabs": false
112
+ },
113
+ "create-react-native-library": {
114
+ "type": "library",
115
+ "languages": "js",
116
+ "tools": [
117
+ "eslint"
118
+ ],
119
+ "version": "0.63.0"
120
+ }
121
+ }
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import { TouchableOpacity, StyleSheet, ActivityIndicator } from 'react-native';
3
+ import type { StyleProp, ViewStyle, TextStyle } from 'react-native';
4
+ import { useTheme } from '../context/ThemeContext';
5
+ import { Typography } from './Typography';
6
+
7
+ interface ButtonProps {
8
+ onPress: () => void;
9
+ title: string;
10
+ variant?: 'primary' | 'secondary' | 'outline';
11
+ disabled?: boolean;
12
+ loading?: boolean;
13
+ style?: StyleProp<ViewStyle>;
14
+ textStyle?: StyleProp<TextStyle>;
15
+ }
16
+
17
+ export const Button: React.FC<ButtonProps> = ({
18
+ onPress,
19
+ title,
20
+ variant = 'primary',
21
+ disabled = false,
22
+ loading = false,
23
+ style,
24
+ textStyle,
25
+ }) => {
26
+ const theme = useTheme();
27
+
28
+ const getButtonStyle = () => {
29
+ switch (variant) {
30
+ case 'primary':
31
+ return {
32
+ backgroundColor: theme.primary,
33
+ };
34
+ case 'secondary':
35
+ return {
36
+ backgroundColor: theme.secondary,
37
+ };
38
+ case 'outline':
39
+ return {
40
+ backgroundColor: 'transparent',
41
+ borderWidth: 1.5,
42
+ borderColor: theme.primary,
43
+ };
44
+ default:
45
+ return {};
46
+ }
47
+ };
48
+
49
+ const getTextColor = () => {
50
+ if (disabled) return theme.textSecondary;
51
+ switch (variant) {
52
+ case 'primary':
53
+ return theme.textInverse;
54
+ case 'secondary':
55
+ case 'outline':
56
+ return theme.primary;
57
+ default:
58
+ return theme.textInverse;
59
+ }
60
+ };
61
+
62
+ return (
63
+ <TouchableOpacity
64
+ activeOpacity={0.8}
65
+ onPress={onPress}
66
+ disabled={disabled || loading}
67
+ style={[
68
+ styles.button,
69
+ getButtonStyle(),
70
+ disabled && { backgroundColor: theme.border, borderColor: theme.border },
71
+ style,
72
+ ]}
73
+ >
74
+ {loading ? (
75
+ <ActivityIndicator color={getTextColor()} />
76
+ ) : (
77
+ <Typography
78
+ variant="button"
79
+ color={getTextColor()}
80
+ style={[styles.text, textStyle]}
81
+ >
82
+ {title}
83
+ </Typography>
84
+ )}
85
+ </TouchableOpacity>
86
+ );
87
+ };
88
+
89
+ const styles = StyleSheet.create({
90
+ button: {
91
+ height: 48,
92
+ borderRadius: 24, // Rounded pill design
93
+ justifyContent: 'center',
94
+ alignItems: 'center',
95
+ paddingHorizontal: 24,
96
+ flexDirection: 'row',
97
+ },
98
+ text: {
99
+ letterSpacing: 0.2,
100
+ },
101
+ });
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import { View, StyleSheet, TouchableOpacity } from 'react-native';
3
+ import type { StyleProp, ViewStyle } from 'react-native';
4
+ import { useTheme } from '../context/ThemeContext';
5
+
6
+ interface CardProps {
7
+ children: React.ReactNode;
8
+ style?: StyleProp<ViewStyle>;
9
+ onPress?: () => void;
10
+ bordered?: boolean;
11
+ elevation?: number;
12
+ }
13
+
14
+ export const Card: React.FC<CardProps> = ({
15
+ children,
16
+ style,
17
+ onPress,
18
+ bordered = false,
19
+ elevation = 1,
20
+ }) => {
21
+ const theme = useTheme();
22
+
23
+ const cardStyle = [
24
+ styles.card,
25
+ {
26
+ backgroundColor: theme.cardBackground,
27
+ borderColor: theme.border,
28
+ borderWidth: bordered ? 1 : 0,
29
+ },
30
+ elevation > 0 && {
31
+ shadowColor: '#0F172A',
32
+ shadowOffset: { width: 0, height: elevation * 2 },
33
+ shadowOpacity: 0.05 * elevation,
34
+ shadowRadius: elevation * 3,
35
+ elevation: elevation * 2,
36
+ },
37
+ style,
38
+ ];
39
+
40
+ if (onPress) {
41
+ return (
42
+ <TouchableOpacity activeOpacity={0.9} onPress={onPress} style={cardStyle}>
43
+ {children}
44
+ </TouchableOpacity>
45
+ );
46
+ }
47
+
48
+ return <View style={cardStyle}>{children}</View>;
49
+ };
50
+
51
+ const styles = StyleSheet.create({
52
+ card: {
53
+ borderRadius: 16,
54
+ padding: 16,
55
+ marginVertical: 8,
56
+ },
57
+ });
@@ -0,0 +1,93 @@
1
+ import React from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import type { StyleProp, TextStyle, ViewStyle } from 'react-native';
4
+ import Svg, { Circle } from 'react-native-svg';
5
+ import { useTheme } from '../context/ThemeContext';
6
+ import { Typography } from './Typography';
7
+
8
+ interface CircularProgressProps {
9
+ progress: number; // 0 to 1
10
+ size?: number;
11
+ strokeWidth?: number;
12
+ color?: string;
13
+ backgroundColor?: string;
14
+ showText?: boolean;
15
+ textStyle?: StyleProp<TextStyle>;
16
+ style?: StyleProp<ViewStyle>;
17
+ }
18
+
19
+ export const CircularProgress: React.FC<CircularProgressProps> = ({
20
+ progress,
21
+ size = 64,
22
+ strokeWidth = 6,
23
+ color,
24
+ backgroundColor,
25
+ showText = true,
26
+ textStyle,
27
+ style,
28
+ }) => {
29
+ const theme = useTheme();
30
+
31
+ const cappedProgress = Math.max(0, Math.min(1, progress));
32
+ const radius = (size - strokeWidth) / 2;
33
+ const circumference = radius * 2 * Math.PI;
34
+ const strokeDashoffset = circumference - cappedProgress * circumference;
35
+
36
+ const progressColor = color || theme.primary;
37
+ const bgStrokeColor = backgroundColor || theme.secondary;
38
+
39
+ return (
40
+ <View style={[styles.container, { width: size, height: size }, style]}>
41
+ <Svg width={size} height={size}>
42
+ <Circle
43
+ cx={size / 2}
44
+ cy={size / 2}
45
+ r={radius}
46
+ stroke={bgStrokeColor}
47
+ strokeWidth={strokeWidth}
48
+ fill="transparent"
49
+ />
50
+ <Circle
51
+ cx={size / 2}
52
+ cy={size / 2}
53
+ r={radius}
54
+ stroke={progressColor}
55
+ strokeWidth={strokeWidth}
56
+ fill="transparent"
57
+ strokeDasharray={circumference}
58
+ strokeDashoffset={strokeDashoffset}
59
+ strokeLinecap="round"
60
+ transform={`rotate(-90 ${size / 2} ${size / 2})`}
61
+ />
62
+ </Svg>
63
+ {showText && (
64
+ <View style={styles.textContainer}>
65
+ <Typography
66
+ variant="label"
67
+ bold
68
+ color={theme.textPrimary}
69
+ style={[styles.text, textStyle]}
70
+ >
71
+ {`${Math.round(cappedProgress * 100)}%`}
72
+ </Typography>
73
+ </View>
74
+ )}
75
+ </View>
76
+ );
77
+ };
78
+
79
+ const styles = StyleSheet.create({
80
+ container: {
81
+ justifyContent: 'center',
82
+ alignItems: 'center',
83
+ position: 'relative',
84
+ },
85
+ textContainer: {
86
+ position: 'absolute',
87
+ justifyContent: 'center',
88
+ alignItems: 'center',
89
+ },
90
+ text: {
91
+ textAlign: 'center',
92
+ },
93
+ });