@khanacademy/math-input 0.3.2 → 0.5.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/CHANGELOG.md +8 -0
- package/README.md +1 -1
- package/{build/math-input.css → dist/es/index.css} +0 -150
- package/dist/es/index.js +2 -0
- package/dist/es/index.js.map +1 -0
- package/dist/index.css +586 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.flow +2 -0
- package/dist/index.js.map +1 -0
- package/dist/strings.js +71 -0
- package/index.html +20 -0
- package/less/echo.less +56 -0
- package/less/main.less +5 -0
- package/less/overrides.less +129 -0
- package/less/popover.less +22 -0
- package/less/tabbar.less +6 -0
- package/package.json +38 -70
- package/src/actions/index.js +57 -0
- package/src/components/__tests__/gesture-state-machine_test.js +437 -0
- package/src/components/__tests__/node-manager_test.js +89 -0
- package/src/components/__tests__/two-page-keypad_test.js +42 -0
- package/src/components/app.js +73 -0
- package/src/components/common-style.js +47 -0
- package/src/components/compute-layout-parameters.js +157 -0
- package/src/components/corner-decal.js +56 -0
- package/src/components/echo-manager.js +160 -0
- package/src/components/empty-keypad-button.js +49 -0
- package/src/components/expression-keypad.js +323 -0
- package/src/components/fraction-keypad.js +176 -0
- package/src/components/gesture-manager.js +226 -0
- package/src/components/gesture-state-machine.js +283 -0
- package/src/components/icon.js +74 -0
- package/src/components/iconography/arrow.js +22 -0
- package/src/components/iconography/backspace.js +29 -0
- package/src/components/iconography/cdot.js +29 -0
- package/src/components/iconography/cos.js +30 -0
- package/src/components/iconography/cube-root.js +36 -0
- package/src/components/iconography/dismiss.js +25 -0
- package/src/components/iconography/divide.js +34 -0
- package/src/components/iconography/down.js +16 -0
- package/src/components/iconography/equal.js +33 -0
- package/src/components/iconography/exp-2.js +29 -0
- package/src/components/iconography/exp-3.js +29 -0
- package/src/components/iconography/exp.js +29 -0
- package/src/components/iconography/frac.js +44 -0
- package/src/components/iconography/geq.js +33 -0
- package/src/components/iconography/gt.js +33 -0
- package/src/components/iconography/index.js +45 -0
- package/src/components/iconography/jump-into-numerator.js +41 -0
- package/src/components/iconography/jump-out-base.js +30 -0
- package/src/components/iconography/jump-out-denominator.js +41 -0
- package/src/components/iconography/jump-out-exponent.js +30 -0
- package/src/components/iconography/jump-out-numerator.js +41 -0
- package/src/components/iconography/jump-out-parentheses.js +33 -0
- package/src/components/iconography/left-paren.js +33 -0
- package/src/components/iconography/left.js +16 -0
- package/src/components/iconography/leq.js +33 -0
- package/src/components/iconography/ln.js +29 -0
- package/src/components/iconography/log-n.js +29 -0
- package/src/components/iconography/log.js +29 -0
- package/src/components/iconography/lt.js +33 -0
- package/src/components/iconography/minus.js +32 -0
- package/src/components/iconography/neq.js +33 -0
- package/src/components/iconography/parens.js +33 -0
- package/src/components/iconography/percent.js +49 -0
- package/src/components/iconography/period.js +26 -0
- package/src/components/iconography/plus.js +32 -0
- package/src/components/iconography/radical.js +36 -0
- package/src/components/iconography/right-paren.js +33 -0
- package/src/components/iconography/right.js +16 -0
- package/src/components/iconography/sin.js +30 -0
- package/src/components/iconography/sqrt.js +32 -0
- package/src/components/iconography/tan.js +30 -0
- package/src/components/iconography/times.js +33 -0
- package/src/components/iconography/up.js +16 -0
- package/src/components/input/__tests__/context-tracking_test.js +177 -0
- package/src/components/input/__tests__/math-wrapper.jsx +33 -0
- package/src/components/input/__tests__/mathquill_test.js +747 -0
- package/src/components/input/cursor-contexts.js +29 -0
- package/src/components/input/cursor-handle.js +137 -0
- package/src/components/input/drag-listener.js +75 -0
- package/src/components/input/math-input.js +924 -0
- package/src/components/input/math-wrapper.js +959 -0
- package/src/components/input/scroll-into-view.js +72 -0
- package/src/components/keypad/button-assets.js +492 -0
- package/src/components/keypad/button.js +106 -0
- package/src/components/keypad/button.stories.js +27 -0
- package/src/components/keypad/index.js +64 -0
- package/src/components/keypad/keypad-page-items.js +106 -0
- package/src/components/keypad/keypad-pages.stories.js +32 -0
- package/src/components/keypad/keypad.stories.js +35 -0
- package/src/components/keypad/numeric-input-page.js +100 -0
- package/src/components/keypad/pre-algebra-page.js +98 -0
- package/src/components/keypad/trigonometry-page.js +90 -0
- package/src/components/keypad-button.js +366 -0
- package/src/components/keypad-container.js +303 -0
- package/src/components/keypad.js +154 -0
- package/src/components/many-keypad-button.js +44 -0
- package/src/components/math-icon.js +65 -0
- package/src/components/multi-symbol-grid.js +182 -0
- package/src/components/multi-symbol-popover.js +59 -0
- package/src/components/navigation-pad.js +139 -0
- package/src/components/node-manager.js +129 -0
- package/src/components/popover-manager.js +76 -0
- package/src/components/popover-state-machine.js +173 -0
- package/src/components/prop-types.js +82 -0
- package/src/components/provided-keypad.js +99 -0
- package/src/components/styles.js +38 -0
- package/src/components/svg-icon.js +25 -0
- package/src/components/tabbar/__tests__/tabbar_test.js +65 -0
- package/src/components/tabbar/icons.js +69 -0
- package/src/components/tabbar/item.js +138 -0
- package/src/components/tabbar/tabbar.js +61 -0
- package/src/components/tabbar/tabbar.stories.js +60 -0
- package/src/components/tabbar/types.js +3 -0
- package/src/components/text-icon.js +52 -0
- package/src/components/touchable-keypad-button.js +146 -0
- package/src/components/two-page-keypad.js +99 -0
- package/src/components/velocity-tracker.js +76 -0
- package/src/components/z-indexes.js +9 -0
- package/src/consts.js +74 -0
- package/src/data/key-configs.js +349 -0
- package/src/data/keys.js +72 -0
- package/src/demo.js +8 -0
- package/src/fake-react-native-web/index.js +12 -0
- package/src/fake-react-native-web/text.js +56 -0
- package/src/fake-react-native-web/view.js +91 -0
- package/src/index.js +13 -0
- package/src/native-app.js +84 -0
- package/src/store/index.js +505 -0
- package/src/utils.js +18 -0
- package/tools/svg-to-react/convert.py +111 -0
- package/tools/svg-to-react/icons/math-keypad-icon-0.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-1.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-2.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-3.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-4.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-5.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-6.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-7.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-8.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-9.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-addition.svg +34 -0
- package/tools/svg-to-react/icons/math-keypad-icon-cos.svg +38 -0
- package/tools/svg-to-react/icons/math-keypad-icon-delete.svg +36 -0
- package/tools/svg-to-react/icons/math-keypad-icon-dismiss.svg +36 -0
- package/tools/svg-to-react/icons/math-keypad-icon-division.svg +36 -0
- package/tools/svg-to-react/icons/math-keypad-icon-equals-not.svg +50 -0
- package/tools/svg-to-react/icons/math-keypad-icon-equals.svg +48 -0
- package/tools/svg-to-react/icons/math-keypad-icon-exponent-2.svg +38 -0
- package/tools/svg-to-react/icons/math-keypad-icon-exponent-3.svg +38 -0
- package/tools/svg-to-react/icons/math-keypad-icon-exponent.svg +38 -0
- package/tools/svg-to-react/icons/math-keypad-icon-fraction.svg +42 -0
- package/tools/svg-to-react/icons/math-keypad-icon-greater-than.svg +46 -0
- package/tools/svg-to-react/icons/math-keypad-icon-jump-out-base.svg +44 -0
- package/tools/svg-to-react/icons/math-keypad-icon-jump-out-denominator.svg +48 -0
- package/tools/svg-to-react/icons/math-keypad-icon-jump-out-exponent.svg +44 -0
- package/tools/svg-to-react/icons/math-keypad-icon-jump-out-parentheses.svg +44 -0
- package/tools/svg-to-react/icons/math-keypad-icon-less-than.svg +46 -0
- package/tools/svg-to-react/icons/math-keypad-icon-log-10.svg +36 -0
- package/tools/svg-to-react/icons/math-keypad-icon-log-e.svg +36 -0
- package/tools/svg-to-react/icons/math-keypad-icon-log.svg +38 -0
- package/tools/svg-to-react/icons/math-keypad-icon-multiplication-cross.svg +40 -0
- package/tools/svg-to-react/icons/math-keypad-icon-multiplication-dot.svg +38 -0
- package/tools/svg-to-react/icons/math-keypad-icon-percent.svg +42 -0
- package/tools/svg-to-react/icons/math-keypad-icon-radical-2.svg +36 -0
- package/tools/svg-to-react/icons/math-keypad-icon-radical-3.svg +38 -0
- package/tools/svg-to-react/icons/math-keypad-icon-radical.svg +38 -0
- package/tools/svg-to-react/icons/math-keypad-icon-radix-character.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-sin.svg +38 -0
- package/tools/svg-to-react/icons/math-keypad-icon-subtraction.svg +32 -0
- package/tools/svg-to-react/icons/math-keypad-icon-tan.svg +38 -0
- package/tools/svg-to-react/symbol_map.py +41 -0
- package/LICENSE.txt +0 -21
- package/build/math-input.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/data/keys.js","../../src/fake-react-native-web/text.js","../../src/fake-react-native-web/view.js","../../src/components/common-style.js","../../src/utils.js","../../src/consts.js","../../src/data/key-configs.js","../../src/components/input/cursor-contexts.js","../../src/components/prop-types.js","../../src/components/input/cursor-handle.js","../../src/components/input/drag-listener.js","../../src/components/input/math-wrapper.js","../../src/components/input/scroll-into-view.js","../../src/components/input/math-input.js","../../src/components/gesture-state-machine.js","../../src/components/node-manager.js","../../src/components/popover-state-machine.js","../../src/components/gesture-manager.js","../../src/components/corner-decal.js","../../src/components/styles.js","../../src/components/math-icon.js","../../src/components/iconography/cos.js","../../src/components/iconography/log.js","../../src/components/iconography/equal.js","../../src/components/iconography/sqrt.js","../../src/components/iconography/exp.js","../../src/components/iconography/neq.js","../../src/components/iconography/geq.js","../../src/components/iconography/ln.js","../../src/components/iconography/sin.js","../../src/components/iconography/lt.js","../../src/components/iconography/cube-root.js","../../src/components/iconography/plus.js","../../src/components/iconography/tan.js","../../src/components/iconography/arrow.js","../../src/components/iconography/left-paren.js","../../src/components/iconography/right-paren.js","../../src/components/iconography/gt.js","../../src/components/iconography/divide.js","../../src/components/iconography/period.js","../../src/components/iconography/percent.js","../../src/components/iconography/times.js","../../src/components/iconography/exp-3.js","../../src/components/iconography/exp-2.js","../../src/components/iconography/cdot.js","../../src/components/iconography/log-n.js","../../src/components/iconography/leq.js","../../src/components/iconography/minus.js","../../src/components/iconography/radical.js","../../src/components/iconography/frac.js","../../src/components/iconography/jump-out-parentheses.js","../../src/components/iconography/backspace.js","../../src/components/iconography/dismiss.js","../../src/components/iconography/left.js","../../src/components/iconography/up.js","../../src/components/iconography/down.js","../../src/components/iconography/right.js","../../src/components/iconography/jump-out-exponent.js","../../src/components/iconography/jump-out-base.js","../../src/components/iconography/jump-into-numerator.js","../../src/components/iconography/jump-out-numerator.js","../../src/components/iconography/jump-out-denominator.js","../../src/components/svg-icon.js","../../src/components/text-icon.js","../../src/components/icon.js","../../src/components/multi-symbol-grid.js","../../src/components/keypad-button.js","../../src/components/empty-keypad-button.js","../../src/components/touchable-keypad-button.js","../../src/components/many-keypad-button.js","../../src/components/echo-manager.js","../../src/components/z-indexes.js","../../src/components/multi-symbol-popover.js","../../src/components/popover-manager.js","../../src/components/keypad.js","../../src/actions/index.js","../../src/components/tabbar/icons.js","../../src/components/tabbar/item.js","../../src/components/tabbar/tabbar.js","../../src/components/two-page-keypad.js","../../src/components/expression-keypad.js","../../src/components/fraction-keypad.js","../../src/components/velocity-tracker.js","../../src/store/index.js","../../src/components/compute-layout-parameters.js","../../src/components/navigation-pad.js","../../src/components/keypad-container.js","../../src/components/provided-keypad.js"],"sourcesContent":["// @flow\n/**\n * This file contains constants for keypad buttons that aren't single\n * alphanumeric characters.\n */\n\n// TODO(charlie): There's duplication between this file and key-configs.js.\n// We should clean it up by removing this file and requiring clients to use the\n// `id` field on the key configurations.\nconst Keys = {\n PLUS: \"PLUS\",\n MINUS: \"MINUS\",\n NEGATIVE: \"NEGATIVE\",\n TIMES: \"TIMES\",\n DIVIDE: \"DIVIDE\",\n DECIMAL: \"DECIMAL\",\n PERIOD: \"PERIOD\",\n PERCENT: \"PERCENT\",\n CDOT: \"CDOT\",\n EQUAL: \"EQUAL\",\n NEQ: \"NEQ\",\n GT: \"GT\",\n LT: \"LT\",\n GEQ: \"GEQ\",\n LEQ: \"LEQ\",\n FRAC_INCLUSIVE: \"FRAC_INCLUSIVE\", // mobile native only\n FRAC_EXCLUSIVE: \"FRAC_EXCLUSIVE\", // mobile native only\n FRAC: \"FRAC\",\n EXP: \"EXP\",\n EXP_2: \"EXP_2\",\n EXP_3: \"EXP_3\",\n SQRT: \"SQRT\",\n CUBE_ROOT: \"CUBE_ROOT\",\n RADICAL: \"RADICAL\",\n LEFT_PAREN: \"LEFT_PAREN\",\n RIGHT_PAREN: \"RIGHT_PAREN\",\n LN: \"LN\",\n LOG: \"LOG\",\n LOG_N: \"LOG_N\",\n SIN: \"SIN\",\n COS: \"COS\",\n TAN: \"TAN\",\n\n // TODO(charlie): Add in additional Greek letters.\n PI: \"PI\",\n THETA: \"THETA\",\n\n UP: \"UP\",\n RIGHT: \"RIGHT\",\n DOWN: \"DOWN\",\n LEFT: \"LEFT\",\n BACKSPACE: \"BACKSPACE\",\n DISMISS: \"DISMISS\",\n\n JUMP_OUT_PARENTHESES: \"JUMP_OUT_PARENTHESES\",\n JUMP_OUT_EXPONENT: \"JUMP_OUT_EXPONENT\",\n JUMP_OUT_BASE: \"JUMP_OUT_BASE\",\n JUMP_INTO_NUMERATOR: \"JUMP_INTO_NUMERATOR\",\n JUMP_OUT_NUMERATOR: \"JUMP_OUT_NUMERATOR\",\n JUMP_OUT_DENOMINATOR: \"JUMP_OUT_DENOMINATOR\",\n\n NOOP: \"NOOP\",\n\n // Multi-functional keys.\n FRAC_MULTI: \"FRAC_MULTI\", // mobile native only\n\n // A custom key that captures an arbitrary number of symbols but has no\n // 'default' symbol or action.\n MANY: \"MANY\",\n};\n\nexport default Keys;\n","// @flow\n\nimport {StyleSheet, css} from \"aphrodite\";\nimport * as React from \"react\";\n\nimport type {CSSProperties} from \"aphrodite\";\n\ntype Props = {|\n children: React.Node,\n // The `dynamicStyle` prop is provided for animating dynamic\n // properties, as creating Aphrodite StyleSheets in animation loops is\n // expensive. `dynamicStyle` should be a raw style object, rather than\n // a StyleSheet.\n dynamicStyle?: CSSProperties,\n numberOfLines?: number,\n style?: CSSProperties,\n|};\n\nclass Text extends React.Component<Props> {\n render(): React.Element<\"span\"> {\n const {numberOfLines, style} = this.props;\n\n const className = css(\n styles.initial,\n ...(Array.isArray(style) ? style : [style]),\n numberOfLines === 1 && styles.singleLineStyle,\n );\n\n return (\n <span className={className} style={this.props.dynamicStyle}>\n {this.props.children}\n </span>\n );\n }\n}\n\n// https://github.com/necolas/react-native-web/blob/master/src/components/Text/index.js\nconst styles = StyleSheet.create({\n initial: {\n color: \"inherit\",\n display: \"inline\",\n font: \"inherit\",\n margin: 0,\n padding: 0,\n textDecorationLine: \"none\",\n wordWrap: \"break-word\",\n },\n singleLineStyle: {\n maxWidth: \"100%\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n },\n});\n\nexport default Text;\n","// @flow\n\nimport {StyleSheet, css} from \"aphrodite\";\nimport * as React from \"react\";\n\nimport type {CSSProperties} from \"aphrodite\";\n\ntype Props = {|\n ariaLabel?: string,\n children: React.Node,\n // The `dynamicStyle` prop is provided for animating dynamic\n // properties, as creating Aphrodite StyleSheets in animation loops is\n // expensive. `dynamicStyle` should be a raw style object, rather than\n // a StyleSheet.\n dynamicStyle?: CSSProperties,\n // The `extraClassName` prop should almost never be used. It gives the\n // client a way to provide an additional CSS class name, to augment\n // the class name generated by Aphrodite. (Right now, it's only used to\n // disable some externally-applied CSS that would otherwise be far too\n // difficult to override with inline styles.)\n extraClassName?: string,\n numberOfLines?: number,\n onClick?: () => void,\n onTouchCancel?: () => void,\n onTouchEnd?: () => void,\n onTouchMove?: () => void,\n onTouchStart?: () => void,\n role?: string,\n style?: CSSProperties,\n|};\n\nclass View extends React.Component<Props> {\n // $FlowFixMe[signature-verification-failure]\n static styles = StyleSheet.create({\n // From: https://github.com/necolas/react-native-web/blob/master/src/components/View/index.js\n // eslint-disable-next-line react-native/no-unused-styles\n initial: {\n alignItems: \"stretch\",\n borderWidth: 0,\n borderStyle: \"solid\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexBasis: \"auto\",\n flexDirection: \"column\",\n margin: 0,\n padding: 0,\n position: \"relative\",\n // button and anchor reset\n backgroundColor: \"transparent\",\n color: \"inherit\",\n font: \"inherit\",\n textAlign: \"inherit\",\n textDecorationLine: \"none\",\n // list reset\n listStyle: \"none\",\n // fix flexbox bugs\n maxWidth: \"100%\",\n minHeight: 0,\n minWidth: 0,\n },\n });\n\n render(): React.Element<\"div\"> {\n const className =\n css(\n View.styles.initial,\n ...(Array.isArray(this.props.style)\n ? this.props.style\n : [this.props.style]),\n ) +\n (this.props.extraClassName ? ` ${this.props.extraClassName}` : \"\");\n\n return (\n <div\n className={className}\n style={this.props.dynamicStyle}\n onClick={this.props.onClick}\n onTouchCancel={this.props.onTouchCancel}\n onTouchEnd={this.props.onTouchEnd}\n onTouchMove={this.props.onTouchMove}\n onTouchStart={this.props.onTouchStart}\n aria-label={this.props.ariaLabel}\n role={this.props.role}\n >\n {this.props.children}\n </div>\n );\n }\n}\n\nexport default View;\n","// @flow\n/**\n * Common parameters used to style components.\n */\nimport Color from \"@khanacademy/wonder-blocks-color\";\n\nexport const wonderBlocksBlue = Color.blue;\nexport const offBlack = Color.offBlack;\nexport const offBlack32 = Color.offBlack32;\nexport const offBlack16 = Color.offBlack16;\nexport const offBlack8 = Color.offBlack8;\n\nexport const iconSizeHeightPx = 48;\nexport const iconSizeWidthPx = 48;\nexport const compactKeypadBorderRadiusPx = 4;\nexport const cursorHandleRadiusPx = 11;\n\n// The amount to multiply the radius by to get the distance from the\n// center to the tip of the cursor handle. The cursor is a circle with\n// one quadrant replace with a square. The hypotenuse of the square is\n// 1.045 times the radius of the circle.\nexport const cursorHandleDistanceMultiplier = 1.045;\n\n// Keypad button colors\nexport const valueGrey = \"#FFF\";\nexport const operatorGrey = \"#FAFAFA\";\nexport const controlGrey = \"#F6F7F7\";\nexport const emptyGrey = \"#F0F1F2\";\n\n// Constants defining any borders between elements in the keypad.\nexport const innerBorderColor = offBlack16;\nexport const innerBorderStyle = \"solid\";\nexport const innerBorderWidthPx = 1;\n\n// The width at which a device is classified as a \"tablet\" for the purposes\n// of the keypad layout.\nexport const tabletCutoffPx = 600;\n\n// The dimensions that define various components in the tree, which may be\n// needed outside of those components in order to determine various layout\n// parameters.\nexport const pageIndicatorHeightPx = 16;\nexport const navigationPadWidthPx = 192;\n// HACK(charlie): This should be injected by webapp somehow.\n// TODO(charlie): Add a link to the webapp location as soon as the footer\n// has settled down.\nexport const toolbarHeightPx = 60;\n","// @flow\n\nimport {DecimalSeparators} from \"./consts.js\";\n\n// We expect `window.icu` to be exposed by the parent. When in doubt, we fall\n// back to a period. We can only depend on a subset of what localeplanet\n// provides, however -- the things in `icu-slim.js` (there's a copy in ../lib/\n// for reference).\nexport let decimalSeparator: string;\nif (\n typeof window !== \"undefined\" &&\n window.icu &&\n window.icu.getDecimalFormatSymbols().decimal_separator === \",\"\n) {\n decimalSeparator = DecimalSeparators.COMMA;\n} else {\n decimalSeparator = DecimalSeparators.PERIOD;\n}\n","// @flow\n/**\n * Constants that are shared between multiple files.\n */\n\nexport const KeypadTypes = {\n FRACTION: \"FRACTION\",\n EXPRESSION: \"EXPRESSION\",\n};\n\nexport const KeyTypes = {\n EMPTY: \"EMPTY\",\n // For numerals, variables, and any other characters that themselves\n // compose 'values'.\n VALUE: \"VALUE\",\n // For buttons that insert or adjust math in an input.\n OPERATOR: \"OPERATOR\",\n // For buttons that move the cursor in an input (including via\n // deletion).\n INPUT_NAVIGATION: \"INPUT_NAVIGATION\",\n // For buttons that modify the broader keypad state (e.g., by changing\n // the visible pane).\n KEYPAD_NAVIGATION: \"KEYPAD_NAVIGATION\",\n // For buttons that house multiple buttons and have no action\n // themselves.\n MANY: \"MANY\",\n // For the echo animation that appears on press.\n ECHO: \"ECHO\",\n};\n\nexport const DeviceOrientations = {\n LANDSCAPE: \"LANDSCAPE\",\n PORTRAIT: \"PORTRAIT\",\n};\n\nexport const DeviceTypes = {\n PHONE: \"PHONE\",\n TABLET: \"TABLET\",\n};\n\nexport const LayoutModes = {\n FULLSCREEN: \"FULLSCREEN\",\n COMPACT: \"COMPACT\",\n};\n\nexport const BorderDirections = {\n LEFT: (\"LEFT\": \"LEFT\"),\n BOTTOM: (\"BOTTOM\": \"BOTTOM\"),\n};\nexport const BorderStyles: {|\n [style: string]: $ReadOnlyArray<$Values<typeof BorderDirections>>,\n|} = {\n LEFT: [\"LEFT\"],\n BOTTOM: [\"BOTTOM\"],\n ALL: [\"LEFT\", \"BOTTOM\"],\n NONE: [],\n};\n\nexport const IconTypes = {\n MATH: \"MATH\",\n SVG: \"SVG\",\n TEXT: \"TEXT\",\n};\n\nexport const DecimalSeparators = {\n COMMA: \"COMMA\",\n PERIOD: \"PERIOD\",\n};\n\nexport const EchoAnimationTypes = {\n SLIDE_AND_FADE: \"SLIDE_AND_FADE\",\n FADE_ONLY: \"FADE_ONLY\",\n LONG_FADE_ONLY: \"LONG_FADE_ONLY\",\n};\n","// @flow\n/**\n * This file contains configuration settings for the buttons in the keypad.\n */\nimport * as i18n from \"@khanacademy/wonder-blocks-i18n\";\n\nimport {DecimalSeparators, IconTypes, KeyTypes} from \"../consts.js\";\nimport {decimalSeparator} from \"../utils.js\";\n\nimport Keys from \"./keys.js\";\n\nexport type KeyConfig = {\n id: string,\n type: string,\n ariaLabel: string,\n};\nconst KeyConfigs: Object = {\n // Basic math keys.\n [Keys.PLUS]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a plus sign.\n ariaLabel: i18n._(\"Plus\"),\n },\n [Keys.MINUS]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a minus sign.\n ariaLabel: i18n._(\"Minus\"),\n },\n [Keys.NEGATIVE]: {\n type: KeyTypes.VALUE,\n // I18N: A label for a minus sign.\n ariaLabel: i18n._(\"Negative\"),\n },\n [Keys.TIMES]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a multiplication sign (represented with an 'x').\n ariaLabel: i18n._(\"Multiply\"),\n },\n [Keys.DIVIDE]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a division sign.\n ariaLabel: i18n._(\"Divide\"),\n },\n [Keys.DECIMAL]: {\n type: KeyTypes.VALUE,\n // I18N: A label for a decimal symbol.\n ariaLabel: i18n._(\"Decimal\"),\n icon:\n decimalSeparator === DecimalSeparators.COMMA\n ? {\n // TODO(charlie): Get an SVG icon for the comma, or verify with\n // design that the text-rendered version is acceptable.\n type: IconTypes.TEXT,\n data: \",\",\n }\n : {\n type: IconTypes.SVG,\n data: Keys.PERIOD,\n },\n },\n [Keys.PERCENT]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a percent sign.\n ariaLabel: i18n._(\"Percent\"),\n },\n [Keys.CDOT]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a multiplication sign (represented as a dot).\n ariaLabel: i18n._(\"Multiply\"),\n },\n [Keys.EQUAL]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Equals sign\"),\n },\n [Keys.NEQ]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Not-equals sign\"),\n },\n [Keys.GT]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a 'greater than' sign (represented as '>').\n ariaLabel: i18n._(\"Greater than sign\"),\n },\n [Keys.LT]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a 'less than' sign (represented as '<').\n ariaLabel: i18n._(\"Less than sign\"),\n },\n [Keys.GEQ]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Greater than or equal to sign\"),\n },\n [Keys.LEQ]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Less than or equal to sign\"),\n },\n // mobile native\n [Keys.FRAC_INCLUSIVE]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a button that creates a new fraction and puts the\n // current expression in the numerator of that fraction.\n ariaLabel: i18n._(\"Fraction, with current expression in numerator\"),\n },\n // mobile native\n [Keys.FRAC_EXCLUSIVE]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a button that creates a new fraction next to the\n // cursor.\n ariaLabel: i18n._(\"Fraction, excluding the current expression\"),\n },\n // mobile web\n [Keys.FRAC]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a button that creates a new fraction next to the\n // cursor.\n ariaLabel: i18n._(\"Fraction, excluding the current expression\"),\n },\n [Keys.EXP]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a button that will allow the user to input a custom\n // exponent.\n ariaLabel: i18n._(\"Custom exponent\"),\n },\n [Keys.EXP_2]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a button that will square (take to the second\n // power) some math.\n ariaLabel: i18n._(\"Square\"),\n },\n [Keys.EXP_3]: {\n type: KeyTypes.OPERATOR,\n // I18N: A label for a button that will cube (take to the third power)\n // some math.\n ariaLabel: i18n._(\"Cube\"),\n },\n [Keys.SQRT]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Square root\"),\n },\n [Keys.CUBE_ROOT]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Cube root\"),\n },\n [Keys.RADICAL]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Radical with custom root\"),\n },\n [Keys.LEFT_PAREN]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Left parenthesis\"),\n },\n [Keys.RIGHT_PAREN]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Right parenthesis\"),\n },\n [Keys.LN]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Natural logarithm\"),\n },\n [Keys.LOG]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Logarithm with base 10\"),\n },\n [Keys.LOG_N]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Logarithm with custom base\"),\n },\n [Keys.SIN]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Sine\"),\n },\n [Keys.COS]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Cosine\"),\n },\n [Keys.TAN]: {\n type: KeyTypes.OPERATOR,\n ariaLabel: i18n._(\"Tangent\"),\n },\n [Keys.PI]: {\n type: KeyTypes.VALUE,\n ariaLabel: i18n._(\"Pi\"),\n icon: {\n type: IconTypes.MATH,\n data: \"\\\\pi\",\n },\n },\n [Keys.THETA]: {\n type: KeyTypes.VALUE,\n ariaLabel: i18n._(\"Theta\"),\n icon: {\n type: IconTypes.MATH,\n data: \"\\\\theta\",\n },\n },\n [Keys.NOOP]: {\n type: KeyTypes.EMPTY,\n },\n\n // Input navigation keys.\n [Keys.UP]: {\n type: KeyTypes.INPUT_NAVIGATION,\n ariaLabel: i18n._(\"Up arrow\"),\n },\n [Keys.RIGHT]: {\n type: KeyTypes.INPUT_NAVIGATION,\n ariaLabel: i18n._(\"Right arrow\"),\n },\n [Keys.DOWN]: {\n type: KeyTypes.INPUT_NAVIGATION,\n ariaLabel: i18n._(\"Down arrow\"),\n },\n [Keys.LEFT]: {\n type: KeyTypes.INPUT_NAVIGATION,\n ariaLabel: i18n._(\"Left arrow\"),\n },\n [Keys.JUMP_OUT_PARENTHESES]: {\n type: KeyTypes.INPUT_NAVIGATION,\n ariaLabel: i18n._(\"Navigate right out of a set of parentheses\"),\n },\n [Keys.JUMP_OUT_EXPONENT]: {\n type: KeyTypes.INPUT_NAVIGATION,\n ariaLabel: i18n._(\"Navigate right out of an exponent\"),\n },\n [Keys.JUMP_OUT_BASE]: {\n type: KeyTypes.INPUT_NAVIGATION,\n ariaLabel: i18n._(\"Navigate right out of a base\"),\n },\n [Keys.JUMP_INTO_NUMERATOR]: {\n type: KeyTypes.INPUT_NAVIGATION,\n ariaLabel: i18n._(\"Navigate right into the numerator of a fraction\"),\n },\n [Keys.JUMP_OUT_NUMERATOR]: {\n type: KeyTypes.INPUT_NAVIGATION,\n ariaLabel: i18n._(\n \"Navigate right out of the numerator and into the denominator\",\n ),\n },\n [Keys.JUMP_OUT_DENOMINATOR]: {\n type: KeyTypes.INPUT_NAVIGATION,\n ariaLabel: i18n._(\n \"Navigate right out of the denominator of a fraction\",\n ),\n },\n [Keys.BACKSPACE]: {\n type: KeyTypes.INPUT_NAVIGATION,\n // I18N: A label for a button that will delete some input.\n ariaLabel: i18n._(\"Delete\"),\n },\n\n // Keypad navigation keys.\n [Keys.DISMISS]: {\n type: KeyTypes.KEYPAD_NAVIGATION,\n // I18N: A label for a button that will dismiss/hide a keypad.\n ariaLabel: i18n._(\"Dismiss\"),\n },\n};\n\n// Add in any multi-function buttons. By default, these keys will mix in any\n// configuration settings from their default child key (i.e., the first key in\n// the `childKeyIds` array).\n// TODO(charlie): Make the multi-function button's long-press interaction\n// accessible.\n// NOTE(kevinb): This is only used in the mobile native app.\nKeyConfigs[Keys.FRAC_MULTI] = {\n childKeyIds: [Keys.FRAC_INCLUSIVE, Keys.FRAC_EXCLUSIVE],\n};\n\n// TODO(charlie): Use the numeral color for the 'Many' key.\nKeyConfigs[Keys.MANY] = {\n type: KeyTypes.MANY,\n // childKeyIds will be configured by the client.\n};\n\n// Add in every numeral.\nconst NUMBERS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\nfor (const num of NUMBERS) {\n // TODO(charlie): Consider removing the SVG icons that we have for the\n // numeral keys. They can be rendered just as easily with text (though that\n // would mean that we'd be using text beyond the variable key).\n const textRepresentation = `${num}`;\n KeyConfigs[`NUM_${num}`] = {\n type: KeyTypes.VALUE,\n ariaLabel: textRepresentation,\n icon: {\n type: IconTypes.TEXT,\n data: textRepresentation,\n },\n };\n}\n\n// Add in every variable.\nconst LETTERS = [\n \"A\",\n \"B\",\n \"C\",\n \"D\",\n \"E\",\n \"F\",\n \"G\",\n \"H\",\n \"I\",\n \"J\",\n \"K\",\n \"L\",\n \"M\",\n \"N\",\n \"O\",\n \"P\",\n \"Q\",\n \"R\",\n \"S\",\n \"T\",\n \"U\",\n \"V\",\n \"W\",\n \"X\",\n \"Y\",\n \"Z\",\n];\nfor (const letter of LETTERS) {\n const lowerCaseVariable = letter.toLowerCase();\n const upperCaseVariable = letter.toUpperCase();\n\n for (const textRepresentation of [lowerCaseVariable, upperCaseVariable]) {\n KeyConfigs[textRepresentation] = {\n type: KeyTypes.VALUE,\n ariaLabel: textRepresentation,\n icon: {\n type: IconTypes.MATH,\n data: textRepresentation,\n },\n };\n }\n}\n\nfor (const key of Object.keys(KeyConfigs)) {\n KeyConfigs[key] = {\n id: key,\n // Default to an SVG icon indexed by the key name.\n icon: {\n type: IconTypes.SVG,\n data: key,\n },\n ...KeyConfigs[key],\n };\n}\n\nexport default KeyConfigs;\n","/**\n * Constants that define the various contexts in which a cursor can exist. The\n * active context is determined first by looking at the cursor's siblings (e.g.,\n * for the `BEFORE_FRACTION` context), and then at its direct parent. Though a\n * cursor could in theory be nested in multiple contexts, we only care about the\n * immediate context.\n *\n * TODO(charlie): Add a context to represent being inside of a radical. Right\n * now, we show the dismiss button rather than allowing the user to jump out of\n * the radical.\n */\n\n// The cursor is not in any of the other viable contexts.\nexport const NONE = \"NONE\";\n// The cursor is within a set of parentheses.\nexport const IN_PARENS = \"IN_PARENS\";\n// The cursor is within a superscript (e.g., an exponent).\nexport const IN_SUPER_SCRIPT = \"IN_SUPER_SCRIPT\";\n// The cursor is within a subscript (e.g., the base of a custom logarithm).\nexport const IN_SUB_SCRIPT = \"IN_SUB_SCRIPT\";\n// The cursor is in the numerator of a fraction.\nexport const IN_NUMERATOR = \"IN_NUMERATOR\";\n// The cursor is in the denominator of a fraction.\nexport const IN_DENOMINATOR = \"IN_DENOMINATOR\";\n// The cursor is sitting before a fraction; that is, the cursor is within\n// what looks to be a mixed number preceding a fraction. This will only be\n// the case when the only math between the cursor and the fraction to its\n// write is non-leaf math (numbers and variables).\nexport const BEFORE_FRACTION = \"BEFORE_FRACTION\";\n","/**\n * React PropTypes that may be shared between components.\n */\n\nimport PropTypes from \"prop-types\";\n\nimport {\n BorderDirections,\n EchoAnimationTypes,\n IconTypes,\n KeyTypes,\n KeypadTypes,\n} from \"../consts.js\";\nimport KeyConfigs from \"../data/key-configs.js\";\n\nimport * as CursorContexts from \"./input/cursor-contexts.js\";\n\nexport const iconPropType = PropTypes.shape({\n type: PropTypes.oneOf(Object.keys(IconTypes)).isRequired,\n data: PropTypes.string.isRequired,\n});\n\nexport const keyIdPropType = PropTypes.oneOf(Object.keys(KeyConfigs));\n\nexport const keyConfigPropType = PropTypes.shape({\n ariaLabel: PropTypes.string,\n id: keyIdPropType.isRequired,\n type: PropTypes.oneOf(Object.keys(KeyTypes)).isRequired,\n childKeyIds: PropTypes.arrayOf(keyIdPropType),\n icon: iconPropType.isRequired,\n});\n\nexport const keypadConfigurationPropType = PropTypes.shape({\n keypadType: PropTypes.oneOf(Object.keys(KeypadTypes)).isRequired,\n extraKeys: PropTypes.arrayOf(keyIdPropType),\n});\n\n// NOTE(jared): This is no longer guaranteed to be React element\nexport const keypadElementPropType = PropTypes.shape({\n activate: PropTypes.func.isRequired,\n dismiss: PropTypes.func.isRequired,\n configure: PropTypes.func.isRequired,\n setCursor: PropTypes.func.isRequired,\n setKeyHandler: PropTypes.func.isRequired,\n getDOMNode: PropTypes.func.isRequired,\n});\n\nexport const bordersPropType = PropTypes.arrayOf(\n PropTypes.oneOf(Object.keys(BorderDirections)),\n);\n\nexport const boundingBoxPropType = PropTypes.shape({\n height: PropTypes.number,\n width: PropTypes.number,\n top: PropTypes.number,\n right: PropTypes.number,\n bottom: PropTypes.number,\n left: PropTypes.number,\n});\n\nexport const echoPropType = PropTypes.shape({\n animationId: PropTypes.string.isRequired,\n animationType: PropTypes.oneOf(Object.keys(EchoAnimationTypes)).isRequired,\n borders: bordersPropType,\n id: keyIdPropType.isRequired,\n initialBounds: boundingBoxPropType.isRequired,\n});\n\nexport const cursorContextPropType = PropTypes.oneOf(\n Object.keys(CursorContexts),\n);\n\nexport const popoverPropType = PropTypes.shape({\n parentId: keyIdPropType.isRequired,\n bounds: boundingBoxPropType.isRequired,\n childKeyIds: PropTypes.arrayOf(keyIdPropType).isRequired,\n});\n\nexport const childrenPropType = PropTypes.oneOfType([\n PropTypes.arrayOf(PropTypes.node),\n PropTypes.node,\n]);\n","/**\n * Renders the green tear-shaped handle under the cursor.\n */\n\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nimport {\n cursorHandleRadiusPx,\n cursorHandleDistanceMultiplier,\n} from \"../common-style.js\";\n\nconst touchTargetRadiusPx = 2 * cursorHandleRadiusPx;\nconst touchTargetHeightPx = 2 * touchTargetRadiusPx;\nconst touchTargetWidthPx = 2 * touchTargetRadiusPx;\n\nconst cursorRadiusPx = cursorHandleRadiusPx;\nconst cursorHeightPx = cursorHandleDistanceMultiplier * (cursorRadiusPx * 4);\nconst cursorWidthPx = 4 * cursorRadiusPx;\n\nclass CursorHandle extends React.Component {\n static propTypes = {\n animateIntoPosition: PropTypes.bool,\n onTouchCancel: PropTypes.func.isRequired,\n onTouchEnd: PropTypes.func.isRequired,\n onTouchMove: PropTypes.func.isRequired,\n onTouchStart: PropTypes.func.isRequired,\n visible: PropTypes.bool.isRequired,\n x: PropTypes.number.isRequired,\n y: PropTypes.number.isRequired,\n };\n\n static defaultProps = {\n animateIntoPosition: false,\n visible: false,\n x: 0,\n y: 0,\n };\n\n render() {\n const {x, y, animateIntoPosition} = this.props;\n\n const animationStyle = animateIntoPosition\n ? {\n msTransitionDuration: \"100ms\",\n WebkitTransitionDuration: \"100ms\",\n transitionDuration: \"100ms\",\n msTransitionProperty: \"transform\",\n WebkitTransitionProperty: \"transform\",\n transitionProperty: \"transform\",\n }\n : {};\n const transformString = `translate(${x}px, ${y}px)`;\n\n const outerStyle = {\n position: \"absolute\",\n // This is essentially webapp's interactiveComponent + 1.\n // TODO(charlie): Pull in those styles somehow to avoid breakages.\n zIndex: 4,\n left: -touchTargetWidthPx / 2,\n top: 0,\n msTransform: transformString,\n WebkitTransform: transformString,\n transform: transformString,\n width: touchTargetWidthPx,\n height: touchTargetHeightPx,\n // Touch events that start on the cursor shouldn't be allowed to\n // produce page scrolls.\n touchAction: \"none\",\n ...animationStyle,\n };\n\n return (\n <span\n style={outerStyle}\n onTouchStart={this.props.onTouchStart}\n onTouchMove={this.props.onTouchMove}\n onTouchEnd={this.props.onTouchEnd}\n onTouchCancel={this.props.onTouchCancel}\n >\n <svg\n fill=\"none\"\n width={cursorWidthPx}\n height={cursorHeightPx}\n viewBox={`0 0 ${cursorWidthPx} ${cursorHeightPx}`}\n >\n <filter\n id=\"math-input_cursor\"\n colorInterpolationFilters=\"sRGB\"\n filterUnits=\"userSpaceOnUse\"\n height={cursorHeightPx * 0.87} // ~40\n width={cursorWidthPx * 0.82} // ~36\n x=\"4\"\n y=\"0\"\n >\n <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n <feColorMatrix\n in=\"SourceAlpha\"\n type=\"matrix\"\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\n />\n <feOffset dy=\"4\" />\n <feGaussianBlur stdDeviation=\"4\" />\n <feColorMatrix\n type=\"matrix\"\n values=\"0 0 0 0 0.129412 0 0 0 0 0.141176 0 0 0 0 0.172549 0 0 0 0.08 0\"\n />\n <feBlend\n in2=\"BackgroundImageFix\"\n mode=\"normal\"\n result=\"effect1_dropShadow\"\n />\n <feBlend\n in=\"SourceGraphic\"\n in2=\"effect1_dropShadow\"\n mode=\"normal\"\n result=\"shape\"\n />\n </filter>\n <g filter=\"url(#math-input_cursor)\">\n <path\n d=\"m22 4-7.07 7.0284c-1.3988 1.3901-2.3515 3.1615-2.7376 5.09-.3861 1.9284-.1883 3.9274.5685 5.7441s2.0385 3.3694 3.6831 4.4619c1.6445 1.0925 3.5781 1.6756 5.556 1.6756s3.9115-.5831 5.556-1.6756c1.6446-1.0925 2.9263-2.6452 3.6831-4.4619s.9546-3.8157.5685-5.7441c-.3861-1.9285-1.3388-3.6999-2.7376-5.09z\"\n fill=\"#1865f2\"\n />\n </g>\n <path\n d=\"m14.9301 10.4841 7.0699-7.06989 7.0699 7.06989.0001.0001c1.3988 1.3984 2.3515 3.1802 2.7376 5.1201s.1883 3.9507-.5685 5.7782c-.7568 1.8274-2.0385 3.3894-3.6831 4.4883-1.6445 1.099-3.5781 1.6855-5.556 1.6855s-3.9115-.5865-5.556-1.6855c-1.6446-1.0989-2.9263-2.6609-3.6831-4.4883-.7568-1.8275-.9546-3.8383-.5685-5.7782s1.3388-3.7217 2.7376-5.1201z\"\n stroke=\"#fff\"\n strokeWidth=\"2\"\n />\n </svg>\n </span>\n );\n }\n}\n\nexport default CursorHandle;\n","/**\n * A gesture recognizer that detects 'drags', crudely defined as either scrolls\n * or touches that move a sufficient distance.\n */\n\n// The 'slop' factor, after which we consider the use to be dragging. The value\n// is taken from the Android SDK. It won't be robust to page zoom and the like,\n// but it should be good enough for our purposes.\nconst touchSlopPx = 8;\n\nclass DragListener {\n constructor(onDrag, initialEvent) {\n // We detect drags in two ways. First, by listening for the window\n // scroll event (we consider any legitimate scroll to be a drag).\n this._scrollListener = () => {\n onDrag();\n };\n\n // And second, by listening for touch moves and tracking the each\n // finger's displacement. This allows us to track, e.g., when the user\n // scrolls within an individual view.\n const touchLocationsById = {};\n for (let i = 0; i < initialEvent.changedTouches.length; i++) {\n const touch = initialEvent.changedTouches[i];\n touchLocationsById[touch.identifier] = [\n touch.clientX,\n touch.clientY,\n ];\n }\n\n this._moveListener = (evt) => {\n for (let i = 0; i < evt.changedTouches.length; i++) {\n const touch = evt.changedTouches[i];\n const initialTouchLocation =\n touchLocationsById[touch.identifier];\n if (initialTouchLocation) {\n const touchLocation = [touch.clientX, touch.clientY];\n const dx = touchLocation[0] - initialTouchLocation[0];\n const dy = touchLocation[1] - initialTouchLocation[1];\n\n const squaredDist = dx * dx + dy * dy;\n const squaredTouchSlop = touchSlopPx * touchSlopPx;\n\n if (squaredDist > squaredTouchSlop) {\n onDrag();\n }\n }\n }\n };\n\n // Clean-up any terminated gestures, since some browsers reuse\n // identifiers.\n this._endAndCancelListener = (evt) => {\n for (let i = 0; i < evt.changedTouches.length; i++) {\n delete touchLocationsById[evt.changedTouches[i].identifier];\n }\n };\n }\n\n attach() {\n window.addEventListener(\"scroll\", this._scrollListener);\n window.addEventListener(\"touchmove\", this._moveListener);\n window.addEventListener(\"touchend\", this._endAndCancelListener);\n window.addEventListener(\"touchcancel\", this._endAndCancelListener);\n }\n\n detach() {\n window.removeEventListener(\"scroll\", this._scrollListener);\n window.removeEventListener(\"touchmove\", this._moveListener);\n window.removeEventListener(\"touchend\", this._endAndCancelListener);\n window.removeEventListener(\"touchcancel\", this._endAndCancelListener);\n }\n}\n\nexport default DragListener;\n","/**\n * This file contains a wrapper around MathQuill so that we can provide a\n * more regular interface for the functionality we need while insulating us\n * from MathQuill changes.\n */\n\nimport $ from \"jquery\";\nimport MathQuill from \"mathquill\";\n\nimport {DecimalSeparators} from \"../../consts.js\";\nimport Keys from \"../../data/keys.js\";\nimport {decimalSeparator} from \"../../utils.js\";\n\nimport * as CursorContexts from \"./cursor-contexts.js\";\n\n// Keeping `window` in place for test suite and GitHub Pages.\n// If it does not exist, fall back to CommonJS require. - jsatk\n\nconst decimalSymbol = decimalSeparator === DecimalSeparators.COMMA ? \",\" : \".\";\n\nconst WRITE = \"write\";\nconst CMD = \"cmd\";\nconst KEYSTROKE = \"keystroke\";\nconst MQ_END = 0;\n\n// A mapping from keys that can be pressed on a keypad to the way in which\n// MathQuill should modify its input in response to that key-press. Any keys\n// that do not provide explicit actions (like the numeral keys) will merely\n// write their contents to MathQuill.\nconst KeyActions = {\n [Keys.PLUS]: {str: \"+\", fn: WRITE},\n [Keys.MINUS]: {str: \"-\", fn: WRITE},\n [Keys.NEGATIVE]: {str: \"-\", fn: WRITE},\n [Keys.TIMES]: {str: \"\\\\times\", fn: WRITE},\n [Keys.DIVIDE]: {str: \"\\\\div\", fn: WRITE},\n [Keys.DECIMAL]: {\n str: decimalSymbol,\n fn: WRITE,\n },\n [Keys.EQUAL]: {str: \"=\", fn: WRITE},\n [Keys.NEQ]: {str: \"\\\\neq\", fn: WRITE},\n [Keys.CDOT]: {str: \"\\\\cdot\", fn: WRITE},\n [Keys.PERCENT]: {str: \"%\", fn: WRITE},\n [Keys.LEFT_PAREN]: {str: \"(\", fn: CMD},\n [Keys.RIGHT_PAREN]: {str: \")\", fn: CMD},\n [Keys.SQRT]: {str: \"sqrt\", fn: CMD},\n [Keys.PI]: {str: \"pi\", fn: CMD},\n [Keys.THETA]: {str: \"theta\", fn: CMD},\n [Keys.RADICAL]: {str: \"nthroot\", fn: CMD},\n [Keys.LT]: {str: \"<\", fn: WRITE},\n [Keys.LEQ]: {str: \"\\\\leq\", fn: WRITE},\n [Keys.GT]: {str: \">\", fn: WRITE},\n [Keys.GEQ]: {str: \"\\\\geq\", fn: WRITE},\n [Keys.UP]: {str: \"Up\", fn: KEYSTROKE},\n [Keys.DOWN]: {str: \"Down\", fn: KEYSTROKE},\n // The `FRAC_EXCLUSIVE` variant is handled manually, since we may need to do\n // some additional navigation depending on the cursor position.\n [Keys.FRAC_INCLUSIVE]: {str: \"/\", fn: CMD},\n};\n\nconst NormalCommands = {\n [Keys.LOG]: \"log\",\n [Keys.LN]: \"ln\",\n [Keys.SIN]: \"sin\",\n [Keys.COS]: \"cos\",\n [Keys.TAN]: \"tan\",\n};\n\nconst ArithmeticOperators = [\"+\", \"-\", \"\\\\cdot\", \"\\\\times\", \"\\\\div\"];\nconst EqualityOperators = [\"=\", \"\\\\neq\", \"<\", \"\\\\leq\", \">\", \"\\\\geq\"];\n\nconst Numerals = [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"];\nconst GreekLetters = [\"\\\\theta\", \"\\\\pi\"];\nconst Letters = [\n \"A\",\n \"B\",\n \"C\",\n \"D\",\n \"E\",\n \"F\",\n \"G\",\n \"H\",\n \"I\",\n \"J\",\n \"K\",\n \"L\",\n \"M\",\n \"N\",\n \"O\",\n \"P\",\n \"Q\",\n \"R\",\n \"S\",\n \"T\",\n \"U\",\n \"V\",\n \"W\",\n \"X\",\n \"Y\",\n \"Z\",\n];\n\n// We only consider numerals, variables, and Greek Letters to be proper\n// leaf nodes.\nconst ValidLeaves = [\n ...Numerals,\n ...GreekLetters,\n ...Letters.map((letter) => letter.toLowerCase()),\n ...Letters.map((letter) => letter.toUpperCase()),\n];\n\nconst KeysForJumpContext = {\n [CursorContexts.IN_PARENS]: Keys.JUMP_OUT_PARENTHESES,\n [CursorContexts.IN_SUPER_SCRIPT]: Keys.JUMP_OUT_EXPONENT,\n [CursorContexts.IN_SUB_SCRIPT]: Keys.JUMP_OUT_BASE,\n [CursorContexts.BEFORE_FRACTION]: Keys.JUMP_INTO_NUMERATOR,\n [CursorContexts.IN_NUMERATOR]: Keys.JUMP_OUT_NUMERATOR,\n [CursorContexts.IN_DENOMINATOR]: Keys.JUMP_OUT_DENOMINATOR,\n};\n\nclass MathWrapper {\n constructor(element, options = {}, callbacks = {}) {\n this.MQ = MathQuill.getInterface(2);\n this.mathField = this.MQ.MathField(element, {\n // use a span instead of a textarea so that we don't bring up the\n // native keyboard on mobile when selecting the input\n substituteTextarea: function () {\n return document.createElement(\"span\");\n },\n });\n this.callbacks = callbacks;\n }\n\n focus() {\n // HACK(charlie): We shouldn't reaching into MathQuill internals like\n // this, but it's the easiest way to allow us to manage the focus state\n // ourselves.\n const controller = this.mathField.__controller;\n controller.cursor.show();\n\n // Set MathQuill's internal state to reflect the focus, otherwise it\n // will consistently try to hide the cursor on key-press and introduce\n // layout jank.\n controller.blurred = false;\n }\n\n blur() {\n const controller = this.mathField.__controller;\n controller.cursor.hide();\n controller.blurred = true;\n }\n\n _writeNormalFunction(name) {\n this.mathField.write(`\\\\${name}\\\\left(\\\\right)`);\n this.mathField.keystroke(\"Left\");\n }\n\n /**\n * Handle a key press and return the resulting cursor state.\n *\n * @param {Key} key - an enum representing the key that was pressed\n * @returns {object} a cursor object, consisting of a cursor context\n */\n pressKey(key) {\n const cursor = this.mathField.__controller.cursor;\n\n if (key in KeyActions) {\n const {str, fn} = KeyActions[key];\n\n if (str && fn) {\n this.mathField[fn](str);\n }\n } else if (Object.keys(NormalCommands).includes(key)) {\n this._writeNormalFunction(NormalCommands[key]);\n } else if (key === Keys.FRAC_EXCLUSIVE) {\n // If there's nothing to the left of the cursor, then we want to\n // leave the cursor to the left of the fraction after creating it.\n const shouldNavigateLeft = cursor[this.MQ.L] === MQ_END;\n this.mathField.cmd(\"\\\\frac\");\n if (shouldNavigateLeft) {\n this.mathField.keystroke(\"Left\");\n }\n } else if (key === Keys.FRAC) {\n // eslint-disable-next-line no-unused-vars\n const shouldNavigateLeft = cursor[this.MQ.L] === MQ_END;\n this.mathField.cmd(\"\\\\frac\");\n } else if (key === Keys.LOG_N) {\n this.mathField.write(\"log_{ }\\\\left(\\\\right)\");\n this.mathField.keystroke(\"Left\"); // into parentheses\n this.mathField.keystroke(\"Left\"); // out of parentheses\n this.mathField.keystroke(\"Left\"); // into index\n } else if (key === Keys.CUBE_ROOT) {\n this.mathField.write(\"\\\\sqrt[3]{}\");\n this.mathField.keystroke(\"Left\"); // under the root\n } else if (\n key === Keys.EXP ||\n key === Keys.EXP_2 ||\n key === Keys.EXP_3\n ) {\n this._handleExponent(cursor, key);\n } else if (\n key === Keys.JUMP_OUT_PARENTHESES ||\n key === Keys.JUMP_OUT_EXPONENT ||\n key === Keys.JUMP_OUT_BASE ||\n key === Keys.JUMP_INTO_NUMERATOR ||\n key === Keys.JUMP_OUT_NUMERATOR ||\n key === Keys.JUMP_OUT_DENOMINATOR\n ) {\n this._handleJumpOut(cursor, key);\n } else if (key === Keys.BACKSPACE) {\n this._handleBackspace(cursor);\n } else if (key === Keys.LEFT) {\n this._handleLeftArrow(cursor);\n } else if (key === Keys.RIGHT || key === Keys.JUMP_OUT) {\n this._handleRightArrow(cursor);\n } else if (/^[a-zA-Z]$/.test(key)) {\n this.mathField[WRITE](key);\n } else if (/^NUM_\\d/.test(key)) {\n this.mathField[WRITE](key[4]);\n }\n\n if (!cursor.selection) {\n // don't show the cursor for selections\n cursor.show();\n }\n\n if (this.callbacks.onSelectionChanged) {\n this.callbacks.onSelectionChanged(cursor.selection);\n }\n\n // NOTE(charlie): It's insufficient to do this as an `edited` handler\n // on the MathField, as that handler isn't triggered on navigation\n // events.\n return {\n context: this.contextForCursor(cursor),\n };\n }\n\n /**\n * Place the cursor beside the node located at the given coordinates.\n *\n * @param {number} x - the x coordinate in the viewport\n * @param {number} y - the y coordinate in the viewport\n * @param {Node} hitNode - the node next to which the cursor should be\n * placed; if provided, the coordinates will be used\n * to determine on which side of the node the cursor\n * should be placed\n */\n setCursorPosition(x, y, hitNode) {\n const el = hitNode || document.elementFromPoint(x, y);\n\n if (el) {\n const cursor = this.getCursor();\n\n if (el.hasAttribute(\"mq-root-block\")) {\n // If we're in the empty area place the cursor at the right\n // end of the expression.\n cursor.insAtRightEnd(this.mathField.__controller.root);\n } else {\n // Otherwise place beside the element at x, y.\n const controller = this.mathField.__controller;\n\n const pageX = x - document.body.scrollLeft;\n const pageY = y - document.body.scrollTop;\n controller.seek($(el), pageX, pageY).cursor.startSelection();\n\n // Unless that would leave us mid-command, in which case, we\n // need to adjust and place the cursor inside the parens\n // following the command.\n const command = this._maybeFindCommand(cursor[this.MQ.L]);\n if (command && command.endNode) {\n // NOTE(charlie): endNode should definitely be \\left(.\n cursor.insLeftOf(command.endNode);\n this.mathField.keystroke(\"Right\");\n }\n }\n\n if (this.callbacks.onCursorMove) {\n this.callbacks.onCursorMove({\n context: this.contextForCursor(cursor),\n });\n }\n }\n }\n\n getCursor() {\n return this.mathField.__controller.cursor;\n }\n\n getSelection() {\n return this.getCursor().selection;\n }\n\n getContent() {\n return this.mathField.latex();\n }\n\n setContent(latex) {\n this.mathField.latex(latex);\n }\n\n isEmpty() {\n const cursor = this.getCursor();\n return cursor.parent.id === 1 && cursor[1] === 0 && cursor[-1] === 0;\n }\n\n // Notes about MathQuill\n //\n // MathQuill's stores its layout as nested linked lists. Each node in the\n // list has this.MQ.L '-1' and this.MQ.R '1' properties that define links to\n // the left and right nodes respectively. They also have\n //\n // ctrlSeq: contains the latex code snippet that defines that node.\n // jQ: jQuery object for the DOM node(s) for this MathQuill node.\n // ends: pointers to the nodes at the ends of the container.\n // parent: parent node.\n // blocks: an array containing one or more nodes that make up the node.\n // sub?: subscript node if there is one as is the case in log_n\n //\n // All of the code below is super fragile. Please be especially careful\n // when upgrading MathQuill.\n\n _handleBackspaceInNthRoot(cursor) {\n const isAtLeftEnd = cursor[this.MQ.L] === MQ_END;\n\n const isRootEmpty = this._isInsideEmptyNode(\n cursor.parent.parent.blocks[0].ends,\n );\n\n if (isAtLeftEnd) {\n this._selectNode(cursor.parent.parent, cursor);\n\n if (isRootEmpty) {\n this.mathField.keystroke(\"Backspace\");\n }\n } else {\n this.mathField.keystroke(\"Backspace\");\n }\n }\n\n /**\n * Advances the cursor to the next logical position.\n *\n * @param {cursor} cursor\n * @private\n */\n _handleJumpOut(cursor, key) {\n const context = this.contextForCursor(cursor);\n\n // Validate that the current cursor context matches the key's intent.\n if (KeysForJumpContext[context] !== key) {\n // If we don't have a valid cursor context, yet the user was able\n // to trigger a jump-out key, that's a broken invariant. Rather\n // than throw an error (which would kick the user out of the\n // exercise), we do nothing, as a fallback strategy. The user can\n // still move the cursor manually.\n return;\n }\n\n switch (context) {\n case CursorContexts.IN_PARENS:\n // Insert at the end of the parentheses, and then navigate right\n // once more to get 'beyond' the parentheses.\n cursor.insRightOf(cursor.parent.parent);\n break;\n\n case CursorContexts.BEFORE_FRACTION:\n // Find the nearest fraction to the right of the cursor.\n let fractionNode;\n let visitor = cursor;\n while (visitor[this.MQ.R] !== MQ_END) {\n if (this._isFraction(visitor[this.MQ.R])) {\n fractionNode = visitor[this.MQ.R];\n }\n visitor = visitor[this.MQ.R];\n }\n\n // Jump into it!\n cursor.insLeftOf(fractionNode);\n this.mathField.keystroke(\"Right\");\n break;\n\n case CursorContexts.IN_NUMERATOR:\n // HACK(charlie): I can't find a better way to do this. The goal\n // is to place the cursor at the start of the matching\n // denominator. So, we identify the appropriate node, and\n // continue rightwards until we find ourselves inside of it.\n // It's possible that there are cases in which we don't reach\n // the denominator, though I can't think of any.\n const siblingDenominator = cursor.parent.parent.blocks[1];\n while (cursor.parent !== siblingDenominator) {\n this.mathField.keystroke(\"Right\");\n }\n break;\n\n case CursorContexts.IN_DENOMINATOR:\n cursor.insRightOf(cursor.parent.parent);\n break;\n\n case CursorContexts.IN_SUB_SCRIPT:\n // Insert just beyond the superscript.\n cursor.insRightOf(cursor.parent.parent);\n\n // Navigate right once more, if we're right before parens. This\n // is to handle the standard case in which the subscript is the\n // base of a custom log.\n if (this._isParens(cursor[this.MQ.R])) {\n this.mathField.keystroke(\"Right\");\n }\n break;\n\n case CursorContexts.IN_SUPER_SCRIPT:\n // Insert just beyond the superscript.\n cursor.insRightOf(cursor.parent.parent);\n break;\n\n default:\n throw new Error(\n `Attempted to 'Jump Out' from node, but found no ` +\n `appropriate cursor context: ${context}`,\n );\n }\n }\n\n /**\n * Selects and deletes part of the expression based on the cursor location.\n * See inline comments for precise behavior of different cases.\n *\n * @param {cursor} cursor\n * @private\n */\n _handleBackspace(cursor) {\n if (!cursor.selection) {\n const parent = cursor.parent;\n const grandparent = parent.parent;\n const leftNode = cursor[this.MQ.L];\n\n if (this._isFraction(leftNode)) {\n this._selectNode(leftNode, cursor);\n } else if (this._isSquareRoot(leftNode)) {\n this._selectNode(leftNode, cursor);\n } else if (this._isNthRoot(leftNode)) {\n this._selectNode(leftNode, cursor);\n } else if (this._isNthRootIndex(parent)) {\n this._handleBackspaceInRootIndex(cursor);\n } else if (leftNode.ctrlSeq === \"\\\\left(\") {\n this._handleBackspaceOutsideParens(cursor);\n } else if (grandparent.ctrlSeq === \"\\\\left(\") {\n this._handleBackspaceInsideParens(cursor);\n } else if (this._isInsideLogIndex(cursor)) {\n this._handleBackspaceInLogIndex(cursor);\n } else if (\n leftNode.ctrlSeq === \"\\\\ge \" ||\n leftNode.ctrlSeq === \"\\\\le \"\n ) {\n this._handleBackspaceAfterLigaturedSymbol(cursor);\n } else if (this._isNthRoot(grandparent) && leftNode === MQ_END) {\n this._handleBackspaceInNthRoot(cursor);\n } else {\n this.mathField.keystroke(\"Backspace\");\n }\n } else {\n this.mathField.keystroke(\"Backspace\");\n }\n }\n\n _handleLeftArrow(cursor) {\n // If we're inside a function, and just after the left parentheses, we\n // need to skip the entire function name, rather than move the cursor\n // inside of it. For example, when hitting left from within the\n // parentheses in `cos()`, we want to place the cursor to the left of\n // the entire expression, rather than between the `s` and the left\n // parenthesis.\n // From the cursor's perspective, this requires that our left node is\n // the MQ_END node, that our grandparent is the left parenthesis, and\n // the nodes to the left of our grandparent comprise a valid function\n // name.\n if (cursor[this.MQ.L] === MQ_END) {\n const parent = cursor.parent;\n const grandparent = parent.parent;\n if (grandparent.ctrlSeq === \"\\\\left(\") {\n const command = this._maybeFindCommandBeforeParens(grandparent);\n if (command) {\n cursor.insLeftOf(command.startNode);\n return;\n }\n }\n }\n\n // Otherwise, we default to the standard MathQull left behavior.\n this.mathField.keystroke(\"Left\");\n }\n\n _handleRightArrow(cursor) {\n const command = this._maybeFindCommand(cursor[this.MQ.R]);\n if (command) {\n // Similarly, if a function is to our right, then we need to place\n // the cursor at the start of its parenthetical content, which is\n // done by putting it to the left of ites parentheses and then\n // moving right once.\n cursor.insLeftOf(command.endNode);\n this.mathField.keystroke(\"Right\");\n } else {\n // Otherwise, we default to the standard MathQull right behavior.\n this.mathField.keystroke(\"Right\");\n }\n }\n\n _handleExponent(cursor, key) {\n // If there's an invalid operator preceding the cursor (anything that\n // knowingly cannot be raised to a power), add an empty set of\n // parentheses and apply the exponent to that.\n const invalidPrefixes = [...ArithmeticOperators, ...EqualityOperators];\n\n const precedingNode = cursor[this.MQ.L];\n const shouldPrefixWithParens =\n precedingNode === MQ_END ||\n invalidPrefixes.includes(precedingNode.ctrlSeq.trim());\n if (shouldPrefixWithParens) {\n this.mathField.write(\"\\\\left(\\\\right)\");\n }\n\n // Insert the appropriate exponent operator.\n switch (key) {\n case Keys.EXP:\n this.mathField.cmd(\"^\");\n break;\n\n case Keys.EXP_2:\n case Keys.EXP_3:\n this.mathField.write(`^${key === Keys.EXP_2 ? 2 : 3}`);\n\n // If we enter a square or a cube, we should leave the cursor\n // within the newly inserted parens, if they exist. This takes\n // exactly four left strokes, since the cursor by default would\n // end up to the right of the exponent.\n if (shouldPrefixWithParens) {\n this.mathField.keystroke(\"Left\");\n this.mathField.keystroke(\"Left\");\n this.mathField.keystroke(\"Left\");\n this.mathField.keystroke(\"Left\");\n }\n break;\n\n default:\n throw new Error(`Invalid exponent key: ${key}`);\n }\n }\n\n /**\n * Return the start node, end node, and full name of the command of which\n * the initial node is a part, or `null` if the node is not part of a\n * command.\n *\n * @param {node} initialNode - the node to included as part of the command\n * @returns {null|object} - `null` or an object containing the start node\n * (`startNode`), end node (`endNode`), and full\n * name (`name`) of the command\n * @private\n */\n _maybeFindCommand(initialNode) {\n if (!initialNode) {\n return null;\n }\n\n // MathQuill stores commands as separate characters so that\n // users can delete commands one character at a time. We iterate over\n // the nodes from right to left until we hit a sequence starting with a\n // '\\\\', which signifies the start of a command; then we iterate from\n // left to right until we hit a '\\\\left(', which signifies the end of a\n // command. If we encounter any character that doesn't belong in a\n // command, we return null. We match a single character at a time.\n // Ex) ['\\\\l', 'o', 'g ', '\\\\left(', ...]\n const commandCharRegex = /^[a-z]$/;\n const commandStartRegex = /^\\\\[a-z]$/;\n const commandEndSeq = \"\\\\left(\";\n\n // Note: We whitelist the set of valid commands, since relying solely on\n // a command being prefixed with a backslash leads to undesired\n // behavior. For example, Greek symbols, left parentheses, and square\n // roots all get treated as commands.\n const validCommands = [\"\\\\log\", \"\\\\ln\", \"\\\\cos\", \"\\\\sin\", \"\\\\tan\"];\n\n let name = \"\";\n let startNode;\n let endNode;\n\n // Collect the portion of the command from the current node, leftwards\n // until the start of the command.\n let node = initialNode;\n while (node !== 0) {\n const ctrlSeq = node.ctrlSeq.trim();\n if (commandCharRegex.test(ctrlSeq)) {\n name = ctrlSeq + name;\n } else if (commandStartRegex.test(ctrlSeq)) {\n name = ctrlSeq + name;\n startNode = node;\n break;\n } else {\n break;\n }\n\n node = node[this.MQ.L];\n }\n\n // If we hit the start of a command, then grab the rest of it by\n // iterating rightwards to compute the full name of the command, along\n // with its terminal node.\n if (startNode) {\n // Next, iterate from the start to the right.\n node = initialNode[this.MQ.R];\n while (node !== 0) {\n const ctrlSeq = node.ctrlSeq.trim();\n if (commandCharRegex.test(ctrlSeq)) {\n // If we have a single character, add it to the command\n // name.\n name = name + ctrlSeq;\n } else if (ctrlSeq === commandEndSeq) {\n // If we hit the command end delimiter (the left\n // parentheses surrounding its arguments), stop.\n endNode = node;\n break;\n }\n\n node = node[this.MQ.R];\n }\n if (validCommands.includes(name)) {\n return {name, startNode, endNode};\n } else {\n return null;\n }\n } else {\n return null;\n }\n }\n\n /**\n * Return the start node, end node, and full name of the command to the left\n * of `\\\\left(`, or `null` if there is no command.\n *\n * @param {node} leftParenNode - node where .ctrlSeq == `\\\\left(`\n * @returns {null|object} - `null` or an object containing the start node\n * (`startNode`), end node (`endNode`), and full\n * name (`name`) of the command\n * @private\n */\n _maybeFindCommandBeforeParens(leftParenNode) {\n return this._maybeFindCommand(leftParenNode[this.MQ.L]);\n }\n\n _selectNode(node, cursor) {\n cursor.insLeftOf(node);\n cursor.startSelection();\n cursor.insRightOf(node);\n cursor.select();\n cursor.endSelection();\n }\n\n _isFraction(node) {\n return node.jQ && node.jQ.hasClass(\"mq-fraction\");\n }\n\n _isNumerator(node) {\n return node.jQ && node.jQ.hasClass(\"mq-numerator\");\n }\n\n _isDenominator(node) {\n return node.jQ && node.jQ.hasClass(\"mq-denominator\");\n }\n\n _isSubScript(node) {\n // NOTE(charlie): MyScript has a structure whereby its superscripts seem\n // to be represented as a parent node with 'mq-sup-only' containing a\n // single child with 'mq-sup'.\n return (\n node.jQ &&\n (node.jQ.hasClass(\"mq-sub-only\") || node.jQ.hasClass(\"mq-sub\"))\n );\n }\n\n _isSuperScript(node) {\n // NOTE(charlie): MyScript has a structure whereby its superscripts seem\n // to be represented as a parent node with 'mq-sup-only' containing a\n // single child with 'mq-sup'.\n return (\n node.jQ &&\n (node.jQ.hasClass(\"mq-sup-only\") || node.jQ.hasClass(\"mq-sup\"))\n );\n }\n\n _isParens(node) {\n return node && node.ctrlSeq === \"\\\\left(\";\n }\n\n _isLeaf(node) {\n return (\n node && node.ctrlSeq && ValidLeaves.includes(node.ctrlSeq.trim())\n );\n }\n\n _isSquareRoot(node) {\n return (\n node.blocks &&\n node.blocks[0].jQ &&\n node.blocks[0].jQ.hasClass(\"mq-sqrt-stem\")\n );\n }\n\n _isNthRoot(node) {\n return (\n node.blocks &&\n node.blocks[0].jQ &&\n node.blocks[0].jQ.hasClass(\"mq-nthroot\")\n );\n }\n\n _isNthRootIndex(node) {\n return node.jQ && node.jQ.hasClass(\"mq-nthroot\");\n }\n\n _isInsideLogIndex(cursor) {\n const grandparent = cursor.parent.parent;\n\n if (grandparent && grandparent.jQ.hasClass(\"mq-supsub\")) {\n const command = this._maybeFindCommandBeforeParens(grandparent);\n\n if (command && command.name === \"\\\\log\") {\n return true;\n }\n }\n\n return false;\n }\n\n _isInsideEmptyNode(cursor) {\n return cursor[this.MQ.L] === MQ_END && cursor[this.MQ.R] === MQ_END;\n }\n\n _handleBackspaceInRootIndex(cursor) {\n if (this._isInsideEmptyNode(cursor)) {\n // When deleting the index in a nthroot, we change from the nthroot\n // to a sqrt, e.g. \\sqrt[|]{35x-5} => |\\sqrt{35x-5}. If there's no\n // content under the root, then we delete the whole thing.\n\n const grandparent = cursor.parent.parent;\n const latex = grandparent.latex();\n const reinsertionPoint = grandparent[this.MQ.L];\n\n this._selectNode(grandparent, cursor);\n\n const rootIsEmpty = grandparent.blocks[1].jQ.text() === \"\";\n\n if (rootIsEmpty) {\n // If there is not content under the root then simply delete\n // the whole thing.\n this.mathField.keystroke(\"Backspace\");\n } else {\n // Replace the nthroot with a sqrt if there was content under\n // the root.\n\n // Start by deleting the selection.\n this.mathField.keystroke(\"Backspace\");\n\n // Replace the nth-root with a sqrt.\n this.mathField.write(latex.replace(/^\\\\sqrt\\[\\]/, \"\\\\sqrt\"));\n\n // Adjust the cursor to be to the left the sqrt.\n if (reinsertionPoint === MQ_END) {\n this.mathField.moveToDirEnd(this.MQ.L);\n } else {\n cursor.insRightOf(reinsertionPoint);\n }\n }\n } else {\n if (cursor[this.MQ.L] !== MQ_END) {\n // If the cursor is not at the leftmost position inside the\n // root's index, delete a character.\n this.mathField.keystroke(\"Backspace\");\n } else {\n // TODO(kevinb) verify that we want this behavior after testing\n // Do nothing because we haven't completely deleted the\n // index of the radical.\n }\n }\n }\n\n _handleBackspaceInLogIndex(cursor) {\n if (this._isInsideEmptyNode(cursor)) {\n const grandparent = cursor.parent.parent;\n const command = this._maybeFindCommandBeforeParens(grandparent);\n\n cursor.insLeftOf(command.startNode);\n cursor.startSelection();\n\n if (grandparent[this.MQ.R] !== MQ_END) {\n cursor.insRightOf(grandparent[this.MQ.R]);\n } else {\n cursor.insRightOf(grandparent);\n }\n\n cursor.select();\n cursor.endSelection();\n\n const isLogBodyEmpty =\n grandparent[this.MQ.R].contentjQ.text() === \"\";\n\n if (isLogBodyEmpty) {\n // If there's no content inside the log's parens then delete the\n // whole thing.\n this.mathField.keystroke(\"Backspace\");\n }\n } else {\n this.mathField.keystroke(\"Backspace\");\n }\n }\n\n _handleBackspaceOutsideParens(cursor) {\n // In this case the node with '\\\\left(' for its ctrlSeq\n // is the parent of the expression contained within the\n // parentheses.\n //\n // Handle selecting an expression before deleting:\n // (x+1)| => |(x+1)|\n // \\log(x+1)| => |\\log(x+1)|\n\n const leftNode = cursor[this.MQ.L];\n const rightNode = cursor[this.MQ.R];\n const command = this._maybeFindCommandBeforeParens(leftNode);\n\n if (command && command.startNode) {\n // There's a command before the parens so we select it as well as\n // the parens.\n cursor.insLeftOf(command.startNode);\n cursor.startSelection();\n if (rightNode === MQ_END) {\n cursor.insAtRightEnd(cursor.parent);\n } else {\n cursor.insLeftOf(rightNode);\n }\n cursor.select();\n cursor.endSelection();\n } else {\n cursor.startSelection();\n cursor.insLeftOf(leftNode); // left of \\\\left(\n cursor.select();\n cursor.endSelection();\n }\n }\n\n _handleBackspaceInsideParens(cursor) {\n // Handle situations when the cursor is inside parens or a\n // command that uses parens, e.g. \\log() or \\tan()\n //\n // MathQuill represents log(x+1) in roughly the following way\n // [l, o, g, \\\\left[parent:[x, +, 1]]]\n //\n // If the cursor is inside the parentheses it's next to one of:\n // x, +, or 1. This makes sub_sub_expr its parent and sub_expr\n // it's parent.\n //\n // Interestingly parent doesn't have any nodes to the left or\n // right of it (even though the corresponding DOM node has\n // ( and ) characters on either side.\n //\n // The grandparent's ctrlSeq is `\\\\left(`. The `\\\\right)` isn't\n // stored anywhere. NOTE(kevinb): I believe this is because\n // MathQuill knows what the close paren should be and does the\n // right thing at render time.\n //\n // This conditional branch handles the following cases:\n // - \\log(x+1|) => \\log(x+|)\n // - \\log(|x+1) => |\\log(x+1)|\n // - \\log(|) => |\n\n if (cursor[this.MQ.L] !== MQ_END) {\n // This command contains math and there's some math to\n // the left of the cursor that we should delete normally\n // before doing anything special.\n this.mathField.keystroke(\"Backspace\");\n return;\n }\n\n const grandparent = cursor.parent.parent;\n\n // If the cursors is inside the parens at the start but the command\n // has a subscript as is the case in log_n then move the cursor into\n // the subscript, e.g. \\log_{5}(|x+1) => \\log_{5|}(x+1)\n\n if (grandparent[this.MQ.L].sub) {\n // if there is a subscript\n if (grandparent[this.MQ.L].sub.jQ.text()) {\n // and it contains text\n // move the cursor to the right end of the subscript\n cursor.insAtRightEnd(grandparent[this.MQ.L].sub);\n return;\n }\n }\n\n // Determine if the parens are empty before we modify the\n // cursor's position.\n const isEmpty = this._isInsideEmptyNode(cursor);\n\n // Insert the cursor to the left of the command if there is one\n // or before the '\\\\left(` if there isn't\n const command = this._maybeFindCommandBeforeParens(grandparent);\n\n cursor.insLeftOf((command && command.startNode) || grandparent);\n cursor.startSelection();\n cursor.insRightOf(grandparent);\n cursor.select();\n cursor.endSelection();\n\n // Delete the selection, but only if the parens were empty to\n // begin with.\n if (isEmpty) {\n this.mathField.keystroke(\"Backspace\");\n }\n }\n\n _handleBackspaceAfterLigaturedSymbol(cursor) {\n this.mathField.keystroke(\"Backspace\");\n this.mathField.keystroke(\"Backspace\");\n }\n\n contextForCursor(cursor) {\n // First, try to find any fraction to the right, unimpeded.\n let visitor = cursor;\n while (visitor[this.MQ.R] !== MQ_END) {\n if (this._isFraction(visitor[this.MQ.R])) {\n return CursorContexts.BEFORE_FRACTION;\n } else if (!this._isLeaf(visitor[this.MQ.R])) {\n break;\n }\n visitor = visitor[this.MQ.R];\n }\n\n // If that didn't work, check if the parent or grandparent is a special\n // context, so that we can jump outwards.\n if (this._isParens(cursor.parent && cursor.parent.parent)) {\n return CursorContexts.IN_PARENS;\n } else if (this._isNumerator(cursor.parent)) {\n return CursorContexts.IN_NUMERATOR;\n } else if (this._isDenominator(cursor.parent)) {\n return CursorContexts.IN_DENOMINATOR;\n } else if (this._isSubScript(cursor.parent)) {\n return CursorContexts.IN_SUB_SCRIPT;\n } else if (this._isSuperScript(cursor.parent)) {\n return CursorContexts.IN_SUPER_SCRIPT;\n } else {\n return CursorContexts.NONE;\n }\n }\n\n _isAtTopLevel(cursor) {\n return !cursor.parent.parent;\n }\n}\n\nexport default MathWrapper;\n","/**\n * A single function used to scroll a DOM node into view, optionally taking into\n * account that it may be obscured by the custom keypad. The logic makes the\n * strong assumption that the keypad will be anchored to the bottom of the page\n * in calculating its height, as this method may be called before the keypad has\n * animated into view.\n *\n * TODO(charlie): Move this scroll logic out of our components and into a higher\n * level in the component tree--perhaps even into webapp, beyond Perseus.\n */\n\nimport {toolbarHeightPx} from \"../common-style.js\";\n\n// Taken from https://dev.opera.com/articles/fixing-the-scrolltop-bug/\nfunction bodyOrHtml() {\n if (\"scrollingElement\" in document) {\n return document.scrollingElement;\n }\n // Fallback for legacy browsers\n if (navigator.userAgent.indexOf(\"WebKit\") !== -1) {\n return document.body;\n }\n return document.documentElement;\n}\n\nexport const scrollIntoView = (containerNode, keypadNode) => {\n // TODO(charlie): There's no need for us to be reading the keypad bounds\n // here, since they're pre-determined by logic in the store. We should\n // instead pass around an object that knows the bounds.\n const containerBounds = containerNode.getBoundingClientRect();\n const containerBottomPx = containerBounds.bottom;\n const containerTopPx = containerBounds.top;\n\n // Get the element that scrolls the document.\n const scrollNode = bodyOrHtml();\n\n const desiredMarginPx = 16;\n\n if (keypadNode) {\n // NOTE(charlie): We can't use the bounding rect of the keypad,\n // as it is likely in the process of animating in. Instead, to\n // calculate its top, we make the strong assumption that the\n // keypad will end up anchored at the bottom of the page, but above the\n // toolbar, and use its height, which is known at this point. Note that,\n // in the native apps (where the toolbar is rendered natively), this\n // will result in us leaving excess space between the input and the\n // keypad, but that seems okay.\n const pageHeightPx = window.innerHeight;\n const keypadHeightPx = keypadNode.clientHeight;\n const keypadTopPx = pageHeightPx - (keypadHeightPx + toolbarHeightPx);\n\n if (containerBottomPx > keypadTopPx) {\n // If the input would be obscured by the keypad, scroll such that\n // the bottom of the input is just above the top of the keypad,\n // taking care not to scroll the input out of view.\n const scrollOffset = Math.min(\n containerBottomPx - keypadTopPx + desiredMarginPx,\n containerTopPx,\n );\n\n scrollNode.scrollTop += scrollOffset;\n return;\n }\n }\n\n // Alternatively, if the input is out of the viewport or nearly out\n // of the viewport, scroll it into view. We can do this regardless\n // of whether the keypad has been provided.\n if (containerTopPx < desiredMarginPx) {\n scrollNode.scrollTop -= containerBounds.height + desiredMarginPx;\n }\n};\n","import Color from \"@khanacademy/wonder-blocks-color\";\nimport * as i18n from \"@khanacademy/wonder-blocks-i18n\";\nimport {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport ReactDOM from \"react-dom\";\n\nimport Keys from \"../../data/keys.js\";\nimport {View} from \"../../fake-react-native-web/index.js\";\nimport {\n cursorHandleRadiusPx,\n cursorHandleDistanceMultiplier,\n wonderBlocksBlue,\n offBlack,\n} from \"../common-style.js\";\nimport {keypadElementPropType} from \"../prop-types.js\";\n\nimport CursorHandle from \"./cursor-handle.js\";\nimport DragListener from \"./drag-listener.js\";\nimport MathWrapper from \"./math-wrapper.js\";\nimport {scrollIntoView} from \"./scroll-into-view.js\";\n\nconst constrainingFrictionFactor = 0.8;\n\n// eslint-disable-next-line react/no-unsafe\nclass MathInput extends React.Component {\n static propTypes = {\n // The React element node associated with the keypad that will send\n // key-press events to this input. If provided, this can be used to:\n // (1) Avoid blurring the input, on user interaction with the keypad.\n // (2) Scroll the input into view, if it would otherwise be obscured\n // by the keypad on focus.\n keypadElement: keypadElementPropType,\n onBlur: PropTypes.func,\n onChange: PropTypes.func.isRequired,\n onFocus: PropTypes.func,\n // An extra, vanilla style object, to be applied to the math input.\n style: PropTypes.any,\n value: PropTypes.string,\n };\n\n static defaultProps = {\n style: {},\n value: \"\",\n };\n\n state = {\n focused: false,\n handle: {\n animateIntoPosition: false,\n visible: false,\n x: 0,\n y: 0,\n },\n };\n\n componentDidMount() {\n this._isMounted = true;\n\n this.mathField = new MathWrapper(\n this._mathContainer,\n {},\n {\n onCursorMove: (cursor) => {\n // TODO(charlie): It's not great that there is so much coupling\n // between this keypad and the input behavior. We should wrap\n // this `MathInput` component in an intermediary component\n // that translates accesses on the keypad into vanilla props,\n // to make this input keypad-agnostic.\n this.props.keypadElement &&\n this.props.keypadElement.setCursor(cursor);\n },\n },\n );\n\n // NOTE(charlie): MathQuill binds this handler to manage its\n // drag-to-select behavior. For reasons that I can't explain, the event\n // itself gets triggered even if you tap slightly outside of the\n // bound container (maybe 5px outside of any boundary). As a result, the\n // cursor appears when tapping at those locations, even though the input\n // itself doesn't receive any touch start or mouse down event and, as\n // such, doesn't focus itself. This makes for a confusing UX, as the\n // cursor appears, but the keypad does not and the input otherwise\n // treats itself as unfocused. Thankfully, we don't need this behavior--\n // we manage all of the cursor interactions ourselves--so we can safely\n // unbind the handler.\n this.mathField.mathField.__controller.container.unbind(\n \"mousedown.mathquill\",\n );\n\n this.mathField.setContent(this.props.value);\n\n this._updateInputPadding();\n\n this._container = ReactDOM.findDOMNode(this);\n this._root = this._container.querySelector(\".mq-root-block\");\n this._root.addEventListener(\"scroll\", this._handleScroll);\n\n // Record the initial scroll displacement on touch start. This allows\n // us to detect whether a touch event was a scroll and only blur the\n // input on non-scrolls--blurring the input on scroll makes for a\n // frustrating user experience.\n this.touchStartInitialScroll = null;\n this.recordTouchStartOutside = (evt) => {\n if (this.state.focused) {\n // Only blur if the touch is both outside of the input, and\n // above or to the left or right of the keypad (if it has been\n // provided). The reasoning for not blurring when touches occur\n // below the keypad is that the keypad may be anchored above\n // the 'Check answer' bottom bar, in which case, we don't want\n // to dismiss the keypad on check.\n // TODO(charlie): Inject this logic.\n if (!this._container.contains(evt.target)) {\n let touchDidStartInOrBelowKeypad = false;\n if (\n this.props.keypadElement &&\n this.props.keypadElement.getDOMNode()\n ) {\n const bounds = this._getKeypadBounds();\n for (let i = 0; i < evt.changedTouches.length; i++) {\n const [x, y] = [\n evt.changedTouches[i].clientX,\n evt.changedTouches[i].clientY,\n ];\n if (\n (bounds.left <= x &&\n bounds.right >= x &&\n bounds.top <= y &&\n bounds.bottom >= y) ||\n bounds.bottom < y\n ) {\n touchDidStartInOrBelowKeypad = true;\n break;\n }\n }\n }\n\n if (!touchDidStartInOrBelowKeypad) {\n this.didTouchOutside = true;\n\n if (this.dragListener) {\n this.dragListener.detach();\n }\n\n this.dragListener = new DragListener(() => {\n this.didScroll = true;\n this.dragListener.detach();\n }, evt);\n this.dragListener.attach();\n }\n }\n }\n };\n\n this.blurOnTouchEndOutside = (evt) => {\n // If the user didn't scroll, blur the input.\n // TODO(charlie): Verify that the touch that ended actually started\n // outside the keypad. Right now, you can touch down on the keypad,\n // touch elsewhere, release the finger on the keypad, and trigger a\n // dismissal. This code needs to be generalized to handle\n // multi-touch.\n if (this.state.focused && this.didTouchOutside && !this.didScroll) {\n this.blur();\n }\n\n this.didTouchOutside = false;\n this.didScroll = false;\n\n if (this.dragListener) {\n this.dragListener.detach();\n this.removeListeners = null;\n }\n };\n\n window.addEventListener(\"touchstart\", this.recordTouchStartOutside);\n window.addEventListener(\"touchend\", this.blurOnTouchEndOutside);\n window.addEventListener(\"touchcancel\", this.blurOnTouchEndOutside);\n\n // HACK(benkomalo): if the window resizes, the keypad bounds can\n // change. That's a bit peeking into the internals of the keypad\n // itself, since we know bounds can change only when the viewport\n // changes, but seems like a rare enough thing to get wrong that it's\n // not worth wiring up extra things for the technical \"purity\" of\n // having the keypad notify of changes to us.\n window.addEventListener(\"resize\", this._clearKeypadBoundsCache);\n window.addEventListener(\n \"orientationchange\",\n this._clearKeypadBoundsCache,\n );\n }\n\n UNSAFE_componentWillReceiveProps(props) {\n if (this.props.keypadElement !== props.keypadElement) {\n this._clearKeypadBoundsCache();\n }\n }\n\n componentDidUpdate(prevProps, prevState) {\n if (this.mathField.getContent() !== this.props.value) {\n this.mathField.setContent(this.props.value);\n }\n\n if (prevState.focused !== this.state.focused) {\n this._updateInputPadding();\n }\n }\n\n componentWillUnmount() {\n this._isMounted = false;\n\n window.removeEventListener(\"touchstart\", this.recordTouchStartOutside);\n window.removeEventListener(\"touchend\", this.blurOnTouchEndOutside);\n window.removeEventListener(\"touchcancel\", this.blurOnTouchEndOutside);\n window.removeEventListener(\"resize\", this._clearKeypadBoundsCache());\n window.removeEventListener(\n \"orientationchange\",\n this._clearKeypadBoundsCache(),\n );\n }\n\n _clearKeypadBoundsCache = (keypadNode) => {\n this._keypadBounds = null;\n };\n\n _cacheKeypadBounds = (keypadNode) => {\n this._keypadBounds = keypadNode.getBoundingClientRect();\n };\n\n _updateInputPadding = () => {\n this._container = ReactDOM.findDOMNode(this);\n this._root = this._container.querySelector(\".mq-root-block\");\n\n const padding = this.getInputInnerPadding();\n // NOTE(diedra): This overrides the default 2px padding from Mathquil.\n this._root.style.padding =\n `${padding.paddingTop}px ${padding.paddingRight}px` +\n ` ${padding.paddingBottom}px ${padding.paddingLeft}px`;\n this._root.style.fontSize = `${fontSizePt}pt`;\n };\n\n /** Gets and cache they bounds of the keypadElement */\n _getKeypadBounds = () => {\n if (!this._keypadBounds) {\n const node = this.props.keypadElement.getDOMNode();\n this._cacheKeypadBounds(node);\n }\n return this._keypadBounds;\n };\n\n _updateCursorHandle = (animateIntoPosition) => {\n const containerBounds = this._container.getBoundingClientRect();\n const cursor = this._container.querySelector(\".mq-cursor\");\n const cursorBounds = cursor.getBoundingClientRect();\n\n const cursorWidth = cursorBounds.width;\n const gapBelowCursor = 2;\n\n const inputInnerPadding = this.getInputInnerPadding();\n\n // The cursor should never be further right or left than the edge of the\n // container's values.\n const furthestRightCursorBound =\n containerBounds.right -\n cursorWidth -\n inputInnerPadding.paddingRight;\n const furthestLeftCursorBound =\n containerBounds.left + cursorWidth + inputInnerPadding.paddingLeft;\n\n let cursorBoundsLeft = cursorBounds.left;\n if (cursorBounds.left > furthestRightCursorBound) {\n cursorBoundsLeft = furthestRightCursorBound;\n } else if (cursorBounds.left < furthestLeftCursorBound) {\n cursorBoundsLeft = furthestLeftCursorBound;\n }\n\n this.setState({\n handle: {\n visible: true,\n animateIntoPosition,\n // We subtract containerBounds' left/top to correct for the\n // position of the container within the page.\n x: cursorBoundsLeft + cursorWidth / 2 - containerBounds.left,\n y: cursorBounds.bottom + gapBelowCursor - containerBounds.top,\n },\n });\n };\n\n _hideCursorHandle = () => {\n this.setState({\n handle: {\n visible: false,\n x: 0,\n y: 0,\n },\n });\n };\n\n _handleScroll = () => {\n // If animateIntoPosition is false, the user is currently manually positioning\n // the cursor. This is important because the user can scroll the input field\n // with the curor handle, and we don't want to override that ability.\n // But we do want to hide the handle is the user is just scrolling the input field\n // normally, because the handle will not move with the scroll.\n if (this.state.handle.animateIntoPosition !== false) {\n this._hideCursorHandle();\n }\n };\n\n blur = () => {\n this.mathField.blur();\n this.props.onBlur && this.props.onBlur();\n this.setState({focused: false, handle: {visible: false}});\n };\n\n focus = () => {\n // Pass this component's handleKey method to the keypad so it can call\n // it whenever it needs to trigger a keypress action.\n this.props.keypadElement.setKeyHandler((key) => {\n const cursor = this.mathField.pressKey(key);\n\n // Trigger an `onChange` if the value in the input changed, and hide\n // the cursor handle whenever the user types a key. If the value\n // changed as a result of a keypress, we need to be careful not to\n // call `setState` until after `onChange` has resolved.\n const hideCursor = () => {\n this.setState({\n handle: {\n visible: false,\n },\n });\n };\n const value = this.mathField.getContent();\n if (this.props.value !== value) {\n this.props.onChange(value, hideCursor);\n } else {\n hideCursor();\n }\n\n return cursor;\n });\n\n this.mathField.focus();\n this.props.onFocus && this.props.onFocus();\n this.setState({focused: true}, () => {\n // NOTE(charlie): We use `setTimeout` to allow for a layout pass to\n // occur. Otherwise, the keypad is measured incorrectly. Ideally,\n // we'd use requestAnimationFrame here, but it's unsupported on\n // Android Browser 4.3.\n setTimeout(() => {\n if (this._isMounted) {\n // TODO(benkomalo): the keypad is animating at this point,\n // so we can't call _cacheKeypadBounds(), even though\n // it'd be nice to do so. It should probably be the case\n // that the higher level controller tells us when the\n // keypad is settled (then scrollIntoView wouldn't have\n // to make assumptions about that either).\n const maybeKeypadNode =\n this.props.keypadElement &&\n this.props.keypadElement.getDOMNode();\n scrollIntoView(this._container, maybeKeypadNode);\n }\n });\n });\n };\n\n /**\n * Tries to determine which DOM node to place the cursor next to based on\n * where the user drags the cursor handle. If it finds a node it will\n * place the cursor next to it, update the handle to be under the cursor,\n * and return true. If it doesn't find a node, it returns false.\n *\n * It searches for nodes by doing it tests at the following points:\n *\n * (x - dx, y), (x, y), (x + dx, y)\n *\n * If it doesn't find any nodes from the rendered math it will update y\n * by adding dy.\n *\n * The algorithm ends its search when y goes outside the bounds of\n * containerBounds.\n *\n * @param {ClientRect} containerBounds - bounds of the container node\n * @param {number} x - the initial x coordinate in the viewport\n * @param {number} y - the initial y coordinate in the viewport\n * @param {number} dx - horizontal spacing between elementFromPoint calls\n * @param {number} dy - vertical spacing between elementFromPoint calls,\n * sign determines direction.\n * @returns {boolean} - true if a node was hit, false otherwise.\n */\n _findHitNode = (containerBounds, x, y, dx, dy) => {\n while (y >= containerBounds.top && y <= containerBounds.bottom) {\n y += dy;\n\n const points = [\n [x - dx, y],\n [x, y],\n [x + dx, y],\n ];\n\n const elements = points\n .map((point) => document.elementFromPoint(...point))\n // We exclude the root container itself and any nodes marked\n // as non-leaf which are fractions, parens, and roots. The\n // children of those nodes are included in the list because\n // those are the items we care about placing the cursor next\n // to.\n //\n // MathQuill's mq-non-leaf is not applied to all non-leaf nodes\n // so the naming is a bit confusing. Although fractions are\n // included, neither mq-numerator nor mq-denominator nodes are\n // and neither are subscripts or superscripts.\n .filter(\n (element) =>\n element &&\n this._root.contains(element) &&\n ((!element.classList.contains(\"mq-root-block\") &&\n !element.classList.contains(\"mq-non-leaf\")) ||\n element.classList.contains(\"mq-empty\") ||\n element.classList.contains(\"mq-hasCursor\")),\n );\n\n let hitNode = null;\n\n // Contains only DOMNodes without child elements. These should\n // contain some amount of text though.\n const leafElements = [];\n\n // Contains only DOMNodes with child elements.\n const nonLeafElements = [];\n\n let max = 0;\n const counts = {};\n const elementsById = {};\n\n for (const element of elements) {\n const id = element.getAttribute(\"mathquill-command-id\");\n if (id != null) {\n leafElements.push(element);\n\n counts[id] = (counts[id] || 0) + 1;\n elementsById[id] = element;\n } else {\n nonLeafElements.push(element);\n }\n }\n\n // When determining which DOMNode to place the cursor beside, we\n // prefer leaf nodes. Hitting a leaf node is a good sign that the\n // cursor is really close to some piece of math that has been\n // rendered because leaf nodes contain text. Non-leaf nodes may\n // contain a lot of whitespace so the cursor may be further away\n // from actual text within the expression.\n //\n // Since we're doing three hit tests per loop it's possible that\n // we hit multiple leaf nodes at the same time. In this case we\n // we prefer the DOMNode with the most hits.\n // TODO(kevinb) consider preferring nodes hit by [x, y].\n for (const [id, count] of Object.entries(counts)) {\n if (count > max) {\n max = count;\n hitNode = elementsById[id];\n }\n }\n\n // It's possible that two non-leaf nodes are right beside each\n // other. We don't bother counting the number of hits for each,\n // b/c this seems like an unlikely situation. Also, ignoring the\n // hit count in the situation should not have serious effects on\n // the overall accuracy of the algorithm.\n if (hitNode == null && nonLeafElements.length > 0) {\n hitNode = nonLeafElements[0];\n }\n\n if (hitNode !== null) {\n this.mathField.setCursorPosition(x, y, hitNode);\n return true;\n }\n }\n\n return false;\n };\n\n /**\n * Inserts the cursor at the DOM node closest to the given coordinates,\n * based on hit-tests conducted using #_findHitNode.\n *\n * @param {number} x - the x coordinate in the viewport\n * @param {number} y - the y coordinate in the viewport\n */\n _insertCursorAtClosestNode = (x, y) => {\n const cursor = this.mathField.getCursor();\n\n // Pre-emptively check if the input has any child nodes; if not, the\n // input is empty, so we throw the cursor at the start.\n if (!this._root.hasChildNodes()) {\n cursor.insAtLeftEnd(this.mathField.mathField.__controller.root);\n return;\n }\n\n // NOTE(diedra): The adding and subtracting of 10 or 15 pixels here accounts\n // for the padding that surrounds the input values.\n if (y > this._containerBounds.bottom) {\n y = this._containerBounds.bottom - 10;\n } else if (y < this._containerBounds.top) {\n y = this._containerBounds.top + 10;\n }\n if (x > this._containerBounds.right) {\n x = this._containerBounds.right - 15;\n } else if (x < this._containerBounds.left) {\n x = this._containerBounds.left + 15;\n }\n\n let dy;\n\n // Vertical spacing between hit tests\n // dy is negative because we're moving upwards.\n dy = -8;\n\n // Horizontal spacing between hit tests\n // Note: This value depends on the font size. If the gap is too small\n // we end up placing the cursor at the end of the expression when we\n // shouldn't.\n const dx = 5;\n\n if (this._findHitNode(this._containerBounds, x, y, dx, dy)) {\n return;\n }\n\n // If we haven't found anything start from the top.\n y = this._containerBounds.top;\n\n // dy is positive b/c we're going downwards.\n dy = 8;\n\n if (this._findHitNode(this._containerBounds, x, y, dx, dy)) {\n return;\n }\n\n const firstChildBounds = this._root.firstChild.getBoundingClientRect();\n const lastChildBounds = this._root.lastChild.getBoundingClientRect();\n\n const left = firstChildBounds.left;\n const right = lastChildBounds.right;\n\n // We've exhausted all of the options. We're likely either to the right\n // or left of all of the math, so we place the cursor at the end to\n // which it's closest.\n if (Math.abs(x - right) < Math.abs(x - left)) {\n cursor.insAtRightEnd(this.mathField.mathField.__controller.root);\n } else {\n cursor.insAtLeftEnd(this.mathField.mathField.__controller.root);\n }\n // In that event, we need to update the cursor context ourselves.\n this.props.keypadElement &&\n this.props.keypadElement.setCursor({\n context: this.mathField.contextForCursor(cursor),\n });\n };\n\n handleTouchStart = (e) => {\n e.stopPropagation();\n\n // Hide the cursor handle on touch start, if the handle itself isn't\n // handling the touch event.\n this._hideCursorHandle();\n\n // Cache the container bounds, so as to avoid re-computing. If we don't\n // have any content, then it's not necessary, since the cursor can't be\n // moved anyway.\n if (this.mathField.getContent() !== \"\") {\n this._containerBounds = this._container.getBoundingClientRect();\n\n // Make the cursor visible and set the handle-less cursor's\n // location.\n const touch = e.changedTouches[0];\n this._insertCursorAtClosestNode(touch.clientX, touch.clientY);\n }\n\n // Trigger a focus event, if we're not already focused.\n if (!this.state.focused) {\n this.focus();\n }\n };\n\n handleTouchMove = (e) => {\n e.stopPropagation();\n\n // Update the handle-less cursor's location on move, if there's any\n // content in the box. Note that if the user touched outside the keypad\n // (e.g., with a different finger) during this touch interaction, we\n // may have blurred, in which case we should ignore the touch (since\n // the cursor is no longer visible and the input is no longer\n // highlighted).\n if (this.mathField.getContent() !== \"\" && this.state.focused) {\n const touch = e.changedTouches[0];\n this._insertCursorAtClosestNode(touch.clientX, touch.clientY);\n }\n };\n\n handleTouchEnd = (e) => {\n e.stopPropagation();\n\n // And on touch-end, reveal the cursor, unless the input is empty. Note\n // that if the user touched outside the keypad (e.g., with a different\n // finger) during this touch interaction, we may have blurred, in which\n // case we should ignore the touch (since the cursor is no longer\n // visible and the input is no longer highlighted).\n if (this.mathField.getContent() !== \"\" && this.state.focused) {\n this._updateCursorHandle();\n }\n };\n\n /**\n * When a touch starts in the cursor handle, we track it so as to avoid\n * handling any touch events ourself.\n *\n * @param {TouchEvent} e - the raw touch event from the browser\n */\n onCursorHandleTouchStart = (e) => {\n // NOTE(charlie): The cursor handle is a child of this view, so whenever\n // it receives a touch event, that event would also typically be bubbled\n // up to our own handlers. However, we want the cursor to handle its own\n // touch events, and for this view to only handle touch events that\n // don't affect the cursor. As such, we `stopPropagation` on any touch\n // events that are being handled by the cursor, so as to avoid handling\n // them in our own touch handlers.\n e.stopPropagation();\n\n e.preventDefault();\n\n // Cache the container bounds, so as to avoid re-computing.\n this._containerBounds = this._container.getBoundingClientRect();\n };\n\n _constrainToBound = (value, min, max, friction) => {\n if (value < min) {\n return min + (value - min) * friction;\n } else if (value > max) {\n return max + (value - max) * friction;\n } else {\n return value;\n }\n };\n\n /**\n * When the user moves the cursor handle update the position of the cursor\n * and the handle.\n *\n * @param {TouchEvent} e - the raw touch event from the browser\n */\n onCursorHandleTouchMove = (e) => {\n e.stopPropagation();\n\n const x = e.changedTouches[0].clientX;\n const y = e.changedTouches[0].clientY;\n\n const relativeX = x - this._containerBounds.left;\n const relativeY =\n y -\n 2 * cursorHandleRadiusPx * cursorHandleDistanceMultiplier -\n this._containerBounds.top;\n\n // We subtract the containerBounds left/top to correct for the\n // MathInput's position on the page. On top of that, we subtract an\n // additional 2 x {height of the cursor} so that the bottom of the\n // cursor tracks the user's finger, to make it visible under their\n // touch.\n this.setState({\n handle: {\n animateIntoPosition: false,\n visible: true,\n // TODO(charlie): Use clientX and clientY to avoid the need for\n // scroll offsets. This likely also means that the cursor\n // detection doesn't work when scrolled, since we're not\n // offsetting those values.\n x: this._constrainToBound(\n relativeX,\n 0,\n this._containerBounds.width,\n constrainingFrictionFactor,\n ),\n y: this._constrainToBound(\n relativeY,\n 0,\n this._containerBounds.height,\n constrainingFrictionFactor,\n ),\n },\n });\n\n // Use a y-coordinate that's just above where the user is actually\n // touching because they're dragging the handle which is a little\n // below where the cursor actually is.\n const distanceAboveFingerToTrySelecting = 22;\n const adjustedY = y - distanceAboveFingerToTrySelecting;\n\n this._insertCursorAtClosestNode(x, adjustedY);\n };\n\n /**\n * When the user releases the cursor handle, animate it back into place.\n *\n * @param {TouchEvent} e - the raw touch event from the browser\n */\n onCursorHandleTouchEnd = (e) => {\n e.stopPropagation();\n\n this._updateCursorHandle(true);\n };\n\n /**\n * If the gesture is cancelled mid-drag, simply hide it.\n *\n * @param {TouchEvent} e - the raw touch event from the browser\n */\n onCursorHandleTouchCancel = (e) => {\n e.stopPropagation();\n\n this._updateCursorHandle(true);\n };\n\n domKeyToMathQuillKey = (key) => {\n const keyMap = {\n \"+\": Keys.PLUS,\n \"-\": Keys.MINUS,\n \"*\": Keys.TIMES,\n \"/\": Keys.DIVIDE,\n \".\": Keys.DECIMAL,\n \"%\": Keys.PERCENT,\n \"=\": Keys.EQUAL,\n \">\": Keys.GT,\n \"<\": Keys.LT,\n \"^\": Keys.EXP,\n };\n\n // Numbers\n if ([\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"].includes(key)) {\n return `NUM_${key}`;\n }\n\n // Movement keys\n else if (key === \"Backspace\") {\n return Keys.BACKSPACE;\n }\n\n // Operators\n else if (key in keyMap) {\n return keyMap[key];\n }\n\n // The key pressed doesn't map to any of the math input operators\n return null;\n };\n\n handleKeyUp = (event) => {\n const mathQuillKey = this.domKeyToMathQuillKey(event.key);\n\n if (mathQuillKey) {\n this.mathField.pressKey(mathQuillKey);\n\n // TODO(diedra): If the new value being added is off-screen to the right\n // due to the max-width of the text box, scroll the box to show the newest\n // value\n const value = this.mathField.getContent();\n if (this.props.value !== value) {\n this.mathField.setContent(this.props.value);\n this.props.onChange(value, false);\n this._hideCursorHandle();\n }\n }\n };\n\n getBorderWidthPx = () => {\n // TODO(diedra): Move these to the common style package.\n const normalBorderWidthPx = 1;\n const focusedBorderWidthPx = 2;\n\n return this.state.focused ? focusedBorderWidthPx : normalBorderWidthPx;\n };\n\n // Calculate the appropriate padding based on the border width (which is\n // considered 'padding', since we're using 'border-box') and the fact\n // that MathQuill automatically applies 2px of padding to the inner\n // input.\n getInputInnerPadding = () => {\n const paddingInset = totalDesiredPadding - this.getBorderWidthPx();\n\n // Now, translate that to the appropriate padding for each direction.\n // The complication here is that we want numerals to be centered within\n // the input. However, Symbola (MathQuill's font of choice) renders\n // numerals with approximately 3px of padding below and 1px of padding\n // above (to make room for ascenders and descenders). So we ignore those\n // padding values for the vertical directions.\n const symbolaPaddingBottom = 3;\n const symbolaPaddingTop = 1;\n const padding = {\n paddingTop: paddingInset - symbolaPaddingTop,\n paddingRight: paddingInset,\n paddingBottom: paddingInset - symbolaPaddingBottom,\n paddingLeft: paddingInset,\n };\n\n return padding;\n };\n\n render() {\n const {focused, handle} = this.state;\n const {style} = this.props;\n\n const innerStyle = {\n ...inlineStyles.innerContainer,\n borderWidth: this.getBorderWidthPx(),\n ...(focused\n ? {\n borderColor: wonderBlocksBlue,\n }\n : {}),\n ...style,\n };\n\n // NOTE(diedra): This label explicitly refers to tapping because this field\n // is currently only seen if the user is using a mobile device.\n // We added the tapping instructions because there is currently a bug where\n // Android users need to use two fingers to tap the input field to make the\n // keyboard appear. It should only require one finger, which is how iOS works.\n // TODO(diedra): Fix the bug that is causing Android to require a two finger tap\n // to the open the keyboard, and then remove the second half of this label.\n const ariaLabel =\n i18n._(\"Math input box\") +\n \" \" +\n i18n._(\"Tap with one or two fingers to open keyboard\");\n\n return (\n <View\n style={styles.input}\n onTouchStart={this.handleTouchStart}\n onTouchMove={this.handleTouchMove}\n onTouchEnd={this.handleTouchEnd}\n onClick={(e) => e.stopPropagation()}\n role={\"textbox\"}\n ariaLabel={ariaLabel}\n >\n {/* NOTE(charlie): This is used purely to namespace the styles in\n overrides.css. */}\n <div\n className=\"keypad-input\"\n tabIndex={\"0\"}\n ref={(node) => {\n this.inputRef = node;\n }}\n onKeyUp={this.handleKeyUp}\n >\n {/* NOTE(charlie): This element must be styled with inline\n styles rather than with Aphrodite classes, as MathQuill\n modifies the class names on the DOM node. */}\n <div\n ref={(node) => {\n this._mathContainer = ReactDOM.findDOMNode(node);\n }}\n style={innerStyle}\n />\n </div>\n {focused && handle.visible && (\n <CursorHandle\n {...handle}\n onTouchStart={this.onCursorHandleTouchStart}\n onTouchMove={this.onCursorHandleTouchMove}\n onTouchEnd={this.onCursorHandleTouchEnd}\n onTouchCancel={this.onCursorHandleTouchCancel}\n />\n )}\n </View>\n );\n }\n}\n\nconst fontSizePt = 18;\nconst inputMaxWidth = 128;\n\n// The height of numerals in Symbola (rendered at 18pt) is about 20px (though\n// they render at 24px due to padding for ascenders and descenders). We want our\n// box to be laid out such that there's 12px of padding between a numeral and the\n// edge of the input, so we use this 20px number as our 'base height' and\n// account for the ascender and descender padding when computing the additional\n// padding in our `render` method.\nconst numeralHeightPx = 20;\nconst totalDesiredPadding = 12;\nconst minHeightPx = numeralHeightPx + totalDesiredPadding * 2;\nconst minWidthPx = 64;\n\nconst styles = StyleSheet.create({\n input: {\n position: \"relative\",\n display: \"inline-block\",\n verticalAlign: \"middle\",\n maxWidth: inputMaxWidth,\n },\n});\n\nconst inlineStyles = {\n // Styles for the inner, MathQuill-ified input element. It's important that\n // these are done with regular inline styles rather than Aphrodite classes\n // as MathQuill adds CSS class names to the element outside of the typical\n // React flow; assigning a class to the element can thus disrupt MathQuill\n // behavior. For example, if the client provided new styles to be applied\n // on focus and the styles here were applied with Aphrodite, then Aphrodite\n // would merge the provided styles with the base styles here, producing a\n // new CSS class name that we would apply to the element, clobbering any CSS\n // class names that MathQuill had applied itself.\n innerContainer: {\n backgroundColor: \"white\",\n minHeight: minHeightPx,\n minWidth: minWidthPx,\n maxWidth: inputMaxWidth,\n boxSizing: \"border-box\",\n position: \"relative\",\n borderStyle: \"solid\",\n borderColor: Color.offBlack50,\n borderRadius: 4,\n color: offBlack,\n },\n};\n\nexport default MathInput;\n","/**\n * The state machine that backs our gesture system. In particular, this state\n * machine manages the interplay between focuses, touch ups, and swiping.\n * It is entirely ignorant of the existence of popovers and the positions of\n * DOM nodes, operating solely on IDs. The state machine does accommodate for\n * multi-touch interactions, tracking gesture state on a per-touch basis.\n */\n\nconst defaults = {\n longPressWaitTimeMs: 50,\n swipeThresholdPx: 20,\n holdIntervalMs: 250,\n};\n\nclass GestureStateMachine {\n constructor(handlers, options, swipeDisabledNodeIds, multiPressableKeys) {\n this.handlers = handlers;\n this.options = {\n ...defaults,\n ...options,\n };\n this.swipeDisabledNodeIds = swipeDisabledNodeIds || [];\n this.multiPressableKeys = multiPressableKeys || [];\n\n // TODO(charlie): Flow-type this file. It's not great that we're now\n // passing around these opaque state objects.\n this.touchState = {};\n this.swipeState = null;\n }\n\n _maybeCancelLongPressForTouch(touchId) {\n const {longPressTimeoutId} = this.touchState[touchId];\n if (longPressTimeoutId) {\n clearTimeout(longPressTimeoutId);\n this.touchState[touchId] = {\n ...this.touchState[touchId],\n longPressTimeoutId: null,\n };\n }\n }\n\n _maybeCancelPressAndHoldForTouch(touchId) {\n const {pressAndHoldIntervalId} = this.touchState[touchId];\n if (pressAndHoldIntervalId) {\n // If there was an interval set to detect holds, clear it out.\n clearInterval(pressAndHoldIntervalId);\n this.touchState[touchId] = {\n ...this.touchState[touchId],\n pressAndHoldIntervalId: null,\n };\n }\n }\n\n _cleanupTouchEvent(touchId) {\n this._maybeCancelLongPressForTouch(touchId);\n this._maybeCancelPressAndHoldForTouch(touchId);\n delete this.touchState[touchId];\n }\n\n /**\n * Handle a focus event on the node with the given identifier, which may be\n * `null` to indicate that the user has dragged their finger off of any\n * registered nodes, but is still in the middle of a gesture.\n *\n * @param {string|null} id - the identifier of the newly focused node, or\n * `null` if no node is focused\n * @param {number} touchId - a unique identifier associated with the touch\n */\n _onFocus(id, touchId) {\n // If we're in the middle of a long-press, cancel it.\n this._maybeCancelLongPressForTouch(touchId);\n\n // Reset any existing hold-detecting interval.\n this._maybeCancelPressAndHoldForTouch(touchId);\n\n // Set the focused node ID and handle the focus event.\n // Note: we can call `onFocus` with `null` IDs. The semantics of an\n // `onFocus` with a `null` ID differs from that of `onBlur`. The former\n // indicates that a gesture that can focus future nodes is still in\n // progress, but that no node is currently focused. The latter\n // indicates that the gesture has ended and nothing will be focused.\n this.touchState[touchId] = {\n ...this.touchState[touchId],\n activeNodeId: id,\n };\n this.handlers.onFocus(id);\n\n if (id) {\n // Handle logic for repeating button presses.\n if (this.multiPressableKeys.includes(id)) {\n // Start by triggering a click, iOS style.\n this.handlers.onTrigger(id);\n\n // Set up a new hold detector for the current button.\n this.touchState[touchId] = {\n ...this.touchState[touchId],\n pressAndHoldIntervalId: setInterval(() => {\n // On every cycle, trigger the click handler.\n this.handlers.onTrigger(id);\n }, this.options.holdIntervalMs),\n };\n } else {\n // Set up a new hold detector for the current button.\n this.touchState[touchId] = {\n ...this.touchState[touchId],\n longPressTimeoutId: setTimeout(() => {\n this.handlers.onLongPress(id);\n this.touchState[touchId] = {\n ...this.touchState[touchId],\n longPressTimeoutId: null,\n };\n }, this.options.longPressWaitTimeMs),\n };\n }\n }\n }\n\n /**\n * Clear out all active gesture information.\n */\n _onSwipeStart() {\n for (const activeTouchId of Object.keys(this.touchState)) {\n this._maybeCancelLongPressForTouch(activeTouchId);\n this._maybeCancelPressAndHoldForTouch(activeTouchId);\n }\n this.touchState = {};\n this.handlers.onBlur();\n }\n\n /**\n * A function that returns the identifier of the node over which the touch\n * event occurred. This is provided as a piece of lazy computation, as\n * computing the DOM node for a given point is expensive, and the state\n * machine won't always need that information. For example, if the user is\n * swiping, then `onTouchMove` needs to be performant and doesn't care about\n * the node over which the touch occurred.\n *\n * @typedef idComputation\n * @returns {DOMNode} - the identifier of the node over which the touch\n * occurred\n */\n\n /**\n * Handle a touch-start event on the node with the given identifer.\n *\n * @param {idComputation} getId - a function that returns identifier of the\n * node over which the start event occurred\n * @param {number} touchId - a unique identifier associated with the touch\n */\n onTouchStart(getId, touchId, pageX) {\n // Ignore any touch events that start mid-swipe.\n if (this.swipeState) {\n return;\n }\n\n if (this.touchState[touchId]) {\n // It turns out we can get multiple touch starts with no\n // intervening move, end, or cancel events in Android WebViews.\n // TODO(benkomalo): it's not entirely clear why this happens, but\n // it seems to happen with the backspace button. It may be related\n // to FastClick (https://github.com/ftlabs/fastclick/issues/71)\n // though I haven't verified, and it's probably good to be robust\n // here anyways.\n return;\n }\n\n const startingNodeId = getId();\n this.touchState[touchId] = {\n swipeLocked: this.swipeDisabledNodeIds.includes(startingNodeId),\n startX: pageX,\n };\n\n this._onFocus(startingNodeId, touchId);\n }\n\n /**\n * Handle a touch-move event on the node with the given identifer.\n *\n * @param {idComputation} getId - a function that returns identifier of the\n * node over which the move event occurred\n * @param {number} touchId - a unique identifier associated with the touch\n * @param {number} pageX - the x coordinate of the touch\n * @param {boolean} swipeEnabled - whether the system should allow for\n * transitions into a swiping state\n */\n onTouchMove(getId, touchId, pageX, swipeEnabled) {\n if (this.swipeState) {\n // Only respect the finger that started a swipe. Any other lingering\n // gestures are ignored.\n if (this.swipeState.touchId === touchId) {\n this.handlers.onSwipeChange(pageX - this.swipeState.startX);\n }\n } else if (this.touchState[touchId]) {\n // It could be touch events started outside the keypad and\n // moved into it; ignore them.\n const {activeNodeId, startX, swipeLocked} =\n this.touchState[touchId];\n\n const dx = pageX - startX;\n const shouldBeginSwiping =\n swipeEnabled &&\n !swipeLocked &&\n Math.abs(dx) > this.options.swipeThresholdPx;\n\n if (shouldBeginSwiping) {\n this._onSwipeStart();\n\n // Trigger the swipe.\n this.swipeState = {\n touchId,\n startX,\n };\n this.handlers.onSwipeChange(pageX - this.swipeState.startX);\n } else {\n const id = getId();\n if (id !== activeNodeId) {\n this._onFocus(id, touchId);\n }\n }\n }\n }\n\n /**\n * Handle a touch-end event on the node with the given identifer.\n *\n * @param {idComputation} getId - a function that returns identifier of the\n * node over which the end event occurred\n * @param {number} touchId - a unique identifier associated with the touch\n * @param {number} pageX - the x coordinate of the touch\n */\n onTouchEnd(getId, touchId, pageX) {\n if (this.swipeState) {\n // Only respect the finger that started a swipe. Any other lingering\n // gestures are ignored.\n if (this.swipeState.touchId === touchId) {\n this.handlers.onSwipeEnd(pageX - this.swipeState.startX);\n this.swipeState = null;\n }\n } else if (this.touchState[touchId]) {\n // It could be touch events started outside the keypad and\n // moved into it; ignore them.\n const {activeNodeId, pressAndHoldIntervalId} =\n this.touchState[touchId];\n\n this._cleanupTouchEvent(touchId);\n\n const didPressAndHold = !!pressAndHoldIntervalId;\n if (didPressAndHold) {\n // We don't trigger a touch end if there was a press and hold,\n // because the key has been triggered at least once and calling\n // the onTouchEnd handler would add an extra trigger.\n this.handlers.onBlur();\n } else {\n // Trigger a touch-end. There's no need to notify clients of a\n // blur as clients are responsible for handling any cleanup in\n // their touch-end handlers.\n this.handlers.onTouchEnd(activeNodeId);\n }\n }\n }\n\n /**\n * Handle a touch-cancel event.\n */\n onTouchCancel(touchId) {\n // If a touch is cancelled and we're swiping, end the swipe with no\n // displacement.\n if (this.swipeState) {\n if (this.swipeState.touchId === touchId) {\n this.handlers.onSwipeEnd(0);\n this.swipeState = null;\n }\n } else if (this.touchState[touchId]) {\n // Otherwise, trigger a full blur. We don't want to trigger a\n // touch-up, since the cancellation means that the user probably\n // didn't release over a key intentionally.\n this._cleanupTouchEvent(touchId);\n this.handlers.onBlur();\n }\n }\n}\n\nexport default GestureStateMachine;\n","/**\n * A manager for our node-to-ID system. In particular, this class is\n * responsible for maintaing a mapping between DOM nodes and node IDs, and\n * translating touch events from the raw positions at which they occur to the\n * nodes over which they are occurring. This differs from browser behavior, in\n * which touch events are only sent to the node in which a touch started.\n */\n\nclass NodeManager {\n constructor() {\n // A mapping from IDs to DOM nodes.\n this._nodesById = {};\n\n // A mapping from IDs to the borders around the DOM nodes, which can be\n // useful for layout purposes.\n this._bordersById = {};\n\n // An ordered list of IDs, where DOM nodes that are \"higher\" on the\n // page come earlier in the list. Note that an ID may be present in\n // this ordered list but not be registered to a DOM node (i.e., if it\n // is registered as a child of another DOM node, but hasn't appeared in\n // the DOM yet).\n this._orderedIds = [];\n\n // Cache bounding boxes aggressively, re-computing on page resize. Our\n // caching here makes the strict assumption that if a node is reasonably\n // assumed to be on-screen, its bounds won't change. For example, if we\n // see that a touch occurred within the bounds of a node, we cache those\n // bounds.\n // TODO(charlie): It'd be great if we could pre-compute these when the\n // page is idle and the keypad is visible (i.e., the nodes are in their\n // proper positions).\n this._cachedBoundingBoxesById = {};\n window.addEventListener(\"resize\", () => {\n this._cachedBoundingBoxesById = {};\n });\n }\n\n /**\n * Register a DOM node with a given identifier.\n *\n * @param {string} id - the identifier of the given node\n * @param {node} domNode - the DOM node linked to the identifier\n * @param {object} borders - an opaque object describing the node's borders\n */\n registerDOMNode(id, domNode, childIds, borders) {\n this._nodesById[id] = domNode;\n this._bordersById[id] = borders;\n\n // Make sure that any children appear first.\n // TODO(charlie): This is a very simplistic system that wouldn't\n // properly handle multiple levels of nesting.\n const allIds = [...(childIds || []), id, ...this._orderedIds];\n\n // De-dupe the list of IDs.\n const orderedIds = [];\n const seenIds = {};\n for (const id of allIds) {\n if (!seenIds[id]) {\n orderedIds.push(id);\n seenIds[id] = true;\n }\n }\n\n this._orderedIds = orderedIds;\n }\n\n /**\n * Unregister the DOM node with the given identifier.\n *\n * @param {string} id - the identifier of the node to unregister\n */\n unregisterDOMNode(id) {\n delete this._nodesById[id];\n }\n\n /**\n * Return the identifier of the topmost node located at the given\n * coordinates.\n *\n * @param {number} x - the x coordinate at which to search for a node\n * @param {number} y - the y coordinate at which to search for a node\n * @returns {null|string} - null or the identifier of the topmost node at\n * the given coordinates\n */\n idForCoords(x, y) {\n for (const id of this._orderedIds) {\n const domNode = this._nodesById[id];\n if (domNode) {\n const bounds = domNode.getBoundingClientRect();\n if (\n bounds.left <= x &&\n bounds.right > x &&\n bounds.top <= y &&\n bounds.bottom > y\n ) {\n this._cachedBoundingBoxesById[id] = bounds;\n return id;\n }\n }\n }\n }\n\n /**\n * Return the necessary layout information, including the bounds and border\n * values, for the node with the given identifier.\n *\n * @param {string} id - the identifier of the node for which to return the\n * layout information\n * @returns {object} - the bounding client rect for the given node, along\n * with its borders\n */\n layoutPropsForId(id) {\n if (!this._cachedBoundingBoxesById[id]) {\n const node = this._nodesById[id];\n\n this._cachedBoundingBoxesById[id] = node\n ? node.getBoundingClientRect()\n : new DOMRect();\n }\n\n return {\n initialBounds: this._cachedBoundingBoxesById[id],\n borders: this._bordersById[id],\n };\n }\n}\n\nexport default NodeManager;\n","/**\n * A state machine for the popover state. In particular, this class manages the\n * mapping of parent nodes to their children, and translates touch events that\n * traverse various nodes to actions that are conditioned on whether a popover\n * is present.\n */\n\nclass PopoverStateMachine {\n constructor(handlers) {\n this.handlers = handlers;\n\n this.activePopover = null;\n this.popovers = {};\n }\n\n /**\n * Register a popover container as containing a set of children.\n *\n * @param {string} id - the identifier of the popover container\n * @param {string[]} childIds - the identifiers of the nodes contained in\n * the popover container\n */\n registerPopover(id, childIds) {\n this.popovers[id] = childIds;\n }\n\n /**\n * Unregister a popover container.\n *\n * @param {string} id - the identifier of the popover container to\n * unregister\n */\n unregisterPopover(id) {\n delete this.popovers[id];\n }\n\n /**\n * @returns {boolean} - whether a popover is active and visible\n */\n isPopoverVisible() {\n return this.activePopover != null;\n }\n\n /**\n * Blur the active nodes.\n */\n onBlur() {\n this.activePopover = null;\n this.handlers.onActiveNodesChanged({\n popover: null,\n focus: null,\n });\n }\n\n /**\n * Handle a focus event on the node with the given identifier.\n *\n * @param {string} id - the identifier of the node that was focused\n */\n onFocus(id) {\n if (this.activePopover) {\n // If we have a popover that is currently active, we focus this\n // node if it's in the popover, and remove any highlight otherwise.\n if (this._isNodeInsidePopover(this.activePopover, id)) {\n this.handlers.onActiveNodesChanged({\n popover: {\n parentId: this.activePopover,\n childIds: this.popovers[this.activePopover],\n },\n focus: id,\n });\n } else {\n this.handlers.onActiveNodesChanged({\n popover: {\n parentId: this.activePopover,\n childIds: this.popovers[this.activePopover],\n },\n focus: null,\n });\n }\n } else {\n this.activePopover = null;\n this.handlers.onActiveNodesChanged({\n popover: null,\n focus: id,\n });\n }\n }\n\n /**\n * Handle a long press event on the node with the given identifier.\n *\n * @param {string} id - the identifier of the node that was long-pressed\n */\n onLongPress(id) {\n // We only care about long presses if they occur on a popover, and we\n // don't already have a popover active.\n if (!this.activePopover && this.popovers[id]) {\n // NOTE(charlie): There's an assumption here that focusing the\n // first child is the correct behavior for a newly focused popover.\n // This relies on the fact that the children are rendered\n // bottom-up. If that rendering changes, this logic will need to\n // change as well.\n this.activePopover = id;\n this.handlers.onActiveNodesChanged({\n popover: {\n parentId: this.activePopover,\n childIds: this.popovers[this.activePopover],\n },\n focus: this._defaultNodeForPopover(this.activePopover),\n });\n }\n }\n\n /**\n * Handle the trigger (click or hold) of the node with the given identifier.\n *\n * @param {string} id - the identifier of the node that was triggered\n */\n onTrigger(id) {\n this.handlers.onClick(id, id, false);\n }\n\n /**\n * Handle a touch-end event on the node with the given identifier.\n *\n * @param {string} id - the identifier of the node over which the touch\n * ended\n */\n onTouchEnd(id) {\n const inPopover = !!this.activePopover;\n if (inPopover) {\n // If we have a popover that is currently active, we trigger a\n // click on this node if and only if it's in the popover, with the\n // exception that, if the node passed back _is_ the active popover,\n // then we trigger its default node. This latter case should only\n // be triggered if the user were to tap down on a popover-enabled\n // node, hold for long enough for the popover to appear, and then\n // release without ever moving their finger, in which case, the\n // underlying gesture system would have no idea that the popover's\n // first child node was now focused.\n if (this._isNodeInsidePopover(this.activePopover, id)) {\n this.handlers.onClick(id, id, inPopover);\n } else if (this.activePopover === id) {\n const keyId = this._defaultNodeForPopover(id);\n this.handlers.onClick(keyId, keyId, inPopover);\n }\n } else if (this.popovers[id]) {\n // Otherwise, if the node is itself a popover revealer, trigger the\n // clicking of its default node, but pass back the popover node ID\n // for layout purposes.\n const keyId = this._defaultNodeForPopover(id);\n const domNodeId = id;\n this.handlers.onClick(keyId, domNodeId, inPopover);\n } else if (id != null) {\n // Finally, if we have no active popover, and we touched up over a\n // valid key, trigger a click.\n this.onTrigger(id);\n }\n\n this.onBlur();\n }\n\n _isNodeInsidePopover(popover, id) {\n return this.popovers[popover].includes(id);\n }\n\n _defaultNodeForPopover(popover) {\n return this.popovers[popover][0];\n }\n}\n\nexport default PopoverStateMachine;\n","/**\n * A high-level manager for our gesture system. In particular, this class\n * connects our various bits of logic for managing gestures and interactions,\n * and links them together.\n */\n\nimport GestureStateMachine from \"./gesture-state-machine.js\";\nimport NodeManager from \"./node-manager.js\";\nimport PopoverStateMachine from \"./popover-state-machine.js\";\n\nconst coordsForEvent = (evt) => {\n return [evt.changedTouches[0].clientX, evt.changedTouches[0].clientY];\n};\n\nclass GestureManager {\n constructor(options, handlers, disabledSwipeKeys, multiPressableKeys) {\n const {swipeEnabled} = options;\n\n this.swipeEnabled = swipeEnabled;\n\n // Events aren't tracked until event tracking is enabled.\n this.trackEvents = false;\n\n this.nodeManager = new NodeManager();\n this.popoverStateMachine = new PopoverStateMachine({\n onActiveNodesChanged: (activeNodes) => {\n const {popover, ...rest} = activeNodes;\n handlers.onActiveNodesChanged({\n popover: popover && {\n parentId: popover.parentId,\n bounds: this.nodeManager.layoutPropsForId(\n popover.parentId,\n ).initialBounds,\n childKeyIds: popover.childIds,\n },\n ...rest,\n });\n },\n /**\n * `onClick` takes two arguments:\n *\n * @param {string} keyId - the identifier key that should initiate\n * a click\n * @param {string} domNodeId - the identifier of the DOM node on\n * which the click should be considered\n * to have occurred\n * @param {bool} inPopover - whether the key was contained within a\n * popover\n *\n * These two parameters will often be equivalent. They will differ,\n * though, when a popover button is itself clicked, in which case\n * we need to mimic the effects of clicking on its 'primary' child\n * key, but animate the click on the popover button.\n */\n onClick: (keyId, domNodeId, inPopover) => {\n handlers.onClick(\n keyId,\n this.nodeManager.layoutPropsForId(domNodeId),\n inPopover,\n );\n },\n });\n this.gestureStateMachine = new GestureStateMachine(\n {\n onFocus: (id) => {\n this.popoverStateMachine.onFocus(id);\n },\n onLongPress: (id) => {\n this.popoverStateMachine.onLongPress(id);\n },\n onTouchEnd: (id) => {\n this.popoverStateMachine.onTouchEnd(id);\n },\n onBlur: () => {\n this.popoverStateMachine.onBlur();\n },\n onSwipeChange: handlers.onSwipeChange,\n onSwipeEnd: handlers.onSwipeEnd,\n onTrigger: (id) => {\n this.popoverStateMachine.onTrigger(id);\n },\n },\n {},\n disabledSwipeKeys,\n multiPressableKeys,\n );\n }\n\n /**\n * Handle a touch-start event that originated in a node registered with the\n * gesture system.\n *\n * @param {TouchEvent} evt - the raw touch event from the browser\n * @param {string} id - the identifier of the DOM node in which the touch\n * occurred\n */\n onTouchStart(evt, id) {\n if (!this.trackEvents) {\n return;\n }\n\n const [x] = coordsForEvent(evt);\n\n // TODO(charlie): It doesn't seem to be guaranteed that every touch\n // event on `changedTouches` originates from the node through which this\n // touch event was sent. In that case, we'd be inappropriately reporting\n // the starting node ID.\n for (let i = 0; i < evt.changedTouches.length; i++) {\n this.gestureStateMachine.onTouchStart(\n () => id,\n evt.changedTouches[i].identifier,\n x,\n );\n }\n\n // If an event started in a view that we're managing, we'll handle it\n // all the way through.\n evt.preventDefault();\n }\n\n /**\n * Handle a touch-move event that originated in a node registered with the\n * gesture system.\n *\n * @param {TouchEvent} evt - the raw touch event from the browser\n */\n onTouchMove(evt) {\n if (!this.trackEvents) {\n return;\n }\n\n const swipeLocked = this.popoverStateMachine.isPopoverVisible();\n const swipeEnabled = this.swipeEnabled && !swipeLocked;\n const [x, y] = coordsForEvent(evt);\n for (let i = 0; i < evt.changedTouches.length; i++) {\n this.gestureStateMachine.onTouchMove(\n () => this.nodeManager.idForCoords(x, y),\n evt.changedTouches[i].identifier,\n x,\n swipeEnabled,\n );\n }\n }\n\n /**\n * Handle a touch-end event that originated in a node registered with the\n * gesture system.\n *\n * @param {TouchEvent} evt - the raw touch event from the browser\n */\n onTouchEnd(evt) {\n if (!this.trackEvents) {\n return;\n }\n\n const [x, y] = coordsForEvent(evt);\n for (let i = 0; i < evt.changedTouches.length; i++) {\n this.gestureStateMachine.onTouchEnd(\n () => this.nodeManager.idForCoords(x, y),\n evt.changedTouches[i].identifier,\n x,\n );\n }\n }\n\n /**\n * Handle a touch-cancel event that originated in a node registered with the\n * gesture system.\n *\n * @param {TouchEvent} evt - the raw touch event from the browser\n */\n onTouchCancel(evt) {\n if (!this.trackEvents) {\n return;\n }\n\n for (let i = 0; i < evt.changedTouches.length; i++) {\n this.gestureStateMachine.onTouchCancel(\n evt.changedTouches[i].identifier,\n );\n }\n }\n\n /**\n * Register a DOM node with a given identifier.\n *\n * @param {string} id - the identifier of the given node\n * @param {node} domNode - the DOM node linked to the identifier\n * @param {string[]} childIds - the identifiers of any DOM nodes that\n * should be considered children of this node,\n * in that they should take priority when\n * intercepting touch events\n * @param {object} borders - an opaque object describing the node's borders\n */\n registerDOMNode(id, domNode, childIds, borders) {\n this.nodeManager.registerDOMNode(id, domNode, childIds, borders);\n this.popoverStateMachine.registerPopover(id, childIds);\n }\n\n /**\n * Unregister the DOM node with the given identifier.\n *\n * @param {string} id - the identifier of the node to unregister\n */\n unregisterDOMNode(id) {\n this.nodeManager.unregisterDOMNode(id);\n this.popoverStateMachine.unregisterPopover(id);\n }\n\n /**\n * Enable event tracking for the gesture manager.\n */\n enableEventTracking() {\n this.trackEvents = true;\n }\n\n /**\n * Disable event tracking for the gesture manager. When called, the gesture\n * manager will drop any events received by managed nodes.\n */\n disableEventTracking() {\n this.trackEvents = false;\n }\n}\n\nexport default GestureManager;\n","/**\n * A small triangular decal to sit in the corner of a parent component.\n */\n\nimport {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport {offBlack} from \"./common-style.js\";\n\nclass CornerDecal extends React.Component {\n static propTypes = {\n style: PropTypes.any,\n };\n\n render() {\n const {style} = this.props;\n\n const containerStyle = [\n styles.container,\n ...(Array.isArray(style) ? style : [style]),\n ];\n\n return (\n <View style={containerStyle}>\n <svg\n width={triangleSizePx}\n height={triangleSizePx}\n viewBox=\"4 4 8 8\"\n >\n <path\n fill={offBlack}\n opacity=\"0.3\"\n d=\"M5.29289322,5.70710678 L10.2928932,10.7071068 C10.9228581,11.3370716 12,10.8909049 12,10 L12,5 C12,4.44771525 11.5522847,4 11,4 L6,4 C5.10909515,4 4.66292836,5.07714192 5.29289322,5.70710678 Z\" // @Nolint\n />\n </svg>\n </View>\n );\n }\n}\n\nconst triangleSizePx = 7;\n\nconst styles = StyleSheet.create({\n container: {\n position: \"absolute\",\n top: 0,\n right: 0,\n width: triangleSizePx,\n height: triangleSizePx,\n },\n});\n\nexport default CornerDecal;\n","/**\n * Common styles shared across components.\n */\n\nimport {StyleSheet} from \"aphrodite\";\n\nimport {compactKeypadBorderRadiusPx} from \"./common-style.js\";\n\nexport default StyleSheet.create({\n row: {\n flexDirection: \"row\",\n },\n column: {\n flexDirection: \"column\",\n },\n oneColumn: {\n flexGrow: 1,\n },\n fullWidth: {\n width: \"100%\",\n },\n stretch: {\n alignItems: \"stretch\",\n },\n centered: {\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n centeredText: {\n textAlign: \"center\",\n },\n roundedTopLeft: {\n borderTopLeftRadius: compactKeypadBorderRadiusPx,\n },\n roundedTopRight: {\n borderTopRightRadius: compactKeypadBorderRadiusPx,\n },\n});\n","/**\n * A component that renders an icon with math (via KaTeX).\n */\n\nimport {StyleSheet} from \"aphrodite\";\nimport katex from \"katex\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport ReactDOM from \"react-dom\";\n\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport {iconSizeHeightPx, iconSizeWidthPx} from \"./common-style.js\";\nimport Styles from \"./styles.js\";\n\nconst {row, centered} = Styles;\n\nclass MathIcon extends React.Component {\n static propTypes = {\n math: PropTypes.string.isRequired,\n style: PropTypes.any,\n };\n\n componentDidMount() {\n this._renderMath();\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.math !== this.props.math) {\n this._renderMath();\n }\n }\n\n _renderMath = () => {\n const {math} = this.props;\n katex.render(math, ReactDOM.findDOMNode(this));\n };\n\n render() {\n const {style} = this.props;\n\n const containerStyle = [\n row,\n centered,\n styles.size,\n styles.base,\n ...(Array.isArray(style) ? style : [style]),\n ];\n\n return <View style={containerStyle} />;\n }\n}\n\nconst styles = StyleSheet.create({\n size: {\n height: iconSizeHeightPx,\n width: iconSizeWidthPx,\n },\n\n base: {\n fontSize: 25,\n },\n});\n\nexport default MathIcon;\n","/**\n * An autogenerated component that renders the COS iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Cos extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M13 12h24v24H13z\" />\n <path\n d=\"M18.182 29.168c1.386 0 2.226-.602 2.674-1.232l-1.162-1.078a1.707 1.707 0 0 1-1.428.728c-1.078 0-1.834-.798-1.834-1.974s.756-1.96 1.834-1.96c.616 0 1.106.252 1.428.728l1.162-1.092c-.448-.616-1.288-1.218-2.674-1.218-2.086 0-3.584 1.47-3.584 3.542 0 2.086 1.498 3.556 3.584 3.556zm6.972 0c2.24 0 3.584-1.624 3.584-3.556 0-1.918-1.344-3.542-3.584-3.542-2.226 0-3.57 1.624-3.57 3.542 0 1.932 1.344 3.556 3.57 3.556zm0-1.582c-1.106 0-1.722-.91-1.722-1.974 0-1.05.616-1.96 1.722-1.96 1.106 0 1.736.91 1.736 1.96 0 1.064-.63 1.974-1.736 1.974zm7.336 1.582c1.876 0 2.926-.938 2.926-2.17 0-2.73-4.004-1.89-4.004-2.898 0-.378.42-.672 1.064-.672.826 0 1.596.35 2.002.784l.714-1.218c-.672-.532-1.582-.924-2.73-.924-1.778 0-2.772.994-2.772 2.128 0 2.66 4.018 1.75 4.018 2.87 0 .42-.364.728-1.134.728-.84 0-1.848-.462-2.338-.924l-.77 1.246c.714.658 1.848 1.05 3.024 1.05z\"\n fill={this.props.color}\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Cos;\n","/**\n * An autogenerated component that renders the LOG iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Log extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M16.776 29v-9.338h-1.778V29h1.778zm4.9.168c2.24 0 3.584-1.624 3.584-3.556 0-1.918-1.344-3.542-3.584-3.542-2.226 0-3.57 1.624-3.57 3.542 0 1.932 1.344 3.556 3.57 3.556zm0-1.582c-1.106 0-1.722-.91-1.722-1.974 0-1.05.616-1.96 1.722-1.96 1.106 0 1.736.91 1.736 1.96 0 1.064-.63 1.974-1.736 1.974zm7.672 4.158c1.666 0 3.654-.63 3.654-3.206v-6.3H31.21v.868c-.546-.686-1.274-1.036-2.086-1.036-1.708 0-2.982 1.232-2.982 3.444 0 2.254 1.288 3.444 2.982 3.444.826 0 1.554-.392 2.086-1.064v.686c0 1.33-1.008 1.708-1.862 1.708-.854 0-1.568-.238-2.114-.84l-.798 1.288c.854.742 1.75 1.008 2.912 1.008zm.336-4.368c-1.008 0-1.708-.7-1.708-1.862 0-1.162.7-1.862 1.708-1.862.588 0 1.232.322 1.526.77v2.184c-.294.434-.938.77-1.526.77z\"\n fill={this.props.color}\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Log;\n","/**\n * An autogenerated component that renders the EQUAL iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Equal extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M16 21h17M16 27h17\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Equal;\n","/**\n * An autogenerated component that renders the SQRT iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Sqrt extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M14 29l4 6 9-14h7\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Sqrt;\n","/**\n * An autogenerated component that renders the EXP iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Exp extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M28 16.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM30 18h4v4h-4v-4zM14 21c0-.552.456-1 1.002-1h9.996A1 1 0 0 1 26 21v14c0 .552-.456 1-1.002 1h-9.996A1 1 0 0 1 14 35V21zm2 1h8v12h-8V22z\"\n fill={this.props.color}\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Exp;\n","/**\n * An autogenerated component that renders the NEQ iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Neq extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M19 33l10-18M16 21h17M16 27h17\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Neq;\n","/**\n * An autogenerated component that renders the GEQ iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Geq extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M16 33h16M16 30l16-6-16-6\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Geq;\n","/**\n * An autogenerated component that renders the LN iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Ln extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M20.836 29v-9.338h-1.778V29h1.778zm8.106 0v-4.774c0-1.316-.714-2.156-2.198-2.156-1.106 0-1.932.532-2.366 1.05v-.882H22.6V29h1.778v-4.55c.294-.406.84-.798 1.54-.798.756 0 1.246.322 1.246 1.26V29h1.778z\"\n fill={this.props.color}\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Ln;\n","/**\n * An autogenerated component that renders the SIN iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Sin extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M18.655 29.168c1.876 0 2.926-.938 2.926-2.17 0-2.73-4.004-1.89-4.004-2.898 0-.378.42-.672 1.064-.672.826 0 1.596.35 2.002.784l.714-1.218c-.672-.532-1.582-.924-2.73-.924-1.778 0-2.772.994-2.772 2.128 0 2.66 4.018 1.75 4.018 2.87 0 .42-.364.728-1.134.728-.84 0-1.848-.462-2.338-.924l-.77 1.246c.714.658 1.848 1.05 3.024 1.05zm5.124-7.658c.588 0 1.064-.476 1.064-1.064 0-.588-.476-1.05-1.064-1.05a1.06 1.06 0 0 0-1.064 1.05c0 .588.49 1.064 1.064 1.064zm.896 7.49v-6.762h-1.778V29h1.778zm8.106 0v-4.774c0-1.316-.714-2.156-2.198-2.156-1.106 0-1.932.532-2.366 1.05v-.882h-1.778V29h1.778v-4.55c.294-.406.84-.798 1.54-.798.756 0 1.246.322 1.246 1.26V29h1.778z\"\n fill={this.props.color}\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Sin;\n","/**\n * An autogenerated component that renders the LT iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Lt extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M32 30l-16-6 16-6\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Lt;\n","/**\n * An autogenerated component that renders the CUBE_ROOT iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass CubeRoot extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M17.91 23.12c1.66 0 2.76-.81 2.76-1.98 0-.96-.86-1.51-1.57-1.58.79-.13 1.46-.72 1.46-1.5 0-1.1-.95-1.83-2.65-1.83-1.23 0-2.11.45-2.67 1.08l.83 1.08c.47-.42 1.05-.64 1.66-.64.64 0 1.12.19 1.12.61 0 .35-.39.52-1.08.52-.25 0-.77 0-.9-.01v1.53c.1-.01.61-.01.9-.01.91 0 1.19.18 1.19.56 0 .37-.38.65-1.12.65-.58 0-1.34-.23-1.82-.7l-.87 1.17c.52.6 1.48 1.05 2.76 1.05z\"\n fill={this.props.color}\n />\n <path\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M14 29l4 6 9-14h7\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default CubeRoot;\n","/**\n * An autogenerated component that renders the PLUS iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Plus extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M19 24h10M24 29V19\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Plus;\n","/**\n * An autogenerated component that renders the TAN iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Tan extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M16.93 29.168c.742 0 1.218-.196 1.484-.434l-.378-1.344c-.098.098-.35.196-.616.196-.392 0-.616-.322-.616-.742v-3.052h1.372v-1.554h-1.372V20.39h-1.792v1.848h-1.12v1.554h1.12v3.528c0 1.204.672 1.848 1.918 1.848zM25.232 29v-4.368c0-1.946-1.414-2.562-2.954-2.562-1.064 0-2.128.336-2.954 1.064l.672 1.19c.574-.532 1.246-.798 1.974-.798.896 0 1.484.448 1.484 1.134v.91c-.448-.532-1.246-.826-2.142-.826-1.078 0-2.352.602-2.352 2.184 0 1.512 1.274 2.24 2.352 2.24.882 0 1.68-.322 2.142-.868v.7h1.778zm-3.206-1.036c-.7 0-1.274-.364-1.274-.994 0-.658.574-1.022 1.274-1.022.574 0 1.134.196 1.428.588v.84c-.294.392-.854.588-1.428.588zM33.338 29v-4.774c0-1.316-.714-2.156-2.198-2.156-1.106 0-1.932.532-2.366 1.05v-.882h-1.778V29h1.778v-4.55c.294-.406.84-.798 1.54-.798.756 0 1.246.322 1.246 1.26V29h1.778z\"\n fill={this.props.color}\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Tan;\n","/**\n * An arrow icon, used by the other navigational keys.\n */\nimport * as React from \"react\";\n\nconst Arrow = (props) => {\n return (\n <g fill=\"none\" fillRule=\"evenodd\" {...props}>\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n stroke=\"#888D93\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M22 18l-6 6 6 6M16 24h16\"\n />\n </g>\n );\n};\n\nexport default Arrow;\n","/**\n * An autogenerated component that renders the LEFT_PAREN iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass LeftParen extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M26 14c-4 6-4 14 0 20\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default LeftParen;\n","/**\n * An autogenerated component that renders the RIGHT_PAREN iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass RightParen extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M23 14c4 6 4 14 0 20\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default RightParen;\n","/**\n * An autogenerated component that renders the GT iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Gt extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M16 30l16-6-16-6\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Gt;\n","/**\n * An autogenerated component that renders the DIVIDE iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Divide extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M19 24h10\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <circle fill={this.props.color} cx=\"24\" cy=\"19.5\" r=\"1.5\" />\n <circle fill={this.props.color} cx=\"24\" cy=\"28.5\" r=\"1.5\" />\n </g>\n </svg>\n );\n }\n}\n\nexport default Divide;\n","/**\n * An autogenerated component that renders the PERIOD iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Period extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <circle fill={this.props.color} cx=\"24\" cy=\"30\" r=\"2\" />\n </g>\n </svg>\n );\n }\n}\n\nexport default Period;\n","/**\n * An autogenerated component that renders the PERCENT iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Percent extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <g transform=\"translate(12 12)\">\n <path fill=\"none\" d=\"M0 0h24v24H0z\" />\n <path\n d=\"M16 4L8 20\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <circle\n stroke={this.props.color}\n strokeWidth=\"2\"\n cx=\"7\"\n cy=\"7\"\n r=\"3\"\n />\n <circle\n stroke={this.props.color}\n strokeWidth=\"2\"\n cx=\"17\"\n cy=\"17\"\n r=\"3\"\n />\n </g>\n </g>\n </svg>\n );\n }\n}\n\nexport default Percent;\n","/**\n * An autogenerated component that renders the TIMES iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Times extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M20 20l8 8M28 20l-8 8\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Times;\n","/**\n * An autogenerated component that renders the EXP_3 iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Exp3 extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M14 21c0-.552.456-1 1.002-1h9.996A1 1 0 0 1 26 21v14c0 .552-.456 1-1.002 1h-9.996A1 1 0 0 1 14 35V21zm2 1h8v12h-8V22zM30.92 23.12c1.66 0 2.76-.81 2.76-1.98 0-.96-.86-1.51-1.57-1.58.79-.13 1.46-.72 1.46-1.5 0-1.1-.95-1.83-2.65-1.83-1.23 0-2.11.45-2.67 1.08l.83 1.08c.47-.42 1.05-.64 1.66-.64.64 0 1.12.19 1.12.61 0 .35-.39.52-1.08.52-.25 0-.77 0-.9-.01v1.53c.1-.01.61-.01.9-.01.91 0 1.19.18 1.19.56 0 .37-.38.65-1.12.65-.58 0-1.34-.23-1.82-.7l-.87 1.17c.52.6 1.48 1.05 2.76 1.05z\"\n fill={this.props.color}\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Exp3;\n","/**\n * An autogenerated component that renders the EXP_2 iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Exp2 extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M14 21c0-.552.456-1 1.002-1h9.996A1 1 0 0 1 26 21v14c0 .552-.456 1-1.002 1h-9.996A1 1 0 0 1 14 35V21zm2 1h8v12h-8V22zM33.67 23v-1.5h-2.44c1.66-1.16 2.39-2.03 2.39-3.05 0-1.34-1.13-2.22-2.7-2.22-.93 0-1.99.33-2.7 1.11l.95 1.14c.48-.45 1.04-.73 1.78-.73.49 0 .92.24.92.7 0 .66-.54 1.12-3.43 3.21V23h5.23z\"\n fill={this.props.color}\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Exp2;\n","/**\n * An autogenerated component that renders the CDOT iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Cdot extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <g transform=\"translate(12 12)\">\n <path fill=\"none\" d=\"M0 0h24v24H0z\" />\n <circle fill={this.props.color} cx=\"12\" cy=\"12\" r=\"3\" />\n </g>\n </g>\n </svg>\n );\n }\n}\n\nexport default Cdot;\n","/**\n * An autogenerated component that renders the LOG_N iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass LogN extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M30 28.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM32 30h4v4h-4v-4zM12.776 29v-9.338h-1.778V29h1.778zm4.9.168c2.24 0 3.584-1.624 3.584-3.556 0-1.918-1.344-3.542-3.584-3.542-2.226 0-3.57 1.624-3.57 3.542 0 1.932 1.344 3.556 3.57 3.556zm0-1.582c-1.106 0-1.722-.91-1.722-1.974 0-1.05.616-1.96 1.722-1.96 1.106 0 1.736.91 1.736 1.96 0 1.064-.63 1.974-1.736 1.974zm7.672 4.158c1.666 0 3.654-.63 3.654-3.206v-6.3H27.21v.868c-.546-.686-1.274-1.036-2.086-1.036-1.708 0-2.982 1.232-2.982 3.444 0 2.254 1.288 3.444 2.982 3.444.826 0 1.554-.392 2.086-1.064v.686c0 1.33-1.008 1.708-1.862 1.708-.854 0-1.568-.238-2.114-.84l-.798 1.288c.854.742 1.75 1.008 2.912 1.008zm.336-4.368c-1.008 0-1.708-.7-1.708-1.862 0-1.162.7-1.862 1.708-1.862.588 0 1.232.322 1.526.77v2.184c-.294.434-.938.77-1.526.77z\"\n fill={this.props.color}\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default LogN;\n","/**\n * An autogenerated component that renders the LEQ iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Leq extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M16 33h16M32 30l-16-6 16-6\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Leq;\n","/**\n * An autogenerated component that renders the MINUS iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Minus extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M19 24h10\"\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Minus;\n","/**\n * An autogenerated component that renders the RADICAL iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass Radical extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M13 16.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM15 18h4v4h-4v-4z\"\n fill={this.props.color}\n />\n <path\n stroke={this.props.color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M14 29l4 6 9-14h7\"\n />\n </g>\n </svg>\n );\n }\n}\n\nexport default Radical;\n","/**\n * An autogenerated component that renders the FRAC iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nclass FracInclusive extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n };\n\n render() {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <g transform=\"translate(12 12)\">\n <path fill=\"none\" d=\"M0 0h24v24H0z\" />\n <path\n d=\"M8 16.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997H8.997c-.55 0-.997-.453-.997-.997v-6.006zM10 18h4v4h-4v-4z\"\n fill={this.props.color}\n />\n <rect\n fill={this.props.color}\n x=\"2\"\n y=\"11\"\n width=\"20\"\n height=\"2\"\n rx=\"1\"\n />\n <path\n d=\"M8 .997C8 .447 8.453 0 8.997 0h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997H8.997C8.447 8 8 7.547 8 7.003V.997zM10 2h4v4h-4V2z\"\n fill={this.props.color}\n />\n </g>\n </g>\n </svg>\n );\n }\n}\n\nexport default FracInclusive;\n","/**\n * An autogenerated component that renders the JUMP_OUT_PARENTHESES iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport * as React from \"react\";\n\nconst JumpOutParentheses = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M24 18c3 3 3 9 0 12M18 18c-3 3-3 9 0 12\"\n stroke=\"#888D93\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n stroke=\"#78C008\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M32 27l3-3-3-3M22 24h12\"\n />\n </g>\n </svg>\n );\n};\n\nexport default JumpOutParentheses;\n","/**\n * An autogenerated component that renders the BACKSPACE iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport * as React from \"react\";\n\nconst Backspace = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M13 24l6 6h14V18H19l-6 6zm-1.414-1.414l6-6A2 2 0 0 1 19 16h14a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H19a2 2 0 0 1-1.414-.586l-6-6a2 2 0 0 1 0-2.828z\"\n fill=\"#888D93\"\n />\n <path\n d=\"M23 21l6 6M29 21l-6 6\"\n stroke=\"#888D93\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n};\n\nexport default Backspace;\n","/**\n * An autogenerated component that renders the DISMISS iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport * as React from \"react\";\n\nconst Dismiss = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path\n d=\"M18 21l6 6 6-6\"\n strokeLinecap=\"round\"\n strokeWidth=\"2\"\n stroke=\"#71B307\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n};\n\nexport default Dismiss;\n","/**\n * An component that renders the LEFT iconograpy in SVG.\n */\nimport * as React from \"react\";\n\nimport Arrow from \"./arrow.js\";\n\nconst Left = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <Arrow />\n </svg>\n );\n};\n\nexport default Left;\n","/**\n * A component that renders the UP iconograpy in SVG.\n */\nimport * as React from \"react\";\n\nimport Arrow from \"./arrow.js\";\n\nconst Up = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <Arrow transform=\"rotate(90 24 24)\" />\n </svg>\n );\n};\n\nexport default Up;\n","/**\n * A component that renders the DOWN iconograpy in SVG.\n */\nimport * as React from \"react\";\n\nimport Arrow from \"./arrow.js\";\n\nconst Down = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <Arrow transform=\"rotate(270 24 24)\" />\n </svg>\n );\n};\n\nexport default Down;\n","/**\n * A component that renders the RIGHT iconograpy in SVG.\n */\nimport * as React from \"react\";\n\nimport Arrow from \"./arrow.js\";\n\nconst Right = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <Arrow transform=\"rotate(180 24 24)\" />\n </svg>\n );\n};\n\nexport default Right;\n","/**\n * An autogenerated component that renders the JUMP_OUT_EXPONENT iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport * as React from \"react\";\n\nconst JumpOutExponent = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M35 19v16M23 19l8 8M31 23v4h-4\"\n stroke=\"#78C008\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M12 12.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM14 14h4v4h-4v-4z\"\n fill=\"#888D93\"\n />\n </g>\n </svg>\n );\n};\n\nexport default JumpOutExponent;\n","/**\n * An autogenerated component that renders the JUMP_OUT_BASE iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport * as React from \"react\";\n\nconst JumpOutBase = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M12 28.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM14 30h4v4h-4v-4z\"\n fill=\"#888D93\"\n />\n <path\n d=\"M35 13v16M23 29l8-8M27 21h4v4\"\n stroke=\"#78C008\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </g>\n </svg>\n );\n};\n\nexport default JumpOutBase;\n","/**\n * An autogenerated component that renders the JUMP_INTO_NUMERATOR iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport * as React from \"react\";\n\nconst JumpIntoNumerator = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n d=\"M13 16v16M17 22l6-6M23 20v-4h-4\"\n stroke=\"#78C008\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M26 27.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM28 29h4v4h-4v-4z\"\n fill=\"#888D93\"\n />\n <path\n d=\"M35 24H25\"\n stroke=\"#888D93\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M26 13.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM28 15h4v4h-4v-4z\"\n fill=\"#78C008\"\n />\n </g>\n </svg>\n );\n};\n\nexport default JumpIntoNumerator;\n","/**\n * An autogenerated component that renders the JUMP_OUT_NUMERATOR iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport * as React from \"react\";\n\nconst JumpOutNumerator = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path fill=\"none\" d=\"M0 0h48v48H0z\" />\n <path fill=\"none\" d=\"M12 12h24v24H12z\" />\n <path\n stroke=\"#78C008\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M33 29l-3 3-3-3M30 18v14\"\n />\n <path\n d=\"M16 27.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM18 29h4v4h-4v-4z\"\n fill=\"#78C008\"\n />\n <path\n d=\"M25 24H15\"\n stroke=\"#888D93\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M16 13.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM18 15h4v4h-4v-4z\"\n fill=\"#888D93\"\n />\n </g>\n </svg>\n );\n};\n\nexport default JumpOutNumerator;\n","/**\n * An autogenerated component that renders the JUMP_OUT_DENOMINATOR iconograpy in SVG.\n *\n * Generated with: https://gist.github.com/crm416/3c7abc88e520eaed72347af240b32590.\n */\nimport * as React from \"react\";\n\nconst JumpOutDenominator = () => {\n return (\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\">\n <g fill=\"none\" fillRule=\"evenodd\">\n <path d=\"M0 0h48v48H0z\" />\n <path d=\"M12 12h24v24H12z\" />\n <path\n d=\"M35 16v16m-4-4v-4h-4m-2 6l6-6\"\n stroke=\"#78C008\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M14 27.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM16 29h4v4h-4v-4z\"\n fill=\"#888D93\"\n />\n <path\n d=\"M23 24H13\"\n stroke=\"#888D93\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M14 13.997c0-.55.453-.997.997-.997h6.006c.55 0 .997.453.997.997v6.006c0 .55-.453.997-.997.997h-6.006c-.55 0-.997-.453-.997-.997v-6.006zM16 15h4v4h-4v-4z\"\n fill=\"#888D93\"\n />\n </g>\n </svg>\n );\n};\n\nexport default JumpOutDenominator;\n","/**\n * A component that renders a single SVG icon.\n */\n\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nimport * as Iconography from \"./iconography/index.js\";\n\nclass SvgIcon extends React.Component {\n static propTypes = {\n color: PropTypes.string.isRequired,\n name: PropTypes.string.isRequired,\n };\n\n render() {\n const {color, name} = this.props;\n\n // eslint-disable-next-line import/namespace\n const SvgForName = Iconography[name];\n return <SvgForName color={color} />;\n }\n}\n\nexport default SvgIcon;\n","/**\n * A component that renders a text-based icon.\n */\n\nimport {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nimport {View, Text} from \"../fake-react-native-web/index.js\";\n\nimport {iconSizeHeightPx, iconSizeWidthPx} from \"./common-style.js\";\nimport Styles from \"./styles.js\";\n\nconst {row, centered} = Styles;\n\nclass TextIcon extends React.Component {\n static propTypes = {\n character: PropTypes.string.isRequired,\n style: PropTypes.any,\n };\n\n render() {\n const {character, style} = this.props;\n\n const containerStyle = [\n row,\n centered,\n styles.size,\n styles.base,\n ...(Array.isArray(style) ? style : [style]),\n ];\n return (\n <View style={containerStyle}>\n <Text>{character}</Text>\n </View>\n );\n }\n}\n\nconst styles = StyleSheet.create({\n size: {\n height: iconSizeHeightPx,\n width: iconSizeWidthPx,\n },\n\n base: {\n fontFamily: \"Proxima Nova\",\n fontSize: 25,\n },\n});\n\nexport default TextIcon;\n","/**\n * A component that renders an icon for a symbol with the given name.\n */\n\nimport {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nimport {IconTypes} from \"../consts.js\";\n\nimport {offBlack} from \"./common-style.js\";\nimport MathIcon from \"./math-icon.js\";\nimport {iconPropType} from \"./prop-types.js\";\nimport SvgIcon from \"./svg-icon.js\";\nimport TextIcon from \"./text-icon.js\";\n\nconst focusedColor = \"#FFF\";\nconst unfocusedColor = offBlack;\n\nclass Icon extends React.PureComponent {\n static propTypes = {\n focused: PropTypes.bool,\n icon: iconPropType.isRequired,\n // An Aphrodite style object, or an array of Aphrodite style objects.\n // Note that custom styles will only be applied to text and math icons\n // (and not SVG icons).\n style: PropTypes.any,\n };\n\n render() {\n const {focused, icon, style} = this.props;\n\n const styleWithFocus = [\n focused ? styles.focused : styles.unfocused,\n ...(Array.isArray(style) ? style : [style]),\n ];\n\n switch (icon.type) {\n case IconTypes.MATH:\n return <MathIcon math={icon.data} style={styleWithFocus} />;\n\n case IconTypes.SVG:\n // TODO(charlie): Support passing style objects to `SvgIcon`.\n // This will require migrating the individual icons to use\n // `currentColor` and accept a `className` prop, rather than\n // relying on an explicit color prop.\n return (\n <SvgIcon\n name={icon.data}\n color={focused ? focusedColor : unfocusedColor}\n />\n );\n\n case IconTypes.TEXT:\n return (\n <TextIcon character={icon.data} style={styleWithFocus} />\n );\n }\n\n throw new Error(\"No icon or symbol provided\");\n }\n}\n\nconst styles = StyleSheet.create({\n unfocused: {\n color: unfocusedColor,\n },\n\n focused: {\n color: focusedColor,\n },\n});\n\nexport default Icon;\n","/**\n * A grid of symbols, rendered as text and positioned based on the number of\n * symbols provided. Up to four symbols will be shown.\n */\n\nimport {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nimport {IconTypes} from \"../consts.js\";\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport {iconSizeHeightPx, iconSizeWidthPx} from \"./common-style.js\";\nimport Icon from \"./icon.js\";\nimport {iconPropType} from \"./prop-types.js\";\nimport Styles from \"./styles.js\";\n\nconst {row, column, centered, fullWidth} = Styles;\n\nclass MultiSymbolGrid extends React.Component {\n static propTypes = {\n focused: PropTypes.bool,\n icons: PropTypes.arrayOf(iconPropType).isRequired,\n };\n\n render() {\n const {focused, icons} = this.props;\n\n // Validate that we only received math-based icons. Right now, this\n // component only supports math icons (and it should only be passed\n // variables and Greek letters, which are always rendered as math).\n // Supporting other types of icons is possible but would require\n // some styles coercion and doesn't seem worthwhile right now.\n icons.forEach((icon) => {\n if (icon.type !== IconTypes.MATH) {\n throw new Error(\n `Received invalid icon: type=${icon.type}, ` +\n `data=${icon.data}`,\n );\n }\n });\n\n if (icons.length === 1) {\n return <Icon icon={icons[0]} focused={focused} />;\n } else {\n const primaryIconStyle = styles.base;\n const secondaryIconStyle = [styles.base, styles.secondary];\n\n if (icons.length === 2) {\n return (\n <View style={[row, styles.size]}>\n <View\n style={[\n column,\n centered,\n fullWidth,\n styles.middleLeft,\n ]}\n >\n <Icon\n style={primaryIconStyle}\n icon={icons[0]}\n focused={focused}\n />\n </View>\n <View\n style={[\n column,\n centered,\n fullWidth,\n styles.middleRight,\n ]}\n >\n <Icon\n style={secondaryIconStyle}\n icon={icons[1]}\n focused={focused}\n />\n </View>\n </View>\n );\n } else if (icons.length >= 3) {\n return (\n <View style={[column, styles.size]}>\n <View style={row}>\n <View style={[centered, fullWidth, styles.topLeft]}>\n <Icon\n style={primaryIconStyle}\n icon={icons[0]}\n focused={focused}\n />\n </View>\n <View\n style={[centered, fullWidth, styles.topRight]}\n >\n <Icon\n style={secondaryIconStyle}\n icon={icons[1]}\n focused={focused}\n />\n </View>\n </View>\n <View style={row}>\n <View\n style={[centered, fullWidth, styles.bottomLeft]}\n >\n <Icon\n style={secondaryIconStyle}\n icon={icons[2]}\n focused={focused}\n />\n </View>\n <View\n style={[\n centered,\n fullWidth,\n styles.bottomRight,\n ]}\n >\n {icons[3] && (\n <Icon\n style={secondaryIconStyle}\n icon={icons[3]}\n focused={focused}\n />\n )}\n </View>\n </View>\n </View>\n );\n }\n }\n\n throw new Error(\"Invalid number of icons:\", icons.length);\n }\n}\n\nconst verticalInsetPx = 2;\nconst horizontalInsetPx = 4;\n\nconst styles = StyleSheet.create({\n size: {\n height: iconSizeHeightPx,\n width: iconSizeWidthPx,\n },\n\n // For the three- and four-icon layouts.\n bottomLeft: {\n marginBottom: verticalInsetPx,\n marginLeft: horizontalInsetPx,\n },\n topLeft: {\n marginTop: verticalInsetPx,\n marginLeft: horizontalInsetPx,\n },\n topRight: {\n marginTop: verticalInsetPx,\n marginRight: horizontalInsetPx,\n },\n bottomRight: {\n marginBottom: verticalInsetPx,\n marginRight: horizontalInsetPx,\n },\n\n // For the two-icon layout.\n middleLeft: {\n marginLeft: horizontalInsetPx,\n },\n middleRight: {\n marginRight: horizontalInsetPx,\n },\n\n base: {\n fontSize: 18,\n },\n\n secondary: {\n opacity: 0.3,\n },\n});\n\nexport default MultiSymbolGrid;\n","/**\n * A component that renders a keypad button.\n */\n\nimport {StyleSheet, css} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport {connect} from \"react-redux\";\n\nimport {KeyTypes, BorderDirections, BorderStyles} from \"../consts.js\";\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport {\n wonderBlocksBlue,\n innerBorderColor,\n innerBorderStyle,\n innerBorderWidthPx,\n valueGrey,\n operatorGrey,\n controlGrey,\n emptyGrey,\n} from \"./common-style.js\";\nimport CornerDecal from \"./corner-decal.js\";\nimport Icon from \"./icon.js\";\nimport MultiSymbolGrid from \"./multi-symbol-grid.js\";\nimport {\n bordersPropType,\n iconPropType,\n keyConfigPropType,\n} from \"./prop-types.js\";\n\n// eslint-disable-next-line react/no-unsafe\nclass KeypadButton extends React.PureComponent {\n static propTypes = {\n ariaLabel: PropTypes.string,\n // The borders to display on the button. Typically, this should be set\n // using one of the preset `BorderStyles` options.\n borders: bordersPropType,\n // Any additional keys that can be accessed by long-pressing on the\n // button.\n childKeys: PropTypes.arrayOf(keyConfigPropType),\n // Whether the button should be rendered in a 'disabled' state, i.e.,\n // without any touch feedback.\n disabled: PropTypes.bool,\n focused: PropTypes.bool,\n heightPx: PropTypes.number.isRequired,\n icon: iconPropType,\n onTouchCancel: PropTypes.func,\n onTouchEnd: PropTypes.func,\n onTouchMove: PropTypes.func,\n onTouchStart: PropTypes.func,\n popoverEnabled: PropTypes.bool,\n style: PropTypes.any,\n type: PropTypes.oneOf(Object.keys(KeyTypes)).isRequired,\n // NOTE(charlie): We may want to make this optional for phone layouts\n // (and rely on Flexbox instead), since it might not be pixel perfect\n // with borders and such.\n widthPx: PropTypes.number.isRequired,\n };\n\n static defaultProps = {\n borders: BorderStyles.ALL,\n childKeys: [],\n disabled: false,\n focused: false,\n popoverEnabled: false,\n };\n\n UNSAFE_componentWillMount() {\n this.buttonSizeStyle = styleForButtonDimensions(\n this.props.heightPx,\n this.props.widthPx,\n );\n }\n\n componentDidMount() {\n this._preInjectStyles();\n }\n\n UNSAFE_componentWillUpdate(newProps, newState) {\n // Only recompute the Aphrodite StyleSheet when the button height has\n // changed. Though it is safe to recompute the StyleSheet (since\n // they're content-addressable), it saves us a bunch of hashing and\n // other work to cache it here.\n if (\n newProps.heightPx !== this.props.heightPx ||\n newProps.widthPx !== this.props.widthPx\n ) {\n this.buttonSizeStyle = styleForButtonDimensions(\n newProps.heightPx,\n newProps.widthPx,\n );\n\n this._preInjectStyles();\n }\n }\n\n _preInjectStyles = () => {\n // HACK(charlie): Pre-inject all of the possible styles for the button.\n // This avoids a flickering effect in the echo animation whereby the\n // echoes vary in size as they animate. Note that we need to account for\n // the \"initial\" styles that `View` will include, as these styles are\n // applied to `View` components and Aphrodite will consolidate the style\n // object. This method must be called whenever a property that\n // influences the possible outcomes of `this._getFocusStyle` and\n // `this._getButtonStyle` changes (such as `this.buttonSizeStyle`).\n for (const type of Object.keys(KeyTypes)) {\n css(View.styles.initial, ...this._getFocusStyle(type));\n\n for (const borders of Object.values(BorderStyles)) {\n css(\n View.styles.initial,\n ...this._getButtonStyle(type, borders),\n );\n }\n }\n };\n\n _getFocusStyle = (type) => {\n let focusBackgroundStyle;\n if (\n type === KeyTypes.INPUT_NAVIGATION ||\n type === KeyTypes.KEYPAD_NAVIGATION\n ) {\n focusBackgroundStyle = styles.light;\n } else {\n focusBackgroundStyle = styles.bright;\n }\n\n return [styles.focusBox, focusBackgroundStyle];\n };\n\n _getButtonStyle = (type, borders, style) => {\n // Select the appropriate style for the button.\n let backgroundStyle;\n switch (type) {\n case KeyTypes.EMPTY:\n backgroundStyle = styles.empty;\n break;\n\n case KeyTypes.MANY:\n case KeyTypes.VALUE:\n backgroundStyle = styles.value;\n break;\n\n case KeyTypes.OPERATOR:\n backgroundStyle = styles.operator;\n break;\n\n case KeyTypes.INPUT_NAVIGATION:\n case KeyTypes.KEYPAD_NAVIGATION:\n backgroundStyle = styles.control;\n break;\n\n case KeyTypes.ECHO:\n backgroundStyle = null;\n break;\n }\n\n const borderStyle = [];\n if (borders.indexOf(BorderDirections.LEFT) !== -1) {\n borderStyle.push(styles.leftBorder);\n }\n if (borders.indexOf(BorderDirections.BOTTOM) !== -1) {\n borderStyle.push(styles.bottomBorder);\n }\n\n return [\n styles.buttonBase,\n backgroundStyle,\n ...borderStyle,\n type === KeyTypes.ECHO && styles.echo,\n this.buttonSizeStyle,\n // React Native allows you to set the 'style' props on user defined\n // components.\n // See: https://facebook.github.io/react-native/docs/style.html\n ...(Array.isArray(style) ? style : [style]),\n ];\n };\n\n render() {\n const {\n ariaLabel,\n borders,\n childKeys,\n disabled,\n focused,\n icon,\n onTouchCancel,\n onTouchEnd,\n onTouchMove,\n onTouchStart,\n popoverEnabled,\n style,\n type,\n } = this.props;\n\n // We render in the focus state if the key is focused, or if it's an\n // echo.\n const renderFocused =\n (!disabled && focused) || popoverEnabled || type === KeyTypes.ECHO;\n const buttonStyle = this._getButtonStyle(type, borders, style);\n const focusStyle = this._getFocusStyle(type);\n const iconWrapperStyle = [\n styles.iconWrapper,\n disabled && styles.disabled,\n ];\n\n const eventHandlers = {\n onTouchCancel,\n onTouchEnd,\n onTouchMove,\n onTouchStart,\n };\n\n const maybeFocusBox = renderFocused && <View style={focusStyle} />;\n const maybeCornerDecal = !renderFocused &&\n !disabled &&\n childKeys &&\n childKeys.length > 0 && <CornerDecal style={styles.decalInset} />;\n\n if (type === KeyTypes.EMPTY) {\n return <View style={buttonStyle} {...eventHandlers} />;\n } else if (type === KeyTypes.MANY) {\n // TODO(charlie): Make the long-press interaction accessible. See\n // the TODO in key-configs.js for more.\n const manyButtonA11yMarkup = {\n role: \"button\",\n ariaLabel: childKeys[0].ariaLabel,\n };\n const icons = childKeys.map((keyConfig) => {\n return keyConfig.icon;\n });\n return (\n <View\n style={buttonStyle}\n {...eventHandlers}\n {...manyButtonA11yMarkup}\n >\n {maybeFocusBox}\n <View style={iconWrapperStyle}>\n <MultiSymbolGrid\n icons={icons}\n focused={renderFocused}\n />\n </View>\n {maybeCornerDecal}\n </View>\n );\n } else {\n const a11yMarkup = {\n role: \"button\",\n ariaLabel: ariaLabel,\n };\n\n return (\n <View style={buttonStyle} {...eventHandlers} {...a11yMarkup}>\n {maybeFocusBox}\n <View style={iconWrapperStyle}>\n <Icon icon={icon} focused={renderFocused} />\n </View>\n {maybeCornerDecal}\n </View>\n );\n }\n }\n}\n\nconst focusInsetPx = 4;\nconst focusBoxZIndex = 0;\n\nconst styles = StyleSheet.create({\n buttonBase: {\n // HACK(benkomalo): support old style flex box in Android browsers\n \"-webkit-box-flex\": \"1\",\n flex: 1,\n cursor: \"pointer\",\n // Make the text unselectable\n userSelect: \"none\",\n justifyContent: \"center\",\n alignItems: \"center\",\n // Borders are made selectively visible.\n borderColor: innerBorderColor,\n borderStyle: innerBorderStyle,\n boxSizing: \"border-box\",\n },\n\n decalInset: {\n top: focusInsetPx,\n right: focusInsetPx,\n },\n\n // Overrides for the echo state, where we want to render the borders for\n // layout purposes, but we don't want them to be visible.\n echo: {\n borderColor: \"transparent\",\n },\n\n // Background colors and other base styles that may vary between key types.\n value: {\n backgroundColor: valueGrey,\n },\n operator: {\n backgroundColor: operatorGrey,\n },\n control: {\n backgroundColor: controlGrey,\n },\n empty: {\n backgroundColor: emptyGrey,\n cursor: \"default\",\n },\n\n bright: {\n backgroundColor: wonderBlocksBlue,\n },\n light: {\n backgroundColor: \"rgba(33, 36, 44, 0.1)\",\n },\n\n iconWrapper: {\n zIndex: focusBoxZIndex + 1,\n },\n\n focusBox: {\n position: \"absolute\",\n zIndex: focusBoxZIndex,\n left: focusInsetPx,\n right: focusInsetPx,\n bottom: focusInsetPx,\n top: focusInsetPx,\n borderRadius: 1,\n },\n\n disabled: {\n opacity: 0.3,\n },\n\n // Styles used to render the appropriate borders. Buttons are only allowed\n // to render left and bottom borders, to simplify layout.\n leftBorder: {\n borderLeftWidth: innerBorderWidthPx,\n },\n bottomBorder: {\n borderBottomWidth: innerBorderWidthPx,\n },\n});\n\nconst styleForButtonDimensions = (heightPx, widthPx) => {\n return StyleSheet.create({\n // eslint-disable-next-line react-native/no-unused-styles\n buttonSize: {\n height: heightPx,\n width: widthPx,\n maxWidth: widthPx,\n },\n }).buttonSize;\n};\n\nconst mapStateToProps = (state) => {\n return state.layout.buttonDimensions;\n};\n\nexport default connect(mapStateToProps, null, null, {forwardRef: true})(\n KeypadButton,\n);\n","/**\n * A keypad button containing no symbols and triggering no actions on click.\n */\n\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport {connect} from \"react-redux\";\n\nimport KeyConfigs from \"../data/key-configs.js\";\n\nimport GestureManager from \"./gesture-manager.js\";\nimport KeypadButton from \"./keypad-button.js\";\n\nclass EmptyKeypadButton extends React.Component {\n static propTypes = {\n gestureManager: PropTypes.instanceOf(GestureManager),\n };\n\n render() {\n const {gestureManager, ...rest} = this.props;\n\n // Register touch events on the button, but don't register its DOM node\n // or compute focus state or anything like that. We want the gesture\n // manager to know about touch events that start on empty buttons, but\n // we don't need it to know about their DOM nodes, as it doesn't need\n // to focus them or trigger presses.\n return (\n <KeypadButton\n onTouchStart={(evt) => gestureManager.onTouchStart(evt)}\n onTouchEnd={(evt) => gestureManager.onTouchEnd(evt)}\n onTouchMove={(evt) => gestureManager.onTouchMove(evt)}\n onTouchCancel={(evt) => gestureManager.onTouchCancel(evt)}\n {...KeyConfigs.NOOP}\n {...rest}\n />\n );\n }\n}\n\nconst mapStateToProps = (state) => {\n const {gestures} = state;\n return {\n gestureManager: gestures.gestureManager,\n };\n};\n\nexport default connect(mapStateToProps, null, null, {forwardRef: true})(\n EmptyKeypadButton,\n);\n","/**\n * A touchable wrapper around the base KeypadButton component. This button is\n * responsible for keeping our button ID system (which will be used to handle\n * touch events globally) opaque to the KeypadButton.\n */\n\nimport {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport {connect} from \"react-redux\";\n\nimport {KeyTypes} from \"../consts.js\";\nimport KeyConfigs from \"../data/key-configs.js\";\n\nimport GestureManager from \"./gesture-manager.js\";\nimport KeypadButton from \"./keypad-button.js\";\nimport {bordersPropType, keyIdPropType} from \"./prop-types.js\";\n\nclass TouchableKeypadButton extends React.Component {\n static propTypes = {\n borders: bordersPropType,\n childKeyIds: PropTypes.arrayOf(keyIdPropType),\n disabled: PropTypes.bool,\n focused: PropTypes.bool,\n gestureManager: PropTypes.instanceOf(GestureManager),\n id: keyIdPropType.isRequired,\n popoverEnabled: PropTypes.bool,\n style: PropTypes.any,\n type: PropTypes.oneOf(Object.keys(KeyTypes)).isRequired,\n };\n\n shouldComponentUpdate(newProps) {\n // We take advantage of a few different properties of our key\n // configuration system. Namely, we know that the other props flow\n // directly from the ID, and thus don't need to be checked. If a key has\n // a custom style, we bail out (this should be rare).\n return (\n newProps.id !== this.props.id ||\n newProps.gestureManager !== this.props.gestureManager ||\n newProps.focused !== this.props.focused ||\n newProps.disabled !== this.props.disabled ||\n newProps.popoverEnabled !== this.props.popoverEnabled ||\n newProps.type !== this.props.type ||\n !!newProps.style\n );\n }\n\n componentWillUnmount() {\n const {gestureManager, id} = this.props;\n gestureManager.unregisterDOMNode(id);\n }\n\n render() {\n const {\n borders,\n childKeyIds,\n disabled,\n gestureManager,\n id,\n style,\n ...rest\n } = this.props;\n\n // Only bind the relevant event handlers if the key is enabled.\n const eventHandlers = disabled\n ? {\n onTouchStart: (evt) => evt.preventDefault(),\n }\n : {\n onTouchStart: (evt) => gestureManager.onTouchStart(evt, id),\n onTouchEnd: (evt) => gestureManager.onTouchEnd(evt),\n onTouchMove: (evt) => gestureManager.onTouchMove(evt),\n onTouchCancel: (evt) => gestureManager.onTouchCancel(evt),\n };\n\n const styleWithAddons = [\n ...(Array.isArray(style) ? style : [style]),\n styles.preventScrolls,\n ];\n\n return (\n <KeypadButton\n ref={(node) =>\n gestureManager.registerDOMNode(\n id,\n ReactDOM.findDOMNode(node),\n childKeyIds,\n borders,\n )\n }\n borders={borders}\n disabled={disabled}\n style={styleWithAddons}\n {...eventHandlers}\n {...rest}\n />\n );\n }\n}\n\nconst extractProps = (keyConfig) => {\n const {ariaLabel, icon, type} = keyConfig;\n return {ariaLabel, icon, type};\n};\n\nconst mapStateToProps = (state, ownProps) => {\n const {gestures} = state;\n\n const {keyConfig, ...rest} = ownProps;\n const {id, childKeyIds, type} = keyConfig;\n\n const childKeys = childKeyIds && childKeyIds.map((id) => KeyConfigs[id]);\n\n // Override with the default child props, if the key is a multi-symbol key\n // (but not a many-symbol key, which operates under different rules).\n const useFirstChildProps =\n type !== KeyTypes.MANY && childKeys && childKeys.length > 0;\n\n return {\n ...rest,\n childKeyIds: childKeyIds,\n gestureManager: gestures.gestureManager,\n id: id,\n\n // Add in some gesture state.\n focused: gestures.focus === id,\n popoverEnabled: gestures.popover && gestures.popover.parentId === id,\n\n // Pass down the child keys and any extracted props.\n childKeys,\n ...extractProps(useFirstChildProps ? childKeys[0] : keyConfig),\n };\n};\n\nconst styles = StyleSheet.create({\n preventScrolls: {\n // Touch events that start in the touchable buttons shouldn't be\n // allowed to produce page scrolls.\n touchAction: \"none\",\n },\n});\n\nexport default connect(mapStateToProps, null, null, {forwardRef: true})(\n TouchableKeypadButton,\n);\n","/**\n * A keypad button that displays an arbitrary number of symbols, with no\n * 'default' symbol.\n */\n\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nimport {KeyTypes} from \"../consts.js\";\nimport KeyConfigs from \"../data/key-configs.js\";\nimport Keys from \"../data/keys.js\";\n\nimport EmptyKeypadButton from \"./empty-keypad-button.js\";\nimport {keyIdPropType} from \"./prop-types.js\";\nimport TouchableKeypadButton from \"./touchable-keypad-button.js\";\n\nclass ManyKeypadButton extends React.Component {\n static propTypes = {\n keys: PropTypes.arrayOf(keyIdPropType).isRequired,\n };\n\n render() {\n const {keys, ...rest} = this.props;\n\n // If we have no extra symbols, render an empty button. If we have just\n // one, render a standard button. Otherwise, capture them all in a\n // single button.\n if (keys.length === 0) {\n return <EmptyKeypadButton {...rest} />;\n } else if (keys.length === 1) {\n const keyConfig = KeyConfigs[keys[0]];\n return <TouchableKeypadButton keyConfig={keyConfig} {...rest} />;\n } else {\n const keyConfig = {\n id: Keys.MANY,\n type: KeyTypes.MANY,\n childKeyIds: keys,\n };\n return <TouchableKeypadButton keyConfig={keyConfig} {...rest} />;\n }\n }\n}\n\nexport default ManyKeypadButton;\n","/**\n * A component that renders and animates the selection state effect effect.\n */\n\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport {TransitionGroup, CSSTransition} from \"react-transition-group\";\n\nimport {KeyTypes, EchoAnimationTypes} from \"../consts.js\";\nimport KeyConfigs from \"../data/key-configs.js\";\n\nimport KeypadButton from \"./keypad-button.js\";\nimport {\n echoPropType,\n bordersPropType,\n boundingBoxPropType,\n keyIdPropType,\n} from \"./prop-types.js\";\nimport * as zIndexes from \"./z-indexes.js\";\n\nclass Echo extends React.Component {\n static propTypes = {\n animationDurationMs: PropTypes.number.isRequired,\n borders: bordersPropType,\n id: keyIdPropType.isRequired,\n initialBounds: boundingBoxPropType.isRequired,\n onAnimationFinish: PropTypes.func.isRequired,\n };\n\n componentDidMount() {\n // NOTE(charlie): This is somewhat unfortunate, as the component is\n // encoding information about its own animation, of which it should be\n // ignorant. However, there doesn't seem to be a cleaner way to make\n // this happen, and at least here, all the animation context is\n // colocated in this file.\n const {animationDurationMs, onAnimationFinish} = this.props;\n setTimeout(() => onAnimationFinish(), animationDurationMs);\n }\n\n render() {\n const {borders, id, initialBounds} = this.props;\n const {icon} = KeyConfigs[id];\n\n const containerStyle = {\n zIndex: zIndexes.echo,\n position: \"absolute\",\n pointerEvents: \"none\",\n ...initialBounds,\n };\n\n // NOTE(charlie): In some browsers, Aphrodite doesn't seem to flush its\n // styles quickly enough, so there's a flickering effect on the first\n // animation. Thus, it's much safer to do the styles purely inline.\n // <View> makes this difficult because some of its defaults, which are\n // applied via StyleSheet, will override our inlines.\n return (\n <div style={containerStyle}>\n <KeypadButton\n name={id}\n icon={icon}\n type={KeyTypes.ECHO}\n borders={borders}\n />\n </div>\n );\n }\n}\n\nclass EchoManager extends React.Component {\n static propTypes = {\n echoes: PropTypes.arrayOf(echoPropType),\n onAnimationFinish: PropTypes.func.isRequired,\n };\n\n _animationConfigForType = (animationType) => {\n // NOTE(charlie): These must be kept in sync with the transition\n // durations and classnames specified in echo.css.\n let animationDurationMs;\n let animationTransitionName;\n\n switch (animationType) {\n case EchoAnimationTypes.SLIDE_AND_FADE:\n animationDurationMs = 400;\n animationTransitionName = \"echo-slide-and-fade\";\n break;\n\n case EchoAnimationTypes.FADE_ONLY:\n animationDurationMs = 300;\n animationTransitionName = \"echo-fade-only\";\n break;\n\n case EchoAnimationTypes.LONG_FADE_ONLY:\n animationDurationMs = 400;\n animationTransitionName = \"echo-long-fade-only\";\n break;\n\n default:\n throw new Error(\"Invalid echo animation type:\", animationType);\n }\n\n return {\n animationDurationMs,\n animationTransitionName,\n };\n };\n\n render() {\n const {echoes, onAnimationFinish} = this.props;\n\n return (\n <span>\n {Object.keys(EchoAnimationTypes).map((animationType) => {\n // Collect the relevant parameters for the animation type, and\n // filter for the appropriate echoes.\n const {animationDurationMs, animationTransitionName} =\n this._animationConfigForType(animationType);\n const echoesForType = echoes.filter((echo) => {\n return echo.animationType === animationType;\n });\n\n // TODO(charlie): Manage this animation with Aphrodite styles.\n // Right now, there's a bug in the autoprefixer that breaks CSS\n // transitions on mobile Safari.\n // See: https://github.com/Khan/aphrodite/issues/68.\n // As such, we have to do this with a stylesheet.\n return (\n <TransitionGroup key={animationType}>\n {echoesForType.map((echo) => {\n const {animationId} = echo;\n return (\n <CSSTransition\n classNames={animationTransitionName}\n enter={true}\n exit={false}\n timeout={{\n enter: animationDurationMs,\n }}\n key={animationId}\n >\n <Echo\n animationDurationMs={\n animationDurationMs\n }\n onAnimationFinish={() =>\n onAnimationFinish(animationId)\n }\n {...echo}\n />\n </CSSTransition>\n );\n })}\n </TransitionGroup>\n );\n })}\n </span>\n );\n }\n}\n\nexport default EchoManager;\n","// @flow\n/**\n * This file contains all of the z-index values used throughout the math-input\n * component and its children.\n */\n\nexport const popover = 1;\nexport const echo = 2;\nexport const keypad = 1060;\n","/**\n * A popover that renders a set of keys floating above the page.\n */\n\nimport {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nimport {BorderStyles} from \"../consts.js\";\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport {keyConfigPropType} from \"./prop-types.js\";\nimport TouchableKeypadButton from \"./touchable-keypad-button.js\";\nimport * as zIndexes from \"./z-indexes.js\";\n\nclass MultiSymbolPopover extends React.Component {\n static propTypes = {\n keys: PropTypes.arrayOf(keyConfigPropType),\n };\n\n render() {\n const {keys} = this.props;\n\n // TODO(charlie): We have to require this lazily because of a cyclic\n // dependence in our components.\n return (\n <View style={styles.container}>\n {keys.map((key) => {\n return (\n <TouchableKeypadButton\n key={key.id}\n keyConfig={key}\n borders={BorderStyles.NONE}\n />\n );\n })}\n </View>\n );\n }\n}\n\nconst styles = StyleSheet.create({\n container: {\n flexDirection: \"column-reverse\",\n position: \"relative\",\n width: \"100%\",\n borderRadius: 2,\n boxShadow: \"0 2px 6px rgba(0, 0, 0, 0.3)\",\n zIndex: zIndexes.popover,\n },\n\n // eslint-disable-next-line react-native/no-unused-styles\n popoverButton: {\n backgroundColor: \"#FFF\",\n borderWidth: 0,\n },\n});\n\nexport default MultiSymbolPopover;\n","/**\n * A component that renders and animates the popovers that appear over the\n * multi-functional keys.\n */\n\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport {CSSTransition} from \"react-transition-group\";\n\nimport KeyConfigs from \"../data/key-configs.js\";\n\nimport MultiSymbolPopover from \"./multi-symbol-popover.js\";\nimport {\n boundingBoxPropType,\n keyConfigPropType,\n popoverPropType,\n} from \"./prop-types.js\";\n\n// NOTE(charlie): These must be kept in sync with the transition durations and\n// classnames specified in popover.less.\nconst animationTransitionName = \"popover\";\nconst animationDurationMs = 200;\n\n// A container component used to position a popover absolutely at a specific\n// position.\nclass PopoverContainer extends React.Component {\n static propTypes = {\n bounds: boundingBoxPropType.isRequired,\n childKeys: PropTypes.arrayOf(keyConfigPropType).isRequired,\n };\n\n render() {\n const {bounds, childKeys} = this.props;\n\n const containerStyle = {\n position: \"absolute\",\n ...bounds,\n };\n\n return (\n <div style={containerStyle}>\n <MultiSymbolPopover keys={childKeys} />\n </div>\n );\n }\n}\n\nclass PopoverManager extends React.Component {\n static propTypes = {\n popover: popoverPropType,\n };\n\n render() {\n const {popover} = this.props;\n\n return popover ? (\n <CSSTransition\n in={true}\n classNames={animationTransitionName}\n enter={true}\n exit={false}\n timeout={{\n enter: animationDurationMs,\n }}\n >\n <PopoverContainer\n key={popover.childKeyIds[0]}\n bounds={popover.bounds}\n childKeys={popover.childKeyIds.map((id) => KeyConfigs[id])}\n />\n </CSSTransition>\n ) : null;\n }\n}\n\nexport default PopoverManager;\n","/**\n * A keypad component that acts as a container for rows or columns of buttons,\n * and manages the rendering of echo animations on top of those buttons.\n */\n\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport {connect} from \"react-redux\";\n\nimport {removeEcho} from \"../actions/index.js\";\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport EchoManager from \"./echo-manager.js\";\nimport PopoverManager from \"./popover-manager.js\";\nimport {echoPropType, popoverPropType} from \"./prop-types.js\";\n\n// eslint-disable-next-line react/no-unsafe\nclass Keypad extends React.Component {\n static propTypes = {\n children: PropTypes.oneOfType([\n PropTypes.arrayOf(PropTypes.node),\n PropTypes.node,\n ]),\n removeEcho: PropTypes.func.isRequired,\n style: PropTypes.any,\n\n // The props below are injected by redux\n\n // Whether the keypad is active, i.e., whether it should be rendered as\n // visible or invisible.\n active: PropTypes.bool,\n echoes: PropTypes.arrayOf(echoPropType).isRequired,\n popover: popoverPropType,\n };\n\n componentDidMount() {\n this._isMounted = true;\n\n window.addEventListener(\"resize\", this._onResize);\n this._updateSizeAndPosition();\n }\n\n UNSAFE_componentWillReceiveProps(newProps) {\n if (!this._container && (newProps.popover || newProps.echoes.length)) {\n this._computeContainer();\n }\n }\n\n componentWillUnmount() {\n this._isMounted = false;\n\n window.removeEventListener(\"resize\", this._onResize);\n }\n\n _computeContainer = () => {\n const domNode = ReactDOM.findDOMNode(this);\n this._container = domNode.getBoundingClientRect();\n };\n\n _updateSizeAndPosition = () => {\n // Mark the container for recalculation next time the keypad is\n // opened.\n // TODO(charlie): Since we're not recalculating the container\n // immediately, if you were to resize the page while a popover were\n // active, you'd likely get unexpected behavior. This seems very\n // difficult to do and, as such, incredibly unlikely, but we may\n // want to reconsider the caching here.\n this._container = null;\n };\n\n _onResize = () => {\n // Whenever the page resizes, we need to recompute the container's\n // bounding box. This is the only time that the bounding box can change.\n\n // Throttle resize events -- taken from:\n // https://developer.mozilla.org/en-US/docs/Web/Events/resize\n if (this._resizeTimeout == null) {\n this._resizeTimeout = setTimeout(() => {\n this._resizeTimeout = null;\n\n if (this._isMounted) {\n this._updateSizeAndPosition();\n }\n }, 66);\n }\n };\n\n render() {\n const {children, echoes, removeEcho, popover, style} = this.props;\n\n // Translate the echo boxes, as they'll be positioned absolutely to\n // this relative container.\n const relativeEchoes = echoes.map((echo) => {\n const {initialBounds, ...rest} = echo;\n return {\n ...rest,\n initialBounds: {\n top: initialBounds.top - this._container.top,\n right: initialBounds.right - this._container.left,\n bottom: initialBounds.bottom - this._container.top,\n left: initialBounds.left - this._container.left,\n width: initialBounds.width,\n height: initialBounds.height,\n },\n };\n });\n\n // Translate the popover bounds from page-absolute to keypad-relative.\n // Note that we only need three bounds, since popovers are anchored to\n // the bottom left corners of the keys over which they appear.\n const relativePopover = popover && {\n ...popover,\n bounds: {\n bottom:\n this._container.height -\n (popover.bounds.bottom - this._container.top),\n left: popover.bounds.left - this._container.left,\n width: popover.bounds.width,\n },\n };\n\n return (\n <View style={style}>\n {children}\n <EchoManager\n echoes={relativeEchoes}\n onAnimationFinish={removeEcho}\n />\n <PopoverManager popover={relativePopover} />\n </View>\n );\n }\n}\n\nconst mapStateToProps = (state) => {\n return {\n ...state.echoes,\n active: state.keypad.active,\n popover: state.gestures.popover,\n };\n};\n\nconst mapDispatchToProps = (dispatch) => {\n return {\n removeEcho: (animationId) => {\n dispatch(removeEcho(animationId));\n },\n };\n};\n\nexport default connect(mapStateToProps, mapDispatchToProps, null, {\n forwardRef: true,\n})(Keypad);\n","// naming convention: verb + noun\n// the noun should be one of the other properties in the object that's\n// being dispatched\n\nexport const dismissKeypad = () => {\n return {\n type: \"DismissKeypad\",\n };\n};\n\nexport const activateKeypad = () => {\n return {\n type: \"ActivateKeypad\",\n };\n};\n\n/**\n * Configure the keypad with the provided configuration parameters.\n *\n * See: `prop-types.js#keypadConfigurationPropType`.\n */\nexport const configureKeypad = (configuration) => {\n return {\n type: \"ConfigureKeypad\",\n configuration,\n };\n};\n\nexport const setPageSize = (pageWidthPx, pageHeightPx) => {\n return {\n type: \"SetPageSize\",\n pageWidthPx,\n pageHeightPx,\n };\n};\n\nexport const removeEcho = (animationId) => {\n return {\n type: \"RemoveEcho\",\n animationId,\n };\n};\n\n// Input-related actions.\nexport const setKeyHandler = (keyHandler) => {\n return {\n type: \"SetKeyHandler\",\n keyHandler,\n };\n};\n\nexport const setCursor = (cursor) => {\n return {\n type: \"SetCursor\",\n cursor,\n };\n};\n","// @flow\n\nimport * as React from \"react\";\n\nimport type {TabbarItemType} from \"./types.js\";\n\nfunction IconAsset({\n tintColor,\n type,\n}: {\n tintColor: string,\n type: TabbarItemType,\n}): React.Node {\n if (type === \"Geometry\") {\n return (\n <svg\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M7.57584 7.09442C7.92723 6.92984 8.3421 6.98339 8.64018 7.23179L26.6402 22.2318C26.9636 22.5013 27.0836 22.9446 26.9403 23.3404C26.7969 23.7363 26.421 24 26 24H8C7.44772 24 7 23.5523 7 23V8.00001C7 7.61199 7.22446 7.259 7.57584 7.09442ZM9 10.1351V17H13C13.5523 17 14 17.4477 14 18V22H23.238L9 10.1351ZM12 22V19H9V22H12Z\"\n fill={tintColor}\n />\n </svg>\n );\n } else if (type === \"Operators\") {\n return (\n <svg\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M29 6H30V7H29V6ZM27 6C27 4.89543 27.8954 4 29 4H30C31.1046 4 32 4.89543 32 6V7C32 8.10457 31.1046 9 30 9H29C27.8954 9 27 8.10457 27 7V6ZM11.1318 6.50386C11.3098 6.19229 11.6411 6 12 6H14C14.5523 6 15 6.44772 15 7C15 7.55228 14.5523 8 14 8H12.5803L8.86824 14.4961C8.68527 14.8163 8.34091 15.0098 7.97225 14.9996C7.6036 14.9894 7.2705 14.7771 7.10557 14.4472L5.10557 10.4472C4.85858 9.95324 5.05881 9.35256 5.55279 9.10557C6.04676 8.85858 6.64744 9.05881 6.89443 9.55279L8.0588 11.8815L11.1318 6.50386ZM7.70676 16.2925C8.09748 16.6829 8.09779 17.316 7.70745 17.7068C7.28543 18.1292 6.84383 18.7303 6.51157 19.3658C6.17039 20.0184 6 20.601 6 21C6 21.3789 6.17235 21.9897 6.51638 22.6649C6.85315 23.3259 7.28488 23.9121 7.66786 24.2557C8.07892 24.6246 8.11314 25.2568 7.74429 25.6679C7.37544 26.0789 6.7432 26.1131 6.33214 25.7443C5.7161 25.1915 5.14783 24.3844 4.73434 23.5728C4.32813 22.7755 3.99999 21.8345 4 21C4.00001 20.1391 4.3301 19.2217 4.73917 18.4392C5.15715 17.6397 5.71554 16.8708 6.29255 16.2932C6.68288 15.9025 7.31605 15.9022 7.70676 16.2925ZM11.2932 16.2925C11.684 15.9022 12.3171 15.9025 12.7075 16.2932C13.2845 16.8708 13.8428 17.6397 14.2608 18.4392C14.6699 19.2217 15 20.1391 15 21C15 21.8345 14.6719 22.7755 14.2657 23.5728C13.8522 24.3844 13.2839 25.1915 12.6679 25.7443C12.2568 26.1131 11.6246 26.0789 11.2557 25.6679C10.8869 25.2568 10.9211 24.6246 11.3321 24.2557C11.7151 23.9121 12.1469 23.3259 12.4836 22.6649C12.8276 21.9897 13 21.3789 13 21C13 20.601 12.8296 20.0184 12.4884 19.3658C12.1562 18.7303 11.7146 18.1292 11.2925 17.7068C10.9022 17.316 10.9025 16.6829 11.2932 16.2925ZM27.9363 17.6489C28.1302 18.166 27.8682 18.7424 27.3511 18.9363L21.848 21L27.3511 23.0637C27.8682 23.2576 28.1302 23.834 27.9363 24.3511C27.7424 24.8682 27.166 25.1302 26.6489 24.9363L18.6489 21.9363C18.2586 21.79 18 21.4168 18 21C18 20.5832 18.2586 20.21 18.6489 20.0637L26.6489 17.0637C27.166 16.8698 27.7424 17.1318 27.9363 17.6489ZM21 8V13H24V8H21ZM20 6C19.4477 6 19 6.44772 19 7V14C19 14.5523 19.4477 15 20 15H25C25.5523 15 26 14.5523 26 14V7C26 6.44772 25.5523 6 25 6H20Z\"\n fill={tintColor}\n />\n </svg>\n );\n } else if (type === \"Numbers\") {\n return (\n <svg\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M10.4123 19.5794V21.0004H4.71434V19.5794H6.73034V14.0214C6.73034 13.9001 6.73267 13.7764 6.73734 13.6504C6.742 13.5244 6.749 13.3961 6.75834 13.2654L5.42834 14.3714C5.335 14.4414 5.244 14.4858 5.15534 14.5044C5.06667 14.5231 4.98267 14.5254 4.90334 14.5114C4.824 14.4928 4.754 14.4648 4.69334 14.4274C4.63267 14.3854 4.586 14.3434 4.55334 14.3014L3.94434 13.4824L7.06634 10.8364H8.65534V19.5794H10.4123ZM18.7924 19.2294C19.0024 19.2294 19.1658 19.2878 19.2824 19.4044C19.4038 19.5211 19.4644 19.6751 19.4644 19.8664V21.0004H12.4224V20.3704C12.4224 20.2491 12.4481 20.1184 12.4994 19.9784C12.5508 19.8338 12.6371 19.7031 12.7584 19.5864L15.7684 16.5694C16.0251 16.3128 16.2514 16.0678 16.4474 15.8344C16.6434 15.5964 16.8068 15.3654 16.9374 15.1414C17.0681 14.9128 17.1661 14.6818 17.2314 14.4484C17.2968 14.2151 17.3294 13.9701 17.3294 13.7134C17.3294 13.2608 17.2128 12.9178 16.9794 12.6844C16.7461 12.4464 16.4171 12.3274 15.9924 12.3274C15.8058 12.3274 15.6331 12.3554 15.4744 12.4114C15.3204 12.4628 15.1804 12.5351 15.0544 12.6284C14.9331 12.7218 14.8281 12.8314 14.7394 12.9574C14.6508 13.0834 14.5854 13.2211 14.5434 13.3704C14.4594 13.6038 14.3451 13.7601 14.2004 13.8394C14.0604 13.9141 13.8598 13.9304 13.5984 13.8884L12.5764 13.7064C12.6511 13.2118 12.7911 12.7778 12.9964 12.4044C13.2018 12.0311 13.4584 11.7208 13.7664 11.4734C14.0744 11.2261 14.4268 11.0418 14.8234 10.9204C15.2201 10.7944 15.6471 10.7314 16.1044 10.7314C16.5851 10.7314 17.0214 10.8038 17.4134 10.9484C17.8101 11.0884 18.1484 11.2868 18.4284 11.5434C18.7084 11.7954 18.9254 12.1011 19.0794 12.4604C19.2334 12.8198 19.3104 13.2164 19.3104 13.6504C19.3104 14.0238 19.2568 14.3691 19.1494 14.6864C19.0421 15.0038 18.8951 15.3071 18.7084 15.5964C18.5264 15.8811 18.3141 16.1588 18.0714 16.4294C17.8288 16.7001 17.5721 16.9731 17.3014 17.2484L15.1454 19.4534C15.3834 19.3834 15.6191 19.3298 15.8524 19.2924C16.0858 19.2504 16.3051 19.2294 16.5104 19.2294H18.7924ZM21.4535 13.7064C21.5282 13.2118 21.6682 12.7778 21.8735 12.4044C22.0789 12.0311 22.3355 11.7208 22.6435 11.4734C22.9515 11.2261 23.3015 11.0418 23.6935 10.9204C24.0902 10.7944 24.5172 10.7314 24.9745 10.7314C25.4599 10.7314 25.8939 10.8014 26.2765 10.9414C26.6639 11.0768 26.9905 11.2634 27.2565 11.5014C27.5225 11.7394 27.7255 12.0171 27.8655 12.3344C28.0102 12.6518 28.0825 12.9924 28.0825 13.3564C28.0825 13.6784 28.0475 13.9631 27.9775 14.2104C27.9122 14.4531 27.8119 14.6654 27.6765 14.8474C27.5459 15.0294 27.3825 15.1834 27.1865 15.3094C26.9952 15.4354 26.7735 15.5404 26.5215 15.6244C27.6882 16.0071 28.2715 16.7841 28.2715 17.9554C28.2715 18.4734 28.1759 18.9308 27.9845 19.3274C27.7932 19.7194 27.5365 20.0484 27.2145 20.3144C26.8925 20.5804 26.5169 20.7811 26.0875 20.9164C25.6629 21.0471 25.2172 21.1124 24.7505 21.1124C24.2559 21.1124 23.8195 21.0564 23.4415 20.9444C23.0635 20.8324 22.7299 20.6644 22.4405 20.4404C22.1559 20.2164 21.9109 19.9364 21.7055 19.6004C21.5002 19.2598 21.3205 18.8631 21.1665 18.4104L22.0205 18.0604C22.2445 17.9671 22.4522 17.9414 22.6435 17.9834C22.8395 18.0254 22.9795 18.1281 23.0635 18.2914C23.1569 18.4688 23.2549 18.6321 23.3575 18.7814C23.4649 18.9308 23.5839 19.0614 23.7145 19.1734C23.8452 19.2808 23.9922 19.3648 24.1555 19.4254C24.3235 19.4861 24.5149 19.5164 24.7295 19.5164C25.0002 19.5164 25.2359 19.4721 25.4365 19.3834C25.6372 19.2948 25.8052 19.1804 25.9405 19.0404C26.0759 18.8958 26.1762 18.7348 26.2415 18.5574C26.3115 18.3754 26.3465 18.1958 26.3465 18.0184C26.3465 17.7851 26.3255 17.5751 26.2835 17.3884C26.2415 17.1971 26.1435 17.0361 25.9895 16.9054C25.8402 16.7701 25.6162 16.6674 25.3175 16.5974C25.0235 16.5228 24.6222 16.4854 24.1135 16.4854V15.1274C24.5382 15.1274 24.8859 15.0924 25.1565 15.0224C25.4272 14.9524 25.6395 14.8544 25.7935 14.7284C25.9475 14.6024 26.0525 14.4508 26.1085 14.2734C26.1692 14.0961 26.1995 13.9024 26.1995 13.6924C26.1995 13.2491 26.0829 12.9108 25.8495 12.6774C25.6209 12.4441 25.2942 12.3274 24.8695 12.3274C24.6829 12.3274 24.5102 12.3554 24.3515 12.4114C24.1975 12.4628 24.0575 12.5351 23.9315 12.6284C23.8102 12.7218 23.7052 12.8314 23.6165 12.9574C23.5279 13.0834 23.4625 13.2211 23.4205 13.3704C23.3319 13.6038 23.2175 13.7601 23.0775 13.8394C22.9375 13.9141 22.7345 13.9304 22.4685 13.8884L21.4535 13.7064Z\"\n fill={tintColor}\n />\n </svg>\n );\n }\n\n (type: empty);\n throw new Error(\"Invalid icon type\");\n}\n\nexport default IconAsset;\n","// @flow\n\nimport Clickable from \"@khanacademy/wonder-blocks-clickable\";\nimport Color from \"@khanacademy/wonder-blocks-color\";\nimport {View} from \"@khanacademy/wonder-blocks-core\";\nimport {StyleSheet} from \"aphrodite\";\nimport * as React from \"react\";\n\nimport IconAsset from \"./icons.js\";\n\nimport type {TabbarItemType} from \"./types\";\n\nconst styles = StyleSheet.create({\n base: {\n display: \"flex\",\n width: 44,\n height: 38,\n boxSizing: \"border-box\",\n borderRadius: 3,\n border: `1px solid transparent`,\n marginRight: 1,\n marginLeft: 1,\n },\n hovered: {\n background: `linear-gradient(0deg, rgba(24, 101, 242, 0.32), rgba(24, 101, 242, 0.32)), ${Color.white}`,\n border: \"1px solid #1865F2\",\n },\n pressed: {\n background: \"#1B50B3\",\n },\n focused: {\n outline: \"none\",\n border: `2px solid ${Color.blue}`,\n },\n innerBox: {\n boxSizing: \"border-box\",\n border: `1px solid transparent`,\n borderRadius: 2,\n display: \"flex\",\n flex: 1,\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n innerBoxPressed: {\n border: `1px solid ${Color.white}`,\n },\n activeIndicator: {\n position: \"absolute\",\n boxSizing: \"border-box\",\n bottom: 3,\n width: 36,\n height: 3,\n marginLeft: 3,\n },\n});\n\nfunction imageTintColor(\n itemState: ItemState,\n hovered: boolean,\n focused: boolean,\n pressed: boolean,\n): string {\n if (itemState === \"disabled\") {\n return Color.offBlack64;\n } else if (pressed) {\n return Color.white;\n } else if (itemState === \"active\") {\n return Color.blue;\n } else if (hovered) {\n return Color.blue;\n }\n return Color.offBlack64;\n}\nexport type ItemState = \"active\" | \"inactive\" | \"disabled\";\ntype Props = {\n onClick: () => void,\n itemState: ItemState,\n itemType: TabbarItemType,\n};\n\ntype State = {};\n\nclass TabbarItem extends React.Component<Props, State> {\n render(): React.Node {\n const {onClick, itemType, itemState} = this.props;\n return (\n <Clickable onClick={onClick} disabled={itemState === \"disabled\"}>\n {({hovered, focused, pressed}) => {\n const tintColor = imageTintColor(\n itemState,\n hovered,\n focused,\n pressed,\n );\n\n return (\n <View\n style={[\n styles.base,\n itemState !== \"disabled\" &&\n hovered &&\n styles.hovered,\n focused && styles.focused,\n pressed && styles.pressed,\n ]}\n >\n <View\n style={[\n styles.innerBox,\n pressed && styles.innerBoxPressed,\n ]}\n >\n <IconAsset\n type={itemType}\n tintColor={tintColor}\n />\n </View>\n {itemState === \"active\" && (\n <View\n style={[\n styles.activeIndicator,\n {\n backgroundColor: tintColor,\n },\n ]}\n />\n )}\n </View>\n );\n }}\n </Clickable>\n );\n }\n}\n\nexport const TabbarItemForTesting = TabbarItem;\n\nexport default TabbarItem;\n","// @flow\n\nimport Color from \"@khanacademy/wonder-blocks-color\";\nimport {View} from \"@khanacademy/wonder-blocks-core\";\nimport {StyleSheet} from \"aphrodite\";\nimport * as React from \"react\";\n\nimport TabbarItem from \"./item.js\";\n\nimport type {TabbarItemType} from \"./types.js\";\n\nconst styles = StyleSheet.create({\n tabbar: {\n display: \"flex\",\n flexDirection: \"row\",\n background: Color.offWhite,\n paddingTop: 2,\n paddingBottom: 2,\n borderTop: `1px solid ${Color.offBlack50}`,\n borderBottom: `1px solid ${Color.offBlack50}`,\n },\n});\n\ntype TabbarState = {\n selectedItem: number,\n};\n\ntype TabbarProps = {\n items: Array<TabbarItemType>,\n onSelect: (item: TabbarItemType) => void,\n};\n\nclass Tabbar extends React.Component<TabbarProps, TabbarState> {\n state: TabbarState = {\n selectedItem: 0,\n };\n render(): React.Node {\n const {items, onSelect} = this.props;\n return (\n <View style={styles.tabbar}>\n {items.map((item, index) => (\n <TabbarItem\n key={`tabbar-item-${index}`}\n itemState={\n index === this.state.selectedItem\n ? \"active\"\n : \"inactive\"\n }\n itemType={item}\n onClick={() => {\n this.setState({selectedItem: index});\n onSelect(item);\n }}\n />\n ))}\n </View>\n );\n }\n}\n\nexport default Tabbar;\n","/**\n * A keypad with two pages of keys.\n */\n\nimport {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport {connect} from \"react-redux\";\n\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport {\n innerBorderColor,\n innerBorderStyle,\n innerBorderWidthPx,\n offBlack16,\n} from \"./common-style.js\";\nimport Keypad from \"./keypad.js\";\nimport Styles from \"./styles.js\";\nimport Tabbar from \"./tabbar/tabbar.js\";\n\nconst {column, row, fullWidth} = Styles;\n\nclass TwoPageKeypad extends React.Component {\n static propTypes = {\n currentPage: PropTypes.oneOf([0, 1]).isRequired,\n leftPage: PropTypes.node.isRequired,\n paginationEnabled: PropTypes.bool.isRequired,\n rightPage: PropTypes.node.isRequired,\n };\n\n state = {\n selectedPage: \"Numbers\",\n };\n\n render() {\n const {leftPage, paginationEnabled, rightPage} = this.props;\n\n const {selectedPage} = this.state;\n\n if (paginationEnabled) {\n return (\n <Keypad style={[column, styles.keypad]}>\n <Tabbar\n items={[\"Numbers\", \"Operators\"]}\n onSelect={(selectedItem) => {\n this.setState({selectedPage: selectedItem});\n }}\n />\n <View style={styles.borderTop}>\n {selectedPage === \"Numbers\" && rightPage}\n {selectedPage === \"Operators\" && leftPage}\n </View>\n </Keypad>\n );\n } else {\n return (\n <Keypad style={styles.keypad}>\n <View style={row}>\n <View style={fullWidth}>{leftPage}</View>\n <View style={[styles.borderLeft, fullWidth]}>\n {rightPage}\n </View>\n </View>\n </Keypad>\n );\n }\n }\n}\n\nconst styles = StyleSheet.create({\n keypad: {\n // Set the background to light grey, so that when the user drags the\n // keypad pages past the edges, there's a grey backdrop.\n backgroundColor: offBlack16,\n },\n\n borderTop: {\n borderTop:\n `${innerBorderWidthPx}px ${innerBorderStyle} ` +\n `${innerBorderColor}`,\n },\n borderLeft: {\n borderLeft:\n `${innerBorderWidthPx}px ${innerBorderStyle} ` +\n `${innerBorderColor}`,\n boxSizing: \"content-box\",\n },\n});\n\nconst mapStateToProps = (state) => {\n return {\n paginationEnabled: state.layout.paginationEnabled,\n };\n};\n\nexport default connect(mapStateToProps, null, null, {forwardRef: true})(\n TwoPageKeypad,\n);\n","/**\n * A keypad that includes all of the expression symbols.\n */\n\nimport {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport {connect} from \"react-redux\";\n\nimport {BorderStyles} from \"../consts.js\";\nimport KeyConfigs from \"../data/key-configs.js\";\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport {valueGrey, controlGrey} from \"./common-style.js\";\nimport * as CursorContexts from \"./input/cursor-contexts.js\";\nimport ManyKeypadButton from \"./many-keypad-button.js\";\nimport {cursorContextPropType, keyIdPropType} from \"./prop-types.js\";\nimport Styles from \"./styles.js\";\nimport TouchableKeypadButton from \"./touchable-keypad-button.js\";\nimport TwoPageKeypad from \"./two-page-keypad.js\";\n\nconst {row, column, oneColumn, fullWidth, roundedTopLeft, roundedTopRight} =\n Styles;\n\nclass ExpressionKeypad extends React.Component {\n static propTypes = {\n currentPage: PropTypes.number.isRequired,\n cursorContext: cursorContextPropType.isRequired,\n dynamicJumpOut: PropTypes.bool,\n extraKeys: PropTypes.arrayOf(keyIdPropType),\n roundTopLeft: PropTypes.bool,\n roundTopRight: PropTypes.bool,\n };\n\n static rows = 4;\n static columns = 5;\n\n // Though we include an infinite-key popover in the bottom-left, it's\n // assumed that we don't need to accommodate cases in which that key\n // contains more than four children.\n static maxVisibleRows = 4;\n\n static numPages = 2;\n\n render() {\n const {\n currentPage,\n cursorContext,\n dynamicJumpOut,\n extraKeys,\n roundTopLeft,\n roundTopRight,\n } = this.props;\n\n let dismissOrJumpOutKey;\n if (dynamicJumpOut) {\n switch (cursorContext) {\n case CursorContexts.IN_PARENS:\n dismissOrJumpOutKey = KeyConfigs.JUMP_OUT_PARENTHESES;\n break;\n\n case CursorContexts.IN_SUPER_SCRIPT:\n dismissOrJumpOutKey = KeyConfigs.JUMP_OUT_EXPONENT;\n break;\n\n case CursorContexts.IN_SUB_SCRIPT:\n dismissOrJumpOutKey = KeyConfigs.JUMP_OUT_BASE;\n break;\n\n case CursorContexts.BEFORE_FRACTION:\n dismissOrJumpOutKey = KeyConfigs.JUMP_INTO_NUMERATOR;\n break;\n\n case CursorContexts.IN_NUMERATOR:\n dismissOrJumpOutKey = KeyConfigs.JUMP_OUT_NUMERATOR;\n break;\n\n case CursorContexts.IN_DENOMINATOR:\n dismissOrJumpOutKey = KeyConfigs.JUMP_OUT_DENOMINATOR;\n break;\n\n case CursorContexts.NONE:\n default:\n dismissOrJumpOutKey = KeyConfigs.DISMISS;\n break;\n }\n } else {\n dismissOrJumpOutKey = KeyConfigs.DISMISS;\n }\n\n const rightPageStyle = [\n row,\n fullWidth,\n styles.rightPage,\n roundTopRight && roundedTopRight,\n ];\n const rightPage = (\n <View style={rightPageStyle}>\n <View style={[column, oneColumn]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_7}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_4}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_1}\n borders={BorderStyles.BOTTOM}\n />\n <ManyKeypadButton\n keys={extraKeys}\n borders={BorderStyles.NONE}\n />\n </View>\n <View style={[column, oneColumn]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_8}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_5}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_2}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_0}\n borders={BorderStyles.LEFT}\n />\n </View>\n <View style={[column, oneColumn]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_9}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_6}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_3}\n borders={BorderStyles.BOTTOM}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.DECIMAL}\n borders={BorderStyles.LEFT}\n />\n </View>\n <View style={[column, oneColumn]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.DIVIDE}\n borders={BorderStyles.LEFT}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.TIMES}\n borders={BorderStyles.LEFT}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.MINUS}\n borders={BorderStyles.LEFT}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.PLUS}\n borders={BorderStyles.LEFT}\n />\n </View>\n <View style={[column, oneColumn]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.FRAC}\n style={roundTopRight && roundedTopRight}\n />\n <TouchableKeypadButton keyConfig={KeyConfigs.CDOT} />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.BACKSPACE}\n borders={BorderStyles.LEFT}\n />\n <TouchableKeypadButton\n keyConfig={dismissOrJumpOutKey}\n borders={BorderStyles.LEFT}\n />\n </View>\n </View>\n );\n\n const leftPageStyle = [\n row,\n fullWidth,\n styles.leftPage,\n roundTopLeft && roundedTopLeft,\n ];\n const leftPage = (\n <View style={leftPageStyle}>\n <View style={[column, oneColumn]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.EXP_2}\n borders={BorderStyles.NONE}\n style={roundTopLeft && roundedTopLeft}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.SQRT}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.LOG}\n borders={BorderStyles.BOTTOM}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.SIN}\n borders={BorderStyles.NONE}\n />\n </View>\n <View style={[column, oneColumn]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.EXP_3}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.CUBE_ROOT}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.LN}\n borders={BorderStyles.BOTTOM}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.COS}\n borders={BorderStyles.NONE}\n />\n </View>\n <View style={[column, oneColumn]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.EXP}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.RADICAL}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.LOG_N}\n borders={BorderStyles.BOTTOM}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.TAN}\n borders={BorderStyles.NONE}\n />\n </View>\n <View style={[column, oneColumn]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.GEQ}\n borders={BorderStyles.LEFT}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.EQUAL}\n borders={BorderStyles.LEFT}\n />\n <TouchableKeypadButton keyConfig={KeyConfigs.LEQ} />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.LEFT_PAREN}\n borders={BorderStyles.LEFT}\n />\n </View>\n <View style={[column, oneColumn]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.GT}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NEQ}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.LT}\n borders={BorderStyles.BOTTOM}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.RIGHT_PAREN}\n borders={BorderStyles.NONE}\n />\n </View>\n </View>\n );\n\n return (\n <TwoPageKeypad\n currentPage={currentPage}\n rightPage={rightPage}\n leftPage={leftPage}\n />\n );\n }\n}\n\nconst styles = StyleSheet.create({\n // NOTE(charlie): These backgrounds are applied to as to fill in some\n // unfortunate 'cracks' in the layout. However, not all keys in the first\n // page use this background color (namely, the 'command' keys, backspace and\n // dismiss).\n // TODO(charlie): Apply the proper background between the 'command' keys.\n rightPage: {\n backgroundColor: valueGrey,\n },\n\n leftPage: {\n backgroundColor: controlGrey,\n },\n});\n\nconst mapStateToProps = (state) => {\n return {\n currentPage: state.pager.currentPage,\n cursorContext: state.input.cursor.context,\n dynamicJumpOut: !state.layout.navigationPadEnabled,\n };\n};\n\nexport default connect(mapStateToProps, null, null, {forwardRef: true})(\n ExpressionKeypad,\n);\n","/**\n * A keypad that includes the digits, as well as the symbols required to deal\n * with fractions, decimals, and percents.\n */\n\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport {connect} from \"react-redux\";\n\nimport {BorderStyles} from \"../consts.js\";\nimport KeyConfigs from \"../data/key-configs.js\";\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport * as CursorContexts from \"./input/cursor-contexts.js\";\nimport Keypad from \"./keypad.js\";\nimport {cursorContextPropType} from \"./prop-types.js\";\nimport Styles from \"./styles.js\";\nimport TouchableKeypadButton from \"./touchable-keypad-button.js\";\n\nconst {row, roundedTopLeft, roundedTopRight} = Styles;\n\nclass FractionKeypad extends React.Component {\n static propTypes = {\n cursorContext: cursorContextPropType.isRequired,\n dynamicJumpOut: PropTypes.bool,\n roundTopLeft: PropTypes.bool,\n roundTopRight: PropTypes.bool,\n };\n\n static rows = 4;\n static columns = 4;\n\n // Since we include a two-key popover in the top-right, when the popover\n // is visible, the keypad will expand to fill the equivalent of five\n // rows vertically.\n static maxVisibleRows = 5;\n\n static numPages = 1;\n\n render() {\n const {cursorContext, dynamicJumpOut, roundTopLeft, roundTopRight} =\n this.props;\n\n let dismissOrJumpOutKey;\n if (dynamicJumpOut) {\n switch (cursorContext) {\n case CursorContexts.IN_PARENS:\n dismissOrJumpOutKey = KeyConfigs.JUMP_OUT_PARENTHESES;\n break;\n\n case CursorContexts.IN_SUPER_SCRIPT:\n dismissOrJumpOutKey = KeyConfigs.JUMP_OUT_EXPONENT;\n break;\n\n case CursorContexts.IN_SUB_SCRIPT:\n dismissOrJumpOutKey = KeyConfigs.JUMP_OUT_BASE;\n break;\n\n case CursorContexts.BEFORE_FRACTION:\n dismissOrJumpOutKey = KeyConfigs.JUMP_INTO_NUMERATOR;\n break;\n\n case CursorContexts.IN_NUMERATOR:\n dismissOrJumpOutKey = KeyConfigs.JUMP_OUT_NUMERATOR;\n break;\n\n case CursorContexts.IN_DENOMINATOR:\n dismissOrJumpOutKey = KeyConfigs.JUMP_OUT_DENOMINATOR;\n break;\n\n case CursorContexts.NONE:\n default:\n dismissOrJumpOutKey = KeyConfigs.DISMISS;\n break;\n }\n } else {\n dismissOrJumpOutKey = KeyConfigs.DISMISS;\n }\n\n return (\n <Keypad>\n <View style={row}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_7}\n borders={BorderStyles.NONE}\n style={roundTopLeft && roundedTopLeft}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_8}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_9}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.FRAC}\n disabled={\n // NOTE(charlie): It's only sufficient to use\n // `IN_NUMERATOR` and `IN_DENOMINATOR` here because we\n // don't support parentheses in this keypad. If we did,\n // then when the cursor was inside a parenthetical\n // expression in a numerator or denominator, this check\n // would fail.\n cursorContext === CursorContexts.IN_NUMERATOR ||\n cursorContext === CursorContexts.IN_DENOMINATOR\n }\n style={roundTopRight && roundedTopRight}\n />\n </View>\n <View style={row}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_4}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_5}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_6}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton keyConfig={KeyConfigs.PERCENT} />\n </View>\n <View style={row}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_1}\n borders={BorderStyles.BOTTOM}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_2}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_3}\n borders={BorderStyles.BOTTOM}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.BACKSPACE}\n borders={BorderStyles.LEFT}\n />\n </View>\n <View style={row}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NEGATIVE}\n borders={BorderStyles.NONE}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.NUM_0}\n borders={BorderStyles.LEFT}\n />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.DECIMAL}\n borders={BorderStyles.LEFT}\n />\n <TouchableKeypadButton\n keyConfig={dismissOrJumpOutKey}\n borders={BorderStyles.LEFT}\n />\n </View>\n </Keypad>\n );\n }\n}\n\nconst mapStateToProps = (state) => {\n return {\n cursorContext: state.input.cursor.context,\n dynamicJumpOut: !state.layout.navigationPadEnabled,\n };\n};\n\nexport default connect(mapStateToProps, null, null, {forwardRef: true})(\n FractionKeypad,\n);\n","/**\n * A system for tracking gesture velocity in a single dimension.\n *\n * Velocity is computed by smoothing linearly over the gestures that have\n * occurred in the last 100 milliseconds.\n */\n\nimport now from \"performance-now\";\n\nclass VelocityTracker {\n constructor(options) {\n this.options = {\n velocityTimeout: 100,\n ...options,\n };\n this._events = [];\n }\n\n /**\n * Pushes an event with the given displacement onto the event buffer,\n * associating it with a timestamp. Note that, as this method computes the\n * timestamp for the event at calltime, it should be called immediately\n * after the event occurs.\n *\n * @param {number} x - the cumulative displacement of the event\n */\n push(x) {\n this._events.push({\n x,\n t: now(),\n });\n }\n\n /**\n * Compute the velocity with respect to the events that have been tracked\n * by the system. Velocity is computed by smoothing linearly over recent\n * displacement values.\n *\n * Note that, for performance reasons, a call to `getVelocity` will clear\n * out the event buffer. As such, repeated calls will not return the same\n * value (in particular, a second call in quick succession will return 0).\n *\n * @returns {number} the velocity associated with the tracker\n */\n getVelocity() {\n const events = this._getEvents();\n\n if (events.length < 2) {\n return 0;\n } else {\n const current = events[events.length - 1];\n const first = events[0];\n const dt = current.t - first.t;\n return (current.x - first.x) / dt;\n }\n }\n\n /**\n * Filter the tracked events to exclude any events that occurred too far in\n * the past, and reset the event buffer.\n *\n * @returns {number[]} an array of displacements corresponding to events\n * that occurred in the past `velocityTimeout`\n * milliseconds\n */\n _getEvents() {\n const threshold = now() - this.options.velocityTimeout;\n const recentEvents = this._events.filter((event) => {\n return event.t > threshold;\n });\n this._events = [];\n return recentEvents;\n }\n}\n\nexport default VelocityTracker;\n","// @flow\n\nimport * as Redux from \"redux\";\n\nimport {tabletCutoffPx} from \"../components/common-style.js\";\nimport {computeLayoutParameters} from \"../components/compute-layout-parameters.js\";\nimport ExpressionKeypad from \"../components/expression-keypad.js\";\nimport FractionKeypad from \"../components/fraction-keypad.js\";\nimport GestureManager from \"../components/gesture-manager.js\";\nimport * as CursorContexts from \"../components/input/cursor-contexts.js\";\nimport VelocityTracker from \"../components/velocity-tracker.js\";\nimport {\n DeviceOrientations,\n DeviceTypes,\n EchoAnimationTypes,\n KeyTypes,\n KeypadTypes,\n LayoutModes,\n} from \"../consts.js\";\nimport KeyConfigs from \"../data/key-configs.js\";\nimport Keys from \"../data/keys.js\";\n\nconst keypadForType = {\n [KeypadTypes.FRACTION]: FractionKeypad,\n [KeypadTypes.EXPRESSION]: ExpressionKeypad,\n};\n\nexport const createStore = (): $FlowFixMe => {\n const initialInputState: {|\n keyHandler: $FlowFixMe,\n cursor: $FlowFixMe,\n |} = {\n keyHandler: null,\n cursor: {\n context: CursorContexts.NONE,\n },\n };\n\n const inputReducer = function (state = initialInputState, action) {\n switch (action.type) {\n case \"SetKeyHandler\":\n return {\n ...state,\n keyHandler: action.keyHandler,\n };\n\n case \"PressKey\":\n const keyConfig = KeyConfigs[action.key];\n if (keyConfig.type !== KeyTypes.KEYPAD_NAVIGATION) {\n // This is probably an anti-pattern but it works for the\n // case where we don't actually control the state but we\n // still want to communicate with the other object\n return {\n ...state,\n cursor: state.keyHandler(keyConfig.id),\n };\n }\n\n // TODO(kevinb) get state from MathQuill and store it?\n return state;\n\n case \"SetCursor\":\n return {\n ...state,\n cursor: action.cursor,\n };\n\n default:\n return state;\n }\n };\n\n const defaultKeypadType = KeypadTypes.EXPRESSION;\n\n const initialKeypadState = {\n extraKeys: [\"x\", \"y\", Keys.THETA, Keys.PI],\n keypadType: defaultKeypadType,\n active: false,\n };\n\n const keypadReducer = function (state = initialKeypadState, action) {\n switch (action.type) {\n case \"DismissKeypad\":\n return {\n ...state,\n active: false,\n };\n\n case \"ActivateKeypad\":\n return {\n ...state,\n active: true,\n };\n\n case \"ConfigureKeypad\":\n return {\n ...state,\n // Default `extraKeys` to the empty array.\n extraKeys: [],\n ...action.configuration,\n };\n\n case \"PressKey\":\n const keyConfig = KeyConfigs[action.key];\n // NOTE(charlie): Our keypad system operates by triggering key\n // presses with key IDs in a dumb manner, such that the keys\n // don't know what they can do--instead, the store is\n // responsible for interpreting key presses and triggering the\n // right actions when they occur. Hence, we figure off a\n // dismissal here rather than dispatching a dismiss action in\n // the first place.\n if (keyConfig.id === Keys.DISMISS) {\n return keypadReducer(state, {type: \"DismissKeypad\"});\n }\n return state;\n\n default:\n return state;\n }\n };\n\n // We default to the right-most page. This is done so-as to enforce a\n // consistent orientation between the view pager layout and the flattened\n // layout, where our default page appears on the far right.\n const getDefaultPage = (numPages) => numPages - 1;\n\n const initialPagerState = {\n animateToPosition: false,\n currentPage: getDefaultPage(keypadForType[defaultKeypadType].numPages),\n // The cumulative differential in the horizontal direction for the\n // current swipe.\n dx: 0,\n numPages: keypadForType[defaultKeypadType].numPages,\n pageWidthPx: 0,\n velocityTracker: new VelocityTracker(),\n };\n\n const pagerReducer = function (state = initialPagerState, action) {\n switch (action.type) {\n case \"ConfigureKeypad\":\n const {keypadType} = action.configuration;\n const {numPages} = keypadForType[keypadType];\n return {\n ...state,\n numPages,\n animateToPosition: false,\n currentPage: getDefaultPage(numPages),\n dx: 0,\n };\n\n case \"SetPageSize\":\n return {\n ...state,\n pageWidthPx: action.pageWidthPx,\n };\n\n case \"PressKey\":\n const keyConfig = KeyConfigs[action.key];\n\n // Reset the keypad page if the user performs a math operation.\n if (\n keyConfig.type === KeyTypes.VALUE ||\n keyConfig.type === KeyTypes.OPERATOR\n ) {\n return pagerReducer(state, {type: \"ResetKeypadPage\"});\n }\n return state;\n\n case \"ResetKeypadPage\":\n return {\n ...state,\n animateToPosition: true,\n // We start at the right-most page.\n currentPage: getDefaultPage(state.numPages),\n dx: 0,\n };\n\n case \"PageKeypadRight\":\n const nextPage = Math.min(\n state.currentPage + 1,\n state.numPages - 1,\n );\n return {\n ...state,\n animateToPosition: true,\n currentPage: nextPage,\n dx: 0,\n };\n\n case \"PageKeypadLeft\":\n const prevPage = Math.max(state.currentPage - 1, 0);\n return {\n ...state,\n animateToPosition: true,\n currentPage: prevPage,\n dx: 0,\n };\n\n case \"OnSwipeChange\":\n state.velocityTracker.push(action.dx);\n\n return {\n ...state,\n animateToPosition: false,\n dx: action.dx,\n };\n\n case \"OnSwipeEnd\":\n const {pageWidthPx, velocityTracker} = state;\n const {dx} = action;\n const velocity = velocityTracker.getVelocity();\n\n // NOTE(charlie): These will need refinement. The velocity comes\n // from Framer.\n const minFlingVelocity = 0.1;\n const minFlingDistance = 10;\n\n const shouldPageRight =\n dx < -pageWidthPx / 2 ||\n (velocity < -minFlingVelocity && dx < -minFlingDistance);\n\n const shouldPageLeft =\n dx > pageWidthPx / 2 ||\n (velocity > minFlingVelocity && dx > minFlingDistance);\n\n if (shouldPageRight) {\n return pagerReducer(state, {type: \"PageKeypadRight\"});\n } else if (shouldPageLeft) {\n return pagerReducer(state, {type: \"PageKeypadLeft\"});\n }\n\n return {\n ...state,\n animateToPosition: true,\n dx: 0,\n };\n\n default:\n return state;\n }\n };\n\n const createGestureManager = (swipeEnabled) => {\n return new GestureManager(\n {\n swipeEnabled,\n },\n {\n onSwipeChange: (dx) => {\n store.dispatch({\n type: \"OnSwipeChange\",\n dx,\n });\n },\n onSwipeEnd: (dx) => {\n store.dispatch({\n type: \"OnSwipeEnd\",\n dx,\n });\n },\n onActiveNodesChanged: (activeNodes) => {\n store.dispatch({\n type: \"SetActiveNodes\",\n activeNodes,\n });\n },\n onClick: (key, layoutProps, inPopover) => {\n store.dispatch({\n type: \"PressKey\",\n key,\n ...layoutProps,\n inPopover,\n });\n },\n },\n [],\n [Keys.BACKSPACE, Keys.UP, Keys.RIGHT, Keys.DOWN, Keys.LEFT],\n );\n };\n\n const initialGestureState = {\n popover: null,\n focus: null,\n gestureManager: createGestureManager(\n keypadForType[defaultKeypadType].numPages > 1,\n ),\n };\n\n const gestureReducer = function (state = initialGestureState, action) {\n switch (action.type) {\n case \"DismissKeypad\":\n // NOTE(charlie): In the past, we enforced the \"gesture manager\n // will not receive any events when the keypad is hidden\"\n // assumption by assuming that the keypad would be hidden when\n // dismissed and, as such, that none of its managed DOM nodes\n // would be able to receive touch events. However, on mobile\n // Safari, we're seeing that some of the keys receive touch\n // events even when off-screen, inexplicably. So, to guard\n // against that bug and make the contract explicit, we enable\n // and disable event tracking on activation and dismissal.\n state.gestureManager.disableEventTracking();\n return state;\n\n case \"ActivateKeypad\":\n state.gestureManager.enableEventTracking();\n return state;\n\n case \"SetActiveNodes\":\n return {\n ...state,\n ...action.activeNodes,\n };\n\n case \"ConfigureKeypad\":\n const {keypadType} = action.configuration;\n const {numPages} = keypadForType[keypadType];\n const swipeEnabled = numPages > 1;\n return {\n popover: null,\n focus: null,\n gestureManager: createGestureManager(swipeEnabled),\n };\n\n default:\n return state;\n }\n };\n\n // Used to generate unique animation IDs for the echo animations. The actual\n // values are irrelevant as long as they are unique.\n let _lastAnimationId = 0;\n\n const initialEchoState = {\n echoes: [],\n };\n\n const echoReducer = function (state = initialEchoState, action) {\n switch (action.type) {\n case \"PressKey\":\n const keyConfig = KeyConfigs[action.key];\n\n // Add in the echo animation if the user performs a math\n // operation.\n if (\n keyConfig.type === KeyTypes.VALUE ||\n keyConfig.type === KeyTypes.OPERATOR\n ) {\n return {\n ...state,\n echoes: [\n ...state.echoes,\n {\n animationId: \"\" + _lastAnimationId++,\n animationType: action.inPopover\n ? EchoAnimationTypes.LONG_FADE_ONLY\n : EchoAnimationTypes.FADE_ONLY,\n borders: action.borders,\n id: keyConfig.id,\n initialBounds: action.initialBounds,\n },\n ],\n };\n }\n return state;\n\n case \"RemoveEcho\":\n const remainingEchoes = state.echoes.filter((echo) => {\n return echo.animationId !== action.animationId;\n });\n return {\n ...state,\n echoes: remainingEchoes,\n };\n\n default:\n return state;\n }\n };\n\n const initialLayoutState = {\n gridDimensions: {\n numRows: keypadForType[defaultKeypadType].rows,\n numColumns: keypadForType[defaultKeypadType].columns,\n numMaxVisibleRows: keypadForType[defaultKeypadType].maxVisibleRows,\n numPages: keypadForType[defaultKeypadType].numPages,\n },\n buttonDimensions: {\n widthPx: 48,\n heightPx: 48,\n },\n pageDimensions: {\n pageWidthPx: 0,\n pageHeightPx: 0,\n },\n layoutMode: LayoutModes.FULLSCREEN,\n paginationEnabled: false,\n navigationPadEnabled: false,\n };\n\n /**\n * Compute the additional layout state based on the provided page and grid\n * dimensions.\n */\n const layoutParametersForDimensions = (pageDimensions, gridDimensions) => {\n const {pageWidthPx, pageHeightPx} = pageDimensions;\n\n // Determine the device type and orientation.\n const deviceOrientation =\n pageWidthPx > pageHeightPx\n ? DeviceOrientations.LANDSCAPE\n : DeviceOrientations.PORTRAIT;\n const deviceType =\n Math.min(pageWidthPx, pageHeightPx) > tabletCutoffPx\n ? DeviceTypes.TABLET\n : DeviceTypes.PHONE;\n\n // Using that information, make some decisions (or assumptions)\n // about the resulting layout.\n const navigationPadEnabled = deviceType === DeviceTypes.TABLET;\n const paginationEnabled =\n deviceType === DeviceTypes.PHONE &&\n deviceOrientation === DeviceOrientations.PORTRAIT;\n\n const deviceInfo = {deviceOrientation, deviceType};\n const layoutOptions = {\n navigationPadEnabled,\n paginationEnabled,\n // HACK(charlie): It's not great that we're making assumptions about\n // the toolbar (which is rendered by webapp, and should always be\n // visible and anchored to the bottom of the page for phone and\n // tablet exercises). But this is primarily a heuristic (the goal is\n // to preserve a 'good' amount of space between the top of the\n // keypad and the top of the page) so we afford to have some margin\n // of error.\n toolbarEnabled: true,\n };\n\n return {\n ...computeLayoutParameters(\n gridDimensions,\n pageDimensions,\n deviceInfo,\n layoutOptions,\n ),\n // Pass along some of the layout information, so that other\n // components in the heirarchy can adapt appropriately.\n navigationPadEnabled,\n paginationEnabled,\n };\n };\n\n const layoutReducer = function (state = initialLayoutState, action) {\n switch (action.type) {\n case \"ConfigureKeypad\":\n const {keypadType} = action.configuration;\n const gridDimensions = {\n numRows: keypadForType[keypadType].rows,\n numColumns: keypadForType[keypadType].columns,\n numMaxVisibleRows: keypadForType[keypadType].maxVisibleRows,\n numPages: keypadForType[keypadType].numPages,\n };\n\n return {\n ...state,\n ...layoutParametersForDimensions(\n state.pageDimensions,\n gridDimensions,\n ),\n gridDimensions,\n };\n\n case \"SetPageSize\":\n const {pageWidthPx, pageHeightPx} = action;\n const pageDimensions = {pageWidthPx, pageHeightPx};\n\n return {\n ...state,\n ...layoutParametersForDimensions(\n pageDimensions,\n state.gridDimensions,\n ),\n pageDimensions,\n };\n\n default:\n return state;\n }\n };\n\n const reducer = Redux.combineReducers({\n input: inputReducer,\n keypad: keypadReducer,\n pager: pagerReducer,\n gestures: gestureReducer,\n echoes: echoReducer,\n layout: layoutReducer,\n });\n\n // TODO(charlie): This non-inlined return is necessary so as to allow the\n // gesture manager to dispatch actions on the store in its callbacks. We\n // should come up with a better pattern to remove the two-way dependency.\n const store = Redux.createStore(reducer);\n\n return store;\n};\n","/**\n * An algorithm for computing the appropriate layout parameters for the keypad,\n * including the size of the buttons and whether or not to render fullscreen,\n * taking into account a number of factors including the size of the screen, the\n * orientation of the screen, the presence of browser chrome, the presence of\n * other exercise-related chrome, the size of the input box, the parameters that\n * define the keypad (i.e., the number of rows, columns, and pages), and so\n * forth.\n *\n * The computations herein make some strong assumptions about the sizes of\n * various other elements and the situations under which they will be visible\n * (e.g., browser chrome). However, this is just a heuristic--it's not crucial\n * that our buttons are sized in a pixel-perfect manner, but rather, that we\n * make a balanced use of space.\n *\n * Note that one goal of the algorithm is to avoid resizing the keypad in the\n * face of dynamic browser chrome. In order to avoid that awkwardness, we tend\n * to be conservative in our measurements and make things smaller than they\n * might need to be.\n */\n\nimport {DeviceTypes, DeviceOrientations, LayoutModes} from \"../consts.js\";\n\nimport {\n pageIndicatorHeightPx,\n toolbarHeightPx,\n navigationPadWidthPx,\n innerBorderWidthPx,\n} from \"./common-style.js\";\n\nconst minButtonHeight = 48;\nconst maxButtonSize = 64;\nconst minSpaceAboveKeypad = 32;\n\n// These values are taken from an iPhone 5, but should be consistent with the\n// iPhone 4 as well. Regardless, these are meant to be representative of the\n// possible types of browser chrome that could appear in various context, rather\n// than pixel-perfect for every device.\nconst safariNavBarWhenShrunk = 44;\nconst safariNavBarWhenExpanded = 64;\nconst safariToolbar = 44;\n\n// In mobile Safari, the browser chrome is completely hidden in landscape,\n// though a shrunken navbar and full-sized toolbar on scroll. In portrait, the\n// shrunken navbar is always visible, but expands on scroll (and the toolbar\n// appears as well).\nconst maxLandscapeBrowserChrome = safariNavBarWhenShrunk + safariToolbar;\nconst maxPortraitBrowserChrome =\n safariToolbar + (safariNavBarWhenExpanded - safariNavBarWhenShrunk);\n\n// This represents the 'worst case' aspect ratio that we care about (for\n// portrait layouts). It's taken from the iPhone 4. The height is computed by\n// taking the height of the device and removing the persistent, shrunken navbar.\n// (We don't need to account for the expanded navbar, since we include the\n// difference when reserving space above the keypad.)\nconst worstCaseAspectRatio = 320 / (480 - safariNavBarWhenShrunk);\n\nexport const computeLayoutParameters = (\n {numColumns, numMaxVisibleRows, numPages},\n {pageWidthPx, pageHeightPx},\n {deviceOrientation, deviceType},\n {navigationPadEnabled, paginationEnabled, toolbarEnabled},\n) => {\n // First, compute some values that will be used in multiple computations.\n const effectiveNumColumns = paginationEnabled\n ? numColumns\n : numColumns * numPages;\n\n // Then, compute the button dimensions based on the provided parameters.\n let buttonDimensions;\n if (deviceType === DeviceTypes.PHONE) {\n const isLandscape = deviceOrientation === DeviceOrientations.LANDSCAPE;\n\n // In many cases, the browser chrome will already have been factored\n // into `pageHeightPx`. But we have no way of knowing if that's\n // the case or not. As such, we take a conservative approach and\n // assume that the chrome is _never_ included in `pageHeightPx`.\n const browserChromeHeight = isLandscape\n ? maxLandscapeBrowserChrome\n : maxPortraitBrowserChrome;\n\n // Count up all the space that we need to reserve on the page.\n // Namely, we need to account for:\n // 1. Space between the keypad and the top of the page.\n // 2. The presence of the exercise toolbar.\n // 3. The presence of the view pager indicator.\n // 4. Any browser chrome that may appear later.\n const reservedSpace =\n minSpaceAboveKeypad +\n browserChromeHeight +\n (toolbarEnabled ? toolbarHeightPx : 0) +\n (paginationEnabled ? pageIndicatorHeightPx : 0);\n\n // Next, compute the effective width and height. We can use the page\n // width as the effective width. For the height, though, we take\n // another conservative measure when in portrait by assuming that\n // the device has the worst possible aspect ratio. In other words,\n // we ignore the device height in portrait and assume the worst.\n // This prevents the keypad from changing size when browser chrome\n // appears and disappears.\n const effectiveWidth = pageWidthPx;\n const effectiveHeight = isLandscape\n ? pageHeightPx\n : pageWidthPx / worstCaseAspectRatio;\n const maxKeypadHeight = effectiveHeight - reservedSpace;\n\n // Finally, compute the button height and width. In computing the\n // height, accommodate for the maximum number of rows that will ever be\n // visible (since the toggling of popovers can increase the number of\n // visible rows).\n const buttonHeightPx = Math.max(\n Math.min(maxKeypadHeight / numMaxVisibleRows, maxButtonSize),\n minButtonHeight,\n );\n\n let buttonWidthPx;\n if (numPages > 1) {\n const effectiveNumColumns = paginationEnabled\n ? numColumns\n : numColumns * numPages;\n buttonWidthPx = effectiveWidth / effectiveNumColumns;\n } else {\n buttonWidthPx = isLandscape\n ? maxButtonSize\n : effectiveWidth / numColumns;\n }\n\n buttonDimensions = {\n widthPx: buttonWidthPx,\n heightPx: buttonHeightPx,\n };\n } else if (deviceType === DeviceTypes.TABLET) {\n buttonDimensions = {\n widthPx: maxButtonSize,\n heightPx: maxButtonSize,\n };\n } else {\n throw new Error(\"Invalid device type: \" + deviceType);\n }\n\n // Finally, determine whether the keypad should be rendered in the\n // fullscreen layout by determining its resultant width.\n const numSeparators =\n (navigationPadEnabled ? 1 : 0) +\n (!paginationEnabled ? numPages - 1 : 0);\n const keypadWidth =\n effectiveNumColumns * buttonDimensions.widthPx +\n (navigationPadEnabled ? navigationPadWidthPx : 0) +\n numSeparators * innerBorderWidthPx;\n return {\n buttonDimensions,\n layoutMode:\n keypadWidth >= pageWidthPx\n ? LayoutModes.FULLSCREEN\n : LayoutModes.COMPACT,\n };\n};\n","/**\n * A component that renders a navigation pad, which consists of an arrow for\n * each possible direction.\n */\n\nimport {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\n\nimport {BorderStyles} from \"../consts.js\";\nimport KeyConfigs from \"../data/key-configs.js\";\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport {\n navigationPadWidthPx,\n controlGrey,\n valueGrey,\n offBlack16,\n} from \"./common-style.js\";\nimport Styles from \"./styles.js\";\nimport TouchableKeypadButton from \"./touchable-keypad-button.js\";\n\nconst {row, column, centered, stretch, roundedTopLeft} = Styles;\n\nclass NavigationPad extends React.Component {\n static propTypes = {\n roundTopLeft: PropTypes.bool,\n style: PropTypes.any,\n };\n\n render() {\n // TODO(charlie): Disable the navigational arrows depending on the\n // cursor context.\n const {roundTopLeft, style} = this.props;\n\n const containerStyle = [\n column,\n centered,\n styles.container,\n roundTopLeft && roundedTopLeft,\n ...(Array.isArray(style) ? style : [style]),\n ];\n\n return (\n <View style={containerStyle}>\n <View style={[row, centered]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.UP}\n borders={BorderStyles.NONE}\n style={[styles.navigationKey, styles.topArrow]}\n />\n </View>\n <View style={[row, centered, stretch]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.LEFT}\n borders={BorderStyles.NONE}\n style={[styles.navigationKey, styles.leftArrow]}\n />\n <View style={styles.horizontalSpacer} />\n <TouchableKeypadButton\n keyConfig={KeyConfigs.RIGHT}\n borders={BorderStyles.NONE}\n style={[styles.navigationKey, styles.rightArrow]}\n />\n </View>\n <View style={[row, centered]}>\n <TouchableKeypadButton\n keyConfig={KeyConfigs.DOWN}\n borders={BorderStyles.NONE}\n style={[styles.navigationKey, styles.bottomArrow]}\n />\n </View>\n </View>\n );\n }\n}\n\nconst buttonSizePx = 48;\nconst borderRadiusPx = 4;\nconst borderWidthPx = 1;\n\nconst styles = StyleSheet.create({\n container: {\n backgroundColor: controlGrey,\n width: navigationPadWidthPx,\n },\n\n navigationKey: {\n borderColor: offBlack16,\n backgroundColor: valueGrey,\n width: buttonSizePx,\n height: buttonSizePx,\n\n // Override the default box-sizing so that our buttons are\n // `buttonSizePx` exclusive of their borders.\n boxSizing: \"content-box\",\n },\n\n topArrow: {\n borderTopWidth: borderWidthPx,\n borderLeftWidth: borderWidthPx,\n borderRightWidth: borderWidthPx,\n borderTopLeftRadius: borderRadiusPx,\n borderTopRightRadius: borderRadiusPx,\n },\n\n rightArrow: {\n borderTopWidth: borderWidthPx,\n borderRightWidth: borderWidthPx,\n borderBottomWidth: borderWidthPx,\n borderTopRightRadius: borderRadiusPx,\n borderBottomRightRadius: borderRadiusPx,\n },\n\n bottomArrow: {\n borderBottomWidth: borderWidthPx,\n borderLeftWidth: borderWidthPx,\n borderRightWidth: borderWidthPx,\n borderBottomLeftRadius: borderRadiusPx,\n borderBottomRightRadius: borderRadiusPx,\n },\n\n leftArrow: {\n borderTopWidth: borderWidthPx,\n borderBottomWidth: borderWidthPx,\n borderLeftWidth: borderWidthPx,\n borderTopLeftRadius: borderRadiusPx,\n borderBottomLeftRadius: borderRadiusPx,\n },\n\n horizontalSpacer: {\n background: valueGrey,\n // No need to set a height -- the spacer will be stretched by its\n // parent.\n width: buttonSizePx,\n },\n});\n\nexport default NavigationPad;\n","import {StyleSheet} from \"aphrodite\";\nimport PropTypes from \"prop-types\";\nimport * as React from \"react\";\nimport {connect} from \"react-redux\";\n\nimport {setPageSize} from \"../actions/index.js\";\nimport {KeypadTypes, LayoutModes} from \"../consts.js\";\nimport {View} from \"../fake-react-native-web/index.js\";\n\nimport {\n innerBorderColor,\n innerBorderStyle,\n innerBorderWidthPx,\n compactKeypadBorderRadiusPx,\n} from \"./common-style.js\";\nimport ExpressionKeypad from \"./expression-keypad.js\";\nimport FractionKeypad from \"./fraction-keypad.js\";\nimport NavigationPad from \"./navigation-pad.js\";\nimport {keyIdPropType} from \"./prop-types.js\";\nimport Styles from \"./styles.js\";\nimport * as zIndexes from \"./z-indexes.js\";\n\nconst {row, centered, fullWidth} = Styles;\n\n// eslint-disable-next-line react/no-unsafe\nclass KeypadContainer extends React.Component {\n static propTypes = {\n active: PropTypes.bool,\n extraKeys: PropTypes.arrayOf(keyIdPropType),\n keypadType: PropTypes.oneOf(Object.keys(KeypadTypes)).isRequired,\n layoutMode: PropTypes.oneOf(Object.keys(LayoutModes)).isRequired,\n navigationPadEnabled: PropTypes.bool.isRequired,\n onDismiss: PropTypes.func,\n // A callback that should be triggered with the root React element on\n // mount.\n onElementMounted: PropTypes.func,\n onPageSizeChange: PropTypes.func.isRequired,\n style: PropTypes.any,\n };\n\n state = {\n hasBeenActivated: false,\n viewportWidth: \"100vw\",\n };\n\n UNSAFE_componentWillMount() {\n if (this.props.active) {\n this.setState({\n hasBeenActivated: this.props.active,\n });\n }\n }\n\n componentDidMount() {\n // Relay the initial size metrics.\n this._onResize();\n\n // And update it on resize.\n window.addEventListener(\"resize\", this._throttleResizeHandler);\n window.addEventListener(\n \"orientationchange\",\n this._throttleResizeHandler,\n );\n }\n\n UNSAFE_componentWillReceiveProps(nextProps) {\n if (!this.state.hasBeenActivated && nextProps.active) {\n this.setState({\n hasBeenActivated: true,\n });\n }\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.active && !this.props.active) {\n this.props.onDismiss && this.props.onDismiss();\n }\n }\n\n componentWillUnmount() {\n window.removeEventListener(\"resize\", this._throttleResizeHandler);\n window.removeEventListener(\n \"orientationchange\",\n this._throttleResizeHandler,\n );\n }\n\n _throttleResizeHandler = () => {\n // Throttle the resize callbacks.\n // https://developer.mozilla.org/en-US/docs/Web/Events/resize\n if (this._resizeTimeout == null) {\n this._resizeTimeout = setTimeout(() => {\n this._resizeTimeout = null;\n\n this._onResize();\n }, 66);\n }\n };\n\n _onResize = () => {\n // Whenever the page resizes, we need to force an update, as the button\n // heights and keypad width are computed based on horizontal space.\n this.setState({\n viewportWidth: window.innerWidth,\n });\n\n this.props.onPageSizeChange(window.innerWidth, window.innerHeight);\n };\n\n renderKeypad = () => {\n const {extraKeys, keypadType, layoutMode, navigationPadEnabled} =\n this.props;\n\n const keypadProps = {\n extraKeys,\n // HACK(charlie): In order to properly round the corners of the\n // compact keypad, we need to instruct some of our child views to\n // crop themselves. At least we're colocating all the layout\n // information in this component, though.\n roundTopLeft:\n layoutMode === LayoutModes.COMPACT && !navigationPadEnabled,\n roundTopRight: layoutMode === LayoutModes.COMPACT,\n };\n\n // Select the appropriate keyboard given the type.\n // TODO(charlie): In the future, we might want to move towards a\n // data-driven approach to defining keyboard layouts, and have a\n // generic keyboard that takes some \"keyboard data\" and renders it.\n // However, the keyboards differ pretty heavily right now and it's not\n // clear what that format would look like exactly. Plus, there aren't\n // very many of them. So to keep us moving, we'll just hardcode.\n switch (keypadType) {\n case KeypadTypes.FRACTION:\n return <FractionKeypad {...keypadProps} />;\n\n case KeypadTypes.EXPRESSION:\n return <ExpressionKeypad {...keypadProps} />;\n\n default:\n throw new Error(\"Invalid keypad type: \" + keypadType);\n }\n };\n\n render() {\n const {\n active,\n layoutMode,\n navigationPadEnabled,\n onElementMounted,\n style,\n } = this.props;\n const {hasBeenActivated} = this.state;\n\n // NOTE(charlie): We render the transforms as pure inline styles to\n // avoid an Aphrodite bug in mobile Safari.\n // See: https://github.com/Khan/aphrodite/issues/68.\n const dynamicStyle = {\n ...(active ? inlineStyles.active : inlineStyles.hidden),\n ...(!active && !hasBeenActivated ? inlineStyles.invisible : {}),\n };\n\n const keypadContainerStyle = [\n row,\n centered,\n fullWidth,\n styles.keypadContainer,\n ...(Array.isArray(style) ? style : [style]),\n ];\n\n const keypadStyle = [\n row,\n styles.keypadBorder,\n layoutMode === LayoutModes.FULLSCREEN\n ? styles.fullscreen\n : styles.compact,\n ];\n\n // TODO(charlie): When the keypad is shorter than the width of the\n // screen, add a border on its left and right edges, and round out the\n // corners.\n return (\n <View\n style={keypadContainerStyle}\n dynamicStyle={dynamicStyle}\n extraClassName=\"keypad-container\"\n >\n <View\n style={keypadStyle}\n ref={(element) => {\n if (!this.hasMounted && element) {\n this.hasMounted = true;\n onElementMounted(element);\n }\n }}\n >\n {navigationPadEnabled && (\n <NavigationPad\n roundTopLeft={layoutMode === LayoutModes.COMPACT}\n style={styles.navigationPadContainer}\n />\n )}\n <View style={styles.keypadLayout}>\n {this.renderKeypad()}\n </View>\n </View>\n </View>\n );\n }\n}\n\nconst keypadAnimationDurationMs = 300;\nconst borderWidthPx = 1;\n\nconst styles = StyleSheet.create({\n keypadContainer: {\n bottom: 0,\n left: 0,\n right: 0,\n position: \"fixed\",\n transition: `${keypadAnimationDurationMs}ms ease-out`,\n transitionProperty: \"transform\",\n zIndex: zIndexes.keypad,\n },\n\n keypadBorder: {\n boxShadow: \"0 1px 4px 0 rgba(0, 0, 0, 0.1)\",\n borderColor: \"rgba(0, 0, 0, 0.2)\",\n borderStyle: \"solid\",\n },\n\n fullscreen: {\n borderTopWidth: borderWidthPx,\n },\n\n compact: {\n borderTopRightRadius: compactKeypadBorderRadiusPx,\n borderTopLeftRadius: compactKeypadBorderRadiusPx,\n\n borderTopWidth: borderWidthPx,\n borderRightWidth: borderWidthPx,\n borderLeftWidth: borderWidthPx,\n },\n\n navigationPadContainer: {\n // Add a separator between the navigation pad and the keypad.\n borderRight:\n `${innerBorderWidthPx}px ${innerBorderStyle} ` +\n `${innerBorderColor}`,\n boxSizing: \"content-box\",\n },\n\n // Defer to the navigation pad, such that the navigation pad is always\n // rendered at full-width, and the keypad takes up just the remaining space.\n // TODO(charlie): Avoid shrinking the keys and, instead, make the keypad\n // scrollable.\n keypadLayout: {\n flexGrow: 1,\n // Avoid unitless flex-basis, per: https://philipwalton.com/articles/normalizing-cross-browser-flexbox-bugs/\n flexBasis: \"0%\",\n },\n});\n\n// Note: these don't go through an autoprefixer/aphrodite.\nconst inlineStyles = {\n // If the keypad is yet to have ever been activated, we keep it invisible\n // so as to avoid, e.g., the keypad flashing at the bottom of the page\n // during the initial render.\n invisible: {\n visibility: \"hidden\",\n },\n\n hidden: {\n msTransform: \"translate3d(0, 100%, 0)\",\n WebkitTransform: \"translate3d(0, 100%, 0)\",\n transform: \"translate3d(0, 100%, 0)\",\n },\n\n active: {\n msTransform: \"translate3d(0, 0, 0)\",\n WebkitTransform: \"translate3d(0, 0, 0)\",\n transform: \"translate3d(0, 0, 0)\",\n },\n};\n\nconst mapStateToProps = (state) => {\n return {\n ...state.keypad,\n layoutMode: state.layout.layoutMode,\n navigationPadEnabled: state.layout.navigationPadEnabled,\n };\n};\n\nconst mapDispatchToProps = (dispatch) => {\n return {\n onPageSizeChange: (pageWidthPx, pageHeightPx) => {\n dispatch(setPageSize(pageWidthPx, pageHeightPx));\n },\n };\n};\n\nexport default connect(mapStateToProps, mapDispatchToProps, null, {\n forwardRef: true,\n})(KeypadContainer);\n","/* eslint-disable react/no-unsafe */\n// @flow\nimport * as React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport {Provider} from \"react-redux\";\n\nimport {\n activateKeypad,\n dismissKeypad,\n configureKeypad,\n setCursor,\n setKeyHandler,\n} from \"../actions/index.js\";\nimport {createStore} from \"../store/index.js\";\n\nimport KeypadContainer from \"./keypad-container.js\";\n\ntype Props = {|\n onElementMounted?: ($FlowFixMe) => void,\n|};\n\nclass ProvidedKeypad extends React.Component<Props> {\n mounted: boolean;\n store: $FlowFixMe;\n\n UNSAFE_componentWillMount() {\n this.store = createStore();\n }\n\n componentDidMount() {\n this.mounted = true;\n }\n\n componentWillUnmount() {\n this.mounted = false;\n }\n\n activate: () => void = () => {\n this.store.dispatch(activateKeypad());\n };\n\n dismiss: () => void = () => {\n this.store.dispatch(dismissKeypad());\n };\n\n configure: () => void = (configuration, cb) => {\n this.store.dispatch(configureKeypad(configuration));\n\n // HACK(charlie): In Perseus, triggering a focus causes the keypad to\n // animate into view and re-configure. We'd like to provide the option\n // to re-render the re-configured keypad before animating it into view,\n // to avoid jank in the animation. As such, we support passing a\n // callback into `configureKeypad`. However, implementing this properly\n // would require middleware, etc., so we just hack it on with\n // `setTimeout` for now.\n setTimeout(() => cb && cb());\n };\n\n setCursor: () => void = (cursor) => {\n this.store.dispatch(setCursor(cursor));\n };\n\n setKeyHandler: (keyHandler: $FlowFixMe) => void = (keyHandler) => {\n this.store.dispatch(setKeyHandler(keyHandler));\n };\n\n getDOMNode: () => $Call<typeof ReactDOM.findDOMNode, any> = () => {\n return ReactDOM.findDOMNode(this);\n };\n\n render(): React.Node {\n const {onElementMounted, ...rest} = this.props;\n\n return (\n <Provider store={this.store}>\n <KeypadContainer\n onElementMounted={(element) => {\n // Append the dispatch methods that we want to expose\n // externally to the returned React element.\n const elementWithDispatchMethods = {\n ...element,\n activate: this.activate,\n dismiss: this.dismiss,\n configure: this.configure,\n setCursor: this.setCursor,\n setKeyHandler: this.setKeyHandler,\n getDOMNode: this.getDOMNode,\n };\n onElementMounted &&\n onElementMounted(elementWithDispatchMethods);\n }}\n {...rest}\n />\n </Provider>\n );\n }\n}\n\nexport default ProvidedKeypad;\n"],"names":["Keys","PLUS","MINUS","NEGATIVE","TIMES","DIVIDE","DECIMAL","PERIOD","PERCENT","CDOT","EQUAL","NEQ","GT","LT","GEQ","LEQ","FRAC_INCLUSIVE","FRAC_EXCLUSIVE","FRAC","EXP","EXP_2","EXP_3","SQRT","CUBE_ROOT","RADICAL","LEFT_PAREN","RIGHT_PAREN","LN","LOG","LOG_N","SIN","COS","TAN","PI","THETA","UP","RIGHT","DOWN","LEFT","BACKSPACE","DISMISS","JUMP_OUT_PARENTHESES","JUMP_OUT_EXPONENT","JUMP_OUT_BASE","JUMP_INTO_NUMERATOR","JUMP_OUT_NUMERATOR","JUMP_OUT_DENOMINATOR","NOOP","FRAC_MULTI","MANY","Text","React","Component","render","numberOfLines","style","this","props","className","css","styles","initial","Array","isArray","singleLineStyle","createElement","dynamicStyle","children","StyleSheet","create","color","display","font","margin","padding","textDecorationLine","wordWrap","maxWidth","overflow","textOverflow","whiteSpace","View","extraClassName","concat","onClick","onTouchCancel","onTouchEnd","onTouchMove","onTouchStart","ariaLabel","role","alignItems","borderWidth","borderStyle","boxSizing","flexBasis","flexDirection","position","backgroundColor","textAlign","listStyle","minHeight","minWidth","wonderBlocksBlue","Color","blue","offBlack","offBlack32","offBlack16","offBlack8","decimalSeparator","innerBorderColor","KeypadTypes","FRACTION","EXPRESSION","KeyTypes","EMPTY","VALUE","OPERATOR","INPUT_NAVIGATION","KEYPAD_NAVIGATION","ECHO","DeviceOrientations","DeviceTypes","LayoutModes","FULLSCREEN","COMPACT","BorderDirections","BOTTOM","BorderStyles","ALL","NONE","IconTypes","MATH","SVG","TEXT","DecimalSeparators","EchoAnimationTypes","SLIDE_AND_FADE","FADE_ONLY","LONG_FADE_ONLY","window","icu","getDecimalFormatSymbols","decimal_separator","KeyConfigs","type","i18n","_","icon","data","childKeyIds","num","textRepresentation","letter","lowerCaseVariable","toLowerCase","upperCaseVariable","toUpperCase","key","Object","keys","_objectSpread","id","iconPropType","PropTypes","shape","oneOf","isRequired","string","keyIdPropType","keyConfigPropType","arrayOf","keypadConfigurationPropType","keypadType","extraKeys","keypadElementPropType","activate","func","dismiss","configure","setCursor","setKeyHandler","getDOMNode","bordersPropType","boundingBoxPropType","height","number","width","top","right","bottom","left","echoPropType","animationId","animationType","borders","initialBounds","cursorContextPropType","CursorContexts","popoverPropType","parentId","bounds","oneOfType","node","CursorHandle","x","y","animateIntoPosition","animationStyle","msTransitionDuration","WebkitTransitionDuration","transitionDuration","msTransitionProperty","WebkitTransitionProperty","transitionProperty","transformString","outerStyle","zIndex","msTransform","WebkitTransform","transform","touchAction","fill","cursorHandleDistanceMultiplier","viewBox","colorInterpolationFilters","filterUnits","cursorWidthPx","floodOpacity","result","in","values","dy","stdDeviation","in2","mode","filter","d","stroke","strokeWidth","bool","visible","DragListener","constructor","onDrag","initialEvent","_scrollListener","touchLocationsById","i","changedTouches","length","touch","identifier","clientX","clientY","_moveListener","evt","initialTouchLocation","touchLocation","dx","touchSlopPx","_endAndCancelListener","attach","addEventListener","detach","removeEventListener","WRITE","CMD","KeyActions","str","fn","NormalCommands","ArithmeticOperators","EqualityOperators","Letters","ValidLeaves","map","KeysForJumpContext","IN_PARENS","IN_SUPER_SCRIPT","IN_SUB_SCRIPT","BEFORE_FRACTION","IN_NUMERATOR","IN_DENOMINATOR","MathWrapper","element","callbacks","MQ","MathQuill","getInterface","mathField","MathField","substituteTextarea","document","focus","controller","__controller","cursor","show","blurred","blur","hide","_writeNormalFunction","name","write","keystroke","pressKey","includes","shouldNavigateLeft","L","cmd","_handleExponent","_handleJumpOut","_handleBackspace","_handleLeftArrow","JUMP_OUT","_handleRightArrow","test","selection","onSelectionChanged","context","contextForCursor","setCursorPosition","hitNode","el","elementFromPoint","getCursor","hasAttribute","insAtRightEnd","root","pageX","body","scrollLeft","pageY","scrollTop","seek","$","startSelection","command","_maybeFindCommand","endNode","insLeftOf","onCursorMove","getSelection","getContent","latex","setContent","isEmpty","parent","_handleBackspaceInNthRoot","isAtLeftEnd","isRootEmpty","_isInsideEmptyNode","blocks","ends","_selectNode","insRightOf","visitor","fractionNode","R","_isFraction","siblingDenominator","_isParens","Error","grandparent","leftNode","_isSquareRoot","_isNthRoot","_isNthRootIndex","_handleBackspaceInRootIndex","ctrlSeq","_handleBackspaceOutsideParens","_handleBackspaceInsideParens","_isInsideLogIndex","_handleBackspaceInLogIndex","_handleBackspaceAfterLigaturedSymbol","_maybeFindCommandBeforeParens","startNode","invalidPrefixes","precedingNode","shouldPrefixWithParens","trim","initialNode","commandCharRegex","commandStartRegex","leftParenNode","select","endSelection","jQ","hasClass","_isNumerator","_isDenominator","_isSubScript","_isSuperScript","_isLeaf","reinsertionPoint","text","replace","moveToDirEnd","contentjQ","rightNode","sub","_isAtTopLevel","scrollIntoView","containerNode","keypadNode","containerBounds","getBoundingClientRect","containerBottomPx","containerTopPx","scrollNode","scrollingElement","navigator","userAgent","indexOf","documentElement","keypadTopPx","innerHeight","clientHeight","scrollOffset","Math","min","MathInput","super","arguments","_defineProperty","focused","handle","_keypadBounds","_container","ReactDOM","findDOMNode","_root","querySelector","getInputInnerPadding","paddingTop","paddingRight","paddingBottom","paddingLeft","fontSize","fontSizePt","keypadElement","_cacheKeypadBounds","cursorBounds","cursorWidth","inputInnerPadding","furthestRightCursorBound","furthestLeftCursorBound","cursorBoundsLeft","setState","state","_hideCursorHandle","onBlur","hideCursor","value","onChange","onFocus","setTimeout","_isMounted","maybeKeypadNode","points","elements","point","contains","classList","leafElements","nonLeafElements","max","counts","elementsById","getAttribute","push","count","entries","hasChildNodes","_containerBounds","_findHitNode","firstChildBounds","firstChild","lastChildBounds","lastChild","abs","insAtLeftEnd","e","stopPropagation","_insertCursorAtClosestNode","_updateCursorHandle","preventDefault","friction","relativeX","relativeY","_constrainToBound","distanceAboveFingerToTrySelecting","adjustedY","keyMap","event","mathQuillKey","domKeyToMathQuillKey","paddingInset","totalDesiredPadding","getBorderWidthPx","componentDidMount","_mathContainer","container","unbind","_updateInputPadding","_handleScroll","touchStartInitialScroll","recordTouchStartOutside","target","touchDidStartInOrBelowKeypad","_getKeypadBounds","didTouchOutside","dragListener","didScroll","blurOnTouchEndOutside","removeListeners","_clearKeypadBoundsCache","UNSAFE_componentWillReceiveProps","componentDidUpdate","prevProps","prevState","componentWillUnmount","innerStyle","inlineStyles","innerContainer","borderColor","input","handleTouchStart","handleTouchMove","handleTouchEnd","tabIndex","ref","inputRef","onKeyUp","handleKeyUp","_extends","onCursorHandleTouchStart","onCursorHandleTouchMove","onCursorHandleTouchEnd","onCursorHandleTouchCancel","any","minHeightPx","verticalAlign","offBlack50","borderRadius","defaults","longPressWaitTimeMs","swipeThresholdPx","holdIntervalMs","GestureStateMachine","handlers","options","swipeDisabledNodeIds","multiPressableKeys","touchState","swipeState","_maybeCancelLongPressForTouch","touchId","longPressTimeoutId","clearTimeout","_maybeCancelPressAndHoldForTouch","pressAndHoldIntervalId","clearInterval","_cleanupTouchEvent","_onFocus","activeNodeId","onTrigger","setInterval","onLongPress","_onSwipeStart","activeTouchId","getId","startingNodeId","swipeLocked","startX","swipeEnabled","onSwipeChange","onSwipeEnd","NodeManager","_nodesById","_bordersById","_orderedIds","_cachedBoundingBoxesById","registerDOMNode","domNode","childIds","allIds","orderedIds","seenIds","unregisterDOMNode","idForCoords","layoutPropsForId","DOMRect","PopoverStateMachine","activePopover","popovers","registerPopover","unregisterPopover","isPopoverVisible","onActiveNodesChanged","popover","_isNodeInsidePopover","_defaultNodeForPopover","inPopover","keyId","domNodeId","coordsForEvent","GestureManager","disabledSwipeKeys","trackEvents","nodeManager","popoverStateMachine","activeNodes","rest","_excluded","gestureStateMachine","enableEventTracking","disableEventTracking","CornerDecal","containerStyle","triangleSizePx","opacity","row","column","oneColumn","flexGrow","fullWidth","stretch","centered","justifyContent","centeredText","roundedTopLeft","borderTopLeftRadius","roundedTopRight","borderTopRightRadius","Styles","MathIcon","math","katex","_renderMath","size","base","Cos","fillRule","Log","Equal","strokeLinecap","strokeLinejoin","Sqrt","Exp","Neq","Geq","Ln","Sin","Lt","CubeRoot","Plus","Tan","Arrow","LeftParen","RightParen","Gt","Divide","cx","cy","r","Period","Percent","Times","Exp3","Exp2","Cdot","LogN","Leq","Minus","Radical","FracInclusive","rx","SvgIcon","SvgForName","Iconography","TextIcon","character","fontFamily","unfocusedColor","Icon","PureComponent","styleWithFocus","unfocused","MultiSymbolGrid","icons","forEach","primaryIconStyle","secondaryIconStyle","secondary","middleLeft","middleRight","topLeft","topRight","bottomLeft","bottomRight","marginBottom","marginLeft","marginTop","marginRight","KeypadButton","_getFocusStyle","_getButtonStyle","focusBackgroundStyle","light","bright","focusBox","backgroundStyle","empty","operator","control","leftBorder","bottomBorder","buttonBase","echo","buttonSizeStyle","UNSAFE_componentWillMount","styleForButtonDimensions","heightPx","widthPx","_preInjectStyles","UNSAFE_componentWillUpdate","newProps","newState","childKeys","disabled","popoverEnabled","renderFocused","buttonStyle","focusStyle","iconWrapperStyle","iconWrapper","eventHandlers","maybeFocusBox","maybeCornerDecal","decalInset","manyButtonA11yMarkup","keyConfig","a11yMarkup","flex","userSelect","focusBoxZIndex","borderLeftWidth","borderBottomWidth","buttonSize","KeypadButton$1","connect","layout","buttonDimensions","forwardRef","EmptyKeypadButton","_this$props","gestureManager","instanceOf","EmptyKeypadButton$1","gestures","TouchableKeypadButton","shouldComponentUpdate","styleWithAddons","preventScrolls","TouchableKeypadButton$1","ownProps","_excluded2","useFirstChildProps","extractProps","ManyKeypadButton","Echo","animationDurationMs","onAnimationFinish","pointerEvents","EchoManager","animationTransitionName","echoes","_animationConfigForType","echoesForType","TransitionGroup","CSSTransition","classNames","enter","exit","timeout","MultiSymbolPopover","boxShadow","popoverButton","PopoverContainer","PopoverManager","Keypad","_resizeTimeout","_updateSizeAndPosition","_onResize","_computeContainer","removeEcho","relativeEchoes","relativePopover","active","Keypad$1","keypad","dispatch","IconAsset","_ref","tintColor","xmlns","clipRule","border","hovered","background","white","pressed","outline","innerBox","innerBoxPressed","activeIndicator","TabbarItem","itemType","itemState","Clickable","offBlack64","imageTintColor","tabbar","offWhite","borderTop","borderBottom","Tabbar","selectedItem","items","onSelect","item","index","TwoPageKeypad","selectedPage","leftPage","paginationEnabled","rightPage","borderLeft","currentPage","innerBorderStyle","innerBorderWidthPx","TwoPageKeypad$1","ExpressionKeypad","dismissOrJumpOutKey","cursorContext","dynamicJumpOut","roundTopLeft","roundTopRight","rightPageStyle","NUM_7","NUM_4","NUM_1","NUM_8","NUM_5","NUM_2","NUM_0","NUM_9","NUM_6","NUM_3","leftPageStyle","ExpressionKeypad$1","pager","navigationPadEnabled","FractionKeypad","FractionKeypad$1","VelocityTracker","velocityTimeout","_events","t","now","getVelocity","events","_getEvents","current","first","dt","threshold","recentEvents","keypadForType","createStore","initialInputState","keyHandler","defaultKeypadType","initialKeypadState","getDefaultPage","numPages","initialPagerState","animateToPosition","pageWidthPx","velocityTracker","createGestureManager","store","layoutProps","initialGestureState","_lastAnimationId","initialEchoState","initialLayoutState","gridDimensions","numRows","rows","numColumns","columns","numMaxVisibleRows","maxVisibleRows","pageDimensions","pageHeightPx","layoutMode","layoutParametersForDimensions","deviceOrientation","deviceType","computeLayoutParameters","_ref2","_ref3","_ref4","toolbarEnabled","effectiveNumColumns","isLandscape","maxKeypadHeight","safariNavBarWhenShrunk","safariToolbar","numSeparators","reducer","Redux","combineReducers","action","undefined","keypadReducer","configuration","pagerReducer","nextPage","prevPage","velocity","minFlingVelocity","minFlingDistance","shouldPageRight","shouldPageLeft","remainingEchoes","NavigationPad","navigationKey","topArrow","leftArrow","horizontalSpacer","rightArrow","bottomArrow","borderTopWidth","borderRightWidth","borderBottomRightRadius","borderBottomLeftRadius","KeypadContainer","hasBeenActivated","viewportWidth","innerWidth","onPageSizeChange","keypadProps","_throttleResizeHandler","nextProps","onDismiss","onElementMounted","hidden","invisible","keypadContainerStyle","keypadContainer","keypadStyle","keypadBorder","fullscreen","compact","hasMounted","navigationPadContainer","keypadLayout","renderKeypad","transition","keypadAnimationDurationMs","borderRight","visibility","KeypadContainer$1","setPageSize","ProvidedKeypad","cb","configureKeypad","mounted","_objectWithoutProperties","Provider","elementWithDispatchMethods"],"mappings":"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"}
|