@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,184 +0,0 @@
1
- import type {ActiveNodesObj} from "../../types";
2
-
3
- /**
4
- * A state machine for the popover state. In particular, this class manages the
5
- * mapping of parent nodes to their children, and translates touch events that
6
- * traverse various nodes to actions that are conditioned on whether a popover
7
- * is present.
8
- */
9
-
10
- type Handlers = {
11
- onActiveNodesChanged: (activeNodes: ActiveNodesObj) => void;
12
- onClick: (keyId: string, domNodeId: string, inPopover: boolean) => void;
13
- };
14
-
15
- class PopoverStateMachine {
16
- handlers: Handlers;
17
- popovers: Record<string, ReadonlyArray<string>>;
18
- activePopover: string | null;
19
-
20
- constructor(handlers) {
21
- this.handlers = handlers;
22
-
23
- this.activePopover = null;
24
- this.popovers = {};
25
- }
26
-
27
- /**
28
- * Register a popover container as containing a set of children.
29
- *
30
- * @param {string} id - the identifier of the popover container
31
- * @param {string[]} childIds - the identifiers of the nodes contained in
32
- * the popover container
33
- */
34
- registerPopover(id, childIds) {
35
- this.popovers[id] = childIds;
36
- }
37
-
38
- /**
39
- * Unregister a popover container.
40
- *
41
- * @param {string} id - the identifier of the popover container to
42
- * unregister
43
- */
44
- unregisterPopover(id) {
45
- delete this.popovers[id];
46
- }
47
-
48
- /**
49
- * @returns {boolean} - whether a popover is active and visible
50
- */
51
- isPopoverVisible() {
52
- return this.activePopover != null;
53
- }
54
-
55
- /**
56
- * Blur the active nodes.
57
- */
58
- onBlur() {
59
- this.activePopover = null;
60
- this.handlers.onActiveNodesChanged({
61
- popover: null,
62
- focus: null,
63
- });
64
- }
65
-
66
- /**
67
- * Handle a focus event on the node with the given identifier.
68
- *
69
- * @param {string} id - the identifier of the node that was focused
70
- */
71
- onFocus(id) {
72
- if (this.activePopover) {
73
- // If we have a popover that is currently active, we focus this
74
- // node if it's in the popover, and remove any highlight otherwise.
75
- if (this._isNodeInsidePopover(this.activePopover, id)) {
76
- this.handlers.onActiveNodesChanged({
77
- popover: {
78
- parentId: this.activePopover,
79
- childIds: this.popovers[this.activePopover],
80
- },
81
- focus: id,
82
- });
83
- } else {
84
- this.handlers.onActiveNodesChanged({
85
- popover: {
86
- parentId: this.activePopover,
87
- childIds: this.popovers[this.activePopover],
88
- },
89
- focus: null,
90
- });
91
- }
92
- } else {
93
- this.activePopover = null;
94
- this.handlers.onActiveNodesChanged({
95
- popover: null,
96
- focus: id,
97
- });
98
- }
99
- }
100
-
101
- /**
102
- * Handle a long press event on the node with the given identifier.
103
- *
104
- * @param {string} id - the identifier of the node that was long-pressed
105
- */
106
- onLongPress(id) {
107
- // We only care about long presses if they occur on a popover, and we
108
- // don't already have a popover active.
109
- if (!this.activePopover && this.popovers[id]) {
110
- // NOTE(charlie): There's an assumption here that focusing the
111
- // first child is the correct behavior for a newly focused popover.
112
- // This relies on the fact that the children are rendered
113
- // bottom-up. If that rendering changes, this logic will need to
114
- // change as well.
115
- this.activePopover = id;
116
- this.handlers.onActiveNodesChanged({
117
- popover: {
118
- parentId: id,
119
- childIds: this.popovers[id],
120
- },
121
- focus: this._defaultNodeForPopover(this.activePopover),
122
- });
123
- }
124
- }
125
-
126
- /**
127
- * Handle the trigger (click or hold) of the node with the given identifier.
128
- *
129
- * @param {string} id - the identifier of the node that was triggered
130
- */
131
- onTrigger(id) {
132
- this.handlers.onClick(id, id, false);
133
- }
134
-
135
- /**
136
- * Handle a touch-end event on the node with the given identifier.
137
- *
138
- * @param {string} id - the identifier of the node over which the touch
139
- * ended
140
- */
141
- onTouchEnd(id) {
142
- const inPopover = !!this.activePopover;
143
- if (inPopover) {
144
- // If we have a popover that is currently active, we trigger a
145
- // click on this node if and only if it's in the popover, with the
146
- // exception that, if the node passed back _is_ the active popover,
147
- // then we trigger its default node. This latter case should only
148
- // be triggered if the user were to tap down on a popover-enabled
149
- // node, hold for long enough for the popover to appear, and then
150
- // release without ever moving their finger, in which case, the
151
- // underlying gesture system would have no idea that the popover's
152
- // first child node was now focused.
153
- if (this._isNodeInsidePopover(this.activePopover, id)) {
154
- this.handlers.onClick(id, id, inPopover);
155
- } else if (this.activePopover === id) {
156
- const keyId = this._defaultNodeForPopover(id);
157
- this.handlers.onClick(keyId, keyId, inPopover);
158
- }
159
- } else if (this.popovers[id]) {
160
- // Otherwise, if the node is itself a popover revealer, trigger the
161
- // clicking of its default node, but pass back the popover node ID
162
- // for layout purposes.
163
- const keyId = this._defaultNodeForPopover(id);
164
- const domNodeId = id;
165
- this.handlers.onClick(keyId, domNodeId, inPopover);
166
- } else if (id != null) {
167
- // Finally, if we have no active popover, and we touched up over a
168
- // valid key, trigger a click.
169
- this.onTrigger(id);
170
- }
171
-
172
- this.onBlur();
173
- }
174
-
175
- _isNodeInsidePopover(popover, id) {
176
- return this.popovers[popover].includes(id);
177
- }
178
-
179
- _defaultNodeForPopover(popover) {
180
- return this.popovers[popover][0];
181
- }
182
- }
183
-
184
- export default PopoverStateMachine;
@@ -1,136 +0,0 @@
1
- import * as React from "react";
2
- import ReactDOM from "react-dom";
3
- import {Provider} from "react-redux";
4
-
5
- import KeypadContainer from "./keypad-container";
6
- import {
7
- activateKeypad,
8
- dismissKeypad,
9
- configureKeypad,
10
- setCursor,
11
- setKeyHandler,
12
- } from "./store/actions";
13
- import {createStore} from "./store/index";
14
-
15
- import type {
16
- Cursor,
17
- KeypadConfiguration,
18
- KeyHandler,
19
- KeypadAPI,
20
- } from "../../types";
21
- import type {AnalyticsEventHandlerFn} from "@khanacademy/perseus-core";
22
- import type {StyleType} from "@khanacademy/wonder-blocks-core";
23
-
24
- type Props = {
25
- setKeypadActive: (keypadActive: boolean) => void;
26
- keypadActive: boolean;
27
- onElementMounted?: (arg1: any) => void;
28
- onDismiss?: () => void;
29
- style?: StyleType;
30
-
31
- onAnalyticsEvent: AnalyticsEventHandlerFn;
32
- };
33
-
34
- class ProvidedKeypad extends React.Component<Props> implements KeypadAPI {
35
- store: any;
36
-
37
- constructor(props) {
38
- super(props);
39
- this.store = createStore();
40
- }
41
-
42
- componentDidUpdate(prevProps) {
43
- if (this.props.keypadActive && !prevProps.keypadActive) {
44
- this.store.dispatch(activateKeypad());
45
- }
46
-
47
- if (!this.props.keypadActive && prevProps.keypadActive) {
48
- this.store.dispatch(dismissKeypad());
49
- }
50
- }
51
-
52
- activate: () => void = () => {
53
- this.props.setKeypadActive(true);
54
- };
55
-
56
- dismiss: () => void = () => {
57
- this.props.setKeypadActive(false);
58
- };
59
-
60
- configure: (configuration: KeypadConfiguration, cb: () => void) => void = (
61
- configuration,
62
- cb,
63
- ) => {
64
- this.store.dispatch(configureKeypad(configuration));
65
-
66
- // HACK(charlie): In Perseus, triggering a focus causes the keypad to
67
- // animate into view and re-configure. We'd like to provide the option
68
- // to re-render the re-configured keypad before animating it into view,
69
- // to avoid jank in the animation. As such, we support passing a
70
- // callback into `configureKeypad`. However, implementing this properly
71
- // would require middleware, etc., so we just hack it on with
72
- // `setTimeout` for now.
73
- setTimeout(() => cb && cb());
74
- };
75
-
76
- setCursor: (cursor: Cursor) => void = (cursor) => {
77
- this.store.dispatch(setCursor(cursor));
78
- };
79
-
80
- setKeyHandler: (keyHandler: KeyHandler) => void = (keyHandler) => {
81
- this.store.dispatch(setKeyHandler(keyHandler));
82
- };
83
-
84
- getDOMNode: () => ReturnType<typeof ReactDOM.findDOMNode> = () => {
85
- return ReactDOM.findDOMNode(this);
86
- };
87
-
88
- onElementMounted: (element: any) => void = (element) => {
89
- this.props.onAnalyticsEvent({
90
- type: "math-input:keypad-opened",
91
- payload: {
92
- virtualKeypadVersion: "MATH_INPUT_KEYPAD_V1",
93
- },
94
- });
95
-
96
- // Append the dispatch methods that we want to expose
97
- // externally to the returned React element.
98
- const elementWithDispatchMethods = {
99
- ...element,
100
- activate: this.activate,
101
- dismiss: this.dismiss,
102
- configure: this.configure,
103
- setCursor: this.setCursor,
104
- setKeyHandler: this.setKeyHandler,
105
- getDOMNode: this.getDOMNode,
106
- } as const;
107
- this.props.onElementMounted?.(elementWithDispatchMethods);
108
- };
109
-
110
- onDismiss: () => void = () => {
111
- this.props.onAnalyticsEvent({
112
- type: "math-input:keypad-closed",
113
- payload: {
114
- virtualKeypadVersion: "MATH_INPUT_KEYPAD_V1",
115
- },
116
- });
117
-
118
- this.props.onDismiss?.();
119
- };
120
-
121
- render(): React.ReactNode {
122
- const {style} = this.props;
123
-
124
- return (
125
- <Provider store={this.store}>
126
- <KeypadContainer
127
- onElementMounted={this.onElementMounted}
128
- onDismiss={this.onDismiss}
129
- style={style}
130
- />
131
- </Provider>
132
- );
133
- }
134
- }
135
-
136
- export default ProvidedKeypad;
@@ -1,155 +0,0 @@
1
- import type Key from "../../../data/keys";
2
- import type {
3
- Bound,
4
- KeypadConfiguration,
5
- KeyHandler,
6
- Cursor,
7
- ActiveNodesObj,
8
- } from "../../../types";
9
-
10
- // naming convention: verb + noun
11
- // the noun should be one of the other properties in the object that's
12
- // being dispatched
13
-
14
- type DismissKeypadAction = {
15
- type: "DismissKeypad";
16
- };
17
-
18
- export const dismissKeypad = (): DismissKeypadAction => {
19
- return {
20
- type: "DismissKeypad",
21
- };
22
- };
23
-
24
- type ActivateKeypadAction = {
25
- type: "ActivateKeypad";
26
- };
27
-
28
- export const activateKeypad = (): ActivateKeypadAction => {
29
- return {
30
- type: "ActivateKeypad",
31
- };
32
- };
33
-
34
- /**
35
- * Configure the keypad with the provided configuration parameters.
36
- */
37
- type ConfigureKeypadAction = {
38
- type: "ConfigureKeypad";
39
- configuration: KeypadConfiguration;
40
- };
41
-
42
- export const configureKeypad = (
43
- configuration: KeypadConfiguration,
44
- ): ConfigureKeypadAction => {
45
- return {
46
- type: "ConfigureKeypad",
47
- configuration,
48
- };
49
- };
50
-
51
- type SetPageSizeAction = {
52
- type: "SetPageSize";
53
- pageWidth: number;
54
- pageHeight: number;
55
- containerWidth: number;
56
- containerHeight: number;
57
- };
58
-
59
- export const setPageSize = (
60
- pageWidth: number,
61
- pageHeight: number,
62
- containerWidth: number,
63
- containerHeight: number,
64
- ): SetPageSizeAction => {
65
- return {
66
- type: "SetPageSize",
67
- pageWidth,
68
- pageHeight,
69
- containerWidth,
70
- containerHeight,
71
- };
72
- };
73
-
74
- type RemoveEchoAction = {
75
- type: "RemoveEcho";
76
- animationId: string;
77
- };
78
-
79
- export const removeEcho = (animationId: string): RemoveEchoAction => {
80
- return {
81
- type: "RemoveEcho",
82
- animationId,
83
- };
84
- };
85
-
86
- // Input-related actions.
87
- type SetKeyHandlerAction = {
88
- type: "SetKeyHandler";
89
- keyHandler: KeyHandler;
90
- };
91
-
92
- export const setKeyHandler = (keyHandler: KeyHandler): SetKeyHandlerAction => {
93
- return {
94
- type: "SetKeyHandler",
95
- keyHandler,
96
- };
97
- };
98
-
99
- type SetCursorAction = {
100
- type: "SetCursor";
101
- cursor: Cursor;
102
- };
103
-
104
- export const setCursor = (cursor: Cursor): SetCursorAction => {
105
- return {
106
- type: "SetCursor",
107
- cursor,
108
- };
109
- };
110
-
111
- // Gesture actions
112
- type SetActiveNodesAction = {
113
- type: "SetActiveNodes";
114
- activeNodes: any;
115
- };
116
-
117
- export const setActiveNodes = (
118
- activeNodes: ActiveNodesObj,
119
- ): SetActiveNodesAction => {
120
- return {
121
- type: "SetActiveNodes",
122
- activeNodes,
123
- };
124
- };
125
-
126
- type PressKeyAction = {
127
- type: "PressKey";
128
- key: Key;
129
- initialBounds: Bound;
130
- inPopover: boolean;
131
- };
132
-
133
- export const pressKey = (
134
- key: Key,
135
- initialBounds: Bound,
136
- inPopover: any,
137
- ): PressKeyAction => {
138
- return {
139
- type: "PressKey",
140
- key,
141
- initialBounds,
142
- inPopover,
143
- };
144
- };
145
-
146
- export type Action =
147
- | DismissKeypadAction
148
- | ActivateKeypadAction
149
- | ConfigureKeypadAction
150
- | SetPageSizeAction
151
- | RemoveEchoAction
152
- | SetKeyHandlerAction
153
- | SetCursorAction
154
- | SetActiveNodesAction
155
- | PressKeyAction;
@@ -1,57 +0,0 @@
1
- import KeyConfigs from "../../../data/key-configs";
2
- import {EchoAnimationType} from "../../../enums";
3
-
4
- import type {Action} from "./actions";
5
- import type {EchoState} from "./types";
6
-
7
- // Used to generate unique animation IDs for the echo animations. The actual
8
- // values are irrelevant as long as they are unique.
9
- let _lastAnimationId = 0;
10
-
11
- const initialEchoState = {
12
- echoes: [],
13
- } as const;
14
-
15
- const echoReducer = function (
16
- state: EchoState = initialEchoState,
17
- action: Action,
18
- ): EchoState {
19
- switch (action.type) {
20
- case "PressKey":
21
- const keyConfig = KeyConfigs[action.key];
22
-
23
- // Add in the echo animation if the user performs a math
24
- // operation.
25
- if (keyConfig.type === "VALUE" || keyConfig.type === "OPERATOR") {
26
- return {
27
- ...state,
28
- echoes: [
29
- ...state.echoes,
30
- {
31
- animationId: "" + _lastAnimationId++,
32
- animationType: action.inPopover
33
- ? EchoAnimationType.LONG_FADE_ONLY
34
- : EchoAnimationType.FADE_ONLY,
35
- id: keyConfig.id,
36
- initialBounds: action.initialBounds,
37
- },
38
- ],
39
- };
40
- }
41
- return state;
42
-
43
- case "RemoveEcho":
44
- const remainingEchoes = state.echoes.filter((echo) => {
45
- return echo.animationId !== action.animationId;
46
- });
47
- return {
48
- ...state,
49
- echoes: remainingEchoes,
50
- };
51
-
52
- default:
53
- return state;
54
- }
55
- };
56
-
57
- export default echoReducer;
@@ -1,110 +0,0 @@
1
- import * as Redux from "redux";
2
-
3
- import GestureManager from "../gesture-manager";
4
-
5
- import {setActiveNodes, pressKey} from "./actions";
6
- import echoReducer from "./echo-reducer";
7
- import inputReducer from "./input-reducer";
8
- import keypadReducer from "./keypad-reducer";
9
- import layoutReducer from "./layout-reducer";
10
- import {defaultKeypadType, keypadForType} from "./shared";
11
-
12
- import type Key from "../../../data/keys";
13
- import type {LayoutProps, ActiveNodesObj} from "../../../types";
14
- import type {Action} from "./actions";
15
- import type {GestureState} from "./types";
16
-
17
- export const createStore = () => {
18
- // TODO(matthewc)[LC-752]: gestureReducer can't be moved from this file
19
- // because it depends on `store` being in scope (see note below)
20
- const createGestureManager = (swipeEnabled: boolean) => {
21
- return new GestureManager(
22
- {
23
- swipeEnabled,
24
- },
25
- {
26
- onActiveNodesChanged: (activeNodes: ActiveNodesObj) => {
27
- store.dispatch(setActiveNodes(activeNodes));
28
- },
29
- onClick: (
30
- key: Key,
31
- layoutProps: LayoutProps,
32
- inPopover: boolean,
33
- ) => {
34
- store.dispatch(
35
- pressKey(key, layoutProps.initialBounds, inPopover),
36
- );
37
- },
38
- },
39
- [],
40
- ["BACKSPACE", "UP", "RIGHT", "DOWN", "LEFT"],
41
- );
42
- };
43
-
44
- const initialGestureState = {
45
- popover: null,
46
- focus: null,
47
- gestureManager: createGestureManager(
48
- keypadForType[defaultKeypadType].numPages > 1,
49
- ),
50
- } as const;
51
-
52
- const gestureReducer = function (
53
- state: GestureState = initialGestureState,
54
- action: Action,
55
- ): GestureState {
56
- switch (action.type) {
57
- case "DismissKeypad":
58
- // NOTE(charlie): In the past, we enforced the "gesture manager
59
- // will not receive any events when the keypad is hidden"
60
- // assumption by assuming that the keypad would be hidden when
61
- // dismissed and, as such, that none of its managed DOM nodes
62
- // would be able to receive touch events. However, on mobile
63
- // Safari, we're seeing that some of the keys receive touch
64
- // events even when off-screen, inexplicably. So, to guard
65
- // against that bug and make the contract explicit, we enable
66
- // and disable event tracking on activation and dismissal.
67
- state.gestureManager.disableEventTracking();
68
- return state;
69
-
70
- case "ActivateKeypad":
71
- state.gestureManager.enableEventTracking();
72
- return state;
73
-
74
- case "SetActiveNodes":
75
- return {
76
- ...state,
77
- ...action.activeNodes,
78
- };
79
-
80
- case "ConfigureKeypad":
81
- const {keypadType} = action.configuration;
82
- const {numPages} = keypadForType[keypadType];
83
- const swipeEnabled = numPages > 1;
84
- return {
85
- popover: null,
86
- focus: null,
87
- gestureManager: createGestureManager(swipeEnabled),
88
- };
89
-
90
- default:
91
- return state;
92
- }
93
- };
94
-
95
- const reducer = Redux.combineReducers({
96
- input: inputReducer,
97
- keypad: keypadReducer,
98
- gestures: gestureReducer,
99
- echoes: echoReducer,
100
- layout: layoutReducer,
101
- });
102
-
103
- // TODO(charlie): This non-inlined return is necessary so as to allow the
104
- // gesture manager to dispatch actions on the store in its callbacks. We
105
- // should come up with a better pattern to remove the two-way dependency.
106
- // eslint-disable-next-line import/no-deprecated
107
- const store = Redux.createStore(reducer);
108
-
109
- return store;
110
- };
@@ -1,55 +0,0 @@
1
- import KeyConfigs from "../../../data/key-configs";
2
- import {CursorContext} from "../../input/cursor-contexts";
3
-
4
- import type {Cursor, KeyHandler} from "../../../types";
5
- import type {Action} from "./actions";
6
- import type {InputState} from "./types";
7
-
8
- const initialInputState: {
9
- keyHandler: KeyHandler | null;
10
- cursor: Cursor;
11
- } = {
12
- keyHandler: null,
13
- cursor: {
14
- context: CursorContext.NONE,
15
- },
16
- };
17
-
18
- const inputReducer = function (
19
- state: InputState = initialInputState,
20
- action: Action,
21
- ): InputState {
22
- switch (action.type) {
23
- case "SetKeyHandler":
24
- return {
25
- ...state,
26
- keyHandler: action.keyHandler,
27
- };
28
-
29
- case "PressKey":
30
- const keyConfig = KeyConfigs[action.key];
31
- if (keyConfig.type !== "KEYPAD_NAVIGATION") {
32
- // This is probably an anti-pattern but it works for the
33
- // case where we don't actually control the state but we
34
- // still want to communicate with the other object
35
- return {
36
- ...state,
37
- cursor: state.keyHandler?.(keyConfig.id),
38
- };
39
- }
40
-
41
- // TODO(kevinb) get state from MathQuill and store it?
42
- return state;
43
-
44
- case "SetCursor":
45
- return {
46
- ...state,
47
- cursor: action.cursor,
48
- };
49
-
50
- default:
51
- return state;
52
- }
53
- };
54
-
55
- export default inputReducer;