cibernox/ember-power-select

View on GitHub
ember-power-select/src/utils/group-utils.ts

Summary

Maintainability
F
5 days
Test Coverage
import { A } from '@ember/array';
import { isEqual } from '@ember/utils';

export type MatcherFn = (option: any, text: string) => number;
export function isGroup(entry: any): boolean {
  return !!entry && !!entry.groupName && !!entry.options;
}

export function countOptions(collection: any): number {
  let counter = 0;
  (function walk(collection): void {
    if (!collection) {
      return;
    }
    for (let i = 0; i < collection.length; i++) {
      const entry = collection.objectAt
        ? collection.objectAt(i)
        : collection[i];
      if (isGroup(entry)) {
        walk(entry.options);
      } else {
        counter++;
      }
    }
  })(collection);
  return counter;
}

export function indexOfOption(collection: any, option: any): number {
  let index = 0;
  return (function walk(collection): number {
    if (!collection) {
      return -1;
    }
    for (let i = 0; i < collection.length; i++) {
      const entry = collection.objectAt
        ? collection.objectAt(i)
        : collection[i];
      if (isGroup(entry)) {
        const result = walk(entry.options);
        if (result > -1) {
          return result;
        }
      } else if (isEqual(entry, option)) {
        return index;
      } else {
        index++;
      }
    }
    return -1;
  })(collection);
}

export function pathForOption(collection: any, option: any): string {
  return (function walk(collection): string {
    if (!collection) {
      return '';
    }
    for (let i = 0; i < collection.length; i++) {
      const entry = collection.objectAt
        ? collection.objectAt(i)
        : collection[i];
      if (isGroup(entry)) {
        const result = walk(entry.options);
        if (result.length > 0) {
          return i + '.' + result;
        }
      } else if (isEqual(entry, option)) {
        return i + '';
      }
    }
    return '';
  })(collection);
}

export function optionAtIndex(
  originalCollection: any,
  index: number,
): { disabled: boolean; option: any } {
  let counter = 0;
  return (
    (function walk(
      collection,
      ancestorIsDisabled,
    ): { disabled: boolean; option: any } | void {
      if (!collection || index < 0) {
        return { disabled: false, option: undefined };
      }
      let localCounter = 0;
      const length = collection.length;
      while (counter <= index && localCounter < length) {
        const entry = collection.objectAt
          ? collection.objectAt(localCounter)
          : collection[localCounter];
        if (isGroup(entry)) {
          const found = walk(
            entry.options,
            ancestorIsDisabled || !!entry.disabled,
          );
          if (found) {
            return found;
          }
        } else if (counter === index) {
          return {
            disabled: ancestorIsDisabled || !!entry.disabled,
            option: entry,
          };
        } else {
          counter++;
        }
        localCounter++;
      }
    })(originalCollection, false) || { disabled: false, option: undefined }
  );
}

export interface Group {
  options: any[];
  disabled?: boolean;
  groupName: string;
}
function copyGroup(group: Group, suboptions: any[]): Group {
  const groupCopy: Group = { groupName: group.groupName, options: suboptions };
  if (Object.prototype.hasOwnProperty.call(group, 'disabled')) {
    groupCopy.disabled = group.disabled;
  }
  return groupCopy;
}

export function findOptionWithOffset(
  options: any,
  text: string,
  matcher: MatcherFn,
  offset: number,
  skipDisabled = false,
): any {
  let counter = 0;
  let foundBeforeOffset;
  let foundAfterOffset = false;
  const canStop = () => !!foundAfterOffset;

  (function walk(options: any, ancestorIsDisabled: boolean): any {
    const length = options.length;

    for (let i = 0; i < length; i++) {
      const entry = options.objectAt ? options.objectAt(i) : options[i];
      const entryIsDisabled = !!entry.disabled;
      if (!skipDisabled || !entryIsDisabled) {
        if (isGroup(entry)) {
          walk(entry.options, ancestorIsDisabled || entryIsDisabled);
          if (canStop()) {
            return;
          }
        } else if (matcher(entry, text) >= 0) {
          if (counter < offset) {
            if (!foundBeforeOffset) {
              foundBeforeOffset = entry;
            }
          } else {
            foundAfterOffset = entry;
          }
          counter++;
        } else {
          counter++;
        }

        if (canStop()) {
          return;
        }
      }
    }
  })(options, false);

  return foundAfterOffset ? foundAfterOffset : foundBeforeOffset;
}

export function filterOptions(
  options: any,
  text: string,
  matcher: MatcherFn,
  skipDisabled = false,
): any[] {
  const opts = A();
  const length = options.length;
  for (let i = 0; i < length; i++) {
    const entry = options.objectAt ? options.objectAt(i) : options[i];
    if (!skipDisabled || !entry.disabled) {
      if (isGroup(entry)) {
        const suboptions = filterOptions(
          entry.options,
          text,
          matcher,
          skipDisabled,
        );
        if (suboptions.length > 0) {
          opts.push(copyGroup(entry, suboptions));
        }
      } else if (matcher(entry, text) >= 0) {
        opts.push(entry);
      }
    }
  }
  return opts;
}

export function defaultHighlighted<T>({
  results,
  highlighted,
  selected,
}: {
  results: T[];
  highlighted: T | undefined;
  selected: T | undefined;
}): T {
  const option = highlighted || selected;
  if (option === undefined || indexOfOption(results, option) === -1) {
    return advanceSelectableOption(results, option, 1);
  }
  return option;
}

export function advanceSelectableOption(
  options: any,
  currentOption: any,
  step: 1 | -1,
) {
  const resultsLength = countOptions(options);
  let startIndex = Math.min(
    Math.max(indexOfOption(options, currentOption) + step, 0),
    resultsLength - 1,
  );
  let { disabled, option } = optionAtIndex(options, startIndex);
  while (option && disabled) {
    const next = optionAtIndex(options, (startIndex += step));
    disabled = next.disabled;
    option = next.option;
  }
  return option;
}

const DIACRITICS: Record<string, string> = {
  'Ⓐ': 'A',
  A: 'A',
  À: 'A',
  Á: 'A',
  Â: 'A',
  Ầ: 'A',
  Ấ: 'A',
  Ẫ: 'A',
  Ẩ: 'A',
  Ã: 'A',
  Ā: 'A',
  Ă: 'A',
  Ằ: 'A',
  Ắ: 'A',
  Ẵ: 'A',
  Ẳ: 'A',
  Ȧ: 'A',
  Ǡ: 'A',
  Ä: 'A',
  Ǟ: 'A',
  Ả: 'A',
  Å: 'A',
  Ǻ: 'A',
  Ǎ: 'A',
  Ȁ: 'A',
  Ȃ: 'A',
  Ạ: 'A',
  Ậ: 'A',
  Ặ: 'A',
  Ḁ: 'A',
  Ą: 'A',
  Ⱥ: 'A',
  Ɐ: 'A',
  Ꜳ: 'AA',
  Æ: 'AE',
  Ǽ: 'AE',
  Ǣ: 'AE',
  Ꜵ: 'AO',
  Ꜷ: 'AU',
  Ꜹ: 'AV',
  Ꜻ: 'AV',
  Ꜽ: 'AY',
  'Ⓑ': 'B',
  B: 'B',
  Ḃ: 'B',
  Ḅ: 'B',
  Ḇ: 'B',
  Ƀ: 'B',
  Ƃ: 'B',
  Ɓ: 'B',
  'Ⓒ': 'C',
  C: 'C',
  Ć: 'C',
  Ĉ: 'C',
  Ċ: 'C',
  Č: 'C',
  Ç: 'C',
  Ḉ: 'C',
  Ƈ: 'C',
  Ȼ: 'C',
  Ꜿ: 'C',
  'Ⓓ': 'D',
  D: 'D',
  Ḋ: 'D',
  Ď: 'D',
  Ḍ: 'D',
  Ḑ: 'D',
  Ḓ: 'D',
  Ḏ: 'D',
  Đ: 'D',
  Ƌ: 'D',
  Ɗ: 'D',
  Ɖ: 'D',
  Ꝺ: 'D',
  DZ: 'DZ',
  DŽ: 'DZ',
  Dz: 'Dz',
  Dž: 'Dz',
  'Ⓔ': 'E',
  E: 'E',
  È: 'E',
  É: 'E',
  Ê: 'E',
  Ề: 'E',
  Ế: 'E',
  Ễ: 'E',
  Ể: 'E',
  Ẽ: 'E',
  Ē: 'E',
  Ḕ: 'E',
  Ḗ: 'E',
  Ĕ: 'E',
  Ė: 'E',
  Ë: 'E',
  Ẻ: 'E',
  Ě: 'E',
  Ȅ: 'E',
  Ȇ: 'E',
  Ẹ: 'E',
  Ệ: 'E',
  Ȩ: 'E',
  Ḝ: 'E',
  Ę: 'E',
  Ḙ: 'E',
  Ḛ: 'E',
  Ɛ: 'E',
  Ǝ: 'E',
  'Ⓕ': 'F',
  F: 'F',
  Ḟ: 'F',
  Ƒ: 'F',
  Ꝼ: 'F',
  'Ⓖ': 'G',
  G: 'G',
  Ǵ: 'G',
  Ĝ: 'G',
  Ḡ: 'G',
  Ğ: 'G',
  Ġ: 'G',
  Ǧ: 'G',
  Ģ: 'G',
  Ǥ: 'G',
  Ɠ: 'G',
  Ꞡ: 'G',
  Ᵹ: 'G',
  Ꝿ: 'G',
  'Ⓗ': 'H',
  H: 'H',
  Ĥ: 'H',
  Ḣ: 'H',
  Ḧ: 'H',
  Ȟ: 'H',
  Ḥ: 'H',
  Ḩ: 'H',
  Ḫ: 'H',
  Ħ: 'H',
  Ⱨ: 'H',
  Ⱶ: 'H',
  Ɥ: 'H',
  'Ⓘ': 'I',
  I: 'I',
  Ì: 'I',
  Í: 'I',
  Î: 'I',
  Ĩ: 'I',
  Ī: 'I',
  Ĭ: 'I',
  İ: 'I',
  Ï: 'I',
  Ḯ: 'I',
  Ỉ: 'I',
  Ǐ: 'I',
  Ȉ: 'I',
  Ȋ: 'I',
  Ị: 'I',
  Į: 'I',
  Ḭ: 'I',
  Ɨ: 'I',
  'Ⓙ': 'J',
  J: 'J',
  Ĵ: 'J',
  Ɉ: 'J',
  'Ⓚ': 'K',
  K: 'K',
  Ḱ: 'K',
  Ǩ: 'K',
  Ḳ: 'K',
  Ķ: 'K',
  Ḵ: 'K',
  Ƙ: 'K',
  Ⱪ: 'K',
  Ꝁ: 'K',
  Ꝃ: 'K',
  Ꝅ: 'K',
  Ꞣ: 'K',
  'Ⓛ': 'L',
  L: 'L',
  Ŀ: 'L',
  Ĺ: 'L',
  Ľ: 'L',
  Ḷ: 'L',
  Ḹ: 'L',
  Ļ: 'L',
  Ḽ: 'L',
  Ḻ: 'L',
  Ł: 'L',
  Ƚ: 'L',
  Ɫ: 'L',
  Ⱡ: 'L',
  Ꝉ: 'L',
  Ꝇ: 'L',
  Ꞁ: 'L',
  LJ: 'LJ',
  Lj: 'Lj',
  'Ⓜ': 'M',
  M: 'M',
  Ḿ: 'M',
  Ṁ: 'M',
  Ṃ: 'M',
  Ɱ: 'M',
  Ɯ: 'M',
  'Ⓝ': 'N',
  N: 'N',
  Ǹ: 'N',
  Ń: 'N',
  Ñ: 'N',
  Ṅ: 'N',
  Ň: 'N',
  Ṇ: 'N',
  Ņ: 'N',
  Ṋ: 'N',
  Ṉ: 'N',
  Ƞ: 'N',
  Ɲ: 'N',
  Ꞑ: 'N',
  Ꞥ: 'N',
  NJ: 'NJ',
  Nj: 'Nj',
  'Ⓞ': 'O',
  O: 'O',
  Ò: 'O',
  Ó: 'O',
  Ô: 'O',
  Ồ: 'O',
  Ố: 'O',
  Ỗ: 'O',
  Ổ: 'O',
  Õ: 'O',
  Ṍ: 'O',
  Ȭ: 'O',
  Ṏ: 'O',
  Ō: 'O',
  Ṑ: 'O',
  Ṓ: 'O',
  Ŏ: 'O',
  Ȯ: 'O',
  Ȱ: 'O',
  Ö: 'O',
  Ȫ: 'O',
  Ỏ: 'O',
  Ő: 'O',
  Ǒ: 'O',
  Ȍ: 'O',
  Ȏ: 'O',
  Ơ: 'O',
  Ờ: 'O',
  Ớ: 'O',
  Ỡ: 'O',
  Ở: 'O',
  Ợ: 'O',
  Ọ: 'O',
  Ộ: 'O',
  Ǫ: 'O',
  Ǭ: 'O',
  Ø: 'O',
  Ǿ: 'O',
  Ɔ: 'O',
  Ɵ: 'O',
  Ꝋ: 'O',
  Ꝍ: 'O',
  Ƣ: 'OI',
  Ꝏ: 'OO',
  Ȣ: 'OU',
  'Ⓟ': 'P',
  P: 'P',
  Ṕ: 'P',
  Ṗ: 'P',
  Ƥ: 'P',
  Ᵽ: 'P',
  Ꝑ: 'P',
  Ꝓ: 'P',
  Ꝕ: 'P',
  'Ⓠ': 'Q',
  Q: 'Q',
  Ꝗ: 'Q',
  Ꝙ: 'Q',
  Ɋ: 'Q',
  'Ⓡ': 'R',
  R: 'R',
  Ŕ: 'R',
  Ṙ: 'R',
  Ř: 'R',
  Ȑ: 'R',
  Ȓ: 'R',
  Ṛ: 'R',
  Ṝ: 'R',
  Ŗ: 'R',
  Ṟ: 'R',
  Ɍ: 'R',
  Ɽ: 'R',
  Ꝛ: 'R',
  Ꞧ: 'R',
  Ꞃ: 'R',
  'Ⓢ': 'S',
  S: 'S',
  ẞ: 'S',
  Ś: 'S',
  Ṥ: 'S',
  Ŝ: 'S',
  Ṡ: 'S',
  Š: 'S',
  Ṧ: 'S',
  Ṣ: 'S',
  Ṩ: 'S',
  Ș: 'S',
  Ş: 'S',
  Ȿ: 'S',
  Ꞩ: 'S',
  Ꞅ: 'S',
  'Ⓣ': 'T',
  T: 'T',
  Ṫ: 'T',
  Ť: 'T',
  Ṭ: 'T',
  Ț: 'T',
  Ţ: 'T',
  Ṱ: 'T',
  Ṯ: 'T',
  Ŧ: 'T',
  Ƭ: 'T',
  Ʈ: 'T',
  Ⱦ: 'T',
  Ꞇ: 'T',
  Ꜩ: 'TZ',
  'Ⓤ': 'U',
  U: 'U',
  Ù: 'U',
  Ú: 'U',
  Û: 'U',
  Ũ: 'U',
  Ṹ: 'U',
  Ū: 'U',
  Ṻ: 'U',
  Ŭ: 'U',
  Ü: 'U',
  Ǜ: 'U',
  Ǘ: 'U',
  Ǖ: 'U',
  Ǚ: 'U',
  Ủ: 'U',
  Ů: 'U',
  Ű: 'U',
  Ǔ: 'U',
  Ȕ: 'U',
  Ȗ: 'U',
  Ư: 'U',
  Ừ: 'U',
  Ứ: 'U',
  Ữ: 'U',
  Ử: 'U',
  Ự: 'U',
  Ụ: 'U',
  Ṳ: 'U',
  Ų: 'U',
  Ṷ: 'U',
  Ṵ: 'U',
  Ʉ: 'U',
  'Ⓥ': 'V',
  V: 'V',
  Ṽ: 'V',
  Ṿ: 'V',
  Ʋ: 'V',
  Ꝟ: 'V',
  Ʌ: 'V',
  Ꝡ: 'VY',
  'Ⓦ': 'W',
  W: 'W',
  Ẁ: 'W',
  Ẃ: 'W',
  Ŵ: 'W',
  Ẇ: 'W',
  Ẅ: 'W',
  Ẉ: 'W',
  Ⱳ: 'W',
  'Ⓧ': 'X',
  X: 'X',
  Ẋ: 'X',
  Ẍ: 'X',
  'Ⓨ': 'Y',
  Y: 'Y',
  Ỳ: 'Y',
  Ý: 'Y',
  Ŷ: 'Y',
  Ỹ: 'Y',
  Ȳ: 'Y',
  Ẏ: 'Y',
  Ÿ: 'Y',
  Ỷ: 'Y',
  Ỵ: 'Y',
  Ƴ: 'Y',
  Ɏ: 'Y',
  Ỿ: 'Y',
  'Ⓩ': 'Z',
  Z: 'Z',
  Ź: 'Z',
  Ẑ: 'Z',
  Ż: 'Z',
  Ž: 'Z',
  Ẓ: 'Z',
  Ẕ: 'Z',
  Ƶ: 'Z',
  Ȥ: 'Z',
  Ɀ: 'Z',
  Ⱬ: 'Z',
  Ꝣ: 'Z',
  'ⓐ': 'a',
  a: 'a',
  ẚ: 'a',
  à: 'a',
  á: 'a',
  â: 'a',
  ầ: 'a',
  ấ: 'a',
  ẫ: 'a',
  ẩ: 'a',
  ã: 'a',
  ā: 'a',
  ă: 'a',
  ằ: 'a',
  ắ: 'a',
  ẵ: 'a',
  ẳ: 'a',
  ȧ: 'a',
  ǡ: 'a',
  ä: 'a',
  ǟ: 'a',
  ả: 'a',
  å: 'a',
  ǻ: 'a',
  ǎ: 'a',
  ȁ: 'a',
  ȃ: 'a',
  ạ: 'a',
  ậ: 'a',
  ặ: 'a',
  ḁ: 'a',
  ą: 'a',
  ⱥ: 'a',
  ɐ: 'a',
  ꜳ: 'aa',
  æ: 'ae',
  ǽ: 'ae',
  ǣ: 'ae',
  ꜵ: 'ao',
  ꜷ: 'au',
  ꜹ: 'av',
  ꜻ: 'av',
  ꜽ: 'ay',
  'ⓑ': 'b',
  b: 'b',
  ḃ: 'b',
  ḅ: 'b',
  ḇ: 'b',
  ƀ: 'b',
  ƃ: 'b',
  ɓ: 'b',
  'ⓒ': 'c',
  c: 'c',
  ć: 'c',
  ĉ: 'c',
  ċ: 'c',
  č: 'c',
  ç: 'c',
  ḉ: 'c',
  ƈ: 'c',
  ȼ: 'c',
  ꜿ: 'c',
  ↄ: 'c',
  'ⓓ': 'd',
  d: 'd',
  ḋ: 'd',
  ď: 'd',
  ḍ: 'd',
  ḑ: 'd',
  ḓ: 'd',
  ḏ: 'd',
  đ: 'd',
  ƌ: 'd',
  ɖ: 'd',
  ɗ: 'd',
  ꝺ: 'd',
  dz: 'dz',
  dž: 'dz',
  'ⓔ': 'e',
  e: 'e',
  è: 'e',
  é: 'e',
  ê: 'e',
  ề: 'e',
  ế: 'e',
  ễ: 'e',
  ể: 'e',
  ẽ: 'e',
  ē: 'e',
  ḕ: 'e',
  ḗ: 'e',
  ĕ: 'e',
  ė: 'e',
  ë: 'e',
  ẻ: 'e',
  ě: 'e',
  ȅ: 'e',
  ȇ: 'e',
  ẹ: 'e',
  ệ: 'e',
  ȩ: 'e',
  ḝ: 'e',
  ę: 'e',
  ḙ: 'e',
  ḛ: 'e',
  ɇ: 'e',
  ɛ: 'e',
  ǝ: 'e',
  'ⓕ': 'f',
  f: 'f',
  ḟ: 'f',
  ƒ: 'f',
  ꝼ: 'f',
  'ⓖ': 'g',
  g: 'g',
  ǵ: 'g',
  ĝ: 'g',
  ḡ: 'g',
  ğ: 'g',
  ġ: 'g',
  ǧ: 'g',
  ģ: 'g',
  ǥ: 'g',
  ɠ: 'g',
  ꞡ: 'g',
  ᵹ: 'g',
  ꝿ: 'g',
  'ⓗ': 'h',
  h: 'h',
  ĥ: 'h',
  ḣ: 'h',
  ḧ: 'h',
  ȟ: 'h',
  ḥ: 'h',
  ḩ: 'h',
  ḫ: 'h',
  ẖ: 'h',
  ħ: 'h',
  ⱨ: 'h',
  ⱶ: 'h',
  ɥ: 'h',
  ƕ: 'hv',
  'ⓘ': 'i',
  i: 'i',
  ì: 'i',
  í: 'i',
  î: 'i',
  ĩ: 'i',
  ī: 'i',
  ĭ: 'i',
  ï: 'i',
  ḯ: 'i',
  ỉ: 'i',
  ǐ: 'i',
  ȉ: 'i',
  ȋ: 'i',
  ị: 'i',
  į: 'i',
  ḭ: 'i',
  ɨ: 'i',
  ı: 'i',
  'ⓙ': 'j',
  j: 'j',
  ĵ: 'j',
  ǰ: 'j',
  ɉ: 'j',
  'ⓚ': 'k',
  k: 'k',
  ḱ: 'k',
  ǩ: 'k',
  ḳ: 'k',
  ķ: 'k',
  ḵ: 'k',
  ƙ: 'k',
  ⱪ: 'k',
  ꝁ: 'k',
  ꝃ: 'k',
  ꝅ: 'k',
  ꞣ: 'k',
  'ⓛ': 'l',
  l: 'l',
  ŀ: 'l',
  ĺ: 'l',
  ľ: 'l',
  ḷ: 'l',
  ḹ: 'l',
  ļ: 'l',
  ḽ: 'l',
  ḻ: 'l',
  ſ: 'l',
  ł: 'l',
  ƚ: 'l',
  ɫ: 'l',
  ⱡ: 'l',
  ꝉ: 'l',
  ꞁ: 'l',
  ꝇ: 'l',
  lj: 'lj',
  'ⓜ': 'm',
  m: 'm',
  ḿ: 'm',
  ṁ: 'm',
  ṃ: 'm',
  ɱ: 'm',
  ɯ: 'm',
  'ⓝ': 'n',
  n: 'n',
  ǹ: 'n',
  ń: 'n',
  ñ: 'n',
  ṅ: 'n',
  ň: 'n',
  ṇ: 'n',
  ņ: 'n',
  ṋ: 'n',
  ṉ: 'n',
  ƞ: 'n',
  ɲ: 'n',
  ʼn: 'n',
  ꞑ: 'n',
  ꞥ: 'n',
  nj: 'nj',
  'ⓞ': 'o',
  o: 'o',
  ò: 'o',
  ó: 'o',
  ô: 'o',
  ồ: 'o',
  ố: 'o',
  ỗ: 'o',
  ổ: 'o',
  õ: 'o',
  ṍ: 'o',
  ȭ: 'o',
  ṏ: 'o',
  ō: 'o',
  ṑ: 'o',
  ṓ: 'o',
  ŏ: 'o',
  ȯ: 'o',
  ȱ: 'o',
  ö: 'o',
  ȫ: 'o',
  ỏ: 'o',
  ő: 'o',
  ǒ: 'o',
  ȍ: 'o',
  ȏ: 'o',
  ơ: 'o',
  ờ: 'o',
  ớ: 'o',
  ỡ: 'o',
  ở: 'o',
  ợ: 'o',
  ọ: 'o',
  ộ: 'o',
  ǫ: 'o',
  ǭ: 'o',
  ø: 'o',
  ǿ: 'o',
  ɔ: 'o',
  ꝋ: 'o',
  ꝍ: 'o',
  ɵ: 'o',
  ƣ: 'oi',
  ȣ: 'ou',
  ꝏ: 'oo',
  'ⓟ': 'p',
  p: 'p',
  ṕ: 'p',
  ṗ: 'p',
  ƥ: 'p',
  ᵽ: 'p',
  ꝑ: 'p',
  ꝓ: 'p',
  ꝕ: 'p',
  'ⓠ': 'q',
  q: 'q',
  ɋ: 'q',
  ꝗ: 'q',
  ꝙ: 'q',
  'ⓡ': 'r',
  r: 'r',
  ŕ: 'r',
  ṙ: 'r',
  ř: 'r',
  ȑ: 'r',
  ȓ: 'r',
  ṛ: 'r',
  ṝ: 'r',
  ŗ: 'r',
  ṟ: 'r',
  ɍ: 'r',
  ɽ: 'r',
  ꝛ: 'r',
  ꞧ: 'r',
  ꞃ: 'r',
  'ⓢ': 's',
  s: 's',
  ß: 's',
  ś: 's',
  ṥ: 's',
  ŝ: 's',
  ṡ: 's',
  š: 's',
  ṧ: 's',
  ṣ: 's',
  ṩ: 's',
  ș: 's',
  ş: 's',
  ȿ: 's',
  ꞩ: 's',
  ꞅ: 's',
  ẛ: 's',
  'ⓣ': 't',
  t: 't',
  ṫ: 't',
  ẗ: 't',
  ť: 't',
  ṭ: 't',
  ț: 't',
  ţ: 't',
  ṱ: 't',
  ṯ: 't',
  ŧ: 't',
  ƭ: 't',
  ʈ: 't',
  ⱦ: 't',
  ꞇ: 't',
  ꜩ: 'tz',
  'ⓤ': 'u',
  u: 'u',
  ù: 'u',
  ú: 'u',
  û: 'u',
  ũ: 'u',
  ṹ: 'u',
  ū: 'u',
  ṻ: 'u',
  ŭ: 'u',
  ü: 'u',
  ǜ: 'u',
  ǘ: 'u',
  ǖ: 'u',
  ǚ: 'u',
  ủ: 'u',
  ů: 'u',
  ű: 'u',
  ǔ: 'u',
  ȕ: 'u',
  ȗ: 'u',
  ư: 'u',
  ừ: 'u',
  ứ: 'u',
  ữ: 'u',
  ử: 'u',
  ự: 'u',
  ụ: 'u',
  ṳ: 'u',
  ų: 'u',
  ṷ: 'u',
  ṵ: 'u',
  ʉ: 'u',
  'ⓥ': 'v',
  v: 'v',
  ṽ: 'v',
  ṿ: 'v',
  ʋ: 'v',
  ꝟ: 'v',
  ʌ: 'v',
  ꝡ: 'vy',
  'ⓦ': 'w',
  w: 'w',
  ẁ: 'w',
  ẃ: 'w',
  ŵ: 'w',
  ẇ: 'w',
  ẅ: 'w',
  ẘ: 'w',
  ẉ: 'w',
  ⱳ: 'w',
  'ⓧ': 'x',
  x: 'x',
  ẋ: 'x',
  ẍ: 'x',
  'ⓨ': 'y',
  y: 'y',
  ỳ: 'y',
  ý: 'y',
  ŷ: 'y',
  ỹ: 'y',
  ȳ: 'y',
  ẏ: 'y',
  ÿ: 'y',
  ỷ: 'y',
  ẙ: 'y',
  ỵ: 'y',
  ƴ: 'y',
  ɏ: 'y',
  ỿ: 'y',
  'ⓩ': 'z',
  z: 'z',
  ź: 'z',
  ẑ: 'z',
  ż: 'z',
  ž: 'z',
  ẓ: 'z',
  ẕ: 'z',
  ƶ: 'z',
  ȥ: 'z',
  ɀ: 'z',
  ⱬ: 'z',
  ꝣ: 'z',
  Ά: 'Α',
  Έ: 'Ε',
  Ή: 'Η',
  Ί: 'Ι',
  Ϊ: 'Ι',
  Ό: 'Ο',
  Ύ: 'Υ',
  Ϋ: 'Υ',
  Ώ: 'Ω',
  ά: 'α',
  έ: 'ε',
  ή: 'η',
  ί: 'ι',
  ϊ: 'ι',
  ΐ: 'ι',
  ό: 'ο',
  ύ: 'υ',
  ϋ: 'υ',
  ΰ: 'υ',
  ω: 'ω',
  ς: 'σ',
};

// Copied from Select2
export function stripDiacritics(text: string | number) {
  // Used 'uni range + named function' from http://jsperf.com/diacritics/18
  function match(a: string) {
    return DIACRITICS[a] || a;
  }

  return `${text}`.replace(/[^\u0000-\u007E]/g, match); // eslint-disable-line
}

export function defaultMatcher(value: string, text: string) {
  return stripDiacritics(value)
    .toUpperCase()
    .indexOf(stripDiacritics(text).toUpperCase());
}

export function defaultTypeAheadMatcher(value: string, text: string) {
  return stripDiacritics(value)
    .toUpperCase()
    .startsWith(stripDiacritics(text).toUpperCase())
    ? 1
    : -1;
}