@khanacademy/math-input 8.1.1 → 8.1.2
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 +8 -0
- 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/es/index.css +1 -1
- package/dist/es/index.js +132 -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.js +130 -134
- 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/keypad/keypad-button.tsx +5 -3
- package/src/components/keypad/mobile-keypad.tsx +4 -0
- 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/fake-react-native-web/view.tsx +2 -0
- package/src/full-math-input.stories.tsx +1 -1
- package/tsconfig-build.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @khanacademy/math-input
|
|
2
2
|
|
|
3
|
+
## 8.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ea9dac75: Bugfix: allow legacy keypad to be positioned absolutely in column
|
|
8
|
+
- 30a99b82: Allow v2 keypad to receive style prop like v1 keypad
|
|
9
|
+
- 3fa556a3: Fixes bug where mouse hover causes grid to expand
|
|
10
|
+
|
|
3
11
|
## 8.1.1
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
|
@@ -18,22 +18,11 @@
|
|
|
18
18
|
* to be conservative in our measurements and make things smaller than they
|
|
19
19
|
* might need to be.
|
|
20
20
|
*/
|
|
21
|
-
import { LayoutMode } from "../../enums";
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
numPages: any;
|
|
26
|
-
}, { pageWidthPx, pageHeightPx }: {
|
|
27
|
-
pageWidthPx: any;
|
|
28
|
-
pageHeightPx: any;
|
|
29
|
-
}, { deviceOrientation, deviceType }: {
|
|
30
|
-
deviceOrientation: any;
|
|
31
|
-
deviceType: any;
|
|
32
|
-
}, { navigationPadEnabled, paginationEnabled, toolbarEnabled }: {
|
|
33
|
-
navigationPadEnabled: any;
|
|
34
|
-
paginationEnabled: any;
|
|
35
|
-
toolbarEnabled: any;
|
|
36
|
-
}) => {
|
|
37
|
-
buttonDimensions: any;
|
|
21
|
+
import { DeviceOrientation, LayoutMode } from "../../enums";
|
|
22
|
+
import { GridDimensions, WidthHeight } from "./store/types";
|
|
23
|
+
type ComputedLayoutProperty = {
|
|
24
|
+
buttonDimensions: WidthHeight;
|
|
38
25
|
layoutMode: LayoutMode;
|
|
39
26
|
};
|
|
27
|
+
export declare const computeLayoutParameters: (gridDimensions: GridDimensions, pageDimensions: WidthHeight, containerDimensions: WidthHeight, deviceOrientation: DeviceOrientation, navigationPadEnabled: boolean, paginationEnabled: boolean, toolbarEnabled: boolean) => ComputedLayoutProperty;
|
|
28
|
+
export {};
|
|
@@ -4,27 +4,18 @@
|
|
|
4
4
|
* Flowgen v1.21.0
|
|
5
5
|
* @flow
|
|
6
6
|
*/
|
|
7
|
-
import { LayoutMode } from "../../enums";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
numMaxVisibleRows: any,
|
|
12
|
-
numPages: any,
|
|
13
|
-
|},
|
|
14
|
-
x: {|
|
|
15
|
-
pageWidthPx: any,
|
|
16
|
-
pageHeightPx: any,
|
|
17
|
-
|},
|
|
18
|
-
x: {|
|
|
19
|
-
deviceOrientation: any,
|
|
20
|
-
deviceType: any,
|
|
21
|
-
|},
|
|
22
|
-
x: {|
|
|
23
|
-
navigationPadEnabled: any,
|
|
24
|
-
paginationEnabled: any,
|
|
25
|
-
toolbarEnabled: any,
|
|
26
|
-
|}
|
|
27
|
-
) => {|
|
|
28
|
-
buttonDimensions: any,
|
|
7
|
+
import { DeviceOrientation, LayoutMode } from "../../enums";
|
|
8
|
+
import { GridDimensions, WidthHeight } from "./store/types";
|
|
9
|
+
declare type ComputedLayoutProperty = {|
|
|
10
|
+
buttonDimensions: WidthHeight,
|
|
29
11
|
layoutMode: LayoutMode,
|
|
30
12
|
|};
|
|
13
|
+
declare export var computeLayoutParameters: (
|
|
14
|
+
gridDimensions: GridDimensions,
|
|
15
|
+
pageDimensions: WidthHeight,
|
|
16
|
+
containerDimensions: WidthHeight,
|
|
17
|
+
deviceOrientation: DeviceOrientation,
|
|
18
|
+
navigationPadEnabled: boolean,
|
|
19
|
+
paginationEnabled: boolean,
|
|
20
|
+
toolbarEnabled: boolean
|
|
21
|
+
) => ComputedLayoutProperty;
|
|
@@ -11,7 +11,7 @@ interface ReduxProps {
|
|
|
11
11
|
interface Props extends ReduxProps {
|
|
12
12
|
onDismiss?: () => void;
|
|
13
13
|
onElementMounted: (element: any) => void;
|
|
14
|
-
onPageSizeChange?: (
|
|
14
|
+
onPageSizeChange?: (pageWidth: number, pageHeight: number, containerWidth: number, containerHeight: number) => void;
|
|
15
15
|
style?: StyleType;
|
|
16
16
|
}
|
|
17
17
|
type State = {
|
|
@@ -19,6 +19,7 @@ type State = {
|
|
|
19
19
|
viewportWidth: string | number;
|
|
20
20
|
};
|
|
21
21
|
declare class KeypadContainer extends React.Component<Props, State> {
|
|
22
|
+
_containerRef: React.RefObject<HTMLDivElement>;
|
|
22
23
|
_resizeTimeout: number | null | undefined;
|
|
23
24
|
hasMounted: boolean | undefined;
|
|
24
25
|
state: {
|
|
@@ -18,7 +18,12 @@ declare interface ReduxProps {
|
|
|
18
18
|
declare type Props = {
|
|
19
19
|
onDismiss?: () => void,
|
|
20
20
|
onElementMounted: (element: any) => void,
|
|
21
|
-
onPageSizeChange?: (
|
|
21
|
+
onPageSizeChange?: (
|
|
22
|
+
pageWidth: number,
|
|
23
|
+
pageHeight: number,
|
|
24
|
+
containerWidth: number,
|
|
25
|
+
containerHeight: number
|
|
26
|
+
) => void,
|
|
22
27
|
style?: StyleType,
|
|
23
28
|
} & ReduxProps;
|
|
24
29
|
declare type State = {|
|
|
@@ -26,6 +31,7 @@ declare type State = {|
|
|
|
26
31
|
viewportWidth: string | number,
|
|
27
32
|
|};
|
|
28
33
|
declare class KeypadContainer extends React.Component<Props, State> {
|
|
34
|
+
_containerRef: React.RefObject<HTMLDivElement>;
|
|
29
35
|
_resizeTimeout: number | null | void;
|
|
30
36
|
hasMounted: boolean | void;
|
|
31
37
|
state: {|
|
|
@@ -18,10 +18,12 @@ type ConfigureKeypadAction = {
|
|
|
18
18
|
export declare const configureKeypad: (configuration: KeypadConfiguration) => ConfigureKeypadAction;
|
|
19
19
|
type SetPageSizeAction = {
|
|
20
20
|
type: "SetPageSize";
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
pageWidth: number;
|
|
22
|
+
pageHeight: number;
|
|
23
|
+
containerWidth: number;
|
|
24
|
+
containerHeight: number;
|
|
23
25
|
};
|
|
24
|
-
export declare const setPageSize: (
|
|
26
|
+
export declare const setPageSize: (pageWidth: number, pageHeight: number, containerWidth: number, containerHeight: number) => SetPageSizeAction;
|
|
25
27
|
type RemoveEchoAction = {
|
|
26
28
|
type: "RemoveEcho";
|
|
27
29
|
animationId: string;
|
|
@@ -32,12 +32,16 @@ declare export var configureKeypad: (
|
|
|
32
32
|
) => ConfigureKeypadAction;
|
|
33
33
|
declare type SetPageSizeAction = {|
|
|
34
34
|
type: "SetPageSize",
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
pageWidth: number,
|
|
36
|
+
pageHeight: number,
|
|
37
|
+
containerWidth: number,
|
|
38
|
+
containerHeight: number,
|
|
37
39
|
|};
|
|
38
40
|
declare export var setPageSize: (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
pageWidth: number,
|
|
42
|
+
pageHeight: number,
|
|
43
|
+
containerWidth: number,
|
|
44
|
+
containerHeight: number
|
|
41
45
|
) => SetPageSizeAction;
|
|
42
46
|
declare type RemoveEchoAction = {|
|
|
43
47
|
type: "RemoveEcho",
|
|
@@ -19,21 +19,21 @@ export interface GestureState {
|
|
|
19
19
|
export interface EchoState {
|
|
20
20
|
echoes: ReadonlyArray<Echo>;
|
|
21
21
|
}
|
|
22
|
+
export type GridDimensions = {
|
|
23
|
+
numRows: number;
|
|
24
|
+
numColumns: number;
|
|
25
|
+
numMaxVisibleRows: number;
|
|
26
|
+
numPages: number;
|
|
27
|
+
};
|
|
28
|
+
export type WidthHeight = {
|
|
29
|
+
width: number;
|
|
30
|
+
height: number;
|
|
31
|
+
};
|
|
22
32
|
export interface LayoutState {
|
|
23
|
-
gridDimensions:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
numPages: number;
|
|
28
|
-
};
|
|
29
|
-
buttonDimensions: {
|
|
30
|
-
widthPx: number;
|
|
31
|
-
heightPx: number;
|
|
32
|
-
};
|
|
33
|
-
pageDimensions: {
|
|
34
|
-
pageWidthPx: number;
|
|
35
|
-
pageHeightPx: number;
|
|
36
|
-
};
|
|
33
|
+
gridDimensions: GridDimensions;
|
|
34
|
+
buttonDimensions: WidthHeight;
|
|
35
|
+
containerDimensions: WidthHeight;
|
|
36
|
+
pageDimensions: WidthHeight;
|
|
37
37
|
layoutMode: LayoutMode;
|
|
38
38
|
paginationEnabled: boolean;
|
|
39
39
|
navigationPadEnabled: boolean;
|
|
@@ -25,21 +25,21 @@ export interface GestureState {
|
|
|
25
25
|
export interface EchoState {
|
|
26
26
|
echoes: $ReadOnlyArray<Echo>;
|
|
27
27
|
}
|
|
28
|
+
export type GridDimensions = {|
|
|
29
|
+
numRows: number,
|
|
30
|
+
numColumns: number,
|
|
31
|
+
numMaxVisibleRows: number,
|
|
32
|
+
numPages: number,
|
|
33
|
+
|};
|
|
34
|
+
export type WidthHeight = {|
|
|
35
|
+
width: number,
|
|
36
|
+
height: number,
|
|
37
|
+
|};
|
|
28
38
|
export interface LayoutState {
|
|
29
|
-
gridDimensions:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
numPages: number,
|
|
34
|
-
|};
|
|
35
|
-
buttonDimensions: {|
|
|
36
|
-
widthPx: number,
|
|
37
|
-
heightPx: number,
|
|
38
|
-
|};
|
|
39
|
-
pageDimensions: {|
|
|
40
|
-
pageWidthPx: number,
|
|
41
|
-
pageHeightPx: number,
|
|
42
|
-
|};
|
|
39
|
+
gridDimensions: GridDimensions;
|
|
40
|
+
buttonDimensions: WidthHeight;
|
|
41
|
+
containerDimensions: WidthHeight;
|
|
42
|
+
pageDimensions: WidthHeight;
|
|
43
43
|
layoutMode: LayoutMode;
|
|
44
44
|
paginationEnabled: boolean;
|
|
45
45
|
navigationPadEnabled: boolean;
|
package/dist/es/index.css
CHANGED
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
border-color: white;
|
|
103
103
|
}
|
|
104
104
|
.keypad-input .mq-hasCursor:empty:not(.mq-root-block):after {
|
|
105
|
-
content:
|
|
105
|
+
content: "c";
|
|
106
106
|
}
|
|
107
107
|
.keypad-input .mq-math-mode .mq-selection .mq-non-leaf,
|
|
108
108
|
.keypad-input .mq-editable-field .mq-selection .mq-non-leaf {
|
package/dist/es/index.js
CHANGED
|
@@ -79,7 +79,8 @@ class View extends React.Component {
|
|
|
79
79
|
onTouchMove: this.props.onTouchMove,
|
|
80
80
|
onTouchStart: this.props.onTouchStart,
|
|
81
81
|
"aria-label": this.props.ariaLabel,
|
|
82
|
-
role: this.props.role
|
|
82
|
+
role: this.props.role,
|
|
83
|
+
ref: this.props.forwardRef
|
|
83
84
|
}, this.props.children);
|
|
84
85
|
}
|
|
85
86
|
}
|
|
@@ -142,10 +143,6 @@ const innerBorderColor = offBlack16;
|
|
|
142
143
|
const innerBorderStyle = "solid";
|
|
143
144
|
const innerBorderWidthPx = 1;
|
|
144
145
|
|
|
145
|
-
// The width at which a device is classified as a "tablet" for the purposes
|
|
146
|
-
// of the keypad layout.
|
|
147
|
-
const tabletCutoffPx = 600;
|
|
148
|
-
|
|
149
146
|
// The dimensions that define various components in the tree, which may be
|
|
150
147
|
// needed outside of those components in order to determine various layout
|
|
151
148
|
// parameters.
|
|
@@ -862,11 +859,6 @@ let DeviceOrientation = /*#__PURE__*/function (DeviceOrientation) {
|
|
|
862
859
|
DeviceOrientation["PORTRAIT"] = "PORTRAIT";
|
|
863
860
|
return DeviceOrientation;
|
|
864
861
|
}({});
|
|
865
|
-
let DeviceType = /*#__PURE__*/function (DeviceType) {
|
|
866
|
-
DeviceType["PHONE"] = "PHONE";
|
|
867
|
-
DeviceType["TABLET"] = "TABLET";
|
|
868
|
-
return DeviceType;
|
|
869
|
-
}({});
|
|
870
862
|
let LayoutMode = /*#__PURE__*/function (LayoutMode) {
|
|
871
863
|
LayoutMode["FULLSCREEN"] = "FULLSCREEN";
|
|
872
864
|
LayoutMode["COMPACT"] = "COMPACT";
|
|
@@ -3833,19 +3825,21 @@ const styles$e = StyleSheet.create({
|
|
|
3833
3825
|
boxSizing: "border-box",
|
|
3834
3826
|
background: Color.white,
|
|
3835
3827
|
borderRadius: 4,
|
|
3836
|
-
|
|
3828
|
+
borderWidth: 2,
|
|
3829
|
+
borderStyle: "solid",
|
|
3830
|
+
borderColor: "transparent",
|
|
3837
3831
|
flex: 1,
|
|
3838
3832
|
minHeight: 42,
|
|
3839
3833
|
minWidth: 42,
|
|
3840
3834
|
padding: 1
|
|
3841
3835
|
},
|
|
3842
3836
|
hovered: {
|
|
3843
|
-
|
|
3837
|
+
borderColor: Color.blue,
|
|
3844
3838
|
padding: 1,
|
|
3845
3839
|
boxShadow: "none"
|
|
3846
3840
|
},
|
|
3847
3841
|
focused: {
|
|
3848
|
-
|
|
3842
|
+
borderColor: Color.blue,
|
|
3849
3843
|
padding: 0,
|
|
3850
3844
|
boxShadow: "none"
|
|
3851
3845
|
},
|
|
@@ -4299,12 +4293,19 @@ class MobileKeypad extends React.Component {
|
|
|
4299
4293
|
});
|
|
4300
4294
|
}
|
|
4301
4295
|
render() {
|
|
4296
|
+
const {
|
|
4297
|
+
style
|
|
4298
|
+
} = this.props;
|
|
4302
4299
|
const {
|
|
4303
4300
|
active,
|
|
4304
4301
|
cursor,
|
|
4305
4302
|
keypadConfig
|
|
4306
4303
|
} = this.state;
|
|
4307
|
-
const containerStyle = [
|
|
4304
|
+
const containerStyle = [
|
|
4305
|
+
// internal styles
|
|
4306
|
+
styles$c.keypadContainer, active ? styles$c.activeKeypadContainer : null,
|
|
4307
|
+
// styles passed as props
|
|
4308
|
+
...(Array.isArray(style) ? style : [style])];
|
|
4308
4309
|
const isExpression = (keypadConfig == null ? void 0 : keypadConfig.keypadType) === "EXPRESSION";
|
|
4309
4310
|
return /*#__PURE__*/React.createElement(View, {
|
|
4310
4311
|
style: containerStyle,
|
|
@@ -6221,8 +6222,8 @@ const styleForButtonDimensions = (heightPx, widthPx) => {
|
|
|
6221
6222
|
};
|
|
6222
6223
|
const mapStateToProps$7 = state => {
|
|
6223
6224
|
return {
|
|
6224
|
-
heightPx: state.layout.buttonDimensions.
|
|
6225
|
-
widthPx: state.layout.buttonDimensions.
|
|
6225
|
+
heightPx: state.layout.buttonDimensions.height,
|
|
6226
|
+
widthPx: state.layout.buttonDimensions.width
|
|
6226
6227
|
};
|
|
6227
6228
|
};
|
|
6228
6229
|
var KeypadButton$1 = connect(mapStateToProps$7, null, null, {
|
|
@@ -6631,11 +6632,13 @@ const configureKeypad = configuration => {
|
|
|
6631
6632
|
configuration
|
|
6632
6633
|
};
|
|
6633
6634
|
};
|
|
6634
|
-
const setPageSize = (
|
|
6635
|
+
const setPageSize = (pageWidth, pageHeight, containerWidth, containerHeight) => {
|
|
6635
6636
|
return {
|
|
6636
6637
|
type: "SetPageSize",
|
|
6637
|
-
|
|
6638
|
-
|
|
6638
|
+
pageWidth,
|
|
6639
|
+
pageHeight,
|
|
6640
|
+
containerWidth,
|
|
6641
|
+
containerHeight
|
|
6639
6642
|
};
|
|
6640
6643
|
};
|
|
6641
6644
|
const removeEcho = animationId => {
|
|
@@ -7362,6 +7365,7 @@ const {
|
|
|
7362
7365
|
class KeypadContainer extends React.Component {
|
|
7363
7366
|
constructor(...args) {
|
|
7364
7367
|
super(...args);
|
|
7368
|
+
this._containerRef = /*#__PURE__*/React.createRef();
|
|
7365
7369
|
this._resizeTimeout = void 0;
|
|
7366
7370
|
this.hasMounted = void 0;
|
|
7367
7371
|
this.state = {
|
|
@@ -7379,13 +7383,15 @@ class KeypadContainer extends React.Component {
|
|
|
7379
7383
|
}
|
|
7380
7384
|
};
|
|
7381
7385
|
this._onResize = () => {
|
|
7382
|
-
var _this$props$onPageSiz, _this$props;
|
|
7386
|
+
var _this$_containerRef$c, _this$_containerRef$c2, _this$props$onPageSiz, _this$props;
|
|
7383
7387
|
// Whenever the page resizes, we need to force an update, as the button
|
|
7384
7388
|
// heights and keypad width are computed based on horizontal space.
|
|
7385
7389
|
this.setState({
|
|
7386
7390
|
viewportWidth: window.innerWidth
|
|
7387
7391
|
});
|
|
7388
|
-
|
|
7392
|
+
const containerWidth = ((_this$_containerRef$c = this._containerRef.current) == null ? void 0 : _this$_containerRef$c.clientWidth) || 0;
|
|
7393
|
+
const containerHeight = ((_this$_containerRef$c2 = this._containerRef.current) == null ? void 0 : _this$_containerRef$c2.clientHeight) || 0;
|
|
7394
|
+
(_this$props$onPageSiz = (_this$props = this.props).onPageSizeChange) == null ? void 0 : _this$props$onPageSiz.call(_this$props, window.innerWidth, window.innerHeight, containerWidth, containerHeight);
|
|
7389
7395
|
};
|
|
7390
7396
|
this.renderKeypad = () => {
|
|
7391
7397
|
const {
|
|
@@ -7480,7 +7486,8 @@ class KeypadContainer extends React.Component {
|
|
|
7480
7486
|
return /*#__PURE__*/React.createElement(View, {
|
|
7481
7487
|
style: keypadContainerStyle,
|
|
7482
7488
|
dynamicStyle: dynamicStyle,
|
|
7483
|
-
extraClassName: "keypad-container"
|
|
7489
|
+
extraClassName: "keypad-container",
|
|
7490
|
+
forwardRef: this._containerRef
|
|
7484
7491
|
}, /*#__PURE__*/React.createElement(View, {
|
|
7485
7492
|
style: keypadStyle,
|
|
7486
7493
|
ref: element => {
|
|
@@ -7566,8 +7573,8 @@ const mapStateToProps = state => {
|
|
|
7566
7573
|
};
|
|
7567
7574
|
const mapDispatchToProps = dispatch => {
|
|
7568
7575
|
return {
|
|
7569
|
-
onPageSizeChange: (
|
|
7570
|
-
dispatch(setPageSize(
|
|
7576
|
+
onPageSizeChange: (pageWidth, pageHeight, containerWidth, containerHeight) => {
|
|
7577
|
+
dispatch(setPageSize(pageWidth, pageHeight, containerWidth, containerHeight));
|
|
7571
7578
|
}
|
|
7572
7579
|
};
|
|
7573
7580
|
};
|
|
@@ -8494,89 +8501,91 @@ const maxPortraitBrowserChrome = safariToolbar + (safariNavBarWhenExpanded - saf
|
|
|
8494
8501
|
// (We don't need to account for the expanded navbar, since we include the
|
|
8495
8502
|
// difference when reserving space above the keypad.)
|
|
8496
8503
|
const worstCaseAspectRatio = 320 / (480 - safariNavBarWhenShrunk);
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
}
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
}
|
|
8508
|
-
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8504
|
+
function getButtonWidth(gridDimensions, containerDimensions, navigationPadEnabled, paginationEnabled, isLandscape) {
|
|
8505
|
+
const {
|
|
8506
|
+
numColumns,
|
|
8507
|
+
numPages
|
|
8508
|
+
} = gridDimensions;
|
|
8509
|
+
|
|
8510
|
+
// We can use the container width as the effective width.
|
|
8511
|
+
let effectiveWidth = containerDimensions.width;
|
|
8512
|
+
if (navigationPadEnabled) {
|
|
8513
|
+
effectiveWidth -= navigationPadWidthPx;
|
|
8514
|
+
}
|
|
8515
|
+
let buttonWidthPx;
|
|
8516
|
+
if (numPages > 1) {
|
|
8517
|
+
const effectiveNumColumns = paginationEnabled ? numColumns : numColumns * numPages;
|
|
8518
|
+
buttonWidthPx = effectiveWidth / effectiveNumColumns;
|
|
8519
|
+
} else {
|
|
8520
|
+
buttonWidthPx = isLandscape ? maxButtonSize : effectiveWidth / numColumns;
|
|
8521
|
+
}
|
|
8522
|
+
return buttonWidthPx;
|
|
8523
|
+
}
|
|
8524
|
+
function getButtonHeight(gridDimensions, pageDimensions, containerDimensions, paginationEnabled, toolbarEnabled, isLandscape) {
|
|
8525
|
+
const {
|
|
8526
|
+
numMaxVisibleRows
|
|
8527
|
+
} = gridDimensions;
|
|
8528
|
+
|
|
8529
|
+
// In many cases, the browser chrome will already have been factored
|
|
8530
|
+
// into `pageHeight`. But we have no way of knowing if that's
|
|
8531
|
+
// the case or not. As such, we take a conservative approach and
|
|
8532
|
+
// assume that the chrome is _never_ included in `pageHeight`.
|
|
8533
|
+
const browserChromeHeight = isLandscape ? maxLandscapeBrowserChrome : maxPortraitBrowserChrome;
|
|
8534
|
+
|
|
8535
|
+
// Count up all the space that we need to reserve on the page.
|
|
8536
|
+
// Namely, we need to account for:
|
|
8537
|
+
// 1. Space between the keypad and the top of the page.
|
|
8538
|
+
// 2. The presence of the exercise toolbar.
|
|
8539
|
+
// 3. The presence of the view pager indicator.
|
|
8540
|
+
// 4. Any browser chrome that may appear later.
|
|
8541
|
+
const reservedSpace = minSpaceAboveKeypad + browserChromeHeight + (toolbarEnabled ? toolbarHeightPx : 0) + (paginationEnabled ? pageIndicatorHeightPx : 0);
|
|
8542
|
+
|
|
8543
|
+
// For the height, we take
|
|
8544
|
+
// another conservative measure when in portrait by assuming that
|
|
8545
|
+
// the device has the worst possible aspect ratio. In other words,
|
|
8546
|
+
// we ignore the device height in portrait and assume the worst.
|
|
8547
|
+
// This prevents the keypad from changing size when browser chrome
|
|
8548
|
+
// appears and disappears.
|
|
8549
|
+
const effectiveHeight = isLandscape ? pageDimensions.height : containerDimensions.width / worstCaseAspectRatio;
|
|
8550
|
+
|
|
8551
|
+
// In computing the
|
|
8552
|
+
// height, accommodate for the maximum number of rows that will ever be
|
|
8553
|
+
// visible (since the toggling of popovers can increase the number of
|
|
8554
|
+
// visible rows).
|
|
8555
|
+
const maxKeypadHeight = effectiveHeight - reservedSpace;
|
|
8556
|
+
const buttonHeightPx = Math.max(Math.min(maxKeypadHeight / numMaxVisibleRows, maxButtonSize), minButtonHeight);
|
|
8557
|
+
return buttonHeightPx;
|
|
8558
|
+
}
|
|
8559
|
+
const computeLayoutParameters = (gridDimensions, pageDimensions, containerDimensions, deviceOrientation, navigationPadEnabled, paginationEnabled, toolbarEnabled) => {
|
|
8560
|
+
const {
|
|
8561
|
+
numColumns,
|
|
8562
|
+
numPages
|
|
8563
|
+
} = gridDimensions;
|
|
8564
|
+
|
|
8512
8565
|
// First, compute some values that will be used in multiple computations.
|
|
8513
8566
|
const effectiveNumColumns = paginationEnabled ? numColumns : numColumns * numPages;
|
|
8514
8567
|
|
|
8515
8568
|
// Then, compute the button dimensions based on the provided parameters.
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
|
|
8523
|
-
// assume that the chrome is _never_ included in `pageHeightPx`.
|
|
8524
|
-
const browserChromeHeight = isLandscape ? maxLandscapeBrowserChrome : maxPortraitBrowserChrome;
|
|
8525
|
-
|
|
8526
|
-
// Count up all the space that we need to reserve on the page.
|
|
8527
|
-
// Namely, we need to account for:
|
|
8528
|
-
// 1. Space between the keypad and the top of the page.
|
|
8529
|
-
// 2. The presence of the exercise toolbar.
|
|
8530
|
-
// 3. The presence of the view pager indicator.
|
|
8531
|
-
// 4. Any browser chrome that may appear later.
|
|
8532
|
-
const reservedSpace = minSpaceAboveKeypad + browserChromeHeight + (toolbarEnabled ? toolbarHeightPx : 0) + (paginationEnabled ? pageIndicatorHeightPx : 0);
|
|
8533
|
-
|
|
8534
|
-
// Next, compute the effective width and height. We can use the page
|
|
8535
|
-
// width as the effective width. For the height, though, we take
|
|
8536
|
-
// another conservative measure when in portrait by assuming that
|
|
8537
|
-
// the device has the worst possible aspect ratio. In other words,
|
|
8538
|
-
// we ignore the device height in portrait and assume the worst.
|
|
8539
|
-
// This prevents the keypad from changing size when browser chrome
|
|
8540
|
-
// appears and disappears.
|
|
8541
|
-
const effectiveWidth = pageWidthPx;
|
|
8542
|
-
const effectiveHeight = isLandscape ? pageHeightPx : pageWidthPx / worstCaseAspectRatio;
|
|
8543
|
-
const maxKeypadHeight = effectiveHeight - reservedSpace;
|
|
8544
|
-
|
|
8545
|
-
// Finally, compute the button height and width. In computing the
|
|
8546
|
-
// height, accommodate for the maximum number of rows that will ever be
|
|
8547
|
-
// visible (since the toggling of popovers can increase the number of
|
|
8548
|
-
// visible rows).
|
|
8549
|
-
const buttonHeightPx = Math.max(Math.min(maxKeypadHeight / numMaxVisibleRows, maxButtonSize), minButtonHeight);
|
|
8550
|
-
let buttonWidthPx;
|
|
8551
|
-
if (numPages > 1) {
|
|
8552
|
-
const _effectiveNumColumns = paginationEnabled ? numColumns : numColumns * numPages;
|
|
8553
|
-
buttonWidthPx = effectiveWidth / _effectiveNumColumns;
|
|
8554
|
-
} else {
|
|
8555
|
-
buttonWidthPx = isLandscape ? maxButtonSize : effectiveWidth / numColumns;
|
|
8556
|
-
}
|
|
8557
|
-
buttonDimensions = {
|
|
8558
|
-
widthPx: buttonWidthPx,
|
|
8559
|
-
heightPx: buttonHeightPx
|
|
8560
|
-
};
|
|
8561
|
-
} else if (deviceType === DeviceType.TABLET) {
|
|
8562
|
-
buttonDimensions = {
|
|
8563
|
-
widthPx: maxButtonSize,
|
|
8564
|
-
heightPx: maxButtonSize
|
|
8565
|
-
};
|
|
8566
|
-
} else {
|
|
8567
|
-
throw new Error("Invalid device type: " + deviceType);
|
|
8568
|
-
}
|
|
8569
|
+
const isLandscape = deviceOrientation === DeviceOrientation.LANDSCAPE;
|
|
8570
|
+
const buttonWidth = getButtonWidth(gridDimensions, containerDimensions, navigationPadEnabled, paginationEnabled, isLandscape);
|
|
8571
|
+
const buttonHeight = getButtonHeight(gridDimensions, pageDimensions, containerDimensions, paginationEnabled, toolbarEnabled, isLandscape);
|
|
8572
|
+
const buttonDimensions = {
|
|
8573
|
+
width: buttonWidth,
|
|
8574
|
+
height: buttonHeight
|
|
8575
|
+
};
|
|
8569
8576
|
|
|
8570
8577
|
// Finally, determine whether the keypad should be rendered in the
|
|
8571
8578
|
// fullscreen layout by determining its resultant width.
|
|
8572
8579
|
const numSeparators = (navigationPadEnabled ? 1 : 0) + (!paginationEnabled ? numPages - 1 : 0);
|
|
8573
|
-
const keypadWidth = effectiveNumColumns * buttonDimensions.
|
|
8580
|
+
const keypadWidth = effectiveNumColumns * buttonDimensions.width + (navigationPadEnabled ? navigationPadWidthPx : 0) + numSeparators * innerBorderWidthPx;
|
|
8574
8581
|
return {
|
|
8575
8582
|
buttonDimensions,
|
|
8576
|
-
layoutMode: keypadWidth >=
|
|
8583
|
+
layoutMode: keypadWidth >= containerDimensions.width ? LayoutMode.FULLSCREEN : LayoutMode.COMPACT
|
|
8577
8584
|
};
|
|
8578
8585
|
};
|
|
8579
8586
|
|
|
8587
|
+
const expandedViewThreshold = 682;
|
|
8588
|
+
const navigationViewThreshold = 800;
|
|
8580
8589
|
const initialLayoutState = {
|
|
8581
8590
|
gridDimensions: {
|
|
8582
8591
|
numRows: keypadForType[defaultKeypadType].rows,
|
|
@@ -8585,12 +8594,16 @@ const initialLayoutState = {
|
|
|
8585
8594
|
numPages: keypadForType[defaultKeypadType].numPages
|
|
8586
8595
|
},
|
|
8587
8596
|
buttonDimensions: {
|
|
8588
|
-
|
|
8589
|
-
|
|
8597
|
+
width: 48,
|
|
8598
|
+
height: 48
|
|
8590
8599
|
},
|
|
8591
8600
|
pageDimensions: {
|
|
8592
|
-
|
|
8593
|
-
|
|
8601
|
+
width: 0,
|
|
8602
|
+
height: 0
|
|
8603
|
+
},
|
|
8604
|
+
containerDimensions: {
|
|
8605
|
+
width: 0,
|
|
8606
|
+
height: 0
|
|
8594
8607
|
},
|
|
8595
8608
|
layoutMode: LayoutMode.FULLSCREEN,
|
|
8596
8609
|
paginationEnabled: false,
|
|
@@ -8601,37 +8614,16 @@ const initialLayoutState = {
|
|
|
8601
8614
|
* Compute the additional layout state based on the provided page and grid
|
|
8602
8615
|
* dimensions.
|
|
8603
8616
|
*/
|
|
8604
|
-
const layoutParametersForDimensions = (pageDimensions, gridDimensions) => {
|
|
8605
|
-
const {
|
|
8606
|
-
pageWidthPx,
|
|
8607
|
-
pageHeightPx
|
|
8608
|
-
} = pageDimensions;
|
|
8609
|
-
|
|
8617
|
+
const layoutParametersForDimensions = (pageDimensions, containerDimensions, gridDimensions) => {
|
|
8610
8618
|
// Determine the device type and orientation.
|
|
8611
|
-
const deviceOrientation =
|
|
8612
|
-
const deviceType = Math.min(pageWidthPx, pageHeightPx) > tabletCutoffPx ? DeviceType.TABLET : DeviceType.PHONE;
|
|
8619
|
+
const deviceOrientation = containerDimensions.width > containerDimensions.height ? DeviceOrientation.LANDSCAPE : DeviceOrientation.PORTRAIT;
|
|
8613
8620
|
|
|
8614
8621
|
// Using that information, make some decisions (or assumptions)
|
|
8615
8622
|
// about the resulting layout.
|
|
8616
|
-
const navigationPadEnabled =
|
|
8617
|
-
const paginationEnabled =
|
|
8618
|
-
const
|
|
8619
|
-
|
|
8620
|
-
deviceType
|
|
8621
|
-
};
|
|
8622
|
-
const layoutOptions = {
|
|
8623
|
-
navigationPadEnabled,
|
|
8624
|
-
paginationEnabled,
|
|
8625
|
-
// HACK(charlie): It's not great that we're making assumptions about
|
|
8626
|
-
// the toolbar (which is rendered by webapp, and should always be
|
|
8627
|
-
// visible and anchored to the bottom of the page for phone and
|
|
8628
|
-
// tablet exercises). But this is primarily a heuristic (the goal is
|
|
8629
|
-
// to preserve a 'good' amount of space between the top of the
|
|
8630
|
-
// keypad and the top of the page) so we afford to have some margin
|
|
8631
|
-
// of error.
|
|
8632
|
-
toolbarEnabled: true
|
|
8633
|
-
};
|
|
8634
|
-
return _extends({}, computeLayoutParameters(gridDimensions, pageDimensions, deviceInfo, layoutOptions), {
|
|
8623
|
+
const navigationPadEnabled = containerDimensions.width > navigationViewThreshold;
|
|
8624
|
+
const paginationEnabled = containerDimensions.width < expandedViewThreshold;
|
|
8625
|
+
const toolbarEnabled = true;
|
|
8626
|
+
return _extends({}, computeLayoutParameters(gridDimensions, pageDimensions, containerDimensions, deviceOrientation, navigationPadEnabled, paginationEnabled, toolbarEnabled), {
|
|
8635
8627
|
// Pass along some of the layout information, so that other
|
|
8636
8628
|
// components in the heirarchy can adapt appropriately.
|
|
8637
8629
|
navigationPadEnabled,
|
|
@@ -8650,20 +8642,28 @@ const layoutReducer = function layoutReducer(state = initialLayoutState, action)
|
|
|
8650
8642
|
numMaxVisibleRows: keypadForType[keypadType].maxVisibleRows,
|
|
8651
8643
|
numPages: keypadForType[keypadType].numPages
|
|
8652
8644
|
};
|
|
8653
|
-
|
|
8645
|
+
const layoutParams = layoutParametersForDimensions(state.pageDimensions, state.containerDimensions, gridDimensions);
|
|
8646
|
+
return _extends({}, state, layoutParams, {
|
|
8654
8647
|
gridDimensions
|
|
8655
8648
|
});
|
|
8656
8649
|
case "SetPageSize":
|
|
8657
8650
|
const {
|
|
8658
|
-
|
|
8659
|
-
|
|
8651
|
+
pageWidth,
|
|
8652
|
+
pageHeight,
|
|
8653
|
+
containerWidth,
|
|
8654
|
+
containerHeight
|
|
8660
8655
|
} = action;
|
|
8661
8656
|
const pageDimensions = {
|
|
8662
|
-
|
|
8663
|
-
|
|
8657
|
+
width: pageWidth,
|
|
8658
|
+
height: pageHeight
|
|
8659
|
+
};
|
|
8660
|
+
const containerDimensions = {
|
|
8661
|
+
width: containerWidth,
|
|
8662
|
+
height: containerHeight
|
|
8664
8663
|
};
|
|
8665
|
-
return _extends({}, state, layoutParametersForDimensions(pageDimensions, state.gridDimensions), {
|
|
8666
|
-
pageDimensions
|
|
8664
|
+
return _extends({}, state, layoutParametersForDimensions(pageDimensions, containerDimensions, state.gridDimensions), {
|
|
8665
|
+
pageDimensions,
|
|
8666
|
+
containerDimensions
|
|
8667
8667
|
});
|
|
8668
8668
|
default:
|
|
8669
8669
|
return state;
|