@khanacademy/math-input 8.1.1 → 8.1.3
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.
- package/CHANGELOG.md +14 -0
- package/dist/components/input/mathquill-types.d.ts +1 -1
- package/dist/components/input/mathquill-types.js.flow +4 -1
- package/dist/components/keypad/mobile-keypad.d.ts +2 -2
- package/dist/components/keypad/mobile-keypad.js.flow +1 -1
- package/dist/components/keypad-legacy/compute-layout-parameters.d.ts +6 -17
- package/dist/components/keypad-legacy/compute-layout-parameters.js.flow +13 -22
- package/dist/components/keypad-legacy/keypad-container.d.ts +2 -1
- package/dist/components/keypad-legacy/keypad-container.js.flow +7 -1
- package/dist/components/keypad-legacy/store/actions.d.ts +5 -3
- package/dist/components/keypad-legacy/store/actions.js.flow +8 -4
- package/dist/components/keypad-legacy/store/types.d.ts +14 -14
- package/dist/components/keypad-legacy/store/types.js.flow +14 -14
- package/dist/components/prop-types.d.ts +12 -0
- package/dist/components/prop-types.js.flow +17 -0
- package/dist/es/index.css +1 -1
- package/dist/es/index.js +133 -132
- package/dist/es/index.js.map +1 -1
- package/dist/fake-react-native-web/view.d.ts +1 -0
- package/dist/fake-react-native-web/view.js.flow +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +131 -134
- package/dist/index.js.flow +1 -0
- package/dist/index.js.map +1 -1
- package/index.html +17 -16
- package/less/echo.less +1 -1
- package/less/overrides.less +1 -1
- package/package.json +1 -1
- package/src/components/input/math-input.tsx +1 -0
- package/src/components/input/mathquill-types.ts +4 -1
- package/src/components/keypad/keypad-button.tsx +5 -3
- package/src/components/keypad/mobile-keypad.tsx +12 -2
- package/src/components/keypad-legacy/compute-layout-parameters.ts +127 -78
- package/src/components/keypad-legacy/keypad-button.tsx +2 -2
- package/src/components/keypad-legacy/keypad-container.tsx +30 -4
- package/src/components/keypad-legacy/store/actions.ts +12 -6
- package/src/components/keypad-legacy/store/layout-reducer.test.ts +171 -0
- package/src/components/keypad-legacy/store/layout-reducer.ts +46 -51
- package/src/components/keypad-legacy/store/types.ts +16 -14
- package/src/components/{prop-types.js → prop-types.ts} +1 -0
- package/src/fake-react-native-web/view.tsx +2 -0
- package/src/full-math-input.stories.tsx +2 -2
- package/src/index.ts +1 -0
- package/tsconfig-build.tsbuildinfo +1 -1
package/index.html
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Math Input</title>
|
|
7
|
+
<link
|
|
8
|
+
rel="stylesheet"
|
|
9
|
+
href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css"
|
|
10
|
+
/>
|
|
11
|
+
<style>
|
|
12
|
+
body {
|
|
13
|
+
margin: 0;
|
|
14
|
+
}
|
|
15
|
+
</style>
|
|
16
|
+
</head>
|
|
3
17
|
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
<title>Math Input</title>
|
|
8
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css">
|
|
9
|
-
<style>
|
|
10
|
-
body {
|
|
11
|
-
margin: 0;
|
|
12
|
-
}
|
|
13
|
-
</style>
|
|
14
|
-
</head>
|
|
15
|
-
|
|
16
|
-
<body>
|
|
17
|
-
<div id="root"></div>
|
|
18
|
-
</body>
|
|
19
|
-
|
|
18
|
+
<body>
|
|
19
|
+
<div id="root"></div>
|
|
20
|
+
</body>
|
|
20
21
|
</html>
|
package/less/echo.less
CHANGED
package/less/overrides.less
CHANGED
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
.mq-hasCursor:empty:not(.mq-root-block):after {
|
|
97
97
|
// Place a 'c' inside for sizing the cursor (for the case explained
|
|
98
98
|
// above); normally, MathQuill already does this for .mq-cursor.
|
|
99
|
-
content:
|
|
99
|
+
content: "c";
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
.mq-math-mode .mq-selection,
|
package/package.json
CHANGED
|
@@ -167,7 +167,10 @@ export type MathFieldConfig = {
|
|
|
167
167
|
edit?: (mathField: MathFieldInterface) => void;
|
|
168
168
|
enter?: (mathField: MathFieldInterface) => void;
|
|
169
169
|
|
|
170
|
-
moveOutOf?: (
|
|
170
|
+
moveOutOf?: (
|
|
171
|
+
direction: MathQuillDirection,
|
|
172
|
+
mathField: MathFieldInterface,
|
|
173
|
+
) => void;
|
|
171
174
|
upOutOf?: (mathField: MathFieldInterface) => void;
|
|
172
175
|
downOutOf?: (mathField: MathFieldInterface) => void;
|
|
173
176
|
|
|
@@ -78,19 +78,21 @@ const styles = StyleSheet.create({
|
|
|
78
78
|
boxSizing: "border-box",
|
|
79
79
|
background: Color.white,
|
|
80
80
|
borderRadius: 4,
|
|
81
|
-
|
|
81
|
+
borderWidth: 2,
|
|
82
|
+
borderStyle: "solid",
|
|
83
|
+
borderColor: "transparent",
|
|
82
84
|
flex: 1,
|
|
83
85
|
minHeight: 42,
|
|
84
86
|
minWidth: 42,
|
|
85
87
|
padding: 1,
|
|
86
88
|
},
|
|
87
89
|
hovered: {
|
|
88
|
-
|
|
90
|
+
borderColor: Color.blue,
|
|
89
91
|
padding: 1,
|
|
90
92
|
boxShadow: "none",
|
|
91
93
|
},
|
|
92
94
|
focused: {
|
|
93
|
-
|
|
95
|
+
borderColor: Color.blue,
|
|
94
96
|
padding: 0,
|
|
95
97
|
boxShadow: "none",
|
|
96
98
|
},
|
|
@@ -3,9 +3,15 @@ import {StyleSheet} from "aphrodite";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import ReactDOM from "react-dom";
|
|
5
5
|
|
|
6
|
-
import Key from "../../data/keys";
|
|
7
6
|
import {View} from "../../fake-react-native-web/index";
|
|
8
|
-
|
|
7
|
+
|
|
8
|
+
import type Key from "../../data/keys";
|
|
9
|
+
import type {
|
|
10
|
+
Cursor,
|
|
11
|
+
KeypadConfiguration,
|
|
12
|
+
KeyHandler,
|
|
13
|
+
KeypadAPI,
|
|
14
|
+
} from "../../types";
|
|
9
15
|
|
|
10
16
|
import Keypad from "./index";
|
|
11
17
|
|
|
@@ -91,11 +97,15 @@ class MobileKeypad extends React.Component<Props, State> implements KeypadAPI {
|
|
|
91
97
|
}
|
|
92
98
|
|
|
93
99
|
render(): React.ReactNode {
|
|
100
|
+
const {style} = this.props;
|
|
94
101
|
const {active, cursor, keypadConfig} = this.state;
|
|
95
102
|
|
|
96
103
|
const containerStyle = [
|
|
104
|
+
// internal styles
|
|
97
105
|
styles.keypadContainer,
|
|
98
106
|
active ? styles.activeKeypadContainer : null,
|
|
107
|
+
// styles passed as props
|
|
108
|
+
...(Array.isArray(style) ? style : [style]),
|
|
99
109
|
];
|
|
100
110
|
|
|
101
111
|
const isExpression = keypadConfig?.keypadType === "EXPRESSION";
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* might need to be.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import {
|
|
22
|
+
import {DeviceOrientation, LayoutMode} from "../../enums";
|
|
23
23
|
import {
|
|
24
24
|
pageIndicatorHeightPx,
|
|
25
25
|
toolbarHeightPx,
|
|
@@ -27,6 +27,8 @@ import {
|
|
|
27
27
|
innerBorderWidthPx,
|
|
28
28
|
} from "../common-style";
|
|
29
29
|
|
|
30
|
+
import {GridDimensions, WidthHeight} from "./store/types";
|
|
31
|
+
|
|
30
32
|
const minButtonHeight = 48;
|
|
31
33
|
const maxButtonSize = 64;
|
|
32
34
|
const minSpaceAboveKeypad = 32;
|
|
@@ -54,88 +56,135 @@ const maxPortraitBrowserChrome =
|
|
|
54
56
|
// difference when reserving space above the keypad.)
|
|
55
57
|
const worstCaseAspectRatio = 320 / (480 - safariNavBarWhenShrunk);
|
|
56
58
|
|
|
59
|
+
type ComputedLayoutProperty = {
|
|
60
|
+
buttonDimensions: WidthHeight;
|
|
61
|
+
layoutMode: LayoutMode;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
function getButtonWidth(
|
|
65
|
+
gridDimensions: GridDimensions,
|
|
66
|
+
containerDimensions: WidthHeight,
|
|
67
|
+
navigationPadEnabled: boolean,
|
|
68
|
+
paginationEnabled: boolean,
|
|
69
|
+
isLandscape: boolean,
|
|
70
|
+
): number {
|
|
71
|
+
const {numColumns, numPages} = gridDimensions;
|
|
72
|
+
|
|
73
|
+
// We can use the container width as the effective width.
|
|
74
|
+
let effectiveWidth = containerDimensions.width;
|
|
75
|
+
if (navigationPadEnabled) {
|
|
76
|
+
effectiveWidth -= navigationPadWidthPx;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let buttonWidthPx;
|
|
80
|
+
if (numPages > 1) {
|
|
81
|
+
const effectiveNumColumns = paginationEnabled
|
|
82
|
+
? numColumns
|
|
83
|
+
: numColumns * numPages;
|
|
84
|
+
buttonWidthPx = effectiveWidth / effectiveNumColumns;
|
|
85
|
+
} else {
|
|
86
|
+
buttonWidthPx = isLandscape
|
|
87
|
+
? maxButtonSize
|
|
88
|
+
: effectiveWidth / numColumns;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return buttonWidthPx;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function getButtonHeight(
|
|
95
|
+
gridDimensions: GridDimensions,
|
|
96
|
+
pageDimensions: WidthHeight,
|
|
97
|
+
containerDimensions: WidthHeight,
|
|
98
|
+
paginationEnabled: boolean,
|
|
99
|
+
toolbarEnabled: boolean,
|
|
100
|
+
isLandscape: boolean,
|
|
101
|
+
) {
|
|
102
|
+
const {numMaxVisibleRows} = gridDimensions;
|
|
103
|
+
|
|
104
|
+
// In many cases, the browser chrome will already have been factored
|
|
105
|
+
// into `pageHeight`. But we have no way of knowing if that's
|
|
106
|
+
// the case or not. As such, we take a conservative approach and
|
|
107
|
+
// assume that the chrome is _never_ included in `pageHeight`.
|
|
108
|
+
const browserChromeHeight = isLandscape
|
|
109
|
+
? maxLandscapeBrowserChrome
|
|
110
|
+
: maxPortraitBrowserChrome;
|
|
111
|
+
|
|
112
|
+
// Count up all the space that we need to reserve on the page.
|
|
113
|
+
// Namely, we need to account for:
|
|
114
|
+
// 1. Space between the keypad and the top of the page.
|
|
115
|
+
// 2. The presence of the exercise toolbar.
|
|
116
|
+
// 3. The presence of the view pager indicator.
|
|
117
|
+
// 4. Any browser chrome that may appear later.
|
|
118
|
+
const reservedSpace =
|
|
119
|
+
minSpaceAboveKeypad +
|
|
120
|
+
browserChromeHeight +
|
|
121
|
+
(toolbarEnabled ? toolbarHeightPx : 0) +
|
|
122
|
+
(paginationEnabled ? pageIndicatorHeightPx : 0);
|
|
123
|
+
|
|
124
|
+
// For the height, we take
|
|
125
|
+
// another conservative measure when in portrait by assuming that
|
|
126
|
+
// the device has the worst possible aspect ratio. In other words,
|
|
127
|
+
// we ignore the device height in portrait and assume the worst.
|
|
128
|
+
// This prevents the keypad from changing size when browser chrome
|
|
129
|
+
// appears and disappears.
|
|
130
|
+
const effectiveHeight = isLandscape
|
|
131
|
+
? pageDimensions.height
|
|
132
|
+
: containerDimensions.width / worstCaseAspectRatio;
|
|
133
|
+
|
|
134
|
+
// In computing the
|
|
135
|
+
// height, accommodate for the maximum number of rows that will ever be
|
|
136
|
+
// visible (since the toggling of popovers can increase the number of
|
|
137
|
+
// visible rows).
|
|
138
|
+
const maxKeypadHeight = effectiveHeight - reservedSpace;
|
|
139
|
+
|
|
140
|
+
const buttonHeightPx = Math.max(
|
|
141
|
+
Math.min(maxKeypadHeight / numMaxVisibleRows, maxButtonSize),
|
|
142
|
+
minButtonHeight,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
return buttonHeightPx;
|
|
146
|
+
}
|
|
147
|
+
|
|
57
148
|
export const computeLayoutParameters = (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
149
|
+
gridDimensions: GridDimensions,
|
|
150
|
+
pageDimensions: WidthHeight,
|
|
151
|
+
containerDimensions: WidthHeight,
|
|
152
|
+
deviceOrientation: DeviceOrientation,
|
|
153
|
+
navigationPadEnabled: boolean,
|
|
154
|
+
paginationEnabled: boolean,
|
|
155
|
+
toolbarEnabled: boolean,
|
|
156
|
+
): ComputedLayoutProperty => {
|
|
157
|
+
const {numColumns, numPages} = gridDimensions;
|
|
158
|
+
|
|
63
159
|
// First, compute some values that will be used in multiple computations.
|
|
64
160
|
const effectiveNumColumns = paginationEnabled
|
|
65
161
|
? numColumns
|
|
66
162
|
: numColumns * numPages;
|
|
67
163
|
|
|
68
164
|
// Then, compute the button dimensions based on the provided parameters.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
// Next, compute the effective width and height. We can use the page
|
|
94
|
-
// width as the effective width. For the height, though, we take
|
|
95
|
-
// another conservative measure when in portrait by assuming that
|
|
96
|
-
// the device has the worst possible aspect ratio. In other words,
|
|
97
|
-
// we ignore the device height in portrait and assume the worst.
|
|
98
|
-
// This prevents the keypad from changing size when browser chrome
|
|
99
|
-
// appears and disappears.
|
|
100
|
-
const effectiveWidth = pageWidthPx;
|
|
101
|
-
const effectiveHeight = isLandscape
|
|
102
|
-
? pageHeightPx
|
|
103
|
-
: pageWidthPx / worstCaseAspectRatio;
|
|
104
|
-
const maxKeypadHeight = effectiveHeight - reservedSpace;
|
|
105
|
-
|
|
106
|
-
// Finally, compute the button height and width. In computing the
|
|
107
|
-
// height, accommodate for the maximum number of rows that will ever be
|
|
108
|
-
// visible (since the toggling of popovers can increase the number of
|
|
109
|
-
// visible rows).
|
|
110
|
-
const buttonHeightPx = Math.max(
|
|
111
|
-
Math.min(maxKeypadHeight / numMaxVisibleRows, maxButtonSize),
|
|
112
|
-
minButtonHeight,
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
let buttonWidthPx;
|
|
116
|
-
if (numPages > 1) {
|
|
117
|
-
const effectiveNumColumns = paginationEnabled
|
|
118
|
-
? numColumns
|
|
119
|
-
: numColumns * numPages;
|
|
120
|
-
buttonWidthPx = effectiveWidth / effectiveNumColumns;
|
|
121
|
-
} else {
|
|
122
|
-
buttonWidthPx = isLandscape
|
|
123
|
-
? maxButtonSize
|
|
124
|
-
: effectiveWidth / numColumns;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
buttonDimensions = {
|
|
128
|
-
widthPx: buttonWidthPx,
|
|
129
|
-
heightPx: buttonHeightPx,
|
|
130
|
-
};
|
|
131
|
-
} else if (deviceType === DeviceType.TABLET) {
|
|
132
|
-
buttonDimensions = {
|
|
133
|
-
widthPx: maxButtonSize,
|
|
134
|
-
heightPx: maxButtonSize,
|
|
135
|
-
};
|
|
136
|
-
} else {
|
|
137
|
-
throw new Error("Invalid device type: " + deviceType);
|
|
138
|
-
}
|
|
165
|
+
const isLandscape = deviceOrientation === DeviceOrientation.LANDSCAPE;
|
|
166
|
+
|
|
167
|
+
const buttonWidth = getButtonWidth(
|
|
168
|
+
gridDimensions,
|
|
169
|
+
containerDimensions,
|
|
170
|
+
navigationPadEnabled,
|
|
171
|
+
paginationEnabled,
|
|
172
|
+
isLandscape,
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
const buttonHeight = getButtonHeight(
|
|
176
|
+
gridDimensions,
|
|
177
|
+
pageDimensions,
|
|
178
|
+
containerDimensions,
|
|
179
|
+
paginationEnabled,
|
|
180
|
+
toolbarEnabled,
|
|
181
|
+
isLandscape,
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const buttonDimensions = {
|
|
185
|
+
width: buttonWidth,
|
|
186
|
+
height: buttonHeight,
|
|
187
|
+
};
|
|
139
188
|
|
|
140
189
|
// Finally, determine whether the keypad should be rendered in the
|
|
141
190
|
// fullscreen layout by determining its resultant width.
|
|
@@ -143,13 +192,13 @@ export const computeLayoutParameters = (
|
|
|
143
192
|
(navigationPadEnabled ? 1 : 0) +
|
|
144
193
|
(!paginationEnabled ? numPages - 1 : 0);
|
|
145
194
|
const keypadWidth =
|
|
146
|
-
effectiveNumColumns * buttonDimensions.
|
|
195
|
+
effectiveNumColumns * buttonDimensions.width +
|
|
147
196
|
(navigationPadEnabled ? navigationPadWidthPx : 0) +
|
|
148
197
|
numSeparators * innerBorderWidthPx;
|
|
149
198
|
return {
|
|
150
199
|
buttonDimensions,
|
|
151
200
|
layoutMode:
|
|
152
|
-
keypadWidth >=
|
|
201
|
+
keypadWidth >= containerDimensions.width
|
|
153
202
|
? LayoutMode.FULLSCREEN
|
|
154
203
|
: LayoutMode.COMPACT,
|
|
155
204
|
};
|
|
@@ -356,8 +356,8 @@ const styleForButtonDimensions = (heightPx, widthPx) => {
|
|
|
356
356
|
|
|
357
357
|
const mapStateToProps = (state: State): ReduxProps => {
|
|
358
358
|
return {
|
|
359
|
-
heightPx: state.layout.buttonDimensions.
|
|
360
|
-
widthPx: state.layout.buttonDimensions.
|
|
359
|
+
heightPx: state.layout.buttonDimensions.height,
|
|
360
|
+
widthPx: state.layout.buttonDimensions.width,
|
|
361
361
|
};
|
|
362
362
|
};
|
|
363
363
|
|
|
@@ -34,7 +34,12 @@ interface ReduxProps {
|
|
|
34
34
|
interface Props extends ReduxProps {
|
|
35
35
|
onDismiss?: () => void;
|
|
36
36
|
onElementMounted: (element: any) => void;
|
|
37
|
-
onPageSizeChange?: (
|
|
37
|
+
onPageSizeChange?: (
|
|
38
|
+
pageWidth: number,
|
|
39
|
+
pageHeight: number,
|
|
40
|
+
containerWidth: number,
|
|
41
|
+
containerHeight: number,
|
|
42
|
+
) => void;
|
|
38
43
|
style?: StyleType;
|
|
39
44
|
}
|
|
40
45
|
|
|
@@ -45,6 +50,7 @@ type State = {
|
|
|
45
50
|
|
|
46
51
|
// eslint-disable-next-line react/no-unsafe
|
|
47
52
|
class KeypadContainer extends React.Component<Props, State> {
|
|
53
|
+
_containerRef = React.createRef<HTMLDivElement>();
|
|
48
54
|
_resizeTimeout: number | null | undefined;
|
|
49
55
|
hasMounted: boolean | undefined;
|
|
50
56
|
|
|
@@ -113,7 +119,14 @@ class KeypadContainer extends React.Component<Props, State> {
|
|
|
113
119
|
this.setState({
|
|
114
120
|
viewportWidth: window.innerWidth,
|
|
115
121
|
});
|
|
116
|
-
this.
|
|
122
|
+
const containerWidth = this._containerRef.current?.clientWidth || 0;
|
|
123
|
+
const containerHeight = this._containerRef.current?.clientHeight || 0;
|
|
124
|
+
this.props.onPageSizeChange?.(
|
|
125
|
+
window.innerWidth,
|
|
126
|
+
window.innerHeight,
|
|
127
|
+
containerWidth,
|
|
128
|
+
containerHeight,
|
|
129
|
+
);
|
|
117
130
|
};
|
|
118
131
|
|
|
119
132
|
renderKeypad = () => {
|
|
@@ -198,6 +211,7 @@ class KeypadContainer extends React.Component<Props, State> {
|
|
|
198
211
|
style={keypadContainerStyle}
|
|
199
212
|
dynamicStyle={dynamicStyle}
|
|
200
213
|
extraClassName="keypad-container"
|
|
214
|
+
forwardRef={this._containerRef}
|
|
201
215
|
>
|
|
202
216
|
<View
|
|
203
217
|
style={keypadStyle}
|
|
@@ -305,8 +319,20 @@ const mapStateToProps = (state: ReduxState): ReduxProps => {
|
|
|
305
319
|
|
|
306
320
|
const mapDispatchToProps = (dispatch) => {
|
|
307
321
|
return {
|
|
308
|
-
onPageSizeChange: (
|
|
309
|
-
|
|
322
|
+
onPageSizeChange: (
|
|
323
|
+
pageWidth: number,
|
|
324
|
+
pageHeight: number,
|
|
325
|
+
containerWidth: number,
|
|
326
|
+
containerHeight: number,
|
|
327
|
+
) => {
|
|
328
|
+
dispatch(
|
|
329
|
+
setPageSize(
|
|
330
|
+
pageWidth,
|
|
331
|
+
pageHeight,
|
|
332
|
+
containerWidth,
|
|
333
|
+
containerHeight,
|
|
334
|
+
),
|
|
335
|
+
);
|
|
310
336
|
},
|
|
311
337
|
};
|
|
312
338
|
};
|
|
@@ -51,18 +51,24 @@ export const configureKeypad = (
|
|
|
51
51
|
|
|
52
52
|
type SetPageSizeAction = {
|
|
53
53
|
type: "SetPageSize";
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
pageWidth: number;
|
|
55
|
+
pageHeight: number;
|
|
56
|
+
containerWidth: number;
|
|
57
|
+
containerHeight: number;
|
|
56
58
|
};
|
|
57
59
|
|
|
58
60
|
export const setPageSize = (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
pageWidth: number,
|
|
62
|
+
pageHeight: number,
|
|
63
|
+
containerWidth: number,
|
|
64
|
+
containerHeight: number,
|
|
61
65
|
): SetPageSizeAction => {
|
|
62
66
|
return {
|
|
63
67
|
type: "SetPageSize",
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
pageWidth,
|
|
69
|
+
pageHeight,
|
|
70
|
+
containerWidth,
|
|
71
|
+
containerHeight,
|
|
66
72
|
};
|
|
67
73
|
};
|
|
68
74
|
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {KeypadType} from "../../../enums";
|
|
2
|
+
|
|
3
|
+
import {configureKeypad, setPageSize} from "./actions";
|
|
4
|
+
import layoutReducer from "./layout-reducer";
|
|
5
|
+
|
|
6
|
+
function initState() {
|
|
7
|
+
// This is just simulating the Redux action that initializes state
|
|
8
|
+
// @ts-expect-error TS2345
|
|
9
|
+
let state = layoutReducer(undefined, {type: "@redux-init"});
|
|
10
|
+
state = layoutReducer(
|
|
11
|
+
state,
|
|
12
|
+
configureKeypad({keypadType: KeypadType.EXPRESSION}),
|
|
13
|
+
);
|
|
14
|
+
return state;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe("layout reducer", () => {
|
|
18
|
+
it("enables pagination on small screens portrait (iPhone)", () => {
|
|
19
|
+
// Arrange
|
|
20
|
+
let state = initState();
|
|
21
|
+
|
|
22
|
+
// Act
|
|
23
|
+
state = layoutReducer(state, setPageSize(375, 812, 375, 812));
|
|
24
|
+
|
|
25
|
+
// Assert
|
|
26
|
+
expect(state.paginationEnabled).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("does not enable navigation pad on small screens portrait (iPhone)", () => {
|
|
30
|
+
// Arrange
|
|
31
|
+
let state = initState();
|
|
32
|
+
|
|
33
|
+
// Act
|
|
34
|
+
state = layoutReducer(state, setPageSize(375, 812, 375, 812));
|
|
35
|
+
|
|
36
|
+
// Assert
|
|
37
|
+
expect(state.navigationPadEnabled).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("does not enable pagination on medium screens portrait (iPad Mini)", () => {
|
|
41
|
+
// Arrange
|
|
42
|
+
let state = initState();
|
|
43
|
+
|
|
44
|
+
// Act
|
|
45
|
+
state = layoutReducer(state, setPageSize(768, 1024, 768, 1024));
|
|
46
|
+
|
|
47
|
+
// Assert
|
|
48
|
+
expect(state.paginationEnabled).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("does not enable navigation pad on medium screens portrait (iPad Mini)", () => {
|
|
52
|
+
// Arrange
|
|
53
|
+
let state = initState();
|
|
54
|
+
|
|
55
|
+
// Act
|
|
56
|
+
state = layoutReducer(state, setPageSize(768, 1024, 768, 1024));
|
|
57
|
+
|
|
58
|
+
// Assert
|
|
59
|
+
expect(state.navigationPadEnabled).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("does not enable pagination on large screens portrait (iPad)", () => {
|
|
63
|
+
// Arrange
|
|
64
|
+
let state = initState();
|
|
65
|
+
|
|
66
|
+
// Act
|
|
67
|
+
state = layoutReducer(state, setPageSize(810, 1080, 810, 1080));
|
|
68
|
+
|
|
69
|
+
// Assert
|
|
70
|
+
expect(state.paginationEnabled).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("does enable navigation pad on large screens portrait (iPad)", () => {
|
|
74
|
+
// Arrange
|
|
75
|
+
let state = initState();
|
|
76
|
+
|
|
77
|
+
// Act
|
|
78
|
+
state = layoutReducer(state, setPageSize(810, 1080, 810, 1080));
|
|
79
|
+
|
|
80
|
+
// Assert
|
|
81
|
+
expect(state.navigationPadEnabled).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("does not enable pagination on small screens landscape (iPhone)", () => {
|
|
85
|
+
// Arrange
|
|
86
|
+
let state = initState();
|
|
87
|
+
|
|
88
|
+
// Act
|
|
89
|
+
state = layoutReducer(state, setPageSize(812, 375, 812, 375));
|
|
90
|
+
|
|
91
|
+
// Assert
|
|
92
|
+
expect(state.paginationEnabled).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("does enable navigation pad on small screens landscape (iPhone)", () => {
|
|
96
|
+
// Arrange
|
|
97
|
+
let state = initState();
|
|
98
|
+
|
|
99
|
+
// Act
|
|
100
|
+
state = layoutReducer(state, setPageSize(812, 375, 812, 375));
|
|
101
|
+
|
|
102
|
+
// Assert
|
|
103
|
+
expect(state.navigationPadEnabled).toBe(true);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("does not enable pagination on medium screens landscape (iPad Mini)", () => {
|
|
107
|
+
// Arrange
|
|
108
|
+
let state = initState();
|
|
109
|
+
|
|
110
|
+
// Act
|
|
111
|
+
state = layoutReducer(state, setPageSize(1024, 768, 1024, 768));
|
|
112
|
+
|
|
113
|
+
// Assert
|
|
114
|
+
expect(state.paginationEnabled).toBe(false);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("does enable navigation pad on medium screens landscape (iPad Mini)", () => {
|
|
118
|
+
// Arrange
|
|
119
|
+
let state = initState();
|
|
120
|
+
|
|
121
|
+
// Act
|
|
122
|
+
state = layoutReducer(state, setPageSize(1024, 768, 1024, 768));
|
|
123
|
+
|
|
124
|
+
// Assert
|
|
125
|
+
expect(state.navigationPadEnabled).toBe(true);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("does not enable pagination on large screens landscape (iPad)", () => {
|
|
129
|
+
// Arrange
|
|
130
|
+
let state = initState();
|
|
131
|
+
|
|
132
|
+
// Act
|
|
133
|
+
state = layoutReducer(state, setPageSize(1080, 810, 1080, 810));
|
|
134
|
+
|
|
135
|
+
// Assert
|
|
136
|
+
expect(state.paginationEnabled).toBe(false);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("does enable navigation pad on large screens landscape (iPad)", () => {
|
|
140
|
+
// Arrange
|
|
141
|
+
let state = initState();
|
|
142
|
+
|
|
143
|
+
// Act
|
|
144
|
+
state = layoutReducer(state, setPageSize(1080, 810, 1080, 810));
|
|
145
|
+
|
|
146
|
+
// Assert
|
|
147
|
+
expect(state.navigationPadEnabled).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("does enable pagination in small containers on big screens", () => {
|
|
151
|
+
// Arrange
|
|
152
|
+
let state = initState();
|
|
153
|
+
|
|
154
|
+
// Act
|
|
155
|
+
state = layoutReducer(state, setPageSize(2000, 2000, 300, 300));
|
|
156
|
+
|
|
157
|
+
// Assert
|
|
158
|
+
expect(state.paginationEnabled).toBe(true);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("does not enable navigation in small containers on big screens", () => {
|
|
162
|
+
// Arrange
|
|
163
|
+
let state = initState();
|
|
164
|
+
|
|
165
|
+
// Act
|
|
166
|
+
state = layoutReducer(state, setPageSize(2000, 2000, 300, 300));
|
|
167
|
+
|
|
168
|
+
// Assert
|
|
169
|
+
expect(state.navigationPadEnabled).toBe(false);
|
|
170
|
+
});
|
|
171
|
+
});
|