@magmamath/students-features 1.3.25 → 1.3.26-rc.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 (213) hide show
  1. package/dist/commonjs/features/fluency/components/Fluency.js +63 -0
  2. package/dist/commonjs/features/fluency/components/Fluency.js.map +1 -0
  3. package/dist/commonjs/features/fluency/components/day-streak-counter/DayStreak.js +91 -0
  4. package/dist/commonjs/features/fluency/components/day-streak-counter/DayStreak.js.map +1 -0
  5. package/dist/commonjs/features/fluency/components/day-streak-counter/DayStreakCounter.js +73 -0
  6. package/dist/commonjs/features/fluency/components/day-streak-counter/DayStreakCounter.js.map +1 -0
  7. package/dist/commonjs/features/fluency/components/matrix/FluencyMatrix.js +35 -0
  8. package/dist/commonjs/features/fluency/components/matrix/FluencyMatrix.js.map +1 -0
  9. package/dist/commonjs/features/fluency/components/matrix/components/MatrixFill.js +91 -0
  10. package/dist/commonjs/features/fluency/components/matrix/components/MatrixFill.js.map +1 -0
  11. package/dist/commonjs/features/fluency/components/matrix/components/MatrixLegend.js +118 -0
  12. package/dist/commonjs/features/fluency/components/matrix/components/MatrixLegend.js.map +1 -0
  13. package/dist/commonjs/features/fluency/components/select-math-operator/MathOperatorRow.js +43 -0
  14. package/dist/commonjs/features/fluency/components/select-math-operator/MathOperatorRow.js.map +1 -0
  15. package/dist/commonjs/features/fluency/components/select-math-operator/ProgressBar.js +124 -0
  16. package/dist/commonjs/features/fluency/components/select-math-operator/ProgressBar.js.map +1 -0
  17. package/dist/commonjs/features/fluency/components/select-math-operator/SelectMathOperator.js +75 -0
  18. package/dist/commonjs/features/fluency/components/select-math-operator/SelectMathOperator.js.map +1 -0
  19. package/dist/commonjs/features/fluency/components/start-banner/BannerFlashcards.js +80 -0
  20. package/dist/commonjs/features/fluency/components/start-banner/BannerFlashcards.js.map +1 -0
  21. package/dist/commonjs/features/fluency/components/start-banner/MathFlashcard.js +73 -0
  22. package/dist/commonjs/features/fluency/components/start-banner/MathFlashcard.js.map +1 -0
  23. package/dist/commonjs/features/fluency/components/start-banner/StartBanner.js +98 -0
  24. package/dist/commonjs/features/fluency/components/start-banner/StartBanner.js.map +1 -0
  25. package/dist/commonjs/features/fluency/fluency.constants.js +77 -0
  26. package/dist/commonjs/features/fluency/fluency.constants.js.map +1 -0
  27. package/dist/commonjs/features/fluency/fluency.helpers.js +9 -0
  28. package/dist/commonjs/features/fluency/fluency.helpers.js.map +1 -0
  29. package/dist/commonjs/features/fluency/fluency.types.js +2 -0
  30. package/dist/commonjs/features/fluency/fluency.types.js.map +1 -0
  31. package/dist/commonjs/features/fluency/hooks/useFluencyModeUIPreset.js +15 -0
  32. package/dist/commonjs/features/fluency/hooks/useFluencyModeUIPreset.js.map +1 -0
  33. package/dist/commonjs/features/fluency/index.js +60 -0
  34. package/dist/commonjs/features/fluency/index.js.map +1 -0
  35. package/dist/commonjs/features/fluency/model/FluencyApiModel.js +11 -0
  36. package/dist/commonjs/features/fluency/model/FluencyApiModel.js.map +1 -0
  37. package/dist/commonjs/features/fluency/model/FluencyDaysStreakModel.js +9 -0
  38. package/dist/commonjs/features/fluency/model/FluencyDaysStreakModel.js.map +1 -0
  39. package/dist/commonjs/features/fluency/model/FluencyMatrixModel.js +9 -0
  40. package/dist/commonjs/features/fluency/model/FluencyMatrixModel.js.map +1 -0
  41. package/dist/commonjs/features/fluency/model/FluencyModel.js +24 -0
  42. package/dist/commonjs/features/fluency/model/FluencyModel.js.map +1 -0
  43. package/dist/commonjs/features/fluency/model/fluency.instance.js +11 -0
  44. package/dist/commonjs/features/fluency/model/fluency.instance.js.map +1 -0
  45. package/dist/commonjs/index.js +12 -0
  46. package/dist/commonjs/index.js.map +1 -1
  47. package/dist/module/features/fluency/components/Fluency.js +57 -0
  48. package/dist/module/features/fluency/components/Fluency.js.map +1 -0
  49. package/dist/module/features/fluency/components/day-streak-counter/DayStreak.js +85 -0
  50. package/dist/module/features/fluency/components/day-streak-counter/DayStreak.js.map +1 -0
  51. package/dist/module/features/fluency/components/day-streak-counter/DayStreakCounter.js +67 -0
  52. package/dist/module/features/fluency/components/day-streak-counter/DayStreakCounter.js.map +1 -0
  53. package/dist/module/features/fluency/components/matrix/FluencyMatrix.js +29 -0
  54. package/dist/module/features/fluency/components/matrix/FluencyMatrix.js.map +1 -0
  55. package/dist/module/features/fluency/components/matrix/components/MatrixFill.js +85 -0
  56. package/dist/module/features/fluency/components/matrix/components/MatrixFill.js.map +1 -0
  57. package/dist/module/features/fluency/components/matrix/components/MatrixLegend.js +112 -0
  58. package/dist/module/features/fluency/components/matrix/components/MatrixLegend.js.map +1 -0
  59. package/dist/module/features/fluency/components/select-math-operator/MathOperatorRow.js +37 -0
  60. package/dist/module/features/fluency/components/select-math-operator/MathOperatorRow.js.map +1 -0
  61. package/dist/module/features/fluency/components/select-math-operator/ProgressBar.js +118 -0
  62. package/dist/module/features/fluency/components/select-math-operator/ProgressBar.js.map +1 -0
  63. package/dist/module/features/fluency/components/select-math-operator/SelectMathOperator.js +69 -0
  64. package/dist/module/features/fluency/components/select-math-operator/SelectMathOperator.js.map +1 -0
  65. package/dist/module/features/fluency/components/start-banner/BannerFlashcards.js +74 -0
  66. package/dist/module/features/fluency/components/start-banner/BannerFlashcards.js.map +1 -0
  67. package/dist/module/features/fluency/components/start-banner/MathFlashcard.js +67 -0
  68. package/dist/module/features/fluency/components/start-banner/MathFlashcard.js.map +1 -0
  69. package/dist/module/features/fluency/components/start-banner/StartBanner.js +92 -0
  70. package/dist/module/features/fluency/components/start-banner/StartBanner.js.map +1 -0
  71. package/dist/module/features/fluency/fluency.constants.js +73 -0
  72. package/dist/module/features/fluency/fluency.constants.js.map +1 -0
  73. package/dist/module/features/fluency/fluency.helpers.js +4 -0
  74. package/dist/module/features/fluency/fluency.helpers.js.map +1 -0
  75. package/dist/module/features/fluency/fluency.types.js +2 -0
  76. package/dist/module/features/fluency/fluency.types.js.map +1 -0
  77. package/dist/module/features/fluency/hooks/useFluencyModeUIPreset.js +10 -0
  78. package/dist/module/features/fluency/hooks/useFluencyModeUIPreset.js.map +1 -0
  79. package/dist/module/features/fluency/index.js +8 -0
  80. package/dist/module/features/fluency/index.js.map +1 -0
  81. package/dist/module/features/fluency/model/FluencyApiModel.js +6 -0
  82. package/dist/module/features/fluency/model/FluencyApiModel.js.map +1 -0
  83. package/dist/module/features/fluency/model/FluencyDaysStreakModel.js +4 -0
  84. package/dist/module/features/fluency/model/FluencyDaysStreakModel.js.map +1 -0
  85. package/dist/module/features/fluency/model/FluencyMatrixModel.js +4 -0
  86. package/dist/module/features/fluency/model/FluencyMatrixModel.js.map +1 -0
  87. package/dist/module/features/fluency/model/FluencyModel.js +19 -0
  88. package/dist/module/features/fluency/model/FluencyModel.js.map +1 -0
  89. package/dist/module/features/fluency/model/fluency.instance.js +7 -0
  90. package/dist/module/features/fluency/model/fluency.instance.js.map +1 -0
  91. package/dist/module/index.js +1 -0
  92. package/dist/module/index.js.map +1 -1
  93. package/dist/typescript/commonjs/features/fluency/__tests__/FluencyModel.test.d.ts +2 -0
  94. package/dist/typescript/commonjs/features/fluency/__tests__/FluencyModel.test.d.ts.map +1 -0
  95. package/dist/typescript/commonjs/features/fluency/components/Fluency.d.ts +8 -0
  96. package/dist/typescript/commonjs/features/fluency/components/Fluency.d.ts.map +1 -0
  97. package/dist/typescript/commonjs/features/fluency/components/day-streak-counter/DayStreak.d.ts +11 -0
  98. package/dist/typescript/commonjs/features/fluency/components/day-streak-counter/DayStreak.d.ts.map +1 -0
  99. package/dist/typescript/commonjs/features/fluency/components/day-streak-counter/DayStreakCounter.d.ts +5 -0
  100. package/dist/typescript/commonjs/features/fluency/components/day-streak-counter/DayStreakCounter.d.ts.map +1 -0
  101. package/dist/typescript/commonjs/features/fluency/components/matrix/FluencyMatrix.d.ts +5 -0
  102. package/dist/typescript/commonjs/features/fluency/components/matrix/FluencyMatrix.d.ts.map +1 -0
  103. package/dist/typescript/commonjs/features/fluency/components/matrix/components/MatrixFill.d.ts +5 -0
  104. package/dist/typescript/commonjs/features/fluency/components/matrix/components/MatrixFill.d.ts.map +1 -0
  105. package/dist/typescript/commonjs/features/fluency/components/matrix/components/MatrixLegend.d.ts +5 -0
  106. package/dist/typescript/commonjs/features/fluency/components/matrix/components/MatrixLegend.d.ts.map +1 -0
  107. package/dist/typescript/commonjs/features/fluency/components/select-math-operator/MathOperatorRow.d.ts +13 -0
  108. package/dist/typescript/commonjs/features/fluency/components/select-math-operator/MathOperatorRow.d.ts.map +1 -0
  109. package/dist/typescript/commonjs/features/fluency/components/select-math-operator/ProgressBar.d.ts +8 -0
  110. package/dist/typescript/commonjs/features/fluency/components/select-math-operator/ProgressBar.d.ts.map +1 -0
  111. package/dist/typescript/commonjs/features/fluency/components/select-math-operator/SelectMathOperator.d.ts +5 -0
  112. package/dist/typescript/commonjs/features/fluency/components/select-math-operator/SelectMathOperator.d.ts.map +1 -0
  113. package/dist/typescript/commonjs/features/fluency/components/start-banner/BannerFlashcards.d.ts +11 -0
  114. package/dist/typescript/commonjs/features/fluency/components/start-banner/BannerFlashcards.d.ts.map +1 -0
  115. package/dist/typescript/commonjs/features/fluency/components/start-banner/MathFlashcard.d.ts +28 -0
  116. package/dist/typescript/commonjs/features/fluency/components/start-banner/MathFlashcard.d.ts.map +1 -0
  117. package/dist/typescript/commonjs/features/fluency/components/start-banner/StartBanner.d.ts +5 -0
  118. package/dist/typescript/commonjs/features/fluency/components/start-banner/StartBanner.d.ts.map +1 -0
  119. package/dist/typescript/commonjs/features/fluency/fluency.constants.d.ts +24 -0
  120. package/dist/typescript/commonjs/features/fluency/fluency.constants.d.ts.map +1 -0
  121. package/dist/typescript/commonjs/features/fluency/fluency.helpers.d.ts +2 -0
  122. package/dist/typescript/commonjs/features/fluency/fluency.helpers.d.ts.map +1 -0
  123. package/dist/typescript/commonjs/features/fluency/fluency.types.d.ts +2 -0
  124. package/dist/typescript/commonjs/features/fluency/fluency.types.d.ts.map +1 -0
  125. package/dist/typescript/commonjs/features/fluency/hooks/useFluencyModeUIPreset.d.ts +3 -0
  126. package/dist/typescript/commonjs/features/fluency/hooks/useFluencyModeUIPreset.d.ts.map +1 -0
  127. package/dist/typescript/commonjs/features/fluency/index.d.ts +6 -0
  128. package/dist/typescript/commonjs/features/fluency/index.d.ts.map +1 -0
  129. package/dist/typescript/commonjs/features/fluency/model/FluencyApiModel.d.ts +6 -0
  130. package/dist/typescript/commonjs/features/fluency/model/FluencyApiModel.d.ts.map +1 -0
  131. package/dist/typescript/commonjs/features/fluency/model/FluencyDaysStreakModel.d.ts +3 -0
  132. package/dist/typescript/commonjs/features/fluency/model/FluencyDaysStreakModel.d.ts.map +1 -0
  133. package/dist/typescript/commonjs/features/fluency/model/FluencyMatrixModel.d.ts +3 -0
  134. package/dist/typescript/commonjs/features/fluency/model/FluencyMatrixModel.d.ts.map +1 -0
  135. package/dist/typescript/commonjs/features/fluency/model/FluencyModel.d.ts +17 -0
  136. package/dist/typescript/commonjs/features/fluency/model/FluencyModel.d.ts.map +1 -0
  137. package/dist/typescript/commonjs/features/fluency/model/fluency.instance.d.ts +3 -0
  138. package/dist/typescript/commonjs/features/fluency/model/fluency.instance.d.ts.map +1 -0
  139. package/dist/typescript/commonjs/index.d.ts +1 -0
  140. package/dist/typescript/commonjs/index.d.ts.map +1 -1
  141. package/dist/typescript/module/features/fluency/__tests__/FluencyModel.test.d.ts +2 -0
  142. package/dist/typescript/module/features/fluency/__tests__/FluencyModel.test.d.ts.map +1 -0
  143. package/dist/typescript/module/features/fluency/components/Fluency.d.ts +8 -0
  144. package/dist/typescript/module/features/fluency/components/Fluency.d.ts.map +1 -0
  145. package/dist/typescript/module/features/fluency/components/day-streak-counter/DayStreak.d.ts +11 -0
  146. package/dist/typescript/module/features/fluency/components/day-streak-counter/DayStreak.d.ts.map +1 -0
  147. package/dist/typescript/module/features/fluency/components/day-streak-counter/DayStreakCounter.d.ts +5 -0
  148. package/dist/typescript/module/features/fluency/components/day-streak-counter/DayStreakCounter.d.ts.map +1 -0
  149. package/dist/typescript/module/features/fluency/components/matrix/FluencyMatrix.d.ts +5 -0
  150. package/dist/typescript/module/features/fluency/components/matrix/FluencyMatrix.d.ts.map +1 -0
  151. package/dist/typescript/module/features/fluency/components/matrix/components/MatrixFill.d.ts +5 -0
  152. package/dist/typescript/module/features/fluency/components/matrix/components/MatrixFill.d.ts.map +1 -0
  153. package/dist/typescript/module/features/fluency/components/matrix/components/MatrixLegend.d.ts +5 -0
  154. package/dist/typescript/module/features/fluency/components/matrix/components/MatrixLegend.d.ts.map +1 -0
  155. package/dist/typescript/module/features/fluency/components/select-math-operator/MathOperatorRow.d.ts +13 -0
  156. package/dist/typescript/module/features/fluency/components/select-math-operator/MathOperatorRow.d.ts.map +1 -0
  157. package/dist/typescript/module/features/fluency/components/select-math-operator/ProgressBar.d.ts +8 -0
  158. package/dist/typescript/module/features/fluency/components/select-math-operator/ProgressBar.d.ts.map +1 -0
  159. package/dist/typescript/module/features/fluency/components/select-math-operator/SelectMathOperator.d.ts +5 -0
  160. package/dist/typescript/module/features/fluency/components/select-math-operator/SelectMathOperator.d.ts.map +1 -0
  161. package/dist/typescript/module/features/fluency/components/start-banner/BannerFlashcards.d.ts +11 -0
  162. package/dist/typescript/module/features/fluency/components/start-banner/BannerFlashcards.d.ts.map +1 -0
  163. package/dist/typescript/module/features/fluency/components/start-banner/MathFlashcard.d.ts +28 -0
  164. package/dist/typescript/module/features/fluency/components/start-banner/MathFlashcard.d.ts.map +1 -0
  165. package/dist/typescript/module/features/fluency/components/start-banner/StartBanner.d.ts +5 -0
  166. package/dist/typescript/module/features/fluency/components/start-banner/StartBanner.d.ts.map +1 -0
  167. package/dist/typescript/module/features/fluency/fluency.constants.d.ts +24 -0
  168. package/dist/typescript/module/features/fluency/fluency.constants.d.ts.map +1 -0
  169. package/dist/typescript/module/features/fluency/fluency.helpers.d.ts +2 -0
  170. package/dist/typescript/module/features/fluency/fluency.helpers.d.ts.map +1 -0
  171. package/dist/typescript/module/features/fluency/fluency.types.d.ts +2 -0
  172. package/dist/typescript/module/features/fluency/fluency.types.d.ts.map +1 -0
  173. package/dist/typescript/module/features/fluency/hooks/useFluencyModeUIPreset.d.ts +3 -0
  174. package/dist/typescript/module/features/fluency/hooks/useFluencyModeUIPreset.d.ts.map +1 -0
  175. package/dist/typescript/module/features/fluency/index.d.ts +6 -0
  176. package/dist/typescript/module/features/fluency/index.d.ts.map +1 -0
  177. package/dist/typescript/module/features/fluency/model/FluencyApiModel.d.ts +6 -0
  178. package/dist/typescript/module/features/fluency/model/FluencyApiModel.d.ts.map +1 -0
  179. package/dist/typescript/module/features/fluency/model/FluencyDaysStreakModel.d.ts +3 -0
  180. package/dist/typescript/module/features/fluency/model/FluencyDaysStreakModel.d.ts.map +1 -0
  181. package/dist/typescript/module/features/fluency/model/FluencyMatrixModel.d.ts +3 -0
  182. package/dist/typescript/module/features/fluency/model/FluencyMatrixModel.d.ts.map +1 -0
  183. package/dist/typescript/module/features/fluency/model/FluencyModel.d.ts +17 -0
  184. package/dist/typescript/module/features/fluency/model/FluencyModel.d.ts.map +1 -0
  185. package/dist/typescript/module/features/fluency/model/fluency.instance.d.ts +3 -0
  186. package/dist/typescript/module/features/fluency/model/fluency.instance.d.ts.map +1 -0
  187. package/dist/typescript/module/index.d.ts +1 -0
  188. package/dist/typescript/module/index.d.ts.map +1 -1
  189. package/package.json +1 -1
  190. package/src/features/fluency/__tests__/FluencyModel.test.ts +28 -0
  191. package/src/features/fluency/components/Fluency.tsx +59 -0
  192. package/src/features/fluency/components/day-streak-counter/DayStreak.tsx +82 -0
  193. package/src/features/fluency/components/day-streak-counter/DayStreakCounter.tsx +51 -0
  194. package/src/features/fluency/components/matrix/FluencyMatrix.tsx +30 -0
  195. package/src/features/fluency/components/matrix/components/MatrixFill.tsx +86 -0
  196. package/src/features/fluency/components/matrix/components/MatrixLegend.tsx +112 -0
  197. package/src/features/fluency/components/select-math-operator/MathOperatorRow.tsx +38 -0
  198. package/src/features/fluency/components/select-math-operator/ProgressBar.tsx +127 -0
  199. package/src/features/fluency/components/select-math-operator/SelectMathOperator.tsx +90 -0
  200. package/src/features/fluency/components/start-banner/BannerFlashcards.tsx +45 -0
  201. package/src/features/fluency/components/start-banner/MathFlashcard.tsx +69 -0
  202. package/src/features/fluency/components/start-banner/StartBanner.tsx +92 -0
  203. package/src/features/fluency/fluency.constants.ts +75 -0
  204. package/src/features/fluency/fluency.helpers.ts +1 -0
  205. package/src/features/fluency/fluency.types.ts +1 -0
  206. package/src/features/fluency/hooks/useFluencyModeUIPreset.ts +8 -0
  207. package/src/features/fluency/index.ts +5 -0
  208. package/src/features/fluency/model/FluencyApiModel.ts +5 -0
  209. package/src/features/fluency/model/FluencyDaysStreakModel.ts +1 -0
  210. package/src/features/fluency/model/FluencyMatrixModel.ts +1 -0
  211. package/src/features/fluency/model/FluencyModel.ts +24 -0
  212. package/src/features/fluency/model/fluency.instance.ts +3 -0
  213. package/src/index.ts +1 -0
@@ -0,0 +1,112 @@
1
+ import React from 'react'
2
+ import { View, Text, StyleSheet } from 'react-native'
3
+ import {
4
+ BORDER_RADIUS,
5
+ Button,
6
+ ButtonSize,
7
+ ButtonVariant,
8
+ COLORS,
9
+ PlayIcon,
10
+ SPACING,
11
+ } from '@magmamath/react-native-ui'
12
+ import { useFluencyModeUIPreset } from '../../../hooks/useFluencyModeUIPreset'
13
+
14
+ const LEGEND_DOT_SIZE = 14
15
+ const LEGEND_DOT_BORDER_RADIUS = 3
16
+ const LEGEND_LABEL_FONT_SIZE = 12
17
+
18
+ type LegendItem = {
19
+ label: string
20
+ color: string
21
+ withBorder?: boolean
22
+ }
23
+
24
+ type MatrixLegendProps = {}
25
+
26
+ export const MatrixLegend = ({}: MatrixLegendProps) => {
27
+ const { mastery, buttonColor, operatorName } = useFluencyModeUIPreset()
28
+
29
+ const legendItems: LegendItem[] = [
30
+ { label: 'Not started', color: COLORS.NEUTRAL_2, withBorder: true },
31
+ { label: 'Learning', color: mastery.learning },
32
+ { label: 'Growing', color: mastery.growing },
33
+ { label: 'Strong', color: mastery.strong },
34
+ { label: 'Mastered', color: mastery.mastered },
35
+ ]
36
+
37
+ return (
38
+ <View style={styles.container}>
39
+ <View style={styles.legendItems}>
40
+ {legendItems.map((item) => (
41
+ <View key={item.label} style={styles.legendItem}>
42
+ <View
43
+ style={[
44
+ styles.legendDot,
45
+ { backgroundColor: item.color },
46
+ item.withBorder && styles.legendDotBorder,
47
+ ]}
48
+ />
49
+ <Text style={styles.legendLabel}>{item.label}</Text>
50
+ </View>
51
+ ))}
52
+ </View>
53
+ <Button
54
+ // TODO: Wire to the practice action when the model gains a startPractice event.
55
+ onPress={() => {}}
56
+ variant={ButtonVariant.PRIMARY}
57
+ size={ButtonSize.MEDIUM}
58
+ colorScheme={buttonColor}
59
+ icon={<PlayIcon color={COLORS.NEUTRAL_1} />}
60
+ raiseLevel={3}
61
+ style={{ container: styles.practiceButton, text: styles.practiceButtonText }}
62
+ >
63
+ {`Practice ${operatorName}`}
64
+ </Button>
65
+ </View>
66
+ )
67
+ }
68
+
69
+ const styles = StyleSheet.create({
70
+ container: {
71
+ height: 65,
72
+ flexDirection: 'row',
73
+ alignItems: 'flex-end',
74
+ justifyContent: 'space-between',
75
+ backgroundColor: COLORS.NEUTRAL_2,
76
+ borderBottomWidth: 1,
77
+ borderBottomColor: COLORS.NEUTRAL_5,
78
+ paddingHorizontal: SPACING[300],
79
+ paddingVertical: SPACING[300],
80
+ borderTopLeftRadius: BORDER_RADIUS[400],
81
+ borderTopRightRadius: BORDER_RADIUS[400],
82
+ },
83
+ legendItems: {
84
+ flexDirection: 'row',
85
+ alignItems: 'center',
86
+ gap: SPACING[400],
87
+ },
88
+ legendItem: {
89
+ flexDirection: 'row',
90
+ alignItems: 'center',
91
+ gap: SPACING[150],
92
+ },
93
+ legendDot: {
94
+ width: LEGEND_DOT_SIZE,
95
+ height: LEGEND_DOT_SIZE,
96
+ borderRadius: LEGEND_DOT_BORDER_RADIUS,
97
+ },
98
+ legendDotBorder: {
99
+ borderWidth: 0.5,
100
+ borderColor: COLORS.NEUTRAL_5,
101
+ },
102
+ legendLabel: {
103
+ fontSize: LEGEND_LABEL_FONT_SIZE,
104
+ color: COLORS.NEUTRAL_7,
105
+ },
106
+ practiceButton: {
107
+ alignSelf: 'center',
108
+ },
109
+ practiceButtonText: {
110
+ textTransform: 'uppercase',
111
+ },
112
+ })
@@ -0,0 +1,38 @@
1
+ import React, { ReactNode } from 'react'
2
+ import { StyleSheet, View } from 'react-native'
3
+ import { COLORS, SelectOption, SelectOptionColor, SPACING } from '@magmamath/react-native-ui'
4
+ import { ProgressBar } from './ProgressBar'
5
+
6
+ export type MathOperatorRowProps = {
7
+ title: string
8
+ icon: ReactNode
9
+ progress: number
10
+ color: SelectOptionColor
11
+ selected: boolean
12
+ onSelect: () => void
13
+ showDivider?: boolean
14
+ }
15
+
16
+ export const MathOperatorRow = ({
17
+ title,
18
+ icon,
19
+ progress,
20
+ color,
21
+ selected,
22
+ onSelect,
23
+ showDivider = true,
24
+ }: MathOperatorRowProps) => (
25
+ <View>
26
+ <SelectOption title={title} icon={icon} color={color} selected={selected} onPress={onSelect} />
27
+ <ProgressBar progress={progress} color={color} />
28
+ {showDivider && <View style={styles.divider} />}
29
+ </View>
30
+ )
31
+
32
+ const styles = StyleSheet.create({
33
+ divider: {
34
+ height: 1,
35
+ backgroundColor: COLORS.NEUTRAL_3,
36
+ marginVertical: SPACING[600],
37
+ },
38
+ })
@@ -0,0 +1,127 @@
1
+ import React from 'react'
2
+ import { StyleSheet, View } from 'react-native'
3
+ import {
4
+ BORDER_RADIUS,
5
+ COLORS,
6
+ HeadingVariants,
7
+ SelectOptionColor,
8
+ SPACING,
9
+ Typography,
10
+ } from '@magmamath/react-native-ui'
11
+
12
+ type ProgressShades = {
13
+ low: string
14
+ medium: string
15
+ high: string
16
+ max: string
17
+ }
18
+
19
+ const PROGRESS_COLOR_SHADES: Record<SelectOptionColor, ProgressShades> = {
20
+ [SelectOptionColor.GREEN]: {
21
+ low: COLORS.GREEN_2,
22
+ medium: COLORS.GREEN_3,
23
+ high: COLORS.GREEN_6,
24
+ max: COLORS.GREEN_7,
25
+ },
26
+ [SelectOptionColor.ORANGE]: {
27
+ low: COLORS.ORANGE_2,
28
+ medium: COLORS.ORANGE_3,
29
+ high: COLORS.ORANGE_6,
30
+ max: COLORS.ORANGE_7,
31
+ },
32
+ [SelectOptionColor.BLUE]: {
33
+ low: COLORS.BLUE_2,
34
+ medium: COLORS.BLUE_3,
35
+ high: COLORS.BLUE_6,
36
+ max: COLORS.BLUE_7,
37
+ },
38
+ [SelectOptionColor.RED]: {
39
+ low: COLORS.RED_2,
40
+ medium: COLORS.RED_3,
41
+ high: COLORS.RED_6,
42
+ max: COLORS.RED_7,
43
+ },
44
+ [SelectOptionColor.YELLOW]: {
45
+ low: COLORS.YELLOW_2,
46
+ medium: COLORS.YELLOW_3,
47
+ high: COLORS.YELLOW_6,
48
+ max: COLORS.YELLOW_7,
49
+ },
50
+ [SelectOptionColor.PURPLE]: {
51
+ low: COLORS.PURPLE_2,
52
+ medium: COLORS.PURPLE_3,
53
+ high: COLORS.PURPLE_6,
54
+ max: COLORS.PURPLE_7,
55
+ },
56
+ [SelectOptionColor.GREY]: {
57
+ low: COLORS.NEUTRAL_2,
58
+ medium: COLORS.NEUTRAL_3,
59
+ high: COLORS.NEUTRAL_6,
60
+ max: COLORS.NEUTRAL_7,
61
+ },
62
+ [SelectOptionColor.SUNSET]: {
63
+ low: COLORS.RED_2,
64
+ medium: COLORS.RED_3,
65
+ high: COLORS.RED_6,
66
+ max: COLORS.RED_7,
67
+ },
68
+ }
69
+
70
+ const PRIMARY_COLOR_MAP: Record<SelectOptionColor, string> = {
71
+ [SelectOptionColor.GREEN]: COLORS.PRIMARY_GREEN,
72
+ [SelectOptionColor.ORANGE]: COLORS.PRIMARY_ORANGE,
73
+ [SelectOptionColor.BLUE]: COLORS.PRIMARY_BLUE,
74
+ [SelectOptionColor.RED]: COLORS.PRIMARY_RED,
75
+ [SelectOptionColor.YELLOW]: COLORS.PRIMARY_YELLOW,
76
+ [SelectOptionColor.PURPLE]: COLORS.PRIMARY_PURPLE,
77
+ [SelectOptionColor.GREY]: COLORS.NEUTRAL_6,
78
+ [SelectOptionColor.SUNSET]: COLORS.PRIMARY_RED,
79
+ }
80
+
81
+ const getFillColor = (shades: ProgressShades, progress: number): string => {
82
+ if (progress <= 10) return shades.low
83
+ if (progress <= 20) return shades.medium
84
+ if (progress <= 80) return shades.high
85
+ return shades.max
86
+ }
87
+
88
+ export type ProgressBarProps = {
89
+ progress: number
90
+ color: SelectOptionColor
91
+ }
92
+
93
+ export const ProgressBar = ({ progress, color = SelectOptionColor.GREEN }: ProgressBarProps) => {
94
+ const normalized = Math.round(Math.min(100, Math.max(0, progress)))
95
+ const fillColor = getFillColor(PROGRESS_COLOR_SHADES[color], normalized)
96
+ const textColor = PRIMARY_COLOR_MAP[color]
97
+ return (
98
+ <View style={styles.container}>
99
+ <View style={styles.track}>
100
+ <View style={[styles.fill, { backgroundColor: fillColor, width: `${normalized}%` }]} />
101
+ </View>
102
+ <Typography variant={HeadingVariants.H10} style={{ color: textColor }}>
103
+ {normalized}%
104
+ </Typography>
105
+ </View>
106
+ )
107
+ }
108
+
109
+ const styles = StyleSheet.create({
110
+ container: {
111
+ flexDirection: 'row',
112
+ marginTop: SPACING[200],
113
+ gap: SPACING[200],
114
+ alignItems: 'center',
115
+ },
116
+ track: {
117
+ flex: 1,
118
+ height: 18,
119
+ backgroundColor: COLORS.NEUTRAL_3,
120
+ borderRadius: BORDER_RADIUS[450],
121
+ overflow: 'hidden',
122
+ },
123
+ fill: {
124
+ height: '100%',
125
+ borderRadius: BORDER_RADIUS[450],
126
+ },
127
+ })
@@ -0,0 +1,90 @@
1
+ import React from 'react'
2
+ import { StyleSheet, View } from 'react-native'
3
+ import {
4
+ BORDER_RADIUS,
5
+ COLORS,
6
+ CrossIcon,
7
+ MinusIcon,
8
+ PlusIcon,
9
+ SelectOptionColor,
10
+ SHADOWS,
11
+ SPACING,
12
+ } from '@magmamath/react-native-ui'
13
+ import { useUnit } from 'effector-react'
14
+ import { FluencyMode } from '../../fluency.constants'
15
+ import { fluencyModel } from '../../model/fluency.instance'
16
+ import { MathOperatorRow } from './MathOperatorRow'
17
+
18
+ type OperatorConfig = {
19
+ mode: FluencyMode
20
+ title: string
21
+ Icon: React.ComponentType<{ color?: string }>
22
+ color: SelectOptionColor
23
+ progress: number
24
+ }
25
+
26
+ const OPERATOR_CONFIG: OperatorConfig[] = [
27
+ {
28
+ mode: FluencyMode.ADDITION,
29
+ title: 'Addition',
30
+ Icon: PlusIcon,
31
+ color: SelectOptionColor.GREEN,
32
+ progress: 72,
33
+ },
34
+ {
35
+ mode: FluencyMode.SUBTRACTION,
36
+ title: 'Subtraction',
37
+ Icon: MinusIcon,
38
+ color: SelectOptionColor.ORANGE,
39
+ progress: 45,
40
+ },
41
+ {
42
+ mode: FluencyMode.MULTIPLICATION,
43
+ title: 'Multiplication',
44
+ Icon: CrossIcon,
45
+ color: SelectOptionColor.BLUE,
46
+ progress: 18,
47
+ },
48
+ // TODO: Replace with DivisionIcon once added to rn-ui — division needs its own symbol (÷).
49
+ {
50
+ mode: FluencyMode.DIVISION,
51
+ title: 'Division',
52
+ Icon: MinusIcon,
53
+ color: SelectOptionColor.PURPLE,
54
+ progress: 33,
55
+ },
56
+ ]
57
+
58
+ type SelectMathOperatorProps = {}
59
+
60
+ export const SelectMathOperator = ({}: SelectMathOperatorProps) => {
61
+ const { mode } = useUnit({ mode: fluencyModel.$mode })
62
+
63
+ return (
64
+ <View style={styles.container}>
65
+ {OPERATOR_CONFIG.map((op, index) => (
66
+ <MathOperatorRow
67
+ key={op.mode}
68
+ title={op.title}
69
+ icon={<op.Icon color={mode === op.mode ? COLORS.NEUTRAL_1 : undefined} />}
70
+ progress={op.progress}
71
+ color={op.color}
72
+ selected={mode === op.mode}
73
+ onSelect={() => fluencyModel.setMode(op.mode)}
74
+ showDivider={index < OPERATOR_CONFIG.length - 1}
75
+ />
76
+ ))}
77
+ </View>
78
+ )
79
+ }
80
+
81
+ const styles = StyleSheet.create({
82
+ container: {
83
+ width: 270,
84
+ paddingVertical: SPACING[400],
85
+ paddingHorizontal: SPACING[200],
86
+ borderRadius: BORDER_RADIUS[400],
87
+ backgroundColor: COLORS.NEUTRAL_1,
88
+ ...SHADOWS[1],
89
+ },
90
+ })
@@ -0,0 +1,45 @@
1
+ import React from 'react'
2
+ import { MathFlashcard, FlashcardLayout } from './MathFlashcard'
3
+
4
+ export type FlashcardExample = {
5
+ left: string
6
+ right: string
7
+ }
8
+
9
+ const CARD_LAYOUTS: FlashcardLayout[] = [
10
+ {
11
+ card: { width: 146, height: 88, radius: 6 },
12
+ answer: { width: 20, height: 29, radius: 4 },
13
+ fontSize: 26,
14
+ position: { right: 283, top: 31, zIndex: 1 },
15
+ rotation: '21.3deg',
16
+ },
17
+ {
18
+ card: { width: 195, height: 118, radius: 9 },
19
+ answer: { width: 27, height: 38, radius: 6 },
20
+ fontSize: 35,
21
+ position: { right: 148, top: -6, zIndex: 2 },
22
+ rotation: '-15.43deg',
23
+ },
24
+ {
25
+ card: { width: 260, height: 157, radius: 12 },
26
+ answer: { width: 36, height: 51, radius: 8 },
27
+ fontSize: 46,
28
+ position: { right: 0, top: -11, zIndex: 3 },
29
+ rotation: '8.83deg',
30
+ },
31
+ ]
32
+
33
+ type BannerFlashcardsProps = {
34
+ examples: FlashcardExample[]
35
+ }
36
+
37
+ export const BannerFlashcards = ({ examples }: BannerFlashcardsProps) => (
38
+ <>
39
+ {CARD_LAYOUTS.map((layout, index) => {
40
+ const example = examples[index]
41
+ if (!example) return null
42
+ return <MathFlashcard key={index} left={example.left} right={example.right} layout={layout} />
43
+ })}
44
+ </>
45
+ )
@@ -0,0 +1,69 @@
1
+ import React from 'react'
2
+ import { View, Text, StyleSheet } from 'react-native'
3
+ import { COLORS, SHADOWS } from '@magmamath/react-native-ui'
4
+
5
+ export type FlashcardLayout = {
6
+ card: { width: number; height: number; radius: number }
7
+ answer: { width: number; height: number; radius: number }
8
+ fontSize: number
9
+ position: { right: number; top: number; zIndex: number }
10
+ rotation: string
11
+ }
12
+
13
+ type MathFlashcardProps = {
14
+ left: string
15
+ right: string
16
+ layout: FlashcardLayout
17
+ }
18
+
19
+ export const MathFlashcard = ({ left, right, layout }: MathFlashcardProps) => (
20
+ <View
21
+ style={[
22
+ styles.card,
23
+ {
24
+ width: layout.card.width,
25
+ height: layout.card.height,
26
+ borderRadius: layout.card.radius,
27
+ right: layout.position.right,
28
+ top: layout.position.top,
29
+ zIndex: layout.position.zIndex,
30
+ transform: [{ rotate: layout.rotation }],
31
+ },
32
+ ]}
33
+ >
34
+ <View style={styles.row}>
35
+ <Text style={[styles.text, { fontSize: layout.fontSize }]}>{left}</Text>
36
+ <View
37
+ style={[
38
+ styles.answerBox,
39
+ { width: layout.answer.width, height: layout.answer.height, borderRadius: layout.answer.radius },
40
+ ]}
41
+ />
42
+ <Text style={[styles.text, { fontSize: layout.fontSize }]}>{right}</Text>
43
+ </View>
44
+ </View>
45
+ )
46
+
47
+ const styles = StyleSheet.create({
48
+ card: {
49
+ position: 'absolute',
50
+ backgroundColor: COLORS.NEUTRAL_1,
51
+ alignItems: 'center',
52
+ justifyContent: 'center',
53
+ ...SHADOWS[1],
54
+ },
55
+ row: {
56
+ flexDirection: 'row',
57
+ alignItems: 'center',
58
+ gap: 1,
59
+ },
60
+ text: {
61
+ fontWeight: 'bold',
62
+ color: COLORS.BLACK,
63
+ },
64
+ answerBox: {
65
+ backgroundColor: COLORS.NEUTRAL_2,
66
+ borderWidth: 1,
67
+ borderColor: COLORS.NEUTRAL_5,
68
+ },
69
+ })
@@ -0,0 +1,92 @@
1
+ import React from 'react'
2
+ import { View, StyleSheet } from 'react-native'
3
+ import {
4
+ BORDER_RADIUS,
5
+ Button,
6
+ ButtonSize,
7
+ ButtonVariant,
8
+ COLORS,
9
+ PlayIcon,
10
+ SHADOWS,
11
+ SPACING,
12
+ Typography,
13
+ } from '@magmamath/react-native-ui'
14
+ import { BannerFlashcards } from './BannerFlashcards'
15
+ import { useFluencyModeUIPreset } from '../../hooks/useFluencyModeUIPreset'
16
+
17
+ type StartBannerProps = {}
18
+
19
+ export const StartBanner = ({}: StartBannerProps) => {
20
+ const { buttonColor } = useFluencyModeUIPreset()
21
+
22
+ return (
23
+ <View style={styles.container}>
24
+ <View style={styles.buttonContainer}>
25
+ <View style={styles.buttonGroup}>
26
+ <Button
27
+ onPress={() => {}}
28
+ disabled={false}
29
+ isLoading={false}
30
+ isActive={false}
31
+ icon={<PlayIcon color={COLORS.NEUTRAL_1} />}
32
+ variant={ButtonVariant.PRIMARY}
33
+ size={ButtonSize.LARGE}
34
+ colorScheme={buttonColor}
35
+ raiseLevel={6}
36
+ style={{ container: styles.button }}
37
+ >
38
+ Start fluency practice
39
+ </Button>
40
+ <Typography style={styles.buttonSubtitle}>20 individualized ready</Typography>
41
+ </View>
42
+ </View>
43
+
44
+ <BannerFlashcards
45
+ examples={[
46
+ { left: '15*', right: '=30' },
47
+ { left: '10-', right: '=25' },
48
+ { left: '5+', right: '=19' },
49
+ ]}
50
+ />
51
+ </View>
52
+ )
53
+ }
54
+
55
+ const styles = StyleSheet.create({
56
+ container: {
57
+ flex: 1,
58
+ height: '100%',
59
+ justifyContent: 'center',
60
+ paddingVertical: SPACING[400],
61
+ paddingHorizontal: SPACING[800],
62
+ borderRadius: BORDER_RADIUS[400],
63
+ backgroundColor: COLORS.NEUTRAL_1,
64
+ ...SHADOWS[1],
65
+ },
66
+ buttonContainer: {
67
+ alignItems: 'flex-start',
68
+ zIndex: 4,
69
+ },
70
+ buttonGroup: {
71
+ alignItems: 'center',
72
+ gap: SPACING[200],
73
+ },
74
+ button: {
75
+ minWidth: 220,
76
+ maxWidth: 315,
77
+ textTransform: 'uppercase',
78
+ },
79
+ buttonSubtitle: {
80
+ fontSize: 12,
81
+ fontWeight: '700',
82
+ color: COLORS.BLACK,
83
+ textTransform: 'uppercase',
84
+ },
85
+ flashcard: {
86
+ position: 'absolute',
87
+ backgroundColor: COLORS.NEUTRAL_1,
88
+ alignItems: 'center',
89
+ justifyContent: 'center',
90
+ ...SHADOWS[1],
91
+ },
92
+ })
@@ -0,0 +1,75 @@
1
+ import { ButtonColor, COLORS } from '@magmamath/react-native-ui'
2
+
3
+ export enum FluencyMode {
4
+ ADDITION = 'ADDITION',
5
+ SUBTRACTION = 'SUBTRACTION',
6
+ MULTIPLICATION = 'MULTIPLICATION',
7
+ DIVISION = 'DIVISION',
8
+ }
9
+
10
+ export type FluencyModePreset = {
11
+ operatorName: string
12
+ mastery: {
13
+ learning: string
14
+ developing: string
15
+ growing: string
16
+ strong: string
17
+ mastered: string
18
+ }
19
+ buttonColor: ButtonColor
20
+ streakColor: {
21
+ gained: string
22
+ todayBorder: string
23
+ }
24
+ }
25
+
26
+ export const FLUENCY_MODE_PRESETS: Record<FluencyMode, FluencyModePreset> = {
27
+ [FluencyMode.ADDITION]: {
28
+ operatorName: 'Addition',
29
+ mastery: {
30
+ learning: COLORS.GREEN_2,
31
+ developing: COLORS.GREEN_3,
32
+ growing: COLORS.PRIMARY_GREEN,
33
+ strong: COLORS.GREEN_6,
34
+ mastered: COLORS.GREEN_7,
35
+ },
36
+ buttonColor: ButtonColor.GREEN,
37
+ streakColor: { gained: COLORS.PRIMARY_GREEN, todayBorder: COLORS.GREEN_6 },
38
+ },
39
+ [FluencyMode.SUBTRACTION]: {
40
+ operatorName: 'Subtraction',
41
+ mastery: {
42
+ learning: COLORS.ORANGE_2,
43
+ developing: COLORS.ORANGE_3,
44
+ growing: COLORS.PRIMARY_ORANGE,
45
+ strong: COLORS.ORANGE_6,
46
+ mastered: COLORS.ORANGE_7,
47
+ },
48
+ buttonColor: ButtonColor.ORANGE,
49
+ streakColor: { gained: COLORS.PRIMARY_ORANGE, todayBorder: COLORS.ORANGE_6 },
50
+ },
51
+ [FluencyMode.MULTIPLICATION]: {
52
+ operatorName: 'Multiplication',
53
+ mastery: {
54
+ learning: COLORS.BLUE_2,
55
+ developing: COLORS.BLUE_3,
56
+ growing: COLORS.PRIMARY_BLUE,
57
+ strong: COLORS.BLUE_6,
58
+ mastered: COLORS.BLUE_7,
59
+ },
60
+ buttonColor: ButtonColor.BLUE,
61
+ streakColor: { gained: COLORS.PRIMARY_BLUE, todayBorder: COLORS.BLUE_6 },
62
+ },
63
+ [FluencyMode.DIVISION]: {
64
+ operatorName: 'Division',
65
+ mastery: {
66
+ learning: COLORS.PURPLE_2,
67
+ developing: COLORS.PURPLE_3,
68
+ growing: COLORS.PRIMARY_PURPLE,
69
+ strong: COLORS.PURPLE_6,
70
+ mastered: COLORS.PURPLE_7,
71
+ },
72
+ buttonColor: ButtonColor.PURPLE,
73
+ streakColor: { gained: COLORS.PRIMARY_PURPLE, todayBorder: COLORS.PURPLE_6 },
74
+ },
75
+ }
@@ -0,0 +1 @@
1
+ export const getFluency = () => {}
@@ -0,0 +1 @@
1
+ export type Fluency = {}
@@ -0,0 +1,8 @@
1
+ import { useUnit } from 'effector-react'
2
+ import { FLUENCY_MODE_PRESETS, FluencyModePreset } from '../fluency.constants'
3
+ import { fluencyModel } from '../model/fluency.instance'
4
+
5
+ export const useFluencyModeUIPreset = (): FluencyModePreset => {
6
+ const mode = useUnit(fluencyModel.$mode)
7
+ return FLUENCY_MODE_PRESETS[mode]
8
+ }
@@ -0,0 +1,5 @@
1
+ export * from './fluency.constants'
2
+ export * from './fluency.types'
3
+ export * from './fluency.helpers'
4
+ export { Fluency } from './components/Fluency'
5
+ export { FluencyModel } from './model/FluencyModel'
@@ -0,0 +1,5 @@
1
+ type FluencyApiProps = {}
2
+
3
+ export class FluencyApiModel {
4
+ constructor({}: FluencyApiProps) {}
5
+ }
@@ -0,0 +1 @@
1
+ export class FluencyDaysStreakModel {}
@@ -0,0 +1 @@
1
+ export class FluencyMatrixModel {}