@khanacademy/math-input 19.0.0 → 19.2.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.
- package/dist/components/tabbar/item.d.ts +4 -4
- package/dist/es/index.js +88 -42
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +88 -42
- package/dist/index.js.map +1 -1
- package/package.json +23 -23
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { KeypadPageType } from "../../types";
|
|
3
3
|
export type ItemState = "active" | "inactive" | "disabled";
|
|
4
|
-
type
|
|
4
|
+
type TabItemProps = {
|
|
5
5
|
onClick: () => void;
|
|
6
6
|
itemState: ItemState;
|
|
7
7
|
itemType: KeypadPageType;
|
|
8
|
+
focus?: boolean;
|
|
9
|
+
role: "tab" | "button";
|
|
8
10
|
};
|
|
9
|
-
declare
|
|
10
|
-
render(): React.ReactNode;
|
|
11
|
-
}
|
|
11
|
+
declare function TabbarItem(props: TabItemProps): React.ReactElement;
|
|
12
12
|
export declare const TabbarItemForTesting: typeof TabbarItem;
|
|
13
13
|
export default TabbarItem;
|
package/dist/es/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { color } from '@khanacademy/wonder-blocks-tokens';
|
|
|
3
3
|
import { entries } from '@khanacademy/wonder-stuff-core';
|
|
4
4
|
import { StyleSheet, css } from 'aphrodite';
|
|
5
5
|
import * as React from 'react';
|
|
6
|
-
import { useContext, useState, useMemo, useEffect } from 'react';
|
|
6
|
+
import { useContext, useState, useMemo, useRef, useEffect } from 'react';
|
|
7
7
|
import ReactDOM from 'react-dom';
|
|
8
8
|
import { SpeechRuleEngine } from '@khanacademy/mathjax-renderer';
|
|
9
9
|
import MathQuill from 'mathquill';
|
|
@@ -15,7 +15,7 @@ import PropTypes from 'prop-types';
|
|
|
15
15
|
|
|
16
16
|
// This file is processed by a Rollup plugin (replace) to inject the production
|
|
17
17
|
const libName = "@khanacademy/math-input";
|
|
18
|
-
const libVersion = "19.
|
|
18
|
+
const libVersion = "19.2.0";
|
|
19
19
|
addLibraryVersionToPerseusDebug(libName, libVersion);
|
|
20
20
|
|
|
21
21
|
function _extends() {
|
|
@@ -2599,40 +2599,64 @@ function imageTintColor(itemState, hovered, focused, pressed) {
|
|
|
2599
2599
|
}
|
|
2600
2600
|
return color.offBlack64;
|
|
2601
2601
|
}
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2602
|
+
function TabbarItem(props) {
|
|
2603
|
+
const {
|
|
2604
|
+
onClick,
|
|
2605
|
+
itemType,
|
|
2606
|
+
itemState,
|
|
2607
|
+
focus,
|
|
2608
|
+
role
|
|
2609
|
+
} = props;
|
|
2610
|
+
const tabRef = useRef(null);
|
|
2611
|
+
useEffect(() => {
|
|
2612
|
+
let timeout;
|
|
2613
|
+
if (role === "tab" && focus) {
|
|
2614
|
+
/**
|
|
2615
|
+
* When tabs are within a WonderBlocks Popover component, the
|
|
2616
|
+
* manner in which the component is rendered and moved causes
|
|
2617
|
+
* focus to snap to the bottom of the page on first focus.
|
|
2618
|
+
*
|
|
2619
|
+
* This timeout moves around that by delaying the focus enough
|
|
2620
|
+
* to wait for the WonderBlock Popover to move to the correct
|
|
2621
|
+
* location and scroll the user to the correct location.
|
|
2622
|
+
* */
|
|
2623
|
+
timeout = setTimeout(() => {
|
|
2624
|
+
if (tabRef != null && tabRef.current) {
|
|
2625
|
+
// Move element into view when it is focused
|
|
2626
|
+
tabRef == null || tabRef.current.focus();
|
|
2627
|
+
}
|
|
2628
|
+
}, 0);
|
|
2629
|
+
}
|
|
2630
|
+
return () => clearTimeout(timeout);
|
|
2631
|
+
}, [role, focus, tabRef]);
|
|
2632
|
+
return /*#__PURE__*/React.createElement(Clickable, {
|
|
2633
|
+
onClick: onClick,
|
|
2634
|
+
disabled: itemState === "disabled",
|
|
2635
|
+
"aria-label": itemType,
|
|
2636
|
+
style: styles$6.clickable,
|
|
2637
|
+
"aria-selected": itemState === "active",
|
|
2638
|
+
tabIndex: role === "button" ? 0 : focus ? 0 : -1,
|
|
2639
|
+
role: role,
|
|
2640
|
+
ref: tabRef
|
|
2641
|
+
}, ({
|
|
2642
|
+
hovered,
|
|
2643
|
+
focused,
|
|
2644
|
+
pressed
|
|
2645
|
+
}) => {
|
|
2646
|
+
const tintColor = imageTintColor(itemState, hovered, focused, pressed);
|
|
2647
|
+
return /*#__PURE__*/React.createElement(View$1, {
|
|
2648
|
+
style: [styles$6.base, itemState !== "disabled" && hovered && styles$6.hovered, focused && styles$6.focused, pressed && styles$6.pressed]
|
|
2649
|
+
}, /*#__PURE__*/React.createElement(View$1, {
|
|
2650
|
+
style: [styles$6.innerBox, pressed && styles$6.innerBoxPressed]
|
|
2651
|
+
}, /*#__PURE__*/React.createElement(IconAsset, {
|
|
2652
|
+
type: itemType,
|
|
2653
|
+
tintColor: tintColor
|
|
2654
|
+
})), itemState === "active" && /*#__PURE__*/React.createElement(View$1, {
|
|
2655
|
+
style: [styles$6.activeIndicator, {
|
|
2656
|
+
backgroundColor: tintColor
|
|
2657
|
+
}]
|
|
2658
|
+
}));
|
|
2659
|
+
});
|
|
2636
2660
|
}
|
|
2637
2661
|
|
|
2638
2662
|
const styles$5 = StyleSheet.create({
|
|
@@ -2656,19 +2680,42 @@ function Tabbar(props) {
|
|
|
2656
2680
|
onSelectItem,
|
|
2657
2681
|
style
|
|
2658
2682
|
} = props;
|
|
2683
|
+
const selectedIndex = items.indexOf(selectedItem);
|
|
2684
|
+
const [focus, setFocus] = useState(selectedIndex === -1 ? 0 : selectedIndex);
|
|
2685
|
+
/**
|
|
2686
|
+
* Custom function to handle arrow key navigation for the TabBar for each TabItem.
|
|
2687
|
+
* This implementation also circular in that if the user goes past the end of
|
|
2688
|
+
* the list they will go back to the beginning and vise versa.
|
|
2689
|
+
* This is the recommended pattern per WCAG implementation:
|
|
2690
|
+
* https://www.w3.org/WAI/ARIA/apg/patterns/tabs/examples/tabs-manual/
|
|
2691
|
+
* @param e - onKeyDown event data.
|
|
2692
|
+
*/
|
|
2693
|
+
const onArrowKeyFocus = e => {
|
|
2694
|
+
if (e.keyCode === 39) {
|
|
2695
|
+
// Right arrow
|
|
2696
|
+
setFocus(focus === items.length - 1 ? 0 : focus + 1);
|
|
2697
|
+
} else if (e.keyCode === 37) {
|
|
2698
|
+
// Left arrow
|
|
2699
|
+
setFocus(focus === 0 ? items.length - 1 : focus - 1);
|
|
2700
|
+
}
|
|
2701
|
+
};
|
|
2659
2702
|
return /*#__PURE__*/React.createElement(View$1, {
|
|
2660
|
-
style: [styles$5.tabbar, style]
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2703
|
+
style: [styles$5.tabbar, style]
|
|
2704
|
+
}, items.length > 0 && /*#__PURE__*/React.createElement(View$1, {
|
|
2705
|
+
style: [styles$5.pages],
|
|
2706
|
+
role: "tablist",
|
|
2707
|
+
onKeyDown: onArrowKeyFocus
|
|
2708
|
+
}, items.map((item, index) => /*#__PURE__*/React.createElement(TabbarItem, {
|
|
2709
|
+
role: "tab",
|
|
2665
2710
|
key: `tabbar-item-${item}`,
|
|
2666
2711
|
itemState: item === selectedItem ? "active" : "inactive",
|
|
2667
2712
|
itemType: item,
|
|
2713
|
+
focus: focus === index,
|
|
2668
2714
|
onClick: () => {
|
|
2669
2715
|
onSelectItem(item);
|
|
2670
2716
|
}
|
|
2671
2717
|
}))), /*#__PURE__*/React.createElement(View$1, null, onClickClose && /*#__PURE__*/React.createElement(TabbarItem, {
|
|
2718
|
+
role: "button",
|
|
2672
2719
|
itemState: "inactive",
|
|
2673
2720
|
itemType: "Dismiss",
|
|
2674
2721
|
onClick: onClickClose
|
|
@@ -5282,7 +5329,6 @@ function Keypad(props) {
|
|
|
5282
5329
|
style: styles$1.keypadInnerContainer
|
|
5283
5330
|
}, /*#__PURE__*/React.createElement(View$1, {
|
|
5284
5331
|
style: [styles$1.keypadGrid, gridStyle],
|
|
5285
|
-
tabIndex: 0,
|
|
5286
5332
|
"aria-label": "Keypad"
|
|
5287
5333
|
}, selectedPage === "Fractions" && /*#__PURE__*/React.createElement(FractionsPage, {
|
|
5288
5334
|
onClickKey: onClickKey,
|