@khanacademy/math-input 0.3.2 → 0.5.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 (176) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/{build/math-input.css → dist/es/index.css} +0 -150
  4. package/dist/es/index.js +2 -0
  5. package/dist/es/index.js.map +1 -0
  6. package/dist/index.css +586 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +2 -0
  9. package/dist/index.js.flow +2 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/strings.js +71 -0
  12. package/index.html +20 -0
  13. package/less/echo.less +56 -0
  14. package/less/main.less +5 -0
  15. package/less/overrides.less +129 -0
  16. package/less/popover.less +22 -0
  17. package/less/tabbar.less +6 -0
  18. package/package.json +38 -70
  19. package/src/actions/index.js +57 -0
  20. package/src/components/__tests__/gesture-state-machine_test.js +437 -0
  21. package/src/components/__tests__/node-manager_test.js +89 -0
  22. package/src/components/__tests__/two-page-keypad_test.js +42 -0
  23. package/src/components/app.js +73 -0
  24. package/src/components/common-style.js +47 -0
  25. package/src/components/compute-layout-parameters.js +157 -0
  26. package/src/components/corner-decal.js +56 -0
  27. package/src/components/echo-manager.js +160 -0
  28. package/src/components/empty-keypad-button.js +49 -0
  29. package/src/components/expression-keypad.js +323 -0
  30. package/src/components/fraction-keypad.js +176 -0
  31. package/src/components/gesture-manager.js +226 -0
  32. package/src/components/gesture-state-machine.js +283 -0
  33. package/src/components/icon.js +74 -0
  34. package/src/components/iconography/arrow.js +22 -0
  35. package/src/components/iconography/backspace.js +29 -0
  36. package/src/components/iconography/cdot.js +29 -0
  37. package/src/components/iconography/cos.js +30 -0
  38. package/src/components/iconography/cube-root.js +36 -0
  39. package/src/components/iconography/dismiss.js +25 -0
  40. package/src/components/iconography/divide.js +34 -0
  41. package/src/components/iconography/down.js +16 -0
  42. package/src/components/iconography/equal.js +33 -0
  43. package/src/components/iconography/exp-2.js +29 -0
  44. package/src/components/iconography/exp-3.js +29 -0
  45. package/src/components/iconography/exp.js +29 -0
  46. package/src/components/iconography/frac.js +44 -0
  47. package/src/components/iconography/geq.js +33 -0
  48. package/src/components/iconography/gt.js +33 -0
  49. package/src/components/iconography/index.js +45 -0
  50. package/src/components/iconography/jump-into-numerator.js +41 -0
  51. package/src/components/iconography/jump-out-base.js +30 -0
  52. package/src/components/iconography/jump-out-denominator.js +41 -0
  53. package/src/components/iconography/jump-out-exponent.js +30 -0
  54. package/src/components/iconography/jump-out-numerator.js +41 -0
  55. package/src/components/iconography/jump-out-parentheses.js +33 -0
  56. package/src/components/iconography/left-paren.js +33 -0
  57. package/src/components/iconography/left.js +16 -0
  58. package/src/components/iconography/leq.js +33 -0
  59. package/src/components/iconography/ln.js +29 -0
  60. package/src/components/iconography/log-n.js +29 -0
  61. package/src/components/iconography/log.js +29 -0
  62. package/src/components/iconography/lt.js +33 -0
  63. package/src/components/iconography/minus.js +32 -0
  64. package/src/components/iconography/neq.js +33 -0
  65. package/src/components/iconography/parens.js +33 -0
  66. package/src/components/iconography/percent.js +49 -0
  67. package/src/components/iconography/period.js +26 -0
  68. package/src/components/iconography/plus.js +32 -0
  69. package/src/components/iconography/radical.js +36 -0
  70. package/src/components/iconography/right-paren.js +33 -0
  71. package/src/components/iconography/right.js +16 -0
  72. package/src/components/iconography/sin.js +30 -0
  73. package/src/components/iconography/sqrt.js +32 -0
  74. package/src/components/iconography/tan.js +30 -0
  75. package/src/components/iconography/times.js +33 -0
  76. package/src/components/iconography/up.js +16 -0
  77. package/src/components/input/__tests__/context-tracking_test.js +177 -0
  78. package/src/components/input/__tests__/math-wrapper.jsx +33 -0
  79. package/src/components/input/__tests__/mathquill_test.js +747 -0
  80. package/src/components/input/cursor-contexts.js +29 -0
  81. package/src/components/input/cursor-handle.js +137 -0
  82. package/src/components/input/drag-listener.js +75 -0
  83. package/src/components/input/math-input.js +924 -0
  84. package/src/components/input/math-wrapper.js +959 -0
  85. package/src/components/input/scroll-into-view.js +72 -0
  86. package/src/components/keypad/button-assets.js +492 -0
  87. package/src/components/keypad/button.js +106 -0
  88. package/src/components/keypad/button.stories.js +27 -0
  89. package/src/components/keypad/index.js +64 -0
  90. package/src/components/keypad/keypad-page-items.js +106 -0
  91. package/src/components/keypad/keypad-pages.stories.js +32 -0
  92. package/src/components/keypad/keypad.stories.js +35 -0
  93. package/src/components/keypad/numeric-input-page.js +100 -0
  94. package/src/components/keypad/pre-algebra-page.js +98 -0
  95. package/src/components/keypad/trigonometry-page.js +90 -0
  96. package/src/components/keypad-button.js +366 -0
  97. package/src/components/keypad-container.js +303 -0
  98. package/src/components/keypad.js +154 -0
  99. package/src/components/many-keypad-button.js +44 -0
  100. package/src/components/math-icon.js +65 -0
  101. package/src/components/multi-symbol-grid.js +182 -0
  102. package/src/components/multi-symbol-popover.js +59 -0
  103. package/src/components/navigation-pad.js +139 -0
  104. package/src/components/node-manager.js +129 -0
  105. package/src/components/popover-manager.js +76 -0
  106. package/src/components/popover-state-machine.js +173 -0
  107. package/src/components/prop-types.js +82 -0
  108. package/src/components/provided-keypad.js +99 -0
  109. package/src/components/styles.js +38 -0
  110. package/src/components/svg-icon.js +25 -0
  111. package/src/components/tabbar/__tests__/tabbar_test.js +65 -0
  112. package/src/components/tabbar/icons.js +69 -0
  113. package/src/components/tabbar/item.js +138 -0
  114. package/src/components/tabbar/tabbar.js +61 -0
  115. package/src/components/tabbar/tabbar.stories.js +60 -0
  116. package/src/components/tabbar/types.js +3 -0
  117. package/src/components/text-icon.js +52 -0
  118. package/src/components/touchable-keypad-button.js +146 -0
  119. package/src/components/two-page-keypad.js +99 -0
  120. package/src/components/velocity-tracker.js +76 -0
  121. package/src/components/z-indexes.js +9 -0
  122. package/src/consts.js +74 -0
  123. package/src/data/key-configs.js +349 -0
  124. package/src/data/keys.js +72 -0
  125. package/src/demo.js +8 -0
  126. package/src/fake-react-native-web/index.js +12 -0
  127. package/src/fake-react-native-web/text.js +56 -0
  128. package/src/fake-react-native-web/view.js +91 -0
  129. package/src/index.js +13 -0
  130. package/src/native-app.js +84 -0
  131. package/src/store/index.js +505 -0
  132. package/src/utils.js +18 -0
  133. package/tools/svg-to-react/convert.py +111 -0
  134. package/tools/svg-to-react/icons/math-keypad-icon-0.svg +32 -0
  135. package/tools/svg-to-react/icons/math-keypad-icon-1.svg +32 -0
  136. package/tools/svg-to-react/icons/math-keypad-icon-2.svg +32 -0
  137. package/tools/svg-to-react/icons/math-keypad-icon-3.svg +32 -0
  138. package/tools/svg-to-react/icons/math-keypad-icon-4.svg +32 -0
  139. package/tools/svg-to-react/icons/math-keypad-icon-5.svg +32 -0
  140. package/tools/svg-to-react/icons/math-keypad-icon-6.svg +32 -0
  141. package/tools/svg-to-react/icons/math-keypad-icon-7.svg +32 -0
  142. package/tools/svg-to-react/icons/math-keypad-icon-8.svg +32 -0
  143. package/tools/svg-to-react/icons/math-keypad-icon-9.svg +32 -0
  144. package/tools/svg-to-react/icons/math-keypad-icon-addition.svg +34 -0
  145. package/tools/svg-to-react/icons/math-keypad-icon-cos.svg +38 -0
  146. package/tools/svg-to-react/icons/math-keypad-icon-delete.svg +36 -0
  147. package/tools/svg-to-react/icons/math-keypad-icon-dismiss.svg +36 -0
  148. package/tools/svg-to-react/icons/math-keypad-icon-division.svg +36 -0
  149. package/tools/svg-to-react/icons/math-keypad-icon-equals-not.svg +50 -0
  150. package/tools/svg-to-react/icons/math-keypad-icon-equals.svg +48 -0
  151. package/tools/svg-to-react/icons/math-keypad-icon-exponent-2.svg +38 -0
  152. package/tools/svg-to-react/icons/math-keypad-icon-exponent-3.svg +38 -0
  153. package/tools/svg-to-react/icons/math-keypad-icon-exponent.svg +38 -0
  154. package/tools/svg-to-react/icons/math-keypad-icon-fraction.svg +42 -0
  155. package/tools/svg-to-react/icons/math-keypad-icon-greater-than.svg +46 -0
  156. package/tools/svg-to-react/icons/math-keypad-icon-jump-out-base.svg +44 -0
  157. package/tools/svg-to-react/icons/math-keypad-icon-jump-out-denominator.svg +48 -0
  158. package/tools/svg-to-react/icons/math-keypad-icon-jump-out-exponent.svg +44 -0
  159. package/tools/svg-to-react/icons/math-keypad-icon-jump-out-parentheses.svg +44 -0
  160. package/tools/svg-to-react/icons/math-keypad-icon-less-than.svg +46 -0
  161. package/tools/svg-to-react/icons/math-keypad-icon-log-10.svg +36 -0
  162. package/tools/svg-to-react/icons/math-keypad-icon-log-e.svg +36 -0
  163. package/tools/svg-to-react/icons/math-keypad-icon-log.svg +38 -0
  164. package/tools/svg-to-react/icons/math-keypad-icon-multiplication-cross.svg +40 -0
  165. package/tools/svg-to-react/icons/math-keypad-icon-multiplication-dot.svg +38 -0
  166. package/tools/svg-to-react/icons/math-keypad-icon-percent.svg +42 -0
  167. package/tools/svg-to-react/icons/math-keypad-icon-radical-2.svg +36 -0
  168. package/tools/svg-to-react/icons/math-keypad-icon-radical-3.svg +38 -0
  169. package/tools/svg-to-react/icons/math-keypad-icon-radical.svg +38 -0
  170. package/tools/svg-to-react/icons/math-keypad-icon-radix-character.svg +32 -0
  171. package/tools/svg-to-react/icons/math-keypad-icon-sin.svg +38 -0
  172. package/tools/svg-to-react/icons/math-keypad-icon-subtraction.svg +32 -0
  173. package/tools/svg-to-react/icons/math-keypad-icon-tan.svg +38 -0
  174. package/tools/svg-to-react/symbol_map.py +41 -0
  175. package/LICENSE.txt +0 -21
  176. package/build/math-input.js +0 -1
@@ -0,0 +1,177 @@
1
+ import Keys from "../../../data/keys.js";
2
+ import * as CursorContexts from "../cursor-contexts.js";
3
+
4
+ import MathWrapper from "./math-wrapper.jsx";
5
+
6
+ describe("Cursor context", () => {
7
+ let mathField;
8
+ let span;
9
+
10
+ beforeEach(() => {
11
+ span = document.createElement("span");
12
+ document.body.appendChild(span);
13
+
14
+ mathField = new MathWrapper(span);
15
+ });
16
+
17
+ afterEach(() => {
18
+ document.body.removeChild(span);
19
+ });
20
+
21
+ it("should treat number-only expressions as non-jumpable", () => {
22
+ mathField.pressKey("NUM_1");
23
+ mathField.pressKey("NUM_2");
24
+ const cursor = mathField.pressKey("NUM_3");
25
+ expect(cursor.context).toEqual(CursorContexts.NONE);
26
+ });
27
+
28
+ it("should treat numbers and ternary operators as non-jumpable", () => {
29
+ mathField.pressKey("NUM_1");
30
+ mathField.pressKey(Keys.CDOT);
31
+ const cursor = mathField.pressKey("NUM_2");
32
+ expect(cursor.context).toEqual(CursorContexts.NONE);
33
+ });
34
+
35
+ describe("Before fraction", () => {
36
+ it("should detect when immediately to the left", () => {
37
+ const cursor = mathField.pressKey(Keys.FRAC_EXCLUSIVE);
38
+ expect(cursor.context).toEqual(CursorContexts.BEFORE_FRACTION);
39
+ });
40
+
41
+ it("should detect when numbers are between", () => {
42
+ mathField.pressKey("NUM_1");
43
+ mathField.pressKey(Keys.FRAC_EXCLUSIVE);
44
+ mathField.pressKey(Keys.LEFT);
45
+ const cursor = mathField.pressKey(Keys.LEFT);
46
+ expect(cursor.context).toEqual(CursorContexts.BEFORE_FRACTION);
47
+ });
48
+
49
+ it("should not detect when operators are between", () => {
50
+ mathField.pressKey("NUM_1");
51
+ mathField.pressKey(Keys.PLUS);
52
+ mathField.pressKey("NUM_2");
53
+ mathField.pressKey(Keys.FRAC_EXCLUSIVE);
54
+ mathField.pressKey(Keys.LEFT);
55
+ mathField.pressKey(Keys.LEFT);
56
+ mathField.pressKey(Keys.LEFT);
57
+ const cursor = mathField.pressKey(Keys.LEFT);
58
+ expect(cursor.context).toEqual(CursorContexts.NONE);
59
+ });
60
+
61
+ it("should not detect when parens are between", () => {
62
+ mathField.pressKey("NUM_1");
63
+ mathField.pressKey(Keys.LEFT_PAREN);
64
+ mathField.pressKey(Keys.RIGHT_PAREN);
65
+ mathField.pressKey("NUM_2");
66
+ mathField.pressKey(Keys.FRAC_EXCLUSIVE);
67
+ mathField.pressKey(Keys.LEFT);
68
+ mathField.pressKey(Keys.LEFT);
69
+ mathField.pressKey(Keys.LEFT);
70
+ mathField.pressKey(Keys.LEFT);
71
+ const cursor = mathField.pressKey(Keys.LEFT);
72
+ expect(cursor.context).toEqual(CursorContexts.NONE);
73
+ });
74
+ });
75
+
76
+ describe("In parens", () => {
77
+ it("should detect when inside empty parens", () => {
78
+ mathField.pressKey(Keys.LEFT_PAREN);
79
+ mathField.pressKey(Keys.RIGHT_PAREN);
80
+ const cursor = mathField.pressKey(Keys.LEFT);
81
+ expect(cursor.context).toEqual(CursorContexts.IN_PARENS);
82
+ });
83
+
84
+ it("should detect when inside non-empty parens", () => {
85
+ mathField.pressKey(Keys.LEFT_PAREN);
86
+ mathField.pressKey("NUM_2");
87
+ mathField.pressKey(Keys.RIGHT_PAREN);
88
+ const cursor = mathField.pressKey(Keys.LEFT);
89
+ expect(cursor.context).toEqual(CursorContexts.IN_PARENS);
90
+ });
91
+ });
92
+
93
+ describe("In superscript", () => {
94
+ it("should detect when inside empty superscript", () => {
95
+ mathField.pressKey("NUM_2");
96
+ const cursor = mathField.pressKey(Keys.EXP);
97
+ expect(cursor.context).toEqual(CursorContexts.IN_SUPER_SCRIPT);
98
+ });
99
+
100
+ it("should detect when inside non-empty superscript", () => {
101
+ mathField.pressKey("NUM_2");
102
+ mathField.pressKey(Keys.EXP);
103
+ const cursor = mathField.pressKey("NUM_3");
104
+ expect(cursor.context).toEqual(CursorContexts.IN_SUPER_SCRIPT);
105
+ });
106
+ });
107
+
108
+ describe("In subscript", () => {
109
+ it("should detect when inside empty superscript", () => {
110
+ const cursor = mathField.pressKey(Keys.LOG_N);
111
+ expect(cursor.context).toEqual(CursorContexts.IN_SUB_SCRIPT);
112
+ });
113
+
114
+ it("should detect when inside non-empty superscript", () => {
115
+ mathField.pressKey(Keys.LOG_N);
116
+ const cursor = mathField.pressKey("NUM_2");
117
+ expect(cursor.context).toEqual(CursorContexts.IN_SUB_SCRIPT);
118
+ });
119
+ });
120
+
121
+ describe("In numerator", () => {
122
+ it("should detect when inside empty numerator", () => {
123
+ const cursor = mathField.pressKey(Keys.FRAC_INCLUSIVE);
124
+ expect(cursor.context).toEqual(CursorContexts.IN_NUMERATOR);
125
+ });
126
+
127
+ it("should detect when inside non-empty numerator", () => {
128
+ mathField.pressKey(Keys.FRAC_INCLUSIVE);
129
+ const cursor = mathField.pressKey("NUM_2");
130
+ expect(cursor.context).toEqual(CursorContexts.IN_NUMERATOR);
131
+ });
132
+ });
133
+
134
+ describe("In denominator", () => {
135
+ it("should detect when inside empty denominator", () => {
136
+ mathField.pressKey(Keys.FRAC_INCLUSIVE);
137
+ const cursor = mathField.pressKey(Keys.RIGHT);
138
+ expect(cursor.context).toEqual(CursorContexts.IN_DENOMINATOR);
139
+ });
140
+
141
+ it("should detect when inside non-empty denominator", () => {
142
+ mathField.pressKey(Keys.FRAC_INCLUSIVE);
143
+ mathField.pressKey(Keys.RIGHT);
144
+ const cursor = mathField.pressKey("NUM_2");
145
+ expect(cursor.context).toEqual(CursorContexts.IN_DENOMINATOR);
146
+ });
147
+ });
148
+
149
+ describe("Nesting", () => {
150
+ it("should defer to jumping into fraction if possible", () => {
151
+ // Move inside parens, but include a fraction.
152
+ mathField.pressKey(Keys.LEFT_PAREN);
153
+ mathField.pressKey("NUM_2");
154
+ mathField.pressKey(Keys.FRAC_EXCLUSIVE);
155
+ const cursor = mathField.pressKey(Keys.LEFT);
156
+ expect(cursor.context).toEqual(CursorContexts.BEFORE_FRACTION);
157
+ });
158
+
159
+ it("should defer to the nearest parent (1)", () => {
160
+ // Move inside parens, inside a superscript.
161
+ mathField.pressKey("NUM_2");
162
+ mathField.pressKey(Keys.EXP);
163
+ mathField.pressKey(Keys.LEFT_PAREN);
164
+ const cursor = mathField.pressKey("NUM_3");
165
+ expect(cursor.context).toEqual(CursorContexts.IN_PARENS);
166
+ });
167
+
168
+ it("should defer to the nearest parent (2)", () => {
169
+ // Nest fractions, and put cursor in the denominator of the fraction
170
+ // in the numerator.
171
+ mathField.pressKey(Keys.FRAC_INCLUSIVE);
172
+ mathField.pressKey(Keys.FRAC_INCLUSIVE);
173
+ const cursor = mathField.pressKey(Keys.RIGHT);
174
+ expect(cursor.context).toEqual(CursorContexts.IN_DENOMINATOR);
175
+ });
176
+ });
177
+ });
@@ -0,0 +1,33 @@
1
+ import MathQuill from "mathquill";
2
+
3
+ import MathWrapper from "../math-wrapper.js";
4
+
5
+ const MQ = MathQuill.getInterface(2);
6
+
7
+ export default class TestMathWrapper extends MathWrapper {
8
+ getContent() {
9
+ return this.mathField.latex();
10
+ }
11
+
12
+ selectAll() {
13
+ this.mathField.select();
14
+ }
15
+
16
+ clearSelection() {
17
+ this.mathField.clearSelection();
18
+ }
19
+
20
+ moveToStart() {
21
+ this.mathField.moveToDirEnd(MQ.L);
22
+ }
23
+
24
+ isSelected() {
25
+ const selection = this.getSelection();
26
+
27
+ if (selection) {
28
+ return selection.ends[-1][-1] === 0 && selection.ends[1][1] === 0;
29
+ }
30
+
31
+ return false;
32
+ }
33
+ }