import * as _ from 'lodash';
import ___default from 'lodash';
import times from 'lodash/times';
import React from 'react';
import PropTypes from 'prop-types';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import { withStyles } from '@material-ui/core/styles';
import classNames from 'classnames';
import { fade, lighten } from '@material-ui/core/styles/colorManipulator';
import green from '@material-ui/core/colors/green';
import debug from 'debug';
import MathQuill from '@pie-framework/mathquill';

function _extends() {
  _extends = Object.assign || function (target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];

      for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
    }

    return target;
  };

  return _extends.apply(this, arguments);
}

const set$f = o => _extends({}, o, {
  category: 'comparison'
});

const lessThan = set$f({
  name: 'Less than',
  latex: '<',
  command: '\\lt'
});
const greaterThan = set$f({
  name: 'Greater than',
  latex: '>',
  command: '\\gt'
});
const lessThanEqual = set$f({
  name: 'Less than or equal',
  latex: '\\le',
  symbol: '<=',
  command: '\\le',
  ariaLabel: 'less than or equal to'
});
const greaterThanEqual = set$f({
  name: 'Greater than or equal',
  symbol: '>=',
  command: '\\ge',
  latex: '\\ge'
});

var comparison = /*#__PURE__*/Object.freeze({
  __proto__: null,
  greaterThan: greaterThan,
  greaterThanEqual: greaterThanEqual,
  lessThan: lessThan,
  lessThanEqual: lessThanEqual
});

const mkSet = category => o => _extends({}, o, {
  category
});
const transformToKeySetStructure = (data = []) => {
  const structure = [];

  ___default.times(5, () => {
    structure.push([]);
  });

  let ln = data.length;
  let i = 0;
  let j = 0;

  while (j < ln) {
    structure[i++].push(data[j++]);

    if (i === 5) {
      i = 0;
    }
  }

  return structure;
};

const latexAndNameDontExist = base => k => {
  const flattened = ___default.flatten(base);

  const latexExists = flattened.some(b => b.latex === k.latex);
  const nameExists = flattened.some(b => b.name === k.name);
  return !latexExists && !nameExists;
};

const extendKeySet = (base = [], keySetData = []) => {
  keySetData = keySetData.filter(latexAndNameDontExist(base));
  const final = [];

  ___default.times(5 - base.length, () => {
    base.push([]);
  });

  ___default.times(5, () => {
    final.push([]);
  });

  const extra = transformToKeySetStructure(keySetData);

  for (let i = 0; i < 5; i++) {
    final[i] = [...base[i], ...extra[i]];
  }

  return final;
};

const set$e = mkSet('vars');
const x = set$e({
  name: 'X',
  latex: 'x',
  write: 'x'
});
const y = set$e({
  name: 'Y',
  latex: 'y',
  write: 'y'
});
const theta = set$e({
  name: 'Theta',
  latex: '\\theta',
  write: '\\theta'
});

var vars = /*#__PURE__*/Object.freeze({
  __proto__: null,
  theta: theta,
  x: x,
  y: y
});

const set$d = mkSet('fractions');
const blankOverBlank = set$d({
  name: 'blank/blank',
  latex: '\\frac{}{}',
  command: '\\frac',
  ariaLabel: 'fraction'
});
const xOverBlank = set$d({
  latex: '\\frac{x}{ }',
  name: 'X/blank',
  label: 'x/[]',
  command: '/',
  ariaLabel: 'x over blank fraction'
});
const xBlankBlank = set$d({
  name: 'X (blank/blank)',
  latex: 'x\\frac{}{}',
  label: 'x([]/[])',
  command: '\\frac',
  ariaLabel: 'mixed number'
});

var fractions = /*#__PURE__*/Object.freeze({
  __proto__: null,
  blankOverBlank: blankOverBlank,
  xBlankBlank: xBlankBlank,
  xOverBlank: xOverBlank
});

const set$c = mkSet('exponent');
const squared = set$c({
  name: 'Squared',
  latex: 'x^2',
  write: '^2'
});
const xToPowerOfN = set$c({
  name: 'X to the power of n',
  latex: 'x^{}',
  command: '^',
  ariaLabel: 'exponent'
});
const squareRoot = set$c({
  name: 'Square root',
  latex: '\\sqrt{}',
  command: '\\sqrt'
});
const nthRoot = set$c({
  name: 'Nth root',
  latex: '\\sqrt[{}]{}',
  command: '\\nthroot'
});

var exponent = /*#__PURE__*/Object.freeze({
  __proto__: null,
  nthRoot: nthRoot,
  squareRoot: squareRoot,
  squared: squared,
  xToPowerOfN: xToPowerOfN
});

const set$b = mkSet('misc');
const plusMinus = set$b({
  name: 'Plus or Minus',
  latex: '\\pm',
  write: '\\pm'
});
const absValue = set$b({
  name: 'Absolute Value',
  latex: '\\abs{}',
  symbol: '| |',
  command: '|'
});
const parenthesis = set$b({
  name: 'Parenthesis',
  latex: '\\left(\\right)',
  symbol: '( )',
  command: '('
});
const brackets = set$b({
  name: 'Brackets',
  latex: '\\left[\\right]',
  symbol: '[ ]',
  command: '['
});
const percentage = set$b({
  name: 'Percent',
  latex: '%',
  command: '%'
});
const approx = set$b({
  latex: '\\approx',
  command: '\\approx',
  ariaLabel: 'Approximately equal to'
});
const nApprox = set$b({
  latex: '\\napprox',
  command: '\\napprox',
  ariaLabel: 'Not pproximately equal to'
});
const notEqual = set$b({
  latex: '\\neq',
  command: '\\neq',
  ariaLabel: 'Not equals'
});
const similar = set$b({
  latex: '\\sim',
  command: '\\sim',
  ariaLabel: 'Similar'
});
const notSimilar = set$b({
  latex: '\\nsim',
  command: '\\nsim',
  ariaLabel: 'Not similar'
});

var misc = /*#__PURE__*/Object.freeze({
  __proto__: null,
  absValue: absValue,
  approx: approx,
  brackets: brackets,
  nApprox: nApprox,
  notEqual: notEqual,
  notSimilar: notSimilar,
  parenthesis: parenthesis,
  percentage: percentage,
  plusMinus: plusMinus,
  similar: similar
});

const set$a = mkSet('constants');
const pi = set$a({
  name: 'Pi',
  label: 'π',
  latex: '\\pi',
  command: '\\pi',
  category: 'constants'
});
const eulers = set$a({
  name: 'Eulers',
  label: 'e',
  latex: 'e',
  command: 'e',
  category: 'constants'
});
const infinity = set$a({
  name: 'Infinity',
  label: '\\infty',
  latex: '\\infty',
  command: '\\infty',
  category: 'constants'
});
const halfInfinity = set$a({
  name: 'Half Infinity',
  label: '\\propto',
  latex: '\\propto',
  command: '\\propto',
  category: 'constants'
});

var constants = /*#__PURE__*/Object.freeze({
  __proto__: null,
  eulers: eulers,
  halfInfinity: halfInfinity,
  infinity: infinity,
  pi: pi
});

const set$9 = mkSet('trigonometry');
const sin = set$9({
  name: 'sine',
  label: 'sin',
  command: '\\sin',
  latex: '\\sin'
});
const cos = set$9({
  name: 'cosine',
  label: 'cos',
  command: '\\cos',
  latex: '\\cos'
});
const tan = set$9({
  name: 'tanget',
  label: 'tan',
  command: '\\tan',
  latex: '\\tan'
});
const sec = set$9({
  name: 'secant',
  label: 'sec',
  command: '\\sec',
  latex: '\\sec'
});
const csc = set$9({
  name: 'cosecant',
  label: 'csc',
  command: '\\csc',
  latex: '\\csc'
});
const cot = set$9({
  name: 'cotangent',
  label: 'cot',
  command: '\\cot',
  latex: '\\cot'
});

var trigonometry = /*#__PURE__*/Object.freeze({
  __proto__: null,
  cos: cos,
  cot: cot,
  csc: csc,
  sec: sec,
  sin: sin,
  tan: tan
});

const set$8 = o => _extends({}, o, {
  category: 'geometry'
});

const overline = set$8({
  name: 'Line',
  latex: '\\overline{}',
  command: '\\overline'
});
const overRightArrow = set$8({
  name: 'Ray',
  latex: '\\overrightarrow{}',
  command: '\\overrightarrow'
});
const overLeftRightArrow = set$8({
  name: 'Segment',
  latex: '\\overleftrightarrow{\\overline{}}',
  // used this notation to display the pink box
  symbol: 'AB',
  command: '\\overleftrightarrow'
});
const segment = set$8({
  name: 'Segment',
  latex: '\\overleftrightarrow{AB}',
  write: '\\overleftrightarrow{AB}',
  label: 'AB'
});
const parallel = set$8({
  name: 'Parallel',
  latex: '\\parallel',
  command: '\\parallel'
});
const notParallel = set$8({
  name: 'Not Parallel',
  latex: '\\nparallel',
  command: '\\nparallel'
});
const perpindicular = set$8({
  name: 'Perpendicular',
  latex: '\\perp',
  command: '\\perpendicular'
});
const angle = set$8({
  name: 'Angle',
  latex: '\\angle',
  command: '\\angle'
});
const overArc = set$8({
  name: 'Over arc',
  latex: '\\overarc{\\overline{}}',
  // used this notation to display the pink box
  command: '\\overarc'
});
const measureOfAngle = set$8({
  name: 'Measured Angle',
  latex: '\\measuredangle',
  command: ['m', '\\angle']
});
const triangle = set$8({
  name: 'Triangle',
  latex: '\\triangle',
  command: '\\triangle'
});
const square = set$8({
  name: 'Square',
  latex: '\\square',
  command: '\\square'
});
const parallelogram = set$8({
  name: 'Parallelogram',
  latex: '\\parallelogram',
  command: '\\parallelogram'
});
const circledDot = set$8({
  name: 'Circled Dot',
  latex: '\\odot',
  command: '\\odot'
});
const degree = set$8({
  name: 'Degree',
  latex: '\\degree',
  command: '\\degree'
});
const similarTo = set$8({
  name: 'Similar',
  command: '\\sim',
  latex: '\\sim'
});
const congruentTo = set$8({
  name: 'Congruent To',
  command: '\\cong',
  latex: '\\cong'
});
const notCongruentTo = set$8({
  name: 'Not Congruent To',
  command: '\\ncong',
  latex: '\\ncong'
});
const primeArcminute = set$8({
  name: 'Prime',
  label: 'pam',
  // eslint-disable-next-line
  latex: "'",
  // eslint-disable-next-line
  write: "'"
});
const doublePrimeArcSecond = set$8({
  name: 'Double Prime',
  // eslint-disable-next-line
  latex: "''",
  // eslint-disable-next-line
  write: "''"
});
const leftArrow = set$8({
  name: 'Left Arrow',
  latex: '\\leftarrow',
  command: '\\leftarrow'
});
const rightArrow = set$8({
  name: 'Right Arrow',
  latex: '\\rightarrow',
  command: '\\rightarrow'
});
const leftrightArrow = set$8({
  name: 'Left and Right Arrow',
  latex: '\\leftrightarrow',
  command: '\\leftrightarrow'
});

var geometry = /*#__PURE__*/Object.freeze({
  __proto__: null,
  angle: angle,
  circledDot: circledDot,
  congruentTo: congruentTo,
  degree: degree,
  doublePrimeArcSecond: doublePrimeArcSecond,
  leftArrow: leftArrow,
  leftrightArrow: leftrightArrow,
  measureOfAngle: measureOfAngle,
  notCongruentTo: notCongruentTo,
  notParallel: notParallel,
  overArc: overArc,
  overLeftRightArrow: overLeftRightArrow,
  overRightArrow: overRightArrow,
  overline: overline,
  parallel: parallel,
  parallelogram: parallelogram,
  perpindicular: perpindicular,
  primeArcminute: primeArcminute,
  rightArrow: rightArrow,
  segment: segment,
  similarTo: similarTo,
  square: square,
  triangle: triangle
});

const set$7 = mkSet('operators');
const circleDot = set$7({
  name: 'CircleDot',
  label: '⋅',
  write: '\\cdot',
  ariaLabel: 'Dot multiplier'
});

var operators = /*#__PURE__*/Object.freeze({
  __proto__: null,
  circleDot: circleDot
});

const set$6 = mkSet('log');
const log$3 = set$6({
  name: 'Log',
  label: 'log',
  command: '\\log',
  latex: '\\log'
});
const logSubscript = set$6({
  name: 'log base n',
  label: 'log s',
  latex: '\\log_{}',
  command: ['\\log', '_']
});
const ln = set$6({
  name: 'natural log',
  label: 'ln',
  command: '\\ln',
  latex: '\\ln'
});

var log$4 = /*#__PURE__*/Object.freeze({
  __proto__: null,
  ln: ln,
  log: log$3,
  logSubscript: logSubscript
});

const set$5 = mkSet('sub-sup');
const superscript = set$5({
  name: 'Superscript',
  latex: 'x^{}',
  command: '^'
});
const subscript = set$5({
  name: 'Subscript',
  latex: 'x_{}',
  command: '_'
});

var subSup = /*#__PURE__*/Object.freeze({
  __proto__: null,
  subscript: subscript,
  superscript: superscript
});

const set$4 = mkSet('statistics');
const xBar = set$4({
  name: 'X Bar',
  label: 'x̄',
  latex: '\\overline{x}',
  write: '\\overline{x}'
});
const yBar = set$4({
  name: 'Y Bar',
  latex: '\\overline{y}',
  write: '\\overline{y}'
});
const mu = set$4({
  name: 'mu',
  label: 'mu',
  latex: '\\mu',
  write: '\\mu'
});
const sigma = set$4({
  name: 'Sigma',
  ariaLabel: 'Uppercase Sigma',
  label: '\\Sigma',
  latex: '\\Sigma',
  write: '\\Sigma'
});
const smallSigma = set$4({
  name: 'sigma',
  ariaLabel: 'Lowercase Sigma',
  label: '\\sigma',
  latex: '\\sigma',
  write: '\\sigma'
});

var statistics = /*#__PURE__*/Object.freeze({
  __proto__: null,
  mu: mu,
  sigma: sigma,
  smallSigma: smallSigma,
  xBar: xBar,
  yBar: yBar
});

const DELETE = '\u232B';
const LEFT_ARROW = '◀';
const RIGHT_ARROW = '▶';
const DIVIDE = '\u00F7';
const MULTIPLY = '\u00D7';

const set$3 = mkSet('operators');
const equals = set$3({
  write: '=',
  label: '='
});
const plus = set$3({
  write: '+',
  label: '+'
});
const minus = set$3({
  write: '−',
  label: '−'
});
const divide = set$3({
  name: 'divide',
  label: DIVIDE,
  command: '\\divide',
  otherNotation: '\\div'
});
const multiply = set$3({
  name: 'multiply',
  label: MULTIPLY,
  command: '\\times'
});

var basicOperators = /*#__PURE__*/Object.freeze({
  __proto__: null,
  divide: divide,
  equals: equals,
  minus: minus,
  multiply: multiply,
  plus: plus
});

const set$2 = mkSet('matrices');
const singleCellMatrix = set$2({
  name: 'Single Cell Matrix',
  label: '[ ]',
  write: '\\begin{pmatrix}\\end{pmatrix}'
});
const doubleCellMatrix = set$2({
  name: 'Double Cell Matrix',
  label: '[ ] [ ] \\\\newline [ ] [ ]',
  write: '\\begin{bmatrix}&\\\\&\\end{bmatrix}'
});

var matrices = /*#__PURE__*/Object.freeze({
  __proto__: null,
  doubleCellMatrix: doubleCellMatrix,
  singleCellMatrix: singleCellMatrix
});

const digitMap = {
  0: 'zero',
  1: 'one',
  2: 'two',
  3: 'three',
  4: 'four',
  5: 'five',
  6: 'six',
  7: 'seven',
  8: 'eight',
  9: 'nine'
};
const comma$1 = {
  name: 'comma',
  label: ',',
  write: ',',
  category: 'digit'
};
const decimalPoint$1 = {
  name: 'decimal-point',
  label: '.',
  write: '.',
  category: 'digit'
};
var digits = times(10, String).map(n => {
  return {
    name: digitMap[n],
    write: n,
    label: n,
    category: 'digit'
  };
}).reduce((acc, o) => {
  acc[o.name] = o;
  return acc;
}, {
  comma: comma$1,
  decimalPoint: decimalPoint$1
});

const set$1 = mkSet('logic');
const therefore = set$1({
  name: 'Therefore',
  label: '∴',
  write: '∴'
});
const longDivision = set$1({
  name: 'Long division',
  latex: '\\longdiv{}',
  command: '\\longdiv'
});

const set = mkSet('navigation');
const left = set({
  label: LEFT_ARROW,
  keystroke: 'Left',
  ariaLabel: 'Move cursor left'
});
const right = set({
  label: RIGHT_ARROW,
  keystroke: 'Right',
  ariaLabel: 'Move cursor right'
});

const del = {
  label: DELETE,
  category: 'edit',
  keystroke: 'Backspace',
  ariaLabel: 'Delete'
};

const hs = [[blankOverBlank, percentage, x, squared, squareRoot], [circleDot, y, subscript, xToPowerOfN, nthRoot], [plusMinus, lessThan, greaterThan, lessThanEqual, greaterThanEqual], [pi, theta, parenthesis, brackets, absValue], [notEqual, sin, cos, tan, degree]];

const advancedAlgebra = (() => {
  const out = [...hs.map(arr => [...arr])];
  out[0].push({
    name: 'i',
    latex: 'i',
    write: 'i'
  });
  out[1].push(log$3);
  out[2].push(logSubscript);
  out[3].push(ln);
  out[4].push(eulers);
  return out;
})();

const statisticsSet = (() => {
  const out = [...hs.map(arr => [...arr])];
  out[0].push(mu);
  out[1].push(xBar);
  out[2].push(yBar);
  out[3].push(sigma);
  out[4].push(smallSigma);
  return out;
})();

const gradeSets = [{
  predicate: n => n >= 3 && n <= 5,
  set: [[lessThan, greaterThan], [xOverBlank, xBlankBlank], [x, longDivision], [squared, xToPowerOfN]]
}, {
  predicate: n => n >= 6 && n <= 7,
  set: [[degree, lessThan, greaterThan], [circleDot, lessThanEqual, greaterThanEqual], [x, y, squared, xToPowerOfN], [plusMinus, xOverBlank, xBlankBlank, squareRoot], [pi, parenthesis, absValue, nthRoot]]
}, {
  predicate: n => n >= 8 || n === 'HS',
  set: hs
}, {
  predicate: 'non-negative-integers',
  set: [[digits.seven, digits.eight, digits.nine], [digits.four, digits.five, digits.six], [digits.one, digits.two, digits.three], [digits.zero, {
    name: '',
    latex: '',
    write: ''
  }, {
    name: '',
    latex: '',
    write: ''
  }], [left, right, del]]
}, {
  predicate: 'integers',
  set: [[digits.seven, digits.eight, digits.nine], [digits.four, digits.five, digits.six], [digits.one, digits.two, digits.three], [digits.zero, {
    name: '',
    latex: '',
    write: ''
  }, minus], [left, right, del]]
}, {
  predicate: 'decimals',
  set: [[digits.seven, digits.eight, digits.nine], [digits.four, digits.five, digits.six], [digits.one, digits.two, digits.three], [digits.zero, digits.decimalPoint, minus], [left, right, del]]
}, {
  predicate: 'fractions',
  set: [[digits.seven, digits.eight, digits.nine], [digits.four, digits.five, digits.six], [digits.one, digits.two, digits.three], [digits.zero, blankOverBlank, minus], [left, right, del]]
}, {
  predicate: 'geometry',
  set: [[blankOverBlank, degree, primeArcminute, doublePrimeArcSecond, congruentTo, similarTo], [circleDot, angle, measureOfAngle, triangle, notCongruentTo, notSimilar], [sin, cos, tan, pi, squareRoot, nthRoot], [csc, sec, cot, theta, subscript, xToPowerOfN], [overline, overRightArrow, overLeftRightArrow, overArc, perpindicular, parallel]]
}, // {
//   predicate: 'miscellaneous',
//   set: [
//     [
//       subSup.superscript,
//       subSup.subscript,
//       fractions.blankOverBlank,
//       misc.percentage,
//       geometry.segment,
//       geometry.parallel
//     ],
//     [
//       exponent.squareRoot,
//       exponent.nthRoot,
//       misc.absValue,
//       misc.parenthesis,
//       geometry.perpindicular,
//       geometry.angle
//     ],
//     [
//       comparison.lessThan,
//       comparison.greaterThan,
//       geometry.degree,
//       misc.approx,
//       geometry.measureOfAngle,
//       geometry.triangle
//     ],
//     [
//       misc.nApprox,
//       misc.notEqual,
//       geometry.congruentTo,
//       geometry.notCongruentTo,
//       geometry.parallelogram,
//       geometry.circledDot
//     ],
//     [
//       misc.similar,
//       misc.notSimilar,
//       comparison.lessThanEqual,
//       comparison.greaterThanEqual,
//       vars.x,
//       vars.y
//     ]
//   ]
// },
// {
//   predicate: 'everything',
//   set: [
//     [
//       subSup.superscript,
//       subSup.subscript,
//       fractions.blankOverBlank,
//       misc.percentage,
//       geometry.segment,
//       geometry.parallel
//     ],
//     [
//       exponent.squareRoot,
//       exponent.nthRoot,
//       misc.absValue,
//       misc.parenthesis,
//       geometry.perpindicular,
//       geometry.angle
//     ],
//     [
//       comparison.lessThan,
//       comparison.greaterThan,
//       geometry.degree,
//       misc.approx,
//       geometry.measureOfAngle,
//       geometry.triangle
//     ],
//     [
//       misc.nApprox,
//       misc.notEqual,
//       geometry.congruentTo,
//       geometry.notCongruentTo,
//       geometry.parallelogram,
//       geometry.circledDot
//     ],
//     [
//       misc.similar,
//       misc.notSimilar,
//       comparison.lessThanEqual,
//       comparison.greaterThanEqual,
//       vars.x,
//       vars.y
//     ]
//   ]
// },
{
  predicate: 'advanced-algebra',
  set: advancedAlgebra
}, {
  predicate: 'statistics',
  set: statisticsSet
}, {
  predicate: 'item-authoring',
  set: [[divide, blankOverBlank, longDivision, halfInfinity, squared, squareRoot, overline, overRightArrow, overLeftRightArrow, log$3], [multiply, circleDot, {
    name: '',
    latex: '',
    write: ''
  }, subscript, xToPowerOfN, nthRoot, perpindicular, parallel, overArc, logSubscript], [plusMinus, pi, theta, degree, angle, leftArrow, rightArrow, triangle, square, ln], [notEqual, absValue, smallSigma, mu, therefore, sigma, leftrightArrow, sin, cos, tan], [lessThanEqual, greaterThanEqual, {
    name: '',
    latex: '',
    write: ''
  }, {
    name: '',
    latex: '',
    write: ''
  }, infinity, {
    name: '',
    latex: '',
    write: ''
  }, {
    name: '',
    latex: '',
    write: ''
  }, csc, sec, cot]]
}, // for grade 1-2, we want to display the base set only
// we need it here because we don't want to display the default set (grade 8)
{
  predicate: n => n >= 1 && n <= 2,
  set: []
}];
const keysForGrade = n => {
  const number = parseInt(n, 10);
  n = isNaN(number) ? n : number;

  if (!n) {
    return [];
  }

  const match = gradeSets.find(gs => {
    if (typeof gs.predicate === 'string') {
      return gs.predicate === n;
    } else {
      return gs.predicate(n);
    }
  });

  if (match) {
    return match.set || [];
  } // if the grade is not found, return the default set which is grade 8 (as per PD-3549), for mode language it is not the default


  if (n !== 'language') {
    return gradeSets[2].set;
  }
};
const ALL_KEYS = [...Object.values(basicOperators), ...Object.values(comparison), ...Object.values(constants), ...Object.values(digits), ...Object.values(exponent), ...Object.values(fractions), ...Object.values(geometry), ...Object.values(log$4), ...Object.values(matrices), ...Object.values(misc), ...Object.values(operators), ...Object.values(statistics), ...Object.values(subSup), ...Object.values(trigonometry), ...Object.values(vars)];
const normalizeAdditionalKeys = additionalKeys => {
  return (additionalKeys || []).map(additionalkey => {
    const {
      latex
    } = additionalkey;
    const predefinedKey = (ALL_KEYS || []).find(key => latex === key.latex || latex === key.write || latex === key.command || latex === key.otherNotation);
    return !latex ? additionalkey : predefinedKey || additionalkey;
  });
};

// increase the font of parallel notation
const updateSpans = () => {
  const spans = Array.from(document.querySelectorAll('span[mathquill-command-id]'));
  (spans || []).forEach(span => {
    if (span && span.innerText === '∥' && span.className !== 'mq-editable-field') {
      span.style.fontSize = '32px';
    }

    if ((span.innerText === '′' || span.innerText === '′′') && !span.hasAttribute('data-prime')) {
      span.setAttribute('data-prime', 'true');
    }
  });
};

const {
  one,
  two,
  three,
  four,
  five,
  six,
  seven,
  eight,
  nine,
  zero,
  comma,
  decimalPoint
} = digits;
const baseSet = [[seven, eight, nine, divide], [four, five, six, multiply], [one, two, three, minus], [zero, decimalPoint, comma, plus], [left, right, del, equals]];

var index$1 = /*#__PURE__*/Object.freeze({
  __proto__: null,
  baseSet: baseSet,
  comparison: comparison,
  exponent: exponent,
  fractions: fractions,
  misc: misc
});

const registerLineBreak = function registerLineBreak(MQ) {
  MQ.registerEmbed('newLine', () => {
    return {
      htmlString: '<div class="newLine"></div>',
      text: () => 'testText',
      latex: () => '\\embed{newLine}[]'
    };
  });
};

let MQ$1;

if (typeof window !== 'undefined') {
  MQ$1 = MathQuill.getInterface(2);

  if (MQ$1 && MQ$1.registerEmbed) {
    registerLineBreak(MQ$1);
  }
}

const log$2 = debug('math-input:mq:input');
/**
 * Wrapper for MathQuill MQ.MathField.
 */

class Input extends React.Component {
  constructor(...args) {
    super(...args);

    this.onInputEdit = () => {
      log$2('[onInputEdit] ...');
      const {
        onChange
      } = this.props;

      if (!this.mathField) {
        return;
      }

      if (onChange) {
        onChange(this.mathField.latex());
      }
    };

    this.refresh = () => {
      this.blur();
      this.focus();
    };

    this.onKeyPress = event => {
      const keys = Object.keys(this.mathField.__controller.options);

      if (keys.indexOf('ignoreNextMousedown') < 0) {
        // It seems like the controller has the above handler as an option
        // when all the right events are set and everything works fine
        // this seems to work in all cases
        this.refresh();
      }

      if (event.charCode === 13) {
        event.preventDefault();
        return;
      }
    };

    this.onClick = event => {
      const {
        onClick
      } = this.props;
      this.refresh();
      onClick && onClick(event);
    };
  }

  componentDidMount() {
    if (!MQ$1) {
      throw new Error('MQ is not defined - but component has mounted?');
    }

    this.mathField = MQ$1.MathField(this.input, {
      handlers: {
        edit: this.onInputEdit.bind(this)
      }
    });
    this.updateLatex();
  }

  componentDidUpdate() {
    this.updateLatex();
  }

  updateLatex() {
    if (!this.mathField) {
      return;
    }

    const {
      latex
    } = this.props;

    if (latex !== undefined && latex !== null) {
      this.mathField.latex(latex);
    }
  }

  clear() {
    this.mathField.latex('');
    return '';
  }

  blur() {
    log$2('blur mathfield');
    this.mathField.blur();
  }

  focus() {
    log$2('focus mathfield...');
    this.mathField.focus();
  }

  command(v) {
    log$2('command: ', v);

    if (Array.isArray(v)) {
      v.forEach(vv => {
        this.mathField.cmd(vv);
      });
    } else {
      this.mathField.cmd(v);
    }

    this.mathField.focus();
    return this.mathField.latex();
  }

  keystroke(v) {
    this.mathField.keystroke(v);
    this.mathField.focus();
    return this.mathField.latex();
  }

  write(v) {
    log$2('write: ', v);
    this.mathField.write(v);
    this.mathField.focus();
    return this.mathField.latex();
  }

  shouldComponentUpdate(nextProps) {
    log$2('next: ', nextProps.latex);
    log$2('current: ', this.mathField.latex());
    return nextProps.latex !== this.mathField.latex();
  }

  render() {
    const {
      onFocus,
      onBlur,
      classes,
      className
    } = this.props;
    return /*#__PURE__*/React.createElement("span", {
      className: classNames(classes.input, className),
      onKeyDown: this.onKeyPress,
      onClick: this.onClick,
      onFocus: onFocus,
      onBlur: onBlur,
      ref: r => this.input = r
    });
  }

}
Input.propTypes = {
  className: PropTypes.string,
  classes: PropTypes.object.isRequired,
  onClick: PropTypes.func,
  onChange: PropTypes.func,
  latex: PropTypes.string,
  onFocus: PropTypes.func,
  onBlur: PropTypes.func
};

const styles$1 = () => ({});

var input = withStyles(styles$1)(Input);

let MQ;

if (typeof window !== 'undefined') {
  MQ = MathQuill.getInterface(2);
}

const log$1 = debug('pie-lib:math-input:mq:static');
const REGEX = /\\MathQuillMathField\[r\d*\]\{(.*?)\}/g;
const WHITESPACE_REGEX = / /g;

function stripSpaces(string = '') {
  return string.replace(WHITESPACE_REGEX, '');
}

function countBraces(latex) {
  let count = 0;

  for (let i = 0; i < (latex || '').length; i++) {
    if (latex[i] === '{') {
      count++;
    }
  }

  return count;
}
/**
 * Wrapper for MathQuill MQ.MathField.
 */


class Static extends React.Component {
  constructor(props) {
    super(props);

    this.createLiveRegion = () => {
      this.liveRegion = document.createElement('div');
      this.liveRegion.style.position = 'absolute';
      this.liveRegion.style.width = '1px';
      this.liveRegion.style.height = '1px';
      this.liveRegion.style.marginTop = '-1px';
      this.liveRegion.style.clip = 'rect(1px, 1px, 1px, 1px)';
      this.liveRegion.style.overflow = 'hidden';
      this.liveRegion.setAttribute('aria-live', 'polite');
      this.liveRegion.setAttribute('aria-atomic', 'true');
      document.body.appendChild(this.liveRegion);
    };

    this.addEventListeners = () => {
      const input = this.inputRef.current;

      if (input) {
        input.addEventListener('keydown', this.handleKeyDown);
        input.addEventListener('click', this.handleMathKeyboardClick);
      }
    };

    this.removeEventListeners = () => {
      const input = this.inputRef.current;

      if (input) {
        input.removeEventListener('keydown', this.handleKeyDown);
        input.removeEventListener('click', this.handleMathKeyboardClick);
      }
    };

    this.removeLiveRegion = () => {
      if (this.liveRegion) {
        document.body.removeChild(this.liveRegion);
        this.liveRegion = null;
      }
    };

    this.handleKeyDown = event => {
      if ((event == null ? void 0 : event.key) === 'Backspace' || (event == null ? void 0 : event.key) === 'Delete') {
        this.setState({
          isDeleteKeyPressed: true
        });
      }

      this.setState({
        inputSource: 'keyboard'
      });
    };

    this.handleMathKeyboardClick = () => {
      this.setState({
        inputSource: 'mathKeyboard'
      });
    };

    this.onInputEdit = field => {
      if (!this.mathField) {
        return;
      }

      const name = this.props.getFieldName(field, this.mathField.innerFields);

      if (this.props.onSubFieldChange) {
        var _this$inputRef;

        // eslint-disable-next-line no-useless-escape
        const regexMatch = field.latex().match(/[0-9]\\ \\frac\{[^\{]*\}\{ \}/);

        if ((_this$inputRef = this.inputRef) != null && _this$inputRef.current && regexMatch && regexMatch != null && regexMatch.length) {
          try {
            field.__controller.cursor.insLeftOf(field.__controller.cursor.parent[-1].parent);

            field.el().dispatchEvent(new KeyboardEvent('keydown', {
              keyCode: 8
            }));
          } catch (e) {
            // eslint-disable-next-line no-console
            console.error(e.toString());
          }
        } else {
          this.props.onSubFieldChange(name, field.latex());
        }
      }

      this.announceLatexConversion(field.latex());
    };

    this.announceLatexConversion = newLatex => {
      if (!this.state) {
        console.error('State is not initialized');
        return;
      }

      const {
        previousLatex,
        inputSource,
        isDeleteKeyPressed
      } = this.state;
      const announcement = 'Converted to math symbol';

      if (inputSource === 'keyboard' && !isDeleteKeyPressed) {
        const newBraces = countBraces(newLatex);
        const oldBraces = countBraces(previousLatex);

        if (newBraces > oldBraces) {
          this.announceMessage(announcement);
        } else {
          try {
            this.mathField.parseLatex(previousLatex);
            this.mathField.parseLatex(newLatex);

            if (newLatex == previousLatex) {
              this.announceMessage(announcement);
            }
          } catch (e) {
            console.warn('Error parsing latex:', e.message);
            console.warn(e);
          }
        }
      }

      this.setState({
        previousLatex: newLatex,
        isDeleteKeyPressed: false
      });
    };

    this.announceMessage = message => {
      this.setState({
        previousLatex: ''
      });

      if (this.liveRegion) {
        this.liveRegion.textContent = message; // Clear the message after it is announced

        setTimeout(() => {
          this.liveRegion.textContent = '';
        }, 500);
      }
    };

    this.update = () => {
      if (!MQ) {
        throw new Error('MQ is not defined - but component has mounted?');
      }

      if (!this.mathField) {
        var _this$inputRef2;

        this.mathField = MQ.StaticMath((_this$inputRef2 = this.inputRef) == null ? void 0 : _this$inputRef2.current, {
          handlers: {
            edit: this.onInputEdit.bind(this)
          }
        });
      }

      try {
        this.mathField.parseLatex(this.props.latex);
        this.mathField.latex(this.props.latex);
      } catch (e) {
        // default latex if received has errors
        this.mathField.latex('\\MathQuillMathField[r1]{}');
      }
    };

    this.blur = () => {
      log$1('blur mathfield');
      this.mathField.blur();
    };

    this.focus = () => {
      log$1('focus mathfield...');
      this.mathField.focus();
    };

    this.onFocus = e => {
      try {
        let rootBlock = e.target.parentElement.nextSibling;
        let id = parseInt(rootBlock.getAttribute('mathquill-block-id'), 10);

        if (!id) {
          rootBlock = rootBlock.parentElement;
          id = parseInt(rootBlock.getAttribute('mathquill-block-id'), 10);
        }

        const innerField = this.mathField.innerFields.find(f => f.id === id);

        if (innerField) {
          const name = this.props.getFieldName(innerField, this.mathField.innerFields);

          if (this.props.setInput) {
            this.props.setInput(innerField);
          }

          this.props.onSubFieldFocus(name, innerField);
        }
      } catch (err) {
        // eslint-disable-next-line no-console
        console.error('error finding root block', err.message);
      }
    };

    this.state = {
      announcement: '',
      previousLatex: '',
      inputSource: null,
      isDeleteKeyPressed: false
    };
    this.inputRef = /*#__PURE__*/React.createRef();
  }

  componentDidMount() {
    this.update();
    updateSpans();
    this.createLiveRegion();
    this.addEventListeners();
  }

  componentDidUpdate() {
    this.update();
    updateSpans();
  }

  componentWillUnmount() {
    this.removeLiveRegion();
    this.removeEventListeners();
  }

  shouldComponentUpdate(nextProps) {
    try {
      const parsedLatex = this.mathField.parseLatex(nextProps.latex);
      const stripped = stripSpaces(parsedLatex);
      const newFieldCount = (nextProps.latex.match(REGEX) || []).length;
      const out = stripped !== stripSpaces(this.mathField.latex().trim()) || newFieldCount !== Object.keys(this.mathField.innerFields).length / 2;
      log$1('[shouldComponentUpdate] ', out);
      return out;
    } catch (e) {
      // eslint-disable-next-line no-console
      console.warn('Error parsing latex:', e.message, 'skip update'); // eslint-disable-next-line no-console

      console.warn(e);
      return false;
    }
  }

  render() {
    const {
      onBlur,
      className
    } = this.props;
    return /*#__PURE__*/React.createElement("span", {
      className: className,
      onFocus: this.onFocus,
      onBlur: onBlur,
      ref: this.inputRef
    });
  }

}
Static.propTypes = {
  latex: PropTypes.string.isRequired,
  onFocus: PropTypes.func,
  onBlur: PropTypes.func,
  className: PropTypes.string,
  getFieldName: PropTypes.func,
  onSubFieldChange: PropTypes.func,
  onSubFieldFocus: PropTypes.func,
  setInput: PropTypes.func
};
Static.defaultProps = {
  getFieldName: () => {}
};

const commonMqFontStyles = {
  fontFamily: 'MJXZERO, MJXTEX !important',
  '-webkit-font-smoothing': 'antialiased !important',
  '& .mq-math-mode > span > var': {
    fontFamily: 'MJXZERO, MJXTEX-I !important'
  },
  '& .mq-math-mode span var': {
    fontFamily: 'MJXZERO, MJXTEX-I !important'
  },
  '& .mq-math-mode .mq-nonSymbola': {
    fontFamily: 'MJXZERO, MJXTEX-I !important'
  },
  '& .mq-math-mode > span > var.mq-operator-name': {
    fontFamily: 'MJXZERO, MJXTEX !important'
  }
};
const longdivStyles = {
  '& .mq-longdiv-inner': {
    marginTop: '-1px',
    marginLeft: '5px !important;',
    '& > .mq-empty': {
      padding: '0 !important',
      marginLeft: '0px !important',
      marginTop: '2px'
    }
  },
  '& .mq-math-mode .mq-longdiv': {
    display: 'inline-flex !important'
  }
};
const supsubStyles = {
  '& .mq-math-mode sup.mq-nthroot': {
    fontSize: '70% !important',
    verticalAlign: '0.5em !important',
    paddingRight: '0.15em'
  },
  '& .mq-math-mode .mq-supsub': {
    fontSize: '70.7% !important'
  },
  '& .mq-supsub ': {
    fontSize: '70.7%'
  },
  '& .mq-math-mode .mq-supsub.mq-sup-only': {
    verticalAlign: '-0.1em !important',
    '& .mq-sup': {
      marginBottom: '0px !important'
    }
  },

  /* But when the base is a fraction, move it higher */
  '& .mq-math-mode .mq-fraction + .mq-supsub.mq-sup-only': {
    verticalAlign: '0.4em !important'
  },
  '& .mq-math-mode .mq-supsub.mq-sup-only.mq-after-fraction-group': {
    verticalAlign: '0.4em !important'
  }
};
const commonMqKeyboardStyles = {
  '& *': _extends({}, commonMqFontStyles, longdivStyles, {
    '& .mq-math-mode .mq-sqrt-prefix': {
      top: '0 !important'
    },
    '& .mq-math-mode .mq-empty': {
      padding: '9px 1px !important'
    },
    '& .mq-math-mode .mq-supsub': {
      fontSize: '70.7% !important'
    },
    '& .mq-math-mode .mq-sqrt-stem': {
      marginTop: '-5px',
      paddingTop: '4px'
    },
    '& .mq-math-mode .mq-paren': {
      verticalAlign: 'middle !important'
    },
    '& .mq-math-mode .mq-overarrow .mq-overarrow-inner .mq-empty': {
      padding: '0 !important'
    },
    '& .mq-math-mode .mq-overline .mq-overline-inner .mq-empty ': {
      padding: '0 !important'
    }
  })
};
var commonMqStyles = {
  commonMqFontStyles,
  longdivStyles,
  supsubStyles,
  commonMqKeyboardStyles
};

var index = /*#__PURE__*/Object.freeze({
  __proto__: null,
  CommonMqStyles: commonMqStyles,
  Input: input,
  Static: Static
});

const MAIN_CONTAINER_CLASS = 'main-container';
var editableHtmlConstants = {
  MAIN_CONTAINER_CLASS};

/**
 * Sort additional keys.
 *
 * Expects an array of rows.
 * @param {} keys
 */

const sortKeys = keys => {
  // add any missing rows
  _.times(5 - keys.length, () => {
    keys.push([]);
  });

  const out = _.zip.apply(null, keys);

  return out;
};

const log = debug('pie-lib:math-inline:keypad');
const LatexButton = withStyles(theme => ({
  root: {
    textTransform: 'none',
    padding: 0,
    margin: 0,
    fontSize: '110% !important'
  },
  latexButton: {
    pointerEvents: 'none',
    textTransform: 'none !important',
    '& .mq-scaled.mq-sqrt-prefix': {
      transform: 'scale(1, 0.9) !important'
    },
    '& .mq-sup-only .mq-sup': {
      marginBottom: '0.9px !important'
    },
    '& .mq-empty': {
      backgroundColor: `${fade(theme.palette.secondary.main, 0.4)} !important`
    },
    '& .mq-overline .mq-overline-inner': {
      borderTop: '2px solid black'
    },
    '& .mq-non-leaf.mq-overline': {
      borderTop: 'none !important' // fixing PD-4873 - in OT, it has border-top 1px and adds extra line

    },
    '& .mq-overarrow': {
      width: '30px',
      marginTop: '0 !important',
      borderTop: '2px solid black',
      fontFamily: 'Roboto, Helvetica, Arial, sans-serif !important',
      '&.mq-arrow-both': {
        top: '0px !important',
        '& *': {
          lineHeight: '1 !important',
          borderTop: 'none !important' // fixing PD-4873 - in OT, it has border-top 1px and adds extra line,

        },
        '&:before': {
          fontSize: '80%',
          left: 'calc(-13%) !important',
          top: '-0.31em !important'
        },
        '&:after': {
          fontSize: '80% !important',
          right: 'calc(-13%) !important',
          top: '-1.5em'
        },
        '&.mq-empty:before': {
          fontSize: '80%',
          left: 'calc(-13%)',
          top: '-0.26em'
        },
        '&.mq-empty:after': {
          fontSize: '80%',
          right: 'calc(-13%)',
          top: '-0.26em'
        },
        '&.mq-empty': {
          minHeight: '1.4em'
        }
      },
      '&.mq-arrow-right:before': {
        fontSize: '80%',
        right: 'calc(-13%) !important',
        top: '-0.26em !important'
      },
      '& .mq-overarrow-inner': {
        border: 'none !important'
      },
      '& .mq-overarrow-inner .mq-overarrow-inner-right': {
        display: 'none !important'
      }
    },
    '& .mq-root-block': {
      padding: '5px !important'
    },
    '& .mq-overarrow.mq-arrow-both.mq-empty:after': {
      right: '-6px',
      fontSize: '80% !important',
      top: '-3px'
    },
    '& .mq-overarrow.mq-arrow-right.mq-empty:before': {
      right: '-5px',
      fontSize: '80% !important',
      top: '-3px'
    },
    '& .mq-overarrow.mq-arrow-both.mq-empty:before': {
      left: '-6px',
      fontSize: '80% !important',
      top: '-3px'
    },
    '& .mq-longdiv-inner': {
      borderTop: '1px solid !important',
      paddingTop: '1.5px !important'
    },
    '& .mq-parallelogram': {
      lineHeight: 0.85
    },
    '& .mq-overarc': {
      borderTop: '2px solid black !important',
      '& .mq-overline': {
        borderTop: 'none !important' // fixing PD-4873 - in OT, it has border-top 1px and adds extra line

      },
      '& .mq-overline-inner': {
        borderTop: 'none !important',
        paddingTop: '0 !important'
      }
    }
  },
  parallelButton: {
    fontStyle: 'italic !important'
  },
  leftRightArrowButton: {
    '& .mq-overarrow.mq-arrow-both': {
      '& .mq-overline-inner': {
        borderTop: 'none !important',
        paddingTop: '0 !important'
      },
      '&:after': {
        position: 'absolute !important',
        top: '0px !important'
      }
    }
  }
}))(props => {
  let buttonClass;

  if (props.latex === '\\parallel') {
    buttonClass = classNames(props.classes.latexButton, props.mqClassName, props.classes.parallelButton);
  } else if (props.latex === '\\overleftrightarrow{\\overline{}}') {
    buttonClass = classNames(props.classes.latexButton, props.mqClassName, props.classes.leftRightArrowButton);
  } else {
    buttonClass = classNames(props.classes.latexButton, props.mqClassName);
  }

  try {
    const MQ = MathQuill.getInterface(2);
    const span = document.createElement('span');
    span.innerHTML = '';
    const mathField = MQ.StaticMath(span);
    mathField.parseLatex(props.latex);
    mathField.latex(props.latex);
  } catch (e) {
    // received latex has errors - do not create button
    return /*#__PURE__*/React.createElement(React.Fragment, null);
  }

  return /*#__PURE__*/React.createElement(Button, {
    className: classNames(props.classes.root, props.className),
    onClick: props.onClick,
    "aria-label": props.ariaLabel
  }, /*#__PURE__*/React.createElement(Static, {
    className: buttonClass,
    latex: props.latex
  }));
});

const createCustomLayout = layoutObj => {
  if (layoutObj) {
    return {
      gridTemplateColumns: `repeat(${layoutObj.columns}, minmax(min-content, 150px))`,
      gridTemplateRows: `repeat(${layoutObj.rows}, minmax(40px, 60px))`,
      gridAutoFlow: 'initial'
    };
  }

  return {};
};

class KeyPad extends React.Component {
  constructor(props) {
    super(props);

    this.handleKeypadInteraction = () => {
      // Check if the setKeypadInteraction prop is available, which is used for both
      // the language keypad and the special characters keypad
      if (this.props.setKeypadInteraction) {
        this.props.setKeypadInteraction(true);
      }
    };

    this.buttonClick = key => {
      log('[buttonClick]', key);
      const {
        onPress
      } = this.props;
      onPress(key);
    };

    this.flowKeys = (base, extras) => {
      const transposed = [...sortKeys(base), ...sortKeys(extras)];
      return ___default.flatten(transposed);
    };

    this.keyIsNotAllowed = key => {
      const {
        noDecimal
      } = this.props;

      if ((key.write === '.' && key.label === '.' || key.write === ',' && key.label === ',') && noDecimal) {
        return true;
      }

      return false;
    };

    this.keypadRef = /*#__PURE__*/React.createRef();
  }

  componentDidMount() {
    var _this$keypadRef;

    const keyPadElement = (_this$keypadRef = this.keypadRef) == null ? void 0 : _this$keypadRef.current;
    const mainContainer = keyPadElement == null ? void 0 : keyPadElement.closest(`.${editableHtmlConstants.MAIN_CONTAINER_CLASS}`);
    const currentToolbar = keyPadElement == null ? void 0 : keyPadElement.closest('.pie-toolbar'); // need only for math keyboard so we need also controlledKeypadMode

    if (this.props.controlledKeypadMode && mainContainer && currentToolbar) {
      const mainContainerPosition = mainContainer.getBoundingClientRect();
      const currentToolbarPosition = currentToolbar.getBoundingClientRect();
      const difference = mainContainerPosition.top + mainContainerPosition.height - (currentToolbarPosition.top + currentToolbarPosition.height);

      if (difference < 0) {
        const totalHeight = mainContainerPosition.height + mainContainerPosition.top - difference; // increase the height of the main container if keyboard needs it

        if (mainContainer) {
          mainContainer.style.height = `${totalHeight}px`;
        }
      }
    }

    if (keyPadElement) {
      keyPadElement.addEventListener('touchstart', this.handleKeypadInteraction, true);
      keyPadElement.addEventListener('mousedown', this.handleKeypadInteraction, true);
    }
  }

  componentWillUnmount() {
    var _this$keypadRef2;

    const keyPadElement = (_this$keypadRef2 = this.keypadRef) == null ? void 0 : _this$keypadRef2.current; // need only for math keyboard

    if (this.props.controlledKeypadMode && keyPadElement) {
      const mainContainer = keyPadElement.closest(`.${editableHtmlConstants.MAIN_CONTAINER_CLASS}`);

      if (mainContainer) {
        mainContainer.style.height = 'unset';
      }
    }

    if (keyPadElement) {
      keyPadElement.removeEventListener('touchstart', this.handleKeypadInteraction, true);
      keyPadElement.removeEventListener('mousedown', this.handleKeypadInteraction, true);
    }
  }

  render() {
    const {
      classes,
      className,
      baseSet,
      additionalKeys,
      layoutForKeyPad,
      onFocus,
      mode
    } = this.props;
    const noBaseSet = ['non-negative-integers', 'integers', 'decimals', 'fractions', 'item-authoring', 'language'];
    const keysWithoutBaseSet = noBaseSet.includes(mode);
    const allKeys = keysWithoutBaseSet ? this.flowKeys([], additionalKeys || []) : this.flowKeys(baseSet, additionalKeys || []); //, ...sortKeys(additionalKeys)];

    const shift = allKeys.length % 5 ? 1 : 0;

    const style = _extends({
      gridTemplateColumns: `repeat(${Math.floor(allKeys.length / 5) + shift}, minmax(min-content, 150px))`
    }, createCustomLayout(layoutForKeyPad));

    return /*#__PURE__*/React.createElement("div", {
      ref: this.keypadRef,
      className: classNames(classes.keys, className, classes[mode]),
      style: style,
      onFocus: onFocus
    }, allKeys.map((k, index) => {
      const onClick = this.buttonClick.bind(this, k);

      if (!k) {
        return /*#__PURE__*/React.createElement("span", {
          key: `empty-${index}`
        });
      }

      const common = _extends({
        onClick,
        className: classNames(classes.labelButton, !keysWithoutBaseSet && classes[k.category], classes[k.extraClass], k.label === ',' && classes.comma, k.label === '.' && classes.dot),
        disabled: this.keyIsNotAllowed(k),
        key: `${k.label || k.latex || k.command}-${index}`
      }, k.actions || {}, k.extraProps || {});

      if (k.latex) {
        return /*#__PURE__*/React.createElement(LatexButton, _extends({
          latex: k.latex,
          key: index
        }, common, {
          className: classes.latexButton,
          ariaLabel: k.ariaLabel ? k.ariaLabel : k.name || k.label
        }));
      }

      if (k.label) {
        return /*#__PURE__*/React.createElement(Button, _extends({
          key: index
        }, common, {
          className: classNames(common.className, {
            [classes.deleteButton]: k.label === '⌫'
          }),
          "aria-label": k.ariaLabel ? k.ariaLabel : k.name || k.label
        }), k.label);
      } else {
        const Icon = k.icon ? k.icon : 'div';
        return /*#__PURE__*/React.createElement(IconButton, _extends({
          tabIndex: '-1'
        }, common, {
          key: index
        }), /*#__PURE__*/React.createElement(Icon, {
          className: classes.icon
        }));
      }
    }));
  }

}
KeyPad.propTypes = {
  classes: PropTypes.object.isRequired,
  className: PropTypes.string,
  controlledKeypadMode: PropTypes.bool,
  baseSet: PropTypes.array,
  additionalKeys: PropTypes.array,
  layoutForKeyPad: PropTypes.object,
  onPress: PropTypes.func.isRequired,
  onFocus: PropTypes.func,
  noDecimal: PropTypes.bool,
  setKeypadInteraction: PropTypes.func,
  mode: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
};
KeyPad.defaultProps = {
  baseSet: baseSet,
  noDecimal: false
};

const styles = theme => ({
  keys: _extends({}, commonMqKeyboardStyles, {
    width: '100%',
    display: 'grid',
    gridTemplateRows: 'repeat(5, minmax(40px, 60px))',
    gridRowGap: '0px',
    gridColumnGap: '0px',
    gridAutoFlow: 'column'
  }),
  character: {
    textTransform: 'initial !important',
    gridTemplateRows: 'repeat(5, minmax(40px, 50px)) !important'
  },
  language: {
    gridTemplateRows: 'repeat(4, minmax(40px, 50px)) !important',
    '& *': {
      fontFamily: 'Roboto, Helvetica, Arial, sans-serif !important'
    }
  },
  holder: {
    position: 'relative',
    width: '100%',
    height: '100%',
    backgroundColor: '#cef',
    borderRadius: 0,
    padding: `${theme.spacing.unit}px 0 ${theme.spacing.unit}px 0`
  },
  labelButton: {
    minWidth: 'auto',
    fontSize: '140% !important',
    backgroundColor: lighten(theme.palette.primary.light, 0.5),
    '&:hover': {
      backgroundColor: lighten(theme.palette.primary.light, 0.7)
    },
    borderRadius: 0
  },
  latexButton: {
    minWidth: 'auto',
    borderRadius: 0,
    backgroundColor: lighten(theme.palette.primary.light, 0.5),
    '&:hover': {
      backgroundColor: lighten(theme.palette.primary.light, 0.7)
    }
  },
  deleteButton: {
    '& > span': {
      fontFamily: 'Roboto, Helvetica, Arial, sans-serif !important'
    }
  },
  base: {},
  operators: {
    backgroundColor: lighten(theme.palette.secondary.light, 0.5),
    '&:hover': {
      backgroundColor: lighten(theme.palette.secondary.light, 0.7)
    }
  },
  comparison: {
    backgroundColor: lighten(green[500], 0.5),
    '&:hover': {
      backgroundColor: lighten(green[500], 0.7)
    }
  },
  comma: {
    fontSize: '200% !important',
    lineHeight: '100%'
  },
  dot: {
    fontSize: '200% !important',
    lineHeight: '100%'
  },
  icon: {
    height: '30px'
  }
});

var Keypad = withStyles(styles)(KeyPad);

const toOldModel = d => {
  if (d.command) {
    return {
      value: d.command,
      type: 'command'
    };
  } else if (d.write) {
    return {
      value: d.write
    };
  } else if (d.keystroke) {
    return {
      type: 'cursor',
      value: d.keystroke
    };
  }
};

class HorizontalKeypad extends React.Component {
  constructor(...args) {
    super(...args);

    this.keypadPress = data => {
      const {
        onClick
      } = this.props;
      onClick(toOldModel(data));
    };
  }

  render() {
    const {
      mode,
      onFocus,
      controlledKeypadMode,
      noDecimal,
      className,
      additionalKeys,
      layoutForKeyPad,
      setKeypadInteraction
    } = this.props;
    const normalizedKeys = normalizeAdditionalKeys(additionalKeys);
    return /*#__PURE__*/React.createElement(Keypad, {
      className: className,
      controlledKeypadMode: controlledKeypadMode,
      onFocus: onFocus,
      noDecimal: noDecimal,
      layoutForKeyPad: layoutForKeyPad,
      additionalKeys: extendKeySet(keysForGrade(mode), normalizedKeys),
      onPress: this.keypadPress,
      mode: mode,
      setKeypadInteraction: setKeypadInteraction
    });
  }

}
HorizontalKeypad.propTypes = {
  className: PropTypes.string,
  controlledKeypadMode: PropTypes.bool,
  mode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  layoutForKeyPad: PropTypes.object,
  onClick: PropTypes.func.isRequired,
  onFocus: PropTypes.func,
  noDecimal: PropTypes.bool,
  additionalKeys: PropTypes.array,
  setKeypadInteraction: PropTypes.func
};
HorizontalKeypad.defaultProps = {
  mode: 'scientific',
  noDecimal: false,
  additionalKeys: []
};

const addLeftBracket = s => s.indexOf('\\(') === 0 ? s : `\\(${s}`;

const addRightBracket = s => s.indexOf('\\)') === s.length - 2 ? s : `${s}\\)`;

const rmLeftBracket = s => s.indexOf('\\(') === 0 ? s.substring(2) : s;

const rmRightBracket = s => s.indexOf('\\)') === s.length - 2 ? s.substring(0, s.length - 2) : s;

const addBrackets = s => addRightBracket(addLeftBracket(s));

const removeBrackets = s => rmRightBracket(rmLeftBracket(s));

export { HorizontalKeypad, addBrackets, index$1 as keys, keysForGrade, index as mq, removeBrackets, updateSpans };
//# sourceMappingURL=index.js.map
