@khanacademy/math-input 15.1.0 → 16.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 (145) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/components/aphrodite-css-transition-group/util.d.ts +2 -1
  3. package/dist/components/input/math-wrapper.d.ts +1 -1
  4. package/dist/components/keypad/index.d.ts +1 -1
  5. package/dist/components/keypad/mobile-keypad-internals.d.ts +49 -0
  6. package/dist/components/keypad/mobile-keypad.d.ts +4 -48
  7. package/dist/data/key-configs.d.ts +1 -1
  8. package/dist/es/index.js +171 -4744
  9. package/dist/es/index.js.map +1 -1
  10. package/dist/fake-react-native-web/view.d.ts +2 -1
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.js +168 -4722
  13. package/dist/index.js.map +1 -1
  14. package/package.json +2 -2
  15. package/src/components/__tests__/integration.test.tsx +2 -3
  16. package/src/components/input/math-input.tsx +1 -0
  17. package/src/components/input/math-wrapper.ts +2 -2
  18. package/src/components/keypad/__tests__/mobile-keypad.test.tsx +8 -8
  19. package/src/components/keypad/index.tsx +1 -1
  20. package/src/components/keypad/mobile-keypad-internals.tsx +240 -0
  21. package/src/components/keypad/mobile-keypad.tsx +21 -234
  22. package/src/data/key-configs.ts +1 -1
  23. package/src/full-mobile-input.stories.tsx +0 -1
  24. package/src/index.ts +1 -1
  25. package/tsconfig-build.tsbuildinfo +1 -1
  26. package/dist/components/keypad-legacy/compute-layout-parameters.d.ts +0 -28
  27. package/dist/components/keypad-legacy/corner-decal.d.ts +0 -12
  28. package/dist/components/keypad-legacy/echo-manager.d.ts +0 -17
  29. package/dist/components/keypad-legacy/empty-keypad-button.d.ts +0 -13
  30. package/dist/components/keypad-legacy/expression-keypad.d.ts +0 -21
  31. package/dist/components/keypad-legacy/fraction-keypad.d.ts +0 -21
  32. package/dist/components/keypad-legacy/gesture-manager.d.ts +0 -86
  33. package/dist/components/keypad-legacy/gesture-state-machine.d.ts +0 -105
  34. package/dist/components/keypad-legacy/icon.d.ts +0 -15
  35. package/dist/components/keypad-legacy/index.d.ts +0 -1
  36. package/dist/components/keypad-legacy/keypad-button.d.ts +0 -53
  37. package/dist/components/keypad-legacy/keypad-container.d.ts +0 -41
  38. package/dist/components/keypad-legacy/keypad.d.ts +0 -31
  39. package/dist/components/keypad-legacy/many-keypad-button.d.ts +0 -15
  40. package/dist/components/keypad-legacy/math-icon.d.ts +0 -16
  41. package/dist/components/keypad-legacy/multi-symbol-grid.d.ts +0 -14
  42. package/dist/components/keypad-legacy/multi-symbol-popover.d.ts +0 -12
  43. package/dist/components/keypad-legacy/navigation-pad.d.ts +0 -14
  44. package/dist/components/keypad-legacy/node-manager.d.ts +0 -49
  45. package/dist/components/keypad-legacy/popover-manager.d.ts +0 -13
  46. package/dist/components/keypad-legacy/popover-state-machine.d.ts +0 -68
  47. package/dist/components/keypad-legacy/provided-keypad.d.ts +0 -28
  48. package/dist/components/keypad-legacy/store/actions.d.ts +0 -55
  49. package/dist/components/keypad-legacy/store/echo-reducer.d.ts +0 -4
  50. package/dist/components/keypad-legacy/store/index.d.ts +0 -9
  51. package/dist/components/keypad-legacy/store/input-reducer.d.ts +0 -4
  52. package/dist/components/keypad-legacy/store/keypad-reducer.d.ts +0 -4
  53. package/dist/components/keypad-legacy/store/layout-reducer.d.ts +0 -4
  54. package/dist/components/keypad-legacy/store/shared.d.ts +0 -7
  55. package/dist/components/keypad-legacy/store/types.d.ts +0 -47
  56. package/dist/components/keypad-legacy/styles.d.ts +0 -5
  57. package/dist/components/keypad-legacy/svg-icon.d.ts +0 -12
  58. package/dist/components/keypad-legacy/text-icon.d.ts +0 -13
  59. package/dist/components/keypad-legacy/touchable-keypad-button.d.ts +0 -37
  60. package/dist/components/keypad-legacy/two-page-keypad.d.ts +0 -21
  61. package/dist/components/keypad-legacy/z-indexes.d.ts +0 -7
  62. package/dist/components/keypad-switch.d.ts +0 -12
  63. package/src/components/keypad-legacy/__tests__/gesture-state-machine.test.ts +0 -441
  64. package/src/components/keypad-legacy/__tests__/node-manager.test.ts +0 -89
  65. package/src/components/keypad-legacy/compute-layout-parameters.ts +0 -205
  66. package/src/components/keypad-legacy/corner-decal.tsx +0 -56
  67. package/src/components/keypad-legacy/echo-manager.tsx +0 -152
  68. package/src/components/keypad-legacy/empty-keypad-button.tsx +0 -58
  69. package/src/components/keypad-legacy/expression-keypad.tsx +0 -315
  70. package/src/components/keypad-legacy/fraction-keypad.tsx +0 -180
  71. package/src/components/keypad-legacy/gesture-manager.ts +0 -255
  72. package/src/components/keypad-legacy/gesture-state-machine.ts +0 -329
  73. package/src/components/keypad-legacy/icon.tsx +0 -72
  74. package/src/components/keypad-legacy/iconography/arrow.js +0 -22
  75. package/src/components/keypad-legacy/iconography/backspace.js +0 -29
  76. package/src/components/keypad-legacy/iconography/cdot.js +0 -29
  77. package/src/components/keypad-legacy/iconography/cos.js +0 -30
  78. package/src/components/keypad-legacy/iconography/cube-root.js +0 -36
  79. package/src/components/keypad-legacy/iconography/dismiss.js +0 -25
  80. package/src/components/keypad-legacy/iconography/divide.js +0 -34
  81. package/src/components/keypad-legacy/iconography/down.js +0 -16
  82. package/src/components/keypad-legacy/iconography/equal.js +0 -33
  83. package/src/components/keypad-legacy/iconography/exp-2.js +0 -29
  84. package/src/components/keypad-legacy/iconography/exp-3.js +0 -29
  85. package/src/components/keypad-legacy/iconography/exp.js +0 -29
  86. package/src/components/keypad-legacy/iconography/frac.js +0 -44
  87. package/src/components/keypad-legacy/iconography/geq.js +0 -33
  88. package/src/components/keypad-legacy/iconography/gt.js +0 -33
  89. package/src/components/keypad-legacy/iconography/index.js +0 -45
  90. package/src/components/keypad-legacy/iconography/jump-into-numerator.js +0 -41
  91. package/src/components/keypad-legacy/iconography/jump-out-base.js +0 -30
  92. package/src/components/keypad-legacy/iconography/jump-out-denominator.js +0 -41
  93. package/src/components/keypad-legacy/iconography/jump-out-exponent.js +0 -30
  94. package/src/components/keypad-legacy/iconography/jump-out-numerator.js +0 -41
  95. package/src/components/keypad-legacy/iconography/jump-out-parentheses.js +0 -33
  96. package/src/components/keypad-legacy/iconography/left-paren.js +0 -33
  97. package/src/components/keypad-legacy/iconography/left.js +0 -16
  98. package/src/components/keypad-legacy/iconography/leq.js +0 -33
  99. package/src/components/keypad-legacy/iconography/ln.js +0 -29
  100. package/src/components/keypad-legacy/iconography/log-n.js +0 -29
  101. package/src/components/keypad-legacy/iconography/log.js +0 -29
  102. package/src/components/keypad-legacy/iconography/lt.js +0 -33
  103. package/src/components/keypad-legacy/iconography/minus.js +0 -32
  104. package/src/components/keypad-legacy/iconography/neq.js +0 -33
  105. package/src/components/keypad-legacy/iconography/parens.js +0 -33
  106. package/src/components/keypad-legacy/iconography/percent.js +0 -49
  107. package/src/components/keypad-legacy/iconography/period.js +0 -26
  108. package/src/components/keypad-legacy/iconography/plus.js +0 -32
  109. package/src/components/keypad-legacy/iconography/radical.js +0 -36
  110. package/src/components/keypad-legacy/iconography/right-paren.js +0 -33
  111. package/src/components/keypad-legacy/iconography/right.js +0 -16
  112. package/src/components/keypad-legacy/iconography/sin.js +0 -30
  113. package/src/components/keypad-legacy/iconography/sqrt.js +0 -32
  114. package/src/components/keypad-legacy/iconography/tan.js +0 -30
  115. package/src/components/keypad-legacy/iconography/times.js +0 -33
  116. package/src/components/keypad-legacy/iconography/up.js +0 -16
  117. package/src/components/keypad-legacy/index.ts +0 -1
  118. package/src/components/keypad-legacy/keypad-button.tsx +0 -368
  119. package/src/components/keypad-legacy/keypad-container.tsx +0 -358
  120. package/src/components/keypad-legacy/keypad.tsx +0 -162
  121. package/src/components/keypad-legacy/many-keypad-button.tsx +0 -54
  122. package/src/components/keypad-legacy/math-icon.tsx +0 -66
  123. package/src/components/keypad-legacy/multi-symbol-grid.tsx +0 -182
  124. package/src/components/keypad-legacy/multi-symbol-popover.tsx +0 -58
  125. package/src/components/keypad-legacy/navigation-pad.tsx +0 -140
  126. package/src/components/keypad-legacy/node-manager.ts +0 -133
  127. package/src/components/keypad-legacy/popover-manager.tsx +0 -73
  128. package/src/components/keypad-legacy/popover-state-machine.ts +0 -184
  129. package/src/components/keypad-legacy/provided-keypad.tsx +0 -136
  130. package/src/components/keypad-legacy/store/actions.ts +0 -155
  131. package/src/components/keypad-legacy/store/echo-reducer.ts +0 -57
  132. package/src/components/keypad-legacy/store/index.ts +0 -110
  133. package/src/components/keypad-legacy/store/input-reducer.ts +0 -55
  134. package/src/components/keypad-legacy/store/keypad-reducer.ts +0 -58
  135. package/src/components/keypad-legacy/store/layout-reducer.test.ts +0 -171
  136. package/src/components/keypad-legacy/store/layout-reducer.ts +0 -129
  137. package/src/components/keypad-legacy/store/shared.ts +0 -12
  138. package/src/components/keypad-legacy/store/types.ts +0 -78
  139. package/src/components/keypad-legacy/styles.ts +0 -38
  140. package/src/components/keypad-legacy/svg-icon.tsx +0 -24
  141. package/src/components/keypad-legacy/text-icon.tsx +0 -53
  142. package/src/components/keypad-legacy/touchable-keypad-button.tsx +0 -163
  143. package/src/components/keypad-legacy/two-page-keypad.tsx +0 -115
  144. package/src/components/keypad-legacy/z-indexes.ts +0 -8
  145. package/src/components/keypad-switch.tsx +0 -42
@@ -1,358 +0,0 @@
1
- import {StyleSheet} from "aphrodite";
2
- import * as React from "react";
3
- import {connect} from "react-redux";
4
-
5
- import {LayoutMode, KeypadType} from "../../enums";
6
- import {View} from "../../fake-react-native-web/index";
7
- import {
8
- innerBorderColor,
9
- innerBorderStyle,
10
- innerBorderWidthPx,
11
- compactKeypadBorderRadiusPx,
12
- } from "../common-style";
13
-
14
- import ExpressionKeypad from "./expression-keypad";
15
- import FractionKeypad from "./fraction-keypad";
16
- import NavigationPad from "./navigation-pad";
17
- import {setPageSize} from "./store/actions";
18
- import Styles from "./styles";
19
- import * as zIndexes from "./z-indexes";
20
-
21
- import type {State as ReduxState} from "./store/types";
22
- import type {StyleType} from "@khanacademy/wonder-blocks-core";
23
-
24
- const {row, centered, fullWidth} = Styles;
25
-
26
- interface ReduxProps {
27
- active?: boolean;
28
- extraKeys?: ReadonlyArray<string>;
29
- keypadType?: KeypadType;
30
- layoutMode?: LayoutMode;
31
- navigationPadEnabled?: boolean;
32
- }
33
-
34
- interface Props extends ReduxProps {
35
- onDismiss?: () => void;
36
- onElementMounted: (element: any) => void;
37
- onPageSizeChange?: (
38
- pageWidth: number,
39
- pageHeight: number,
40
- containerWidth: number,
41
- containerHeight: number,
42
- ) => void;
43
- style?: StyleType;
44
- }
45
-
46
- type State = {
47
- hasBeenActivated: boolean;
48
- viewportWidth: string | number;
49
- };
50
-
51
- // eslint-disable-next-line react/no-unsafe
52
- class KeypadContainer extends React.Component<Props, State> {
53
- _containerRef = React.createRef<HTMLDivElement>();
54
- _containerResizeObserver: ResizeObserver | null = null;
55
- _resizeTimeout: number | null | undefined;
56
- hasMounted: boolean | undefined;
57
-
58
- state = {
59
- hasBeenActivated: false,
60
- viewportWidth: "100vw",
61
- };
62
-
63
- UNSAFE_componentWillMount() {
64
- if (this.props.active) {
65
- this.setState({
66
- hasBeenActivated: this.props.active,
67
- });
68
- }
69
- }
70
-
71
- componentDidMount() {
72
- // Relay the initial size metrics.
73
- this._onResize();
74
-
75
- // And update it on resize.
76
- window.addEventListener("resize", this._throttleResizeHandler);
77
- window.addEventListener(
78
- "orientationchange",
79
- this._throttleResizeHandler,
80
- );
81
-
82
- // LC-1213: some common older browsers (as of 2023-09-07)
83
- // don't support ResizeObserver
84
- if ("ResizeObserver" in window) {
85
- this._containerResizeObserver = new window.ResizeObserver(
86
- this._throttleResizeHandler,
87
- );
88
-
89
- if (this._containerRef.current) {
90
- this._containerResizeObserver.observe(
91
- this._containerRef.current,
92
- );
93
- }
94
- }
95
- }
96
-
97
- UNSAFE_componentWillReceiveProps(nextProps) {
98
- if (!this.state.hasBeenActivated && nextProps.active) {
99
- this.setState({
100
- hasBeenActivated: true,
101
- });
102
- }
103
- }
104
-
105
- componentDidUpdate(prevProps) {
106
- if (prevProps.active && !this.props.active) {
107
- this.props.onDismiss && this.props.onDismiss();
108
- }
109
- }
110
-
111
- componentWillUnmount() {
112
- window.removeEventListener("resize", this._throttleResizeHandler);
113
- window.removeEventListener(
114
- "orientationchange",
115
- this._throttleResizeHandler,
116
- );
117
- this._containerResizeObserver?.disconnect();
118
- }
119
-
120
- _throttleResizeHandler = () => {
121
- // Throttle the resize callbacks.
122
- // https://developer.mozilla.org/en-US/docs/Web/Events/resize
123
- if (this._resizeTimeout == null) {
124
- this._resizeTimeout = window.setTimeout(() => {
125
- this._resizeTimeout = null;
126
-
127
- this._onResize();
128
- }, 66);
129
- }
130
- };
131
-
132
- _onResize = () => {
133
- // Whenever the page resizes, we need to force an update, as the button
134
- // heights and keypad width are computed based on horizontal space.
135
- this.setState({
136
- viewportWidth: window.innerWidth,
137
- });
138
- const containerWidth = this._containerRef.current?.clientWidth || 0;
139
- const containerHeight = this._containerRef.current?.clientHeight || 0;
140
- this.props.onPageSizeChange?.(
141
- window.innerWidth,
142
- window.innerHeight,
143
- containerWidth,
144
- containerHeight,
145
- );
146
- };
147
-
148
- renderKeypad = () => {
149
- const {extraKeys, keypadType, layoutMode, navigationPadEnabled} =
150
- this.props;
151
-
152
- const keypadProps = {
153
- extraKeys,
154
- // HACK(charlie): In order to properly round the corners of the
155
- // compact keypad, we need to instruct some of our child views to
156
- // crop themselves. At least we're colocating all the layout
157
- // information in this component, though.
158
- roundTopLeft:
159
- layoutMode === LayoutMode.COMPACT && !navigationPadEnabled,
160
- roundTopRight: layoutMode === LayoutMode.COMPACT,
161
- };
162
-
163
- // Select the appropriate keyboard given the type.
164
- // TODO(charlie): In the future, we might want to move towards a
165
- // data-driven approach to defining keyboard layouts, and have a
166
- // generic keyboard that takes some "keyboard data" and renders it.
167
- // However, the keyboards differ pretty heavily right now and it's not
168
- // clear what that format would look like exactly. Plus, there aren't
169
- // very many of them. So to keep us moving, we'll just hardcode.
170
- switch (keypadType) {
171
- case KeypadType.FRACTION:
172
- return <FractionKeypad {...keypadProps} />;
173
-
174
- case KeypadType.EXPRESSION:
175
- return <ExpressionKeypad {...keypadProps} />;
176
-
177
- default:
178
- throw new Error("Invalid keypad type: " + keypadType);
179
- }
180
- };
181
-
182
- render() {
183
- const {
184
- active,
185
- layoutMode,
186
- navigationPadEnabled,
187
- onElementMounted,
188
- style,
189
- } = this.props;
190
- const {hasBeenActivated} = this.state;
191
-
192
- // NOTE(charlie): We render the transforms as pure inline styles to
193
- // avoid an Aphrodite bug in mobile Safari.
194
- // See: https://github.com/Khan/aphrodite/issues/68.
195
- let dynamicStyle = {
196
- ...(active ? inlineStyles.active : inlineStyles.hidden),
197
- };
198
-
199
- if (!active && !hasBeenActivated) {
200
- dynamicStyle = {
201
- ...dynamicStyle,
202
- ...inlineStyles.invisible,
203
- };
204
- }
205
-
206
- const keypadContainerStyle = [
207
- row,
208
- centered,
209
- fullWidth,
210
- styles.keypadContainer,
211
- ...(Array.isArray(style) ? style : [style]),
212
- ];
213
-
214
- const keypadStyle = [
215
- row,
216
- styles.keypadBorder,
217
- layoutMode === LayoutMode.FULLSCREEN
218
- ? styles.fullscreen
219
- : styles.compact,
220
- ];
221
-
222
- // TODO(charlie): When the keypad is shorter than the width of the
223
- // screen, add a border on its left and right edges, and round out the
224
- // corners.
225
- return (
226
- <View
227
- style={keypadContainerStyle}
228
- dynamicStyle={dynamicStyle}
229
- extraClassName="keypad-container"
230
- forwardRef={this._containerRef}
231
- >
232
- <View
233
- style={keypadStyle}
234
- ref={(element) => {
235
- if (!this.hasMounted && element) {
236
- this.hasMounted = true;
237
- onElementMounted(element);
238
- }
239
- }}
240
- >
241
- {navigationPadEnabled && (
242
- <NavigationPad
243
- roundTopLeft={layoutMode === LayoutMode.COMPACT}
244
- style={styles.navigationPadContainer}
245
- />
246
- )}
247
- <View style={styles.keypadLayout}>
248
- {this.renderKeypad()}
249
- </View>
250
- </View>
251
- </View>
252
- );
253
- }
254
- }
255
-
256
- const keypadAnimationDurationMs = 300;
257
- const borderWidthPx = 1;
258
-
259
- const styles = StyleSheet.create({
260
- keypadContainer: {
261
- bottom: 0,
262
- left: 0,
263
- right: 0,
264
- position: "fixed",
265
- transition: `${keypadAnimationDurationMs}ms ease-out`,
266
- transitionProperty: "transform",
267
- zIndex: zIndexes.keypad,
268
- },
269
-
270
- keypadBorder: {
271
- boxShadow: "0 1px 4px 0 rgba(0, 0, 0, 0.1)",
272
- borderColor: "rgba(0, 0, 0, 0.2)",
273
- borderStyle: "solid",
274
- },
275
-
276
- fullscreen: {
277
- borderTopWidth: borderWidthPx,
278
- },
279
-
280
- compact: {
281
- borderTopRightRadius: compactKeypadBorderRadiusPx,
282
- borderTopLeftRadius: compactKeypadBorderRadiusPx,
283
-
284
- borderTopWidth: borderWidthPx,
285
- borderRightWidth: borderWidthPx,
286
- borderLeftWidth: borderWidthPx,
287
- },
288
-
289
- navigationPadContainer: {
290
- // Add a separator between the navigation pad and the keypad.
291
- borderRight:
292
- `${innerBorderWidthPx}px ${innerBorderStyle} ` +
293
- `${innerBorderColor}`,
294
- boxSizing: "content-box",
295
- },
296
-
297
- // Defer to the navigation pad, such that the navigation pad is always
298
- // rendered at full-width, and the keypad takes up just the remaining space.
299
- // TODO(charlie): Avoid shrinking the keys and, instead, make the keypad
300
- // scrollable.
301
- keypadLayout: {
302
- flexGrow: 1,
303
- // Avoid unitless flex-basis, per: https://philipwalton.com/articles/normalizing-cross-browser-flexbox-bugs/
304
- flexBasis: "0%",
305
- },
306
- });
307
-
308
- // Note: these don't go through an autoprefixer/aphrodite.
309
- const inlineStyles = {
310
- // If the keypad is yet to have ever been activated, we keep it invisible
311
- // so as to avoid, e.g., the keypad flashing at the bottom of the page
312
- // during the initial render.
313
- invisible: {
314
- visibility: "hidden",
315
- },
316
-
317
- hidden: {
318
- transform: "translate3d(0, 100%, 0)",
319
- },
320
-
321
- active: {
322
- transform: "translate3d(0, 0, 0)",
323
- },
324
- };
325
-
326
- const mapStateToProps = (state: ReduxState): ReduxProps => {
327
- return {
328
- extraKeys: state.keypad.extraKeys,
329
- keypadType: state.keypad.keypadType,
330
- active: state.keypad.active,
331
- layoutMode: state.layout.layoutMode,
332
- navigationPadEnabled: state.layout.navigationPadEnabled,
333
- };
334
- };
335
-
336
- const mapDispatchToProps = (dispatch) => {
337
- return {
338
- onPageSizeChange: (
339
- pageWidth: number,
340
- pageHeight: number,
341
- containerWidth: number,
342
- containerHeight: number,
343
- ) => {
344
- dispatch(
345
- setPageSize(
346
- pageWidth,
347
- pageHeight,
348
- containerWidth,
349
- containerHeight,
350
- ),
351
- );
352
- },
353
- };
354
- };
355
-
356
- export default connect(mapStateToProps, mapDispatchToProps, null, {
357
- forwardRef: true,
358
- })(KeypadContainer);
@@ -1,162 +0,0 @@
1
- /**
2
- * A keypad component that acts as a container for rows or columns of buttons,
3
- * and manages the rendering of echo animations on top of those buttons.
4
- */
5
-
6
- import * as React from "react";
7
- import ReactDOM from "react-dom";
8
- import {connect} from "react-redux";
9
-
10
- import {View} from "../../fake-react-native-web/index";
11
-
12
- import EchoManager from "./echo-manager";
13
- import PopoverManager from "./popover-manager";
14
- import {removeEcho} from "./store/actions";
15
-
16
- import type {Bound, Popover, Echo} from "../../types";
17
- import type {State} from "./store/types";
18
- import type {StyleType} from "@khanacademy/wonder-blocks-core";
19
-
20
- interface ReduxProps {
21
- active: boolean;
22
- echoes: ReadonlyArray<Echo>;
23
- popover: Popover | null;
24
- }
25
-
26
- interface Props extends ReduxProps {
27
- children: React.ReactNode;
28
- style?: StyleType;
29
- removeEcho?: (animationId: string) => void;
30
- }
31
-
32
- // eslint-disable-next-line react/no-unsafe
33
- class Keypad extends React.Component<Props> {
34
- _isMounted: boolean | undefined;
35
- _resizeTimeout: number | null | undefined;
36
- _container: Bound | null | undefined;
37
-
38
- componentDidMount() {
39
- this._isMounted = true;
40
-
41
- window.addEventListener("resize", this._onResize);
42
- this._updateSizeAndPosition();
43
- }
44
-
45
- UNSAFE_componentWillReceiveProps(newProps) {
46
- if (!this._container && (newProps.popover || newProps.echoes.length)) {
47
- this._computeContainer();
48
- }
49
- }
50
-
51
- componentWillUnmount() {
52
- this._isMounted = false;
53
-
54
- window.removeEventListener("resize", this._onResize);
55
- }
56
-
57
- _computeContainer = () => {
58
- const domNode = ReactDOM.findDOMNode(this) as Element;
59
- this._container = domNode.getBoundingClientRect();
60
- };
61
-
62
- _updateSizeAndPosition = () => {
63
- // Mark the container for recalculation next time the keypad is
64
- // opened.
65
- // TODO(charlie): Since we're not recalculating the container
66
- // immediately, if you were to resize the page while a popover were
67
- // active, you'd likely get unexpected behavior. This seems very
68
- // difficult to do and, as such, incredibly unlikely, but we may
69
- // want to reconsider the caching here.
70
- this._container = null;
71
- };
72
-
73
- _onResize = () => {
74
- // Whenever the page resizes, we need to recompute the container's
75
- // bounding box. This is the only time that the bounding box can change.
76
-
77
- // Throttle resize events -- taken from:
78
- // https://developer.mozilla.org/en-US/docs/Web/Events/resize
79
- if (this._resizeTimeout == null) {
80
- this._resizeTimeout = window.setTimeout(() => {
81
- this._resizeTimeout = null;
82
-
83
- if (this._isMounted) {
84
- this._updateSizeAndPosition();
85
- }
86
- }, 66);
87
- }
88
- };
89
-
90
- render() {
91
- const {children, echoes, removeEcho, popover, style} = this.props;
92
-
93
- // Translate the echo boxes, as they'll be positioned absolutely to
94
- // this relative container.
95
- const relativeEchoes = echoes.map((echo) => {
96
- const {initialBounds, ...rest} = echo;
97
- return {
98
- ...rest,
99
- initialBounds: {
100
- // @ts-expect-error TS2533
101
- top: initialBounds.top - this._container.top,
102
- // @ts-expect-error TS2533
103
- right: initialBounds.right - this._container.left,
104
- // @ts-expect-error TS2533
105
- bottom: initialBounds.bottom - this._container.top,
106
- // @ts-expect-error TS2533
107
- left: initialBounds.left - this._container.left,
108
- width: initialBounds.width,
109
- height: initialBounds.height,
110
- },
111
- };
112
- });
113
-
114
- // Translate the popover bounds from page-absolute to keypad-relative.
115
- // Note that we only need three bounds, since popovers are anchored to
116
- // the bottom left corners of the keys over which they appear.
117
- const relativePopover = popover && {
118
- ...popover,
119
- bounds: {
120
- bottom:
121
- // @ts-expect-error TS2533
122
- this._container.height -
123
- // @ts-expect-error TS2533
124
- (popover.bounds.bottom - this._container.top),
125
- // @ts-expect-error TS2533
126
- left: popover.bounds.left - this._container.left,
127
- width: popover.bounds.width,
128
- },
129
- };
130
-
131
- return (
132
- <View style={style}>
133
- {children}
134
- <EchoManager
135
- echoes={relativeEchoes}
136
- onAnimationFinish={removeEcho}
137
- />
138
- <PopoverManager popover={relativePopover} />
139
- </View>
140
- );
141
- }
142
- }
143
-
144
- const mapStateToProps = (state: State): ReduxProps => {
145
- return {
146
- echoes: state.echoes.echoes,
147
- active: state.keypad.active,
148
- popover: state.gestures.popover,
149
- };
150
- };
151
-
152
- const mapDispatchToProps = (dispatch) => {
153
- return {
154
- removeEcho: (animationId) => {
155
- dispatch(removeEcho(animationId));
156
- },
157
- };
158
- };
159
-
160
- export default connect(mapStateToProps, mapDispatchToProps, null, {
161
- forwardRef: true,
162
- })(Keypad);
@@ -1,54 +0,0 @@
1
- /**
2
- * A keypad button that displays an arbitrary number of symbols, with no
3
- * 'default' symbol.
4
- */
5
-
6
- import * as React from "react";
7
-
8
- import KeyConfigs from "../../data/key-configs";
9
- import {IconType} from "../../enums";
10
-
11
- import EmptyKeypadButton from "./empty-keypad-button";
12
- import TouchableKeypadButton from "./touchable-keypad-button";
13
-
14
- import type {KeyConfig} from "../../types";
15
-
16
- type Props = {
17
- keys: ReadonlyArray<string>;
18
- };
19
-
20
- class ManyKeypadButton extends React.Component<Props> {
21
- static defaultProps = {
22
- keys: [],
23
- };
24
-
25
- render() {
26
- const {keys, ...rest} = this.props;
27
-
28
- // If we have no extra symbols, render an empty button. If we have just
29
- // one, render a standard button. Otherwise, capture them all in a
30
- // single button.
31
- if (keys.length === 0) {
32
- return <EmptyKeypadButton />;
33
- } else if (keys.length === 1) {
34
- const keyConfig = KeyConfigs[keys[0]];
35
- return <TouchableKeypadButton keyConfig={keyConfig} {...rest} />;
36
- } else {
37
- const keyConfig: KeyConfig = {
38
- id: "MANY",
39
- type: "MANY",
40
- childKeyIds: keys,
41
- ariaLabel: keys
42
- .map((key) => KeyConfigs[key].ariaLabel)
43
- .join(", "),
44
- icon: {
45
- type: IconType.SVG,
46
- data: "many",
47
- },
48
- };
49
- return <TouchableKeypadButton keyConfig={keyConfig} {...rest} />;
50
- }
51
- }
52
- }
53
-
54
- export default ManyKeypadButton;
@@ -1,66 +0,0 @@
1
- /**
2
- * A component that renders an icon with math (via KaTeX).
3
- */
4
-
5
- import {StyleSheet} from "aphrodite";
6
- import katex from "katex";
7
- import * as React from "react";
8
- import ReactDOM from "react-dom";
9
-
10
- import {View} from "../../fake-react-native-web/index";
11
- import {iconSizeHeightPx, iconSizeWidthPx} from "../common-style";
12
-
13
- import Styles from "./styles";
14
-
15
- import type {StyleType} from "@khanacademy/wonder-blocks-core";
16
-
17
- const {row, centered} = Styles;
18
-
19
- type Props = {
20
- math: string;
21
- style: StyleType;
22
- };
23
-
24
- class MathIcon extends React.Component<Props> {
25
- componentDidMount() {
26
- this._renderMath();
27
- }
28
-
29
- componentDidUpdate(prevProps) {
30
- if (prevProps.math !== this.props.math) {
31
- this._renderMath();
32
- }
33
- }
34
-
35
- _renderMath = () => {
36
- const {math} = this.props;
37
- katex.render(math, ReactDOM.findDOMNode(this));
38
- };
39
-
40
- render() {
41
- const {style} = this.props;
42
-
43
- const containerStyle = [
44
- row,
45
- centered,
46
- styles.size,
47
- styles.base,
48
- ...(Array.isArray(style) ? style : [style]),
49
- ];
50
-
51
- return <View style={containerStyle} />;
52
- }
53
- }
54
-
55
- const styles = StyleSheet.create({
56
- size: {
57
- height: iconSizeHeightPx,
58
- width: iconSizeWidthPx,
59
- },
60
-
61
- base: {
62
- fontSize: 25,
63
- },
64
- });
65
-
66
- export default MathIcon;