'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var ui = require('@grafana/ui');
var data = require('@grafana/data');
var Calendar = require('react-calendar');
var css = require('@emotion/css');
var e2eSelectors = require('@grafana/e2e-selectors');
var runtime = require('@grafana/runtime');
var reactUse = require('react-use');
var ui$1 = require('@react-awesome-query-builder/ui');
var lodash = require('lodash');
var uuid = require('uuid');
var AutoSizer = require('react-virtualized-auto-sizer');
var sqlFormatter = require('sql-formatter-plus');
var rxjs = require('rxjs');
var operators$1 = require('rxjs/operators');
var dnd = require('@hello-pangea/dnd');
var reactPopperTooltip = require('react-popper-tooltip');
var Prism = require('prismjs');
var DeprecatedReactTestUtils = require('react-dom/test-utils');
require('react-dom');
require('react-dom/client');

function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }

function _interopNamespaceCompat(e) {
  if (e && typeof e === 'object' && 'default' in e) return e;
  var n = Object.create(null);
  if (e) {
    Object.keys(e).forEach(function (k) {
      if (k !== 'default') {
        var d = Object.getOwnPropertyDescriptor(e, k);
        Object.defineProperty(n, k, d.get ? d : {
          enumerable: true,
          get: function () { return e[k]; }
        });
      }
    });
  }
  n.default = e;
  return Object.freeze(n);
}

var React__namespace = /*#__PURE__*/_interopNamespaceCompat(React);
var Calendar__default = /*#__PURE__*/_interopDefaultCompat(Calendar);
var AutoSizer__default = /*#__PURE__*/_interopDefaultCompat(AutoSizer);
var sqlFormatter__default = /*#__PURE__*/_interopDefaultCompat(sqlFormatter);
var Prism__default = /*#__PURE__*/_interopDefaultCompat(Prism);
var DeprecatedReactTestUtils__namespace = /*#__PURE__*/_interopNamespaceCompat(DeprecatedReactTestUtils);

const QueryEditorRow = (props) => {
  var _a, _b;
  const className = (_a = props.className) != null ? _a : "width-8";
  const noFillEnd = (_b = props.noFillEnd) != null ? _b : false;
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gf-form", children: [
    props.label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: `gf-form-label query-keyword ${className}`, children: props.label }),
    props.children,
    /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gf-form--grow", children: noFillEnd || /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gf-form-label gf-form-label--grow" }) })
  ] });
};

const DEFAULT_DELAY = 275;
const useDebounce = (value, delay = DEFAULT_DELAY) => {
  const [debouncedValue, setDebouncedValue] = React.useState(value);
  React.useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
    return () => {
      clearTimeout(handler);
    };
  }, [value]);
  return debouncedValue;
};

const DebounceInput = (props) => {
  const { delay, onDebounce, value, ...rest } = props;
  const [input, setInput] = React.useState(value);
  const debouncedInput = useDebounce(input, delay);
  React.useEffect(() => onDebounce(debouncedInput), [debouncedInput]);
  React.useEffect(() => setInput(value), [value]);
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { onChange: (ev) => setInput(ev.currentTarget.value), value: input, ...rest });
};

function Segment(props) {
  const { delay, onDebounce, value, options, ...rest } = props;
  const [input, setInput] = React.useState(value);
  const debouncedSegment = useDebounce(input, delay);
  React.useEffect(() => onDebounce(debouncedSegment), [debouncedSegment]);
  React.useEffect(() => setInput(value), [value]);
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.Segment,
    {
      options,
      onChange: (ev) => setInput(ev.value),
      value: input,
      ...rest
    }
  );
}

const getStyles$r = (theme) => {
  const containerBorder = theme.isDark ? theme.v1.palette.dark9 : theme.v1.palette.gray5;
  return {
    container: css.css`
      top: -1px;
      position: absolute;
      right: 544px;
      box-shadow: 0px 0px 20px ${theme.v1.colors.dropdownShadow};
      background-color: ${theme.v1.colors.bodyBg};
      z-index: -1;
      border: 1px solid ${containerBorder};
      border-radius: 2px 0 0 2px;

      &:after {
        display: block;
        background-color: ${theme.v1.colors.bodyBg};
        width: 19px;
        height: 100%;
        content: '';
        position: absolute;
        top: 0;
        right: -19px;
        border-left: 1px solid ${theme.v1.colors.border1};
      }
    `,
    modal: css.css`
      z-index: ${theme.v1.zIndex.modal};
    `,
    content: css.css`
      margin: 0 auto;
      width: 268px;
    `,
    backdrop: css.css`
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      background: #202226;
      opacity: 0.7;
      z-index: ${theme.v1.zIndex.modalBackdrop};
      text-align: center;
    `
  };
};
const getBodyStyles = (theme) => {
  const containerBorder = theme.isDark ? theme.v1.palette.dark9 : theme.v1.palette.gray5;
  return {
    title: css.css`
      color: ${theme.colors.text};
      background-color: ${theme.v1.colors.bodyBg};
      font-size: ${theme.v1.typography.size.md};
      border: 1px solid transparent;

      &:hover {
        position: relative;
      }
    `,
    body: css.css`
      z-index: ${theme.zIndex.modal};
      position: fixed;
      background-color: ${theme.v1.colors.bodyBg};
      width: 268px;

      box-shadow: 0px 0px 20px ${theme.v1.colors.dropdownShadow};
      border: 1px solid ${containerBorder};
      border-radius: 2px 0 0 2px;

      .react-calendar__navigation__label,
      .react-calendar__navigation__arrow,
      .react-calendar__navigation {
        padding-top: 4px;
        background-color: inherit;
        color: ${theme.colors.text};
        border: 0;
        font-weight: ${theme.v1.typography.weight.semibold};
      }

      .react-calendar__month-view__weekdays {
        background-color: inherit;
        text-align: center;
        color: ${theme.v1.palette.blue77};

        abbr {
          border: 0;
          text-decoration: none;
          cursor: default;
          display: block;
          padding: 4px 0 4px 0;
        }
      }

      .react-calendar__month-view__days {
        background-color: inherit;
      }

      .react-calendar__tile,
      .react-calendar__tile--now {
        margin-bottom: 4px;
        background-color: inherit;
        height: 26px;
      }

      .react-calendar__navigation__label,
      .react-calendar__navigation > button:focus,
      .time-picker-calendar-tile:focus {
        outline: 0;
      }

      .react-calendar__tile--active,
      .react-calendar__tile--active:hover {
        color: ${theme.v1.palette.white};
        font-weight: ${theme.v1.typography.weight.semibold};
        background: ${theme.v1.palette.blue95};
        box-shadow: none;
        border: 0px;
      }

      .react-calendar__tile--rangeEnd,
      .react-calendar__tile--rangeStart {
        padding: 0;
        border: 0px;
        color: ${theme.v1.palette.white};
        font-weight: ${theme.v1.typography.weight.semibold};
        background: ${theme.v1.palette.blue95};

        abbr {
          background-color: ${theme.v1.palette.blue77};
          border-radius: 100px;
          display: block;
          padding-top: 2px;
          height: 26px;
        }
      }

      .react-calendar__tile--rangeStart {
        border-top-left-radius: 20px;
        border-bottom-left-radius: 20px;
      }

      .react-calendar__tile--rangeEnd {
        border-top-right-radius: 20px;
        border-bottom-right-radius: 20px;
      }
    `
  };
};

const DatePicker = React.memo((props) => {
  const theme = ui.useTheme2();
  const styles = getStyles$r(theme);
  const { isOpen, onClose } = props;
  if (!isOpen) {
    return null;
  }
  return /* @__PURE__ */ jsxRuntime.jsx(ui.ClickOutsideWrapper, { useCapture: true, includeButtonPress: false, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.modal, "data-testid": "date-picker", children: /* @__PURE__ */ jsxRuntime.jsx(Body, { ...props }) }) });
});
DatePicker.displayName = "DatePicker";
const Body = React.memo(({ value, onChange }) => {
  const theme = ui.useTheme2();
  const styles = getBodyStyles(theme);
  return /* @__PURE__ */ jsxRuntime.jsx(
    Calendar__default.default,
    {
      className: styles.body,
      tileClassName: styles.title,
      value: value || /* @__PURE__ */ new Date(),
      nextLabel: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { name: "angle-right" }),
      prevLabel: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { name: "angle-left" }),
      onChange: (ev) => {
        if (!Array.isArray(ev)) {
          onChange(ev);
        }
      },
      locale: "en"
    }
  );
});
Body.displayName = "Body";

function getStyles$q() {
  return {
    input: css.css({
      /* hides the native Calendar picker icon given when using type=date */
      "input[type='date']::-webkit-inner-spin-button, input[type='date']::-webkit-calendar-picker-indicator": {
        display: "none",
        WebkitAppearance: "none"
      }
    })
  };
}

const formatDate = (date) => date.toISOString().split("T")[0];
const DatePickerWithInput = (props) => {
  const { value, onChange, className, ...rest } = props;
  const [open, setOpen] = React.useState(false);
  const styles = getStyles$q();
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Input,
      {
        type: "date",
        placeholder: "Date",
        value: formatDate(value || /* @__PURE__ */ new Date()),
        onClick: () => setOpen(true),
        onChange: () => {
        },
        className: css.cx(styles.input, className),
        ...rest
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(DatePicker, { isOpen: open, value, onChange: (ev) => onChange(ev), onClose: () => setOpen(false) })
  ] });
};

const PluginSignatureBadge = ({ status, ...otherProps }) => {
  const display = getSignatureDisplayModel(status);
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.Badge,
    {
      text: display.text,
      color: display.color,
      icon: display.icon,
      tooltip: display.tooltip,
      ...otherProps
    }
  );
};
function isUnsignedPluginSignature(signature) {
  return signature && signature !== data.PluginSignatureStatus.valid && signature !== data.PluginSignatureStatus.internal;
}
function getSignatureDisplayModel(signature) {
  if (!signature) {
    signature = data.PluginSignatureStatus.invalid;
  }
  switch (signature) {
    case data.PluginSignatureStatus.internal:
      return { text: "Core", icon: "cube", color: "blue", tooltip: "Core plugin that is bundled with Grafana" };
    case data.PluginSignatureStatus.valid:
      return { text: "Signed", icon: "lock", color: "green", tooltip: "Signed and verified plugin" };
    case data.PluginSignatureStatus.invalid:
      return {
        text: "Invalid signature",
        icon: "exclamation-triangle",
        color: "red",
        tooltip: "Invalid plugin signature"
      };
    case data.PluginSignatureStatus.modified:
      return {
        text: "Modified signature",
        icon: "exclamation-triangle",
        color: "red",
        tooltip: "Valid signature but content has been modified"
      };
    case data.PluginSignatureStatus.missing:
      return {
        text: "Missing signature",
        icon: "exclamation-triangle",
        color: "red",
        tooltip: "Missing plugin signature"
      };
  }
  return { text: "Unsigned", icon: "exclamation-triangle", color: "red", tooltip: "Unsigned external plugin" };
}
PluginSignatureBadge.displayName = "PluginSignatureBadge";

var __defProp$4 = Object.defineProperty;
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
class DataSourcePicker extends React.PureComponent {
  constructor(props) {
    super(props);
    __publicField$4(this, "dataSourceSrv", runtime.getDataSourceSrv());
    __publicField$4(this, "state", {});
    __publicField$4(this, "onChange", (item) => {
      const dsSettings = this.dataSourceSrv.getInstanceSettings(item.value);
      if (dsSettings) {
        this.props.onChange(dsSettings);
        this.setState({ error: undefined });
      }
    });
  }
  componentDidMount() {
    const { current } = this.props;
    const dsSettings = this.dataSourceSrv.getInstanceSettings(current);
    if (!dsSettings) {
      this.setState({ error: "Could not find data source " + current });
    }
  }
  getCurrentValue() {
    const { current, hideTextValue, noDefault } = this.props;
    if (!current && noDefault) {
      return {
        label: "No datasources found"
      };
    }
    const ds = this.dataSourceSrv.getInstanceSettings(current);
    if (ds) {
      return {
        label: ds.name.substr(0, 37),
        value: ds.name,
        imgUrl: ds.meta.info.logos.small,
        hideText: hideTextValue,
        meta: ds.meta
      };
    }
    return {
      label: (current != null ? current : "no name") + " - not found",
      value: (current != null ? current : "no name") + " - not found",
      imgUrl: "",
      hideText: hideTextValue
    };
  }
  getDataSourceOptions() {
    const options = this.dataSourceSrv.getList().map((ds) => ({
      value: ds.uid,
      label: ds.name,
      imgUrl: ds.meta.info.logos.small,
      meta: ds.meta
    }));
    return options;
  }
  render() {
    const { autoFocus, onBlur, openMenuOnFocus, placeholder } = this.props;
    const { error } = this.state;
    const options = this.getDataSourceOptions();
    const value = this.getCurrentValue();
    return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-label": e2eSelectors.selectors.components.DataSourcePicker.container, children: /* @__PURE__ */ jsxRuntime.jsx(
      ui.Select,
      {
        className: "ds-picker select-container",
        isMulti: false,
        isClearable: false,
        backspaceRemovesValue: false,
        onChange: this.onChange,
        options,
        autoFocus,
        onBlur,
        openMenuOnFocus,
        maxMenuHeight: 500,
        placeholder,
        noOptionsMessage: "No datasources found",
        value,
        invalid: !!error,
        getOptionLabel: (o) => {
          if (o.meta && isUnsignedPluginSignature(o.meta.signature) && o !== value) {
            return /* @__PURE__ */ jsxRuntime.jsxs(ui.HorizontalGroup, { align: "center", justify: "space-between", children: [
              /* @__PURE__ */ jsxRuntime.jsx("span", { children: o.label }),
              " ",
              /* @__PURE__ */ jsxRuntime.jsx(PluginSignatureBadge, { status: o.meta.signature })
            ] });
          }
          return o.label || "";
        }
      }
    ) });
  }
}
__publicField$4(DataSourcePicker, "defaultProps", {
  autoFocus: false,
  openMenuOnFocus: false,
  placeholder: "Select datasource"
});

const { FormField, Switch } = ui.LegacyForms;
const getStyles$p = ui.stylesFactory(() => ({
  firstRow: css.css`
    display: flex;
  `,
  nameField: css.css`
    flex: 2;
  `,
  regexField: css.css`
    flex: 3;
  `,
  row: css.css`
    display: flex;
    align-items: baseline;
  `
}));
const DataLink = (props) => {
  const { value, onChange, onDelete, suggestions, className } = props;
  const styles = getStyles$p();
  const [showInternalLink, setShowInternalLink] = useInternalLink(value.datasourceUid);
  const handleChange = (field) => (event) => {
    onChange({
      ...value,
      [field]: event.currentTarget.value
    });
  };
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
    /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.firstRow + " gf-form", children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        FormField,
        {
          className: styles.nameField,
          labelWidth: 6,
          inputWidth: null,
          label: "Field",
          type: "text",
          value: value.field,
          tooltip: "Can be exact field name or a regex pattern that will match on the field name.",
          onChange: handleChange("field")
        }
      ),
      /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          variant: "destructive",
          title: "Remove field",
          icon: "times",
          onClick: (event) => {
            event.preventDefault();
            onDelete();
          }
        }
      )
    ] }),
    /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gf-form", children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        FormField,
        {
          className: styles.nameField,
          inputWidth: null,
          label: "Label",
          type: "text",
          value: value.label,
          onChange: handleChange("label"),
          tooltip: "Use to provide a meaningful label to the data matched in the regex"
        }
      ),
      /* @__PURE__ */ jsxRuntime.jsx(
        FormField,
        {
          className: styles.regexField,
          inputWidth: null,
          label: "Regex",
          type: "text",
          value: value.matcherRegex,
          onChange: handleChange("matcherRegex"),
          tooltip: "Use to parse and capture some part of the log message. You can use the captured groups in the template."
        }
      )
    ] }),
    /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gf-form", children: /* @__PURE__ */ jsxRuntime.jsx(
      FormField,
      {
        label: showInternalLink ? "Query" : "URL",
        labelWidth: 6,
        inputEl: /* @__PURE__ */ jsxRuntime.jsx(
          ui.DataLinkInput,
          {
            placeholder: showInternalLink ? "${__value.raw}" : "http://example.com/${__value.raw}",
            value: value.url || "",
            onChange: (newValue) => onChange({
              ...value,
              url: newValue
            }),
            suggestions
          }
        ),
        className: css.css`
            width: 100%;
          `
      }
    ) }),
    /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.row, children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        Switch,
        {
          labelClass: "width-6",
          label: "Internal link",
          checked: showInternalLink,
          onChange: () => {
            if (showInternalLink) {
              onChange({
                ...value,
                datasourceUid: undefined
              });
            }
            setShowInternalLink(!showInternalLink);
          }
        }
      ),
      showInternalLink && /* @__PURE__ */ jsxRuntime.jsx(
        DataSourcePicker,
        {
          onChange: (ds) => {
            onChange({
              ...value,
              datasourceUid: ds.uid
            });
          },
          current: value.datasourceUid
        }
      )
    ] })
  ] });
};
function useInternalLink(datasourceUid) {
  const [showInternalLink, setShowInternalLink] = React.useState(!!datasourceUid);
  const previousUid = reactUse.usePrevious(datasourceUid);
  React.useEffect(() => {
    if (!previousUid && datasourceUid && !showInternalLink) {
      setShowInternalLink(true);
    }
    if (previousUid && !datasourceUid && showInternalLink) {
      setShowInternalLink(false);
    }
  }, [previousUid, datasourceUid, showInternalLink]);
  return [showInternalLink, setShowInternalLink];
}

const getStyles$o = (theme) => ({
  infoText: css.css`
    padding-bottom: ${theme.v1.spacing.md};
    color: ${theme.v1.colors.textWeak};
  `,
  dataLink: css.css`
    margin-bottom: ${theme.v1.spacing.sm};
  `
});
const DataLinks = (props) => {
  const { value, onChange } = props;
  const theme = ui.useTheme2();
  const styles = getStyles$o(theme);
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "page-heading", children: "Data links" }),
    /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.infoText, children: "Add links to existing fields. Links will be shown in log row details next to the field value." }),
    /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gf-form-group", children: [
      value && value.map((field, index) => {
        return /* @__PURE__ */ jsxRuntime.jsx(
          DataLink,
          {
            className: styles.dataLink,
            value: field,
            onChange: (newField) => {
              const newDataLinks = [...value];
              newDataLinks.splice(index, 1, newField);
              onChange(newDataLinks);
            },
            onDelete: () => {
              const newDataLinks = [...value];
              newDataLinks.splice(index, 1);
              onChange(newDataLinks);
            },
            suggestions: [
              {
                value: data.DataLinkBuiltInVars.valueRaw,
                label: "Raw value",
                documentation: "Raw value of the field",
                origin: data.VariableOrigin.Value
              }
            ]
          },
          index
        );
      }),
      /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          variant: "secondary",
          className: css.css`
              margin-right: 10px;
            `,
          icon: "plus",
          onClick: (event) => {
            event.preventDefault();
            const newDataLinks = [...value || [], { field: "", label: "", matcherRegex: "", url: "" }];
            onChange(newDataLinks);
          },
          children: "Add"
        }
      ) })
    ] })
  ] });
};

var QueryEditorPropertyType = /* @__PURE__ */ ((QueryEditorPropertyType2) => {
  QueryEditorPropertyType2["String"] = "string";
  return QueryEditorPropertyType2;
})(QueryEditorPropertyType || {});
var QueryEditorExpressionType = /* @__PURE__ */ ((QueryEditorExpressionType2) => {
  QueryEditorExpressionType2["Property"] = "property";
  QueryEditorExpressionType2["Operator"] = "operator";
  QueryEditorExpressionType2["Or"] = "or";
  QueryEditorExpressionType2["And"] = "and";
  QueryEditorExpressionType2["GroupBy"] = "groupBy";
  QueryEditorExpressionType2["Function"] = "function";
  QueryEditorExpressionType2["FunctionParameter"] = "functionParameter";
  return QueryEditorExpressionType2;
})(QueryEditorExpressionType || {});

function getRawSqlFn(db) {
  return db.toRawSql ? db.toRawSql : (query) => toRawSql(query, Boolean(db.disableDatasets));
}
function toRawSql({ sql, dataset, catalog, table }, disableDatasets) {
  var _a, _b, _c, _d;
  let rawQuery = "";
  if (!sql || !haveColumns(sql.columns)) {
    return rawQuery;
  }
  rawQuery += createSelectClause(sql.columns);
  if (catalog && dataset && table) {
    rawQuery += `FROM ${catalog}.${dataset}.${table} `;
  } else if (!disableDatasets && dataset && table) {
    rawQuery += `FROM ${dataset}.${table} `;
  } else if (table) {
    rawQuery += `FROM ${table} `;
  }
  if (sql.whereString) {
    rawQuery += `WHERE ${sql.whereString} `;
  }
  if ((_b = (_a = sql.groupBy) == null ? undefined : _a[0]) == null ? undefined : _b.property.name) {
    const groupBy = sql.groupBy.map((g) => g.property.name).filter((g) => !lodash.isEmpty(g));
    rawQuery += `GROUP BY ${groupBy.join(", ")} `;
  }
  if ((_c = sql.orderBy) == null ? undefined : _c.property.name) {
    rawQuery += `ORDER BY ${sql.orderBy.property.name} `;
  }
  if (((_d = sql.orderBy) == null ? undefined : _d.property.name) && sql.orderByDirection) {
    rawQuery += `${sql.orderByDirection} `;
  }
  if (sql.limit !== undefined && sql.limit >= 0) {
    rawQuery += `LIMIT ${sql.limit} `;
  }
  return rawQuery;
}
function createSelectClause(sqlColumns) {
  const columns = sqlColumns.map((c) => {
    var _a, _b;
    let rawColumn = "";
    if (c.name) {
      rawColumn += `${c.name}(${(_a = c.parameters) == null ? undefined : _a.map((p) => `${p.name}`)})`;
    } else {
      rawColumn += `${(_b = c.parameters) == null ? undefined : _b.map((p) => `${p.name}`)}`;
    }
    return rawColumn;
  });
  return `SELECT ${columns.join(", ")} `;
}
function haveColumns(columns) {
  if (!columns) {
    return false;
  }
  const haveColumn = columns.some((c) => {
    var _a, _b;
    return ((_a = c.parameters) == null ? undefined : _a.length) || ((_b = c.parameters) == null ? undefined : _b.some((p) => p.name));
  });
  const haveFunction = columns.some((c) => c.name);
  return haveColumn || haveFunction;
}
function setGroupByField(field) {
  return {
    type: QueryEditorExpressionType.GroupBy,
    property: {
      type: QueryEditorPropertyType.String,
      name: field
    }
  };
}
function setPropertyField(field) {
  return {
    type: QueryEditorExpressionType.Property,
    property: {
      type: QueryEditorPropertyType.String,
      name: field
    }
  };
}
function createFunctionField(functionName) {
  return {
    type: QueryEditorExpressionType.Function,
    name: functionName,
    parameters: []
  };
}

function applyQueryDefaults(q) {
  let editorMode = (q == null ? undefined : q.editorMode) || EditorMode.Builder;
  if ((q == null ? undefined : q.editorMode) === undefined && (q == null ? undefined : q.rawSql) !== undefined) {
    editorMode = EditorMode.Code;
  }
  const result = {
    ...q,
    refId: (q == null ? undefined : q.refId) || "A",
    format: (q == null ? undefined : q.format) !== undefined ? q.format : QueryFormat.Table,
    rawSql: (q == null ? undefined : q.rawSql) || "",
    editorMode,
    sql: (q == null ? undefined : q.sql) || {
      columns: [createFunctionField()],
      groupBy: [setGroupByField()],
      limit: 50
    }
  };
  return result;
}

class LinkedToken {
  constructor(type, value, range, previous, next) {
    this.type = type;
    this.value = value;
    this.range = range;
    this.previous = previous;
    this.next = next;
  }
  isKeyword() {
    return this.type === TokenType.Keyword;
  }
  isWhiteSpace() {
    return this.type === TokenType.Whitespace;
  }
  isParenthesis() {
    return this.type === TokenType.Parenthesis;
  }
  isIdentifier() {
    return this.type === TokenType.Identifier;
  }
  isString() {
    return this.type === TokenType.String;
  }
  isNumber() {
    return this.type === TokenType.Number;
  }
  isDoubleQuotedString() {
    return this.type === TokenType.Type;
  }
  isVariable() {
    return this.type === TokenType.Variable;
  }
  isFunction() {
    return this.type === TokenType.Function;
  }
  isOperator() {
    return this.type === TokenType.Operator;
  }
  isTemplateVariable() {
    return this.type === TokenType.Variable;
  }
  is(type, value) {
    const isType = this.type === type;
    return value !== undefined ? isType && compareTokenWithValue(type, this, value) : isType;
  }
  getPreviousNonWhiteSpaceToken() {
    let curr = this.previous;
    while (curr != null) {
      if (!curr.isWhiteSpace()) {
        return curr;
      }
      curr = curr.previous;
    }
    return null;
  }
  getPreviousOfType(type, value) {
    let curr = this.previous;
    while (curr != null) {
      const isType = curr.type === type;
      if (value !== undefined ? isType && compareTokenWithValue(type, curr, value) : isType) {
        return curr;
      }
      curr = curr.previous;
    }
    return null;
  }
  getPreviousUntil(type, ignoreTypes, value) {
    let tokens = [];
    let curr = this.previous;
    while (curr != null) {
      if (ignoreTypes.some((t) => t === (curr == null ? undefined : curr.type))) {
        curr = curr.previous;
        continue;
      }
      const isType = curr.type === type;
      if (value !== undefined ? isType && compareTokenWithValue(type, curr, value) : isType) {
        return tokens;
      }
      if (!curr.isWhiteSpace()) {
        tokens.push(curr);
      }
      curr = curr.previous;
    }
    return tokens;
  }
  getNextUntil(type, ignoreTypes, value) {
    let tokens = [];
    let curr = this.next;
    while (curr != null) {
      if (ignoreTypes.some((t) => t === (curr == null ? undefined : curr.type))) {
        curr = curr.next;
        continue;
      }
      const isType = curr.type === type;
      if (value !== undefined ? isType && compareTokenWithValue(type, curr, value) : isType) {
        return tokens;
      }
      if (!curr.isWhiteSpace()) {
        tokens.push(curr);
      }
      curr = curr.next;
    }
    return tokens;
  }
  getPreviousKeyword() {
    let curr = this.previous;
    while (curr != null) {
      if (curr.isKeyword()) {
        return curr;
      }
      curr = curr.previous;
    }
    return null;
  }
  getNextNonWhiteSpaceToken() {
    let curr = this.next;
    while (curr != null) {
      if (!curr.isWhiteSpace()) {
        return curr;
      }
      curr = curr.next;
    }
    return null;
  }
  getNextOfType(type, value) {
    let curr = this.next;
    while (curr != null) {
      const isType = curr.type === type;
      if (value !== undefined ? isType && compareTokenWithValue(type, curr, value) : isType) {
        return curr;
      }
      curr = curr.next;
    }
    return null;
  }
}
function compareTokenWithValue(type, token, value) {
  return type === TokenType.Keyword || type === TokenType.Operator ? token.value.toLowerCase() === value.toString().toLowerCase() : token.value === value;
}

var OperatorType = /* @__PURE__ */ ((OperatorType2) => {
  OperatorType2[OperatorType2["Comparison"] = 0] = "Comparison";
  OperatorType2[OperatorType2["Logical"] = 1] = "Logical";
  return OperatorType2;
})(OperatorType || {});
var MacroType = /* @__PURE__ */ ((MacroType2) => {
  MacroType2[MacroType2["Value"] = 0] = "Value";
  MacroType2[MacroType2["Filter"] = 1] = "Filter";
  MacroType2[MacroType2["Group"] = 2] = "Group";
  MacroType2[MacroType2["Column"] = 3] = "Column";
  MacroType2[MacroType2["Table"] = 4] = "Table";
  return MacroType2;
})(MacroType || {});
var TokenType = /* @__PURE__ */ ((TokenType2) => {
  TokenType2["Parenthesis"] = "delimiter.parenthesis.sql";
  TokenType2["Whitespace"] = "white.sql";
  TokenType2["Keyword"] = "keyword.sql";
  TokenType2["Delimiter"] = "delimiter.sql";
  TokenType2["Operator"] = "operator.sql";
  TokenType2["Identifier"] = "identifier.sql";
  TokenType2["IdentifierQuote"] = "identifier.quote.sql";
  TokenType2["Type"] = "type.sql";
  TokenType2["Function"] = "predefined.sql";
  TokenType2["Number"] = "number.sql";
  TokenType2["String"] = "string.sql";
  TokenType2["Variable"] = "variable.sql";
  return TokenType2;
})(TokenType || {});
var StatementPosition = /* @__PURE__ */ ((StatementPosition2) => {
  StatementPosition2["Unknown"] = "unknown";
  StatementPosition2["SelectKeyword"] = "selectKeyword";
  StatementPosition2["WithKeyword"] = "withKeyword";
  StatementPosition2["AfterSelectKeyword"] = "afterSelectKeyword";
  StatementPosition2["AfterSelectArguments"] = "afterSelectArguments";
  StatementPosition2["AfterSelectFuncFirstArgument"] = "afterSelectFuncFirstArgument";
  StatementPosition2["SelectAlias"] = "selectAlias";
  StatementPosition2["AfterFromKeyword"] = "afterFromKeyword";
  StatementPosition2["AfterTable"] = "afterTable";
  StatementPosition2["SchemaFuncFirstArgument"] = "schemaFuncFirstArgument";
  StatementPosition2["SchemaFuncExtraArgument"] = "schemaFuncExtraArgument";
  StatementPosition2["FromKeyword"] = "fromKeyword";
  StatementPosition2["AfterFrom"] = "afterFrom";
  StatementPosition2["WhereKeyword"] = "whereKeyword";
  StatementPosition2["WhereComparisonOperator"] = "whereComparisonOperator";
  StatementPosition2["WhereValue"] = "whereValue";
  StatementPosition2["AfterWhereFunctionArgument"] = "afterWhereFunctionArgument";
  StatementPosition2["AfterGroupByFunctionArgument"] = "afterGroupByFunctionArgument";
  StatementPosition2["AfterWhereValue"] = "afterWhereValue";
  StatementPosition2["AfterGroupByKeywords"] = "afterGroupByKeywords";
  StatementPosition2["AfterGroupBy"] = "afterGroupBy";
  StatementPosition2["AfterOrderByKeywords"] = "afterOrderByKeywords";
  StatementPosition2["AfterOrderByFunction"] = "afterOrderByFunction";
  StatementPosition2["AfterOrderByDirection"] = "afterOrderByDirection";
  StatementPosition2["AfterIsOperator"] = "afterIsOperator";
  StatementPosition2["AfterIsNotOperator"] = "afterIsNotOperator";
  StatementPosition2["AfterSchema"] = "afterSchema";
  return StatementPosition2;
})(StatementPosition || {});
var SuggestionKind = /* @__PURE__ */ ((SuggestionKind2) => {
  SuggestionKind2["Schemas"] = "schemas";
  SuggestionKind2["Tables"] = "tables";
  SuggestionKind2["Columns"] = "columns";
  SuggestionKind2["SelectKeyword"] = "selectKeyword";
  SuggestionKind2["WithKeyword"] = "withKeyword";
  SuggestionKind2["FunctionsWithArguments"] = "functionsWithArguments";
  SuggestionKind2["FromKeyword"] = "fromKeyword";
  SuggestionKind2["WhereKeyword"] = "whereKeyword";
  SuggestionKind2["GroupByKeywords"] = "groupByKeywords";
  SuggestionKind2["OrderByKeywords"] = "orderByKeywords";
  SuggestionKind2["FunctionsWithoutArguments"] = "functionsWithoutArguments";
  SuggestionKind2["LimitKeyword"] = "limitKeyword";
  SuggestionKind2["SortOrderDirectionKeyword"] = "sortOrderDirectionKeyword";
  SuggestionKind2["ComparisonOperators"] = "comparisonOperators";
  SuggestionKind2["LogicalOperators"] = "logicalOperators";
  SuggestionKind2["SelectMacro"] = "selectMacro";
  SuggestionKind2["TableMacro"] = "tableMacro";
  SuggestionKind2["FilterMacro"] = "filterMacro";
  SuggestionKind2["GroupMacro"] = "groupMacro";
  SuggestionKind2["BoolValues"] = "boolValues";
  SuggestionKind2["NullValue"] = "nullValue";
  SuggestionKind2["NotKeyword"] = "notKeyword";
  SuggestionKind2["TemplateVariables"] = "templateVariables";
  SuggestionKind2["StarWildCard"] = "starWildCard";
  return SuggestionKind2;
})(SuggestionKind || {});
var CompletionItemPriority = /* @__PURE__ */ ((CompletionItemPriority2) => {
  CompletionItemPriority2["High"] = "a";
  CompletionItemPriority2["MediumHigh"] = "d";
  CompletionItemPriority2["Medium"] = "g";
  CompletionItemPriority2["MediumLow"] = "k";
  CompletionItemPriority2["Low"] = "q";
  return CompletionItemPriority2;
})(CompletionItemPriority || {});
var CompletionItemKind = /* @__PURE__ */ ((CompletionItemKind2) => {
  CompletionItemKind2[CompletionItemKind2["Method"] = 0] = "Method";
  CompletionItemKind2[CompletionItemKind2["Function"] = 1] = "Function";
  CompletionItemKind2[CompletionItemKind2["Constructor"] = 2] = "Constructor";
  CompletionItemKind2[CompletionItemKind2["Field"] = 3] = "Field";
  CompletionItemKind2[CompletionItemKind2["Variable"] = 4] = "Variable";
  CompletionItemKind2[CompletionItemKind2["Class"] = 5] = "Class";
  CompletionItemKind2[CompletionItemKind2["Struct"] = 6] = "Struct";
  CompletionItemKind2[CompletionItemKind2["Interface"] = 7] = "Interface";
  CompletionItemKind2[CompletionItemKind2["Module"] = 8] = "Module";
  CompletionItemKind2[CompletionItemKind2["Property"] = 9] = "Property";
  CompletionItemKind2[CompletionItemKind2["Event"] = 10] = "Event";
  CompletionItemKind2[CompletionItemKind2["Operator"] = 11] = "Operator";
  CompletionItemKind2[CompletionItemKind2["Unit"] = 12] = "Unit";
  CompletionItemKind2[CompletionItemKind2["Value"] = 13] = "Value";
  CompletionItemKind2[CompletionItemKind2["Constant"] = 14] = "Constant";
  CompletionItemKind2[CompletionItemKind2["Enum"] = 15] = "Enum";
  CompletionItemKind2[CompletionItemKind2["EnumMember"] = 16] = "EnumMember";
  CompletionItemKind2[CompletionItemKind2["Keyword"] = 17] = "Keyword";
  CompletionItemKind2[CompletionItemKind2["Text"] = 18] = "Text";
  CompletionItemKind2[CompletionItemKind2["Color"] = 19] = "Color";
  CompletionItemKind2[CompletionItemKind2["File"] = 20] = "File";
  CompletionItemKind2[CompletionItemKind2["Reference"] = 21] = "Reference";
  CompletionItemKind2[CompletionItemKind2["Customcolor"] = 22] = "Customcolor";
  CompletionItemKind2[CompletionItemKind2["Folder"] = 23] = "Folder";
  CompletionItemKind2[CompletionItemKind2["TypeParameter"] = 24] = "TypeParameter";
  CompletionItemKind2[CompletionItemKind2["User"] = 25] = "User";
  CompletionItemKind2[CompletionItemKind2["Issue"] = 26] = "Issue";
  CompletionItemKind2[CompletionItemKind2["Snippet"] = 27] = "Snippet";
  return CompletionItemKind2;
})(CompletionItemKind || {});
var CompletionItemInsertTextRule = /* @__PURE__ */ ((CompletionItemInsertTextRule2) => {
  CompletionItemInsertTextRule2[CompletionItemInsertTextRule2["KeepWhitespace"] = 1] = "KeepWhitespace";
  CompletionItemInsertTextRule2[CompletionItemInsertTextRule2["InsertAsSnippet"] = 4] = "InsertAsSnippet";
  return CompletionItemInsertTextRule2;
})(CompletionItemInsertTextRule || {});
var SQLEditorMode = /* @__PURE__ */ ((SQLEditorMode2) => {
  SQLEditorMode2["Builder"] = "builder";
  SQLEditorMode2["Code"] = "code";
  return SQLEditorMode2;
})(SQLEditorMode || {});

function getStatementPosition(currentToken, statementPositionResolversRegistry) {
  var _a;
  const previousNonWhiteSpace = currentToken == null ? undefined : currentToken.getPreviousNonWhiteSpaceToken();
  const previousKeyword = currentToken == null ? undefined : currentToken.getPreviousKeyword();
  const previousIsSlash = (_a = currentToken == null ? undefined : currentToken.getPreviousNonWhiteSpaceToken()) == null ? undefined : _a.is(TokenType.Operator, "/");
  const resolvers = statementPositionResolversRegistry.list();
  const positions = [];
  for (const resolver of resolvers) {
    if (resolver.resolve(currentToken, previousKeyword != null ? previousKeyword : null, previousNonWhiteSpace != null ? previousNonWhiteSpace : null, Boolean(previousIsSlash))) {
      positions.push(resolver.id);
    }
  }
  if (positions.length === 0) {
    return [StatementPosition.Unknown];
  }
  return positions;
}

const toCompletionItem = (value, range, rest = {}) => {
  const item = {
    label: value,
    insertText: value,
    kind: CompletionItemKind.Field,
    sortText: CompletionItemPriority.Medium,
    range,
    ...rest
  };
  return item;
};

const getStandardSuggestions = async (monaco, currentToken, suggestionKinds, positionContext, suggestionsRegistry) => {
  let suggestions = [];
  const invalidRangeToken = (currentToken == null ? undefined : currentToken.isWhiteSpace()) || (currentToken == null ? undefined : currentToken.isParenthesis()) || (currentToken == null ? undefined : currentToken.isIdentifier()) && currentToken.value.endsWith(".");
  const range = invalidRangeToken || !(currentToken == null ? undefined : currentToken.range) ? monaco.Range.fromPositions(positionContext.position) : currentToken == null ? undefined : currentToken.range;
  for (const suggestion of [...new Set(suggestionKinds)]) {
    const registeredSuggestions = suggestionsRegistry.getIfExists(suggestion);
    if (registeredSuggestions) {
      const su = await registeredSuggestions.suggestions({ ...positionContext, range }, monaco);
      suggestions = [...suggestions, ...su.map((s) => toCompletionItem(s.label, range, { kind: s.kind, ...s }))];
    }
  }
  return Promise.resolve(suggestions);
};

const initSuggestionsKindRegistry = () => {
  return [
    {
      id: StatementPosition.SelectKeyword,
      name: StatementPosition.SelectKeyword,
      kind: [SuggestionKind.SelectKeyword]
    },
    {
      id: StatementPosition.WithKeyword,
      name: StatementPosition.WithKeyword,
      kind: [SuggestionKind.WithKeyword]
    },
    {
      id: StatementPosition.AfterSelectKeyword,
      name: StatementPosition.AfterSelectKeyword,
      kind: [
        SuggestionKind.StarWildCard,
        SuggestionKind.FunctionsWithArguments,
        SuggestionKind.Columns,
        SuggestionKind.SelectMacro
      ]
    },
    {
      id: StatementPosition.AfterSelectFuncFirstArgument,
      name: StatementPosition.AfterSelectFuncFirstArgument,
      kind: [SuggestionKind.Columns]
    },
    {
      id: StatementPosition.AfterGroupByFunctionArgument,
      name: StatementPosition.AfterGroupByFunctionArgument,
      kind: [SuggestionKind.Columns]
    },
    {
      id: StatementPosition.AfterWhereFunctionArgument,
      name: StatementPosition.AfterWhereFunctionArgument,
      kind: [SuggestionKind.Columns]
    },
    {
      id: StatementPosition.AfterSelectArguments,
      name: StatementPosition.AfterSelectArguments,
      kind: [SuggestionKind.Columns]
    },
    {
      id: StatementPosition.AfterFromKeyword,
      name: StatementPosition.AfterFromKeyword,
      kind: [SuggestionKind.Schemas, SuggestionKind.Tables, SuggestionKind.TableMacro]
    },
    {
      id: StatementPosition.AfterSchema,
      name: StatementPosition.AfterSchema,
      kind: [SuggestionKind.Tables, SuggestionKind.TableMacro]
    },
    {
      id: StatementPosition.SelectAlias,
      name: StatementPosition.SelectAlias,
      kind: [SuggestionKind.Columns, SuggestionKind.FunctionsWithArguments]
    },
    {
      id: StatementPosition.FromKeyword,
      name: StatementPosition.FromKeyword,
      kind: [SuggestionKind.FromKeyword]
    },
    {
      id: StatementPosition.AfterFrom,
      name: StatementPosition.AfterFrom,
      kind: [
        SuggestionKind.WhereKeyword,
        SuggestionKind.GroupByKeywords,
        SuggestionKind.OrderByKeywords,
        SuggestionKind.LimitKeyword
      ]
    },
    {
      id: StatementPosition.AfterTable,
      name: StatementPosition.AfterTable,
      kind: [
        SuggestionKind.WhereKeyword,
        SuggestionKind.GroupByKeywords,
        SuggestionKind.OrderByKeywords,
        SuggestionKind.LimitKeyword
      ]
    },
    {
      id: StatementPosition.WhereKeyword,
      name: StatementPosition.WhereKeyword,
      kind: [SuggestionKind.Columns, SuggestionKind.FilterMacro, SuggestionKind.TemplateVariables]
    },
    {
      id: StatementPosition.WhereComparisonOperator,
      name: StatementPosition.WhereComparisonOperator,
      kind: [SuggestionKind.ComparisonOperators]
    },
    {
      id: StatementPosition.WhereValue,
      name: StatementPosition.WhereValue,
      kind: [SuggestionKind.FilterMacro, SuggestionKind.TemplateVariables]
    },
    {
      id: StatementPosition.AfterWhereValue,
      name: StatementPosition.AfterWhereValue,
      kind: [
        SuggestionKind.LogicalOperators,
        SuggestionKind.GroupByKeywords,
        SuggestionKind.OrderByKeywords,
        SuggestionKind.LimitKeyword,
        SuggestionKind.Columns,
        SuggestionKind.TemplateVariables
      ]
    },
    {
      id: StatementPosition.AfterGroupByKeywords,
      name: StatementPosition.AfterGroupByKeywords,
      kind: [SuggestionKind.GroupMacro, SuggestionKind.Columns]
    },
    {
      id: StatementPosition.AfterGroupBy,
      name: StatementPosition.AfterGroupBy,
      kind: [SuggestionKind.OrderByKeywords, SuggestionKind.LimitKeyword]
    },
    {
      id: StatementPosition.AfterOrderByKeywords,
      name: StatementPosition.AfterOrderByKeywords,
      kind: [SuggestionKind.Columns]
    },
    {
      id: StatementPosition.AfterOrderByFunction,
      name: StatementPosition.AfterOrderByFunction,
      kind: [SuggestionKind.SortOrderDirectionKeyword, SuggestionKind.LimitKeyword]
    },
    {
      id: StatementPosition.AfterOrderByDirection,
      name: StatementPosition.AfterOrderByDirection,
      kind: [SuggestionKind.LimitKeyword]
    },
    {
      id: StatementPosition.AfterIsOperator,
      name: StatementPosition.AfterOrderByDirection,
      kind: [SuggestionKind.NotKeyword, SuggestionKind.NullValue, SuggestionKind.BoolValues]
    },
    {
      id: StatementPosition.AfterIsNotOperator,
      name: StatementPosition.AfterOrderByDirection,
      kind: [SuggestionKind.NullValue, SuggestionKind.BoolValues]
    }
  ];
};

function getSuggestionKinds(statementPosition, suggestionsKindRegistry) {
  let result = [];
  for (let i = 0; i < statementPosition.length; i++) {
    const exists = suggestionsKindRegistry.getIfExists(statementPosition[i]);
    if (exists) {
      result = result.concat(exists.kind);
    }
  }
  return result;
}

function linkedTokenBuilder(monaco, model, position, languageId = "sql") {
  var _a;
  let current = null;
  let previous = null;
  const tokensPerLine = monaco.editor.tokenize((_a = model.getValue()) != null ? _a : "", languageId);
  for (let lineIndex = 0; lineIndex < tokensPerLine.length; lineIndex++) {
    const tokens = tokensPerLine[lineIndex];
    if (!tokens.length && previous) {
      const token = {
        offset: 0,
        type: TokenType.Whitespace,
        language: languageId,
        _tokenBrand: undefined
      };
      tokens.push(token);
    }
    for (let columnIndex = 0; columnIndex < tokens.length; columnIndex++) {
      const token = tokens[columnIndex];
      let endColumn = tokens.length > columnIndex + 1 ? tokens[columnIndex + 1].offset + 1 : model.getLineLength(lineIndex + 1) + 1;
      const range = {
        startLineNumber: lineIndex + 1,
        startColumn: token.offset === 0 ? 0 : token.offset + 1,
        endLineNumber: lineIndex + 1,
        endColumn
      };
      const value = model.getValueInRange(range);
      const sqlToken = new LinkedToken(token.type, value, range, previous, null);
      if (monaco.Range.containsPosition(range, position)) {
        current = sqlToken;
      }
      if (previous) {
        previous.next = sqlToken;
      }
      previous = sqlToken;
    }
  }
  return current;
}

const SELECT = "select";
const FROM = "from";
const WHERE = "where";
const GROUP = "group";
const ORDER = "order";
const BY = "by";
const DESC = "desc";
const ASC = "asc";
const LIMIT = "limit";
const WITH = "with";
const AS = "as";
const SCHEMA = "schema";
const AND = "AND";
const OR = "OR";
const LOGICAL_OPERATORS = [AND, OR];
const EQUALS = "=";
const NOT_EQUALS = "!=";
const COMPARISON_OPERATORS = [EQUALS, NOT_EQUALS];
const STD_OPERATORS = [...COMPARISON_OPERATORS];
const conf = {
  comments: {
    lineComment: "--",
    blockComment: ["/*", "*/"]
  },
  brackets: [
    ["{", "}"],
    ["[", "]"],
    ["(", ")"]
  ],
  autoClosingPairs: [
    { open: "{", close: "}" },
    { open: "[", close: "]" },
    { open: "(", close: ")" },
    { open: '"', close: '"' },
    { open: "'", close: "'" }
  ],
  surroundingPairs: [
    { open: "{", close: "}" },
    { open: "[", close: "]" },
    { open: "(", close: ")" },
    { open: '"', close: '"' },
    { open: "'", close: "'" }
  ]
};
const language = {
  defaultToken: "",
  tokenPostfix: ".sql",
  ignoreCase: true,
  brackets: [
    { open: "[", close: "]", token: "delimiter.square" },
    { open: "(", close: ")", token: "delimiter.parenthesis" }
  ],
  keywords: [
    "ABORT",
    "ABSOLUTE",
    "ACTION",
    "ADA",
    "ADD",
    "AFTER",
    "ALL",
    "ALLOCATE",
    "ALTER",
    "ALWAYS",
    "ANALYZE",
    "AND",
    "ANY",
    "ARE",
    "AS",
    "ASC",
    "ASSERTION",
    "AT",
    "ATTACH",
    "AUTHORIZATION",
    "AUTOINCREMENT",
    "AVG",
    "BACKUP",
    "BEFORE",
    "BEGIN",
    "BETWEEN",
    "BIT",
    "BIT_LENGTH",
    "BOTH",
    "BREAK",
    "BROWSE",
    "BULK",
    "BY",
    "CASCADE",
    "CASCADED",
    "CASE",
    "CAST",
    "CATALOG",
    "CHAR",
    "CHARACTER",
    "CHARACTER_LENGTH",
    "CHAR_LENGTH",
    "CHECK",
    "CHECKPOINT",
    "CLOSE",
    "CLUSTERED",
    "COALESCE",
    "COLLATE",
    "COLLATION",
    "COLUMN",
    "COMMIT",
    "COMPUTE",
    "CONFLICT",
    "CONNECT",
    "CONNECTION",
    "CONSTRAINT",
    "CONSTRAINTS",
    "CONTAINS",
    "CONTAINSTABLE",
    "CONTINUE",
    "CONVERT",
    "CORRESPONDING",
    "COUNT",
    "CREATE",
    "CROSS",
    "CURRENT",
    "CURRENT_DATE",
    "CURRENT_TIME",
    "CURRENT_TIMESTAMP",
    "CURRENT_USER",
    "CURSOR",
    "DATABASE",
    "DATE",
    "DAY",
    "DBCC",
    "DEALLOCATE",
    "DEC",
    "DECIMAL",
    "DECLARE",
    "DEFAULT",
    "DEFERRABLE",
    "DEFERRED",
    "DELETE",
    "DENY",
    "DESC",
    "DESCRIBE",
    "DESCRIPTOR",
    "DETACH",
    "DIAGNOSTICS",
    "DISCONNECT",
    "DISK",
    "DISTINCT",
    "DISTRIBUTED",
    "DO",
    "DOMAIN",
    "DOUBLE",
    "DROP",
    "DUMP",
    "EACH",
    "ELSE",
    "END",
    "END-EXEC",
    "ERRLVL",
    "ESCAPE",
    "EXCEPT",
    "EXCEPTION",
    "EXCLUDE",
    "EXCLUSIVE",
    "EXEC",
    "EXECUTE",
    "EXISTS",
    "EXIT",
    "EXPLAIN",
    "EXTERNAL",
    "EXTRACT",
    "FAIL",
    "FALSE",
    "FETCH",
    "FILE",
    "FILLFACTOR",
    "FILTER",
    "FIRST",
    "FLOAT",
    "FOLLOWING",
    "FOR",
    "FOREIGN",
    "FORTRAN",
    "FOUND",
    "FREETEXT",
    "FREETEXTTABLE",
    "FROM",
    "FULL",
    "FUNCTION",
    "GENERATED",
    "GET",
    "GLOB",
    "GLOBAL",
    "GO",
    "GOTO",
    "GRANT",
    "GROUP",
    "GROUPS",
    "HAVING",
    "HOLDLOCK",
    "HOUR",
    "IDENTITY",
    "IDENTITYCOL",
    "IDENTITY_INSERT",
    "IF",
    "IGNORE",
    "IMMEDIATE",
    "IN",
    "INCLUDE",
    "INDEX",
    "INDEXED",
    "INDICATOR",
    "INITIALLY",
    "INNER",
    "INPUT",
    "INSENSITIVE",
    "INSERT",
    "INSTEAD",
    "INT",
    "INTEGER",
    "INTERSECT",
    "INTERVAL",
    "INTO",
    "IS",
    "ISNULL",
    "ISOLATION",
    "JOIN",
    "KEY",
    "KILL",
    "LANGUAGE",
    "LAST",
    "LEADING",
    "LEFT",
    "LEVEL",
    "LIKE",
    "LIMIT",
    "LINENO",
    "LOAD",
    "LOCAL",
    "LOWER",
    "MATCH",
    "MATERIALIZED",
    "MAX",
    "MERGE",
    "MIN",
    "MINUTE",
    "MODULE",
    "MONTH",
    "NAMES",
    "NATIONAL",
    "NATURAL",
    "NCHAR",
    "NEXT",
    "NO",
    "NOCHECK",
    "NONCLUSTERED",
    "NONE",
    "NOT",
    "NOTHING",
    "NOTNULL",
    "NULL",
    "NULLIF",
    "NULLS",
    "NUMERIC",
    "OCTET_LENGTH",
    "OF",
    "OFF",
    "OFFSET",
    "OFFSETS",
    "ON",
    "ONLY",
    "OPEN",
    "OPENDATASOURCE",
    "OPENQUERY",
    "OPENROWSET",
    "OPENXML",
    "OPTION",
    "OR",
    "ORDER",
    "OTHERS",
    "OUTER",
    "OUTPUT",
    "OVER",
    "OVERLAPS",
    "PAD",
    "PARTIAL",
    "PARTITION",
    "PASCAL",
    "PERCENT",
    "PIVOT",
    "PLAN",
    "POSITION",
    "PRAGMA",
    "PRECEDING",
    "PRECISION",
    "PREPARE",
    "PRESERVE",
    "PRIMARY",
    "PRINT",
    "PRIOR",
    "PRIVILEGES",
    "PROC",
    "PROCEDURE",
    "PUBLIC",
    "QUERY",
    "RAISE",
    "RAISERROR",
    "RANGE",
    "READ",
    "READTEXT",
    "REAL",
    "RECONFIGURE",
    "RECURSIVE",
    "REFERENCES",
    "REGEXP",
    "REINDEX",
    "RELATIVE",
    "RELEASE",
    "RENAME",
    "REPLACE",
    "REPLICATION",
    "RESTORE",
    "RESTRICT",
    "RETURN",
    "RETURNING",
    "REVERT",
    "REVOKE",
    "RIGHT",
    "ROLLBACK",
    "ROW",
    "ROWCOUNT",
    "ROWGUIDCOL",
    "ROWS",
    "RULE",
    "SAVE",
    "SAVEPOINT",
    "SCHEMA",
    "SCROLL",
    "SECOND",
    "SECTION",
    "SECURITYAUDIT",
    "SELECT",
    "SEMANTICKEYPHRASETABLE",
    "SEMANTICSIMILARITYDETAILSTABLE",
    "SEMANTICSIMILARITYTABLE",
    "SESSION",
    "SESSION_USER",
    "SET",
    "SETUSER",
    "SHUTDOWN",
    "SIZE",
    "SMALLINT",
    "SOME",
    "SPACE",
    "SQL",
    "SQLCA",
    "SQLCODE",
    "SQLERROR",
    "SQLSTATE",
    "SQLWARNING",
    "STATISTICS",
    "SUBSTRING",
    "SUM",
    "SYSTEM_USER",
    "TABLE",
    "TABLESAMPLE",
    "TEMP",
    "TEMPORARY",
    "TEXTSIZE",
    "THEN",
    "TIES",
    "TIME",
    "TIMESTAMP",
    "TIMEZONE_HOUR",
    "TIMEZONE_MINUTE",
    "TO",
    "TOP",
    "TRAILING",
    "TRAN",
    "TRANSACTION",
    "TRANSLATE",
    "TRANSLATION",
    "TRIGGER",
    "TRIM",
    "TRUE",
    "TRUNCATE",
    "TRY_CONVERT",
    "TSEQUAL",
    "UNBOUNDED",
    "UNION",
    "UNIQUE",
    "UNKNOWN",
    "UNPIVOT",
    "UPDATE",
    "UPDATETEXT",
    "UPPER",
    "USAGE",
    "USE",
    "USER",
    "USING",
    "VACUUM",
    "VALUE",
    "VALUES",
    "VARCHAR",
    "VARYING",
    "VIEW",
    "VIRTUAL",
    "WAITFOR",
    "WHEN",
    "WHENEVER",
    "WHERE",
    "WHILE",
    "WINDOW",
    "WITH",
    "WITHIN GROUP",
    "WITHOUT",
    "WORK",
    "WRITE",
    "WRITETEXT",
    "YEAR",
    "ZONE"
  ],
  operators: [
    // Set
    "EXCEPT",
    "INTERSECT",
    "UNION",
    // Join
    "APPLY",
    "CROSS",
    "FULL",
    "INNER",
    "JOIN",
    "LEFT",
    "OUTER",
    "RIGHT",
    // Predicates
    "CONTAINS",
    "FREETEXT",
    "IS",
    "NULL",
    // Pivoting
    "PIVOT",
    "UNPIVOT",
    // Merging
    "MATCHED"
  ],
  logicalOperators: ["ALL", "AND", "ANY", "BETWEEN", "EXISTS", "IN", "LIKE", "NOT", "OR", "SOME"],
  comparisonOperators: ["<>", ">", "<", ">=", "<=", "=", "!=", "&", "~", "^", "%"],
  builtinFunctions: [
    // Aggregate
    "AVG",
    "CHECKSUM_AGG",
    "COUNT",
    "COUNT_BIG",
    "GROUPING",
    "GROUPING_ID",
    "MAX",
    "MIN",
    "SUM",
    "STDEV",
    "STDEVP",
    "VAR",
    "VARP",
    // Analytic
    "CUME_DIST",
    "FIRST_VALUE",
    "LAG",
    "LAST_VALUE",
    "LEAD",
    "PERCENTILE_CONT",
    "PERCENTILE_DISC",
    "PERCENT_RANK",
    // Collation
    "COLLATE",
    "COLLATIONPROPERTY",
    "TERTIARY_WEIGHTS",
    // Azure
    "FEDERATION_FILTERING_VALUE",
    // Conversion
    "CAST",
    "CONVERT",
    "PARSE",
    "TRY_CAST",
    "TRY_CONVERT",
    "TRY_PARSE",
    // Cryptographic
    "ASYMKEY_ID",
    "ASYMKEYPROPERTY",
    "CERTPROPERTY",
    "CERT_ID",
    "CRYPT_GEN_RANDOM",
    "DECRYPTBYASYMKEY",
    "DECRYPTBYCERT",
    "DECRYPTBYKEY",
    "DECRYPTBYKEYAUTOASYMKEY",
    "DECRYPTBYKEYAUTOCERT",
    "DECRYPTBYPASSPHRASE",
    "ENCRYPTBYASYMKEY",
    "ENCRYPTBYCERT",
    "ENCRYPTBYKEY",
    "ENCRYPTBYPASSPHRASE",
    "HASHBYTES",
    "IS_OBJECTSIGNED",
    "KEY_GUID",
    "KEY_ID",
    "KEY_NAME",
    "SIGNBYASYMKEY",
    "SIGNBYCERT",
    "SYMKEYPROPERTY",
    "VERIFYSIGNEDBYCERT",
    "VERIFYSIGNEDBYASYMKEY",
    // Cursor
    "CURSOR_STATUS",
    // Datatype
    "DATALENGTH",
    "IDENT_CURRENT",
    "IDENT_INCR",
    "IDENT_SEED",
    "IDENTITY",
    "SQL_VARIANT_PROPERTY",
    // Datetime
    "CURRENT_TIMESTAMP",
    "DATEADD",
    "DATEDIFF",
    "DATEFROMPARTS",
    "DATENAME",
    "DATEPART",
    "DATETIME2FROMPARTS",
    "DATETIMEFROMPARTS",
    "DATETIMEOFFSETFROMPARTS",
    "DAY",
    "EOMONTH",
    "GETDATE",
    "GETUTCDATE",
    "ISDATE",
    "MONTH",
    "SMALLDATETIMEFROMPARTS",
    "SWITCHOFFSET",
    "SYSDATETIME",
    "SYSDATETIMEOFFSET",
    "SYSUTCDATETIME",
    "TIMEFROMPARTS",
    "TODATETIMEOFFSET",
    "YEAR",
    // Logical
    "CHOOSE",
    "COALESCE",
    "IIF",
    "NULLIF",
    // Mathematical
    "ABS",
    "ACOS",
    "ASIN",
    "ATAN",
    "ATN2",
    "CEILING",
    "COS",
    "COT",
    "DEGREES",
    "EXP",
    "FLOOR",
    "LOG",
    "LOG10",
    "PI",
    "POWER",
    "RADIANS",
    "RAND",
    "ROUND",
    "SIGN",
    "SIN",
    "SQRT",
    "SQUARE",
    "TAN",
    // Metadata
    "APP_NAME",
    "APPLOCK_MODE",
    "APPLOCK_TEST",
    "ASSEMBLYPROPERTY",
    "COL_LENGTH",
    "COL_NAME",
    "COLUMNPROPERTY",
    "DATABASE_PRINCIPAL_ID",
    "DATABASEPROPERTYEX",
    "DB_ID",
    "DB_NAME",
    "FILE_ID",
    "FILE_IDEX",
    "FILE_NAME",
    "FILEGROUP_ID",
    "FILEGROUP_NAME",
    "FILEGROUPPROPERTY",
    "FILEPROPERTY",
    "FULLTEXTCATALOGPROPERTY",
    "FULLTEXTSERVICEPROPERTY",
    "INDEX_COL",
    "INDEXKEY_PROPERTY",
    "INDEXPROPERTY",
    "OBJECT_DEFINITION",
    "OBJECT_ID",
    "OBJECT_NAME",
    "OBJECT_SCHEMA_NAME",
    "OBJECTPROPERTY",
    "OBJECTPROPERTYEX",
    "ORIGINAL_DB_NAME",
    "PARSENAME",
    "SCHEMA_ID",
    "SCHEMA_NAME",
    "SCOPE_IDENTITY",
    "SERVERPROPERTY",
    "STATS_DATE",
    "TYPE_ID",
    "TYPE_NAME",
    "TYPEPROPERTY",
    // Ranking
    "DENSE_RANK",
    "NTILE",
    "RANK",
    "ROW_NUMBER",
    // Replication
    "PUBLISHINGSERVERNAME",
    // Rowset
    "OPENDATASOURCE",
    "OPENQUERY",
    "OPENROWSET",
    "OPENXML",
    // Security
    "CERTENCODED",
    "CERTPRIVATEKEY",
    "CURRENT_USER",
    "HAS_DBACCESS",
    "HAS_PERMS_BY_NAME",
    "IS_MEMBER",
    "IS_ROLEMEMBER",
    "IS_SRVROLEMEMBER",
    "LOGINPROPERTY",
    "ORIGINAL_LOGIN",
    "PERMISSIONS",
    "PWDENCRYPT",
    "PWDCOMPARE",
    "SESSION_USER",
    "SESSIONPROPERTY",
    "SUSER_ID",
    "SUSER_NAME",
    "SUSER_SID",
    "SUSER_SNAME",
    "SYSTEM_USER",
    "USER",
    "USER_ID",
    "USER_NAME",
    // String
    "ASCII",
    "CHAR",
    "CHARINDEX",
    "CONCAT",
    "DIFFERENCE",
    "FORMAT",
    "LEFT",
    "LEN",
    "LOWER",
    "LTRIM",
    "NCHAR",
    "PATINDEX",
    "QUOTENAME",
    "REPLACE",
    "REPLICATE",
    "REVERSE",
    "RIGHT",
    "RTRIM",
    "SOUNDEX",
    "SPACE",
    "STR",
    "STUFF",
    "SUBSTRING",
    "UNICODE",
    "UPPER",
    // System
    "BINARY_CHECKSUM",
    "CHECKSUM",
    "CONNECTIONPROPERTY",
    "CONTEXT_INFO",
    "CURRENT_REQUEST_ID",
    "ERROR_LINE",
    "ERROR_NUMBER",
    "ERROR_MESSAGE",
    "ERROR_PROCEDURE",
    "ERROR_SEVERITY",
    "ERROR_STATE",
    "FORMATMESSAGE",
    "GETANSINULL",
    "GET_FILESTREAM_TRANSACTION_CONTEXT",
    "HOST_ID",
    "HOST_NAME",
    "ISNULL",
    "ISNUMERIC",
    "MIN_ACTIVE_ROWVERSION",
    "NEWID",
    "NEWSEQUENTIALID",
    "ROWCOUNT_BIG",
    "XACT_STATE",
    // TextImage
    "TEXTPTR",
    "TEXTVALID",
    // Trigger
    "COLUMNS_UPDATED",
    "EVENTDATA",
    "TRIGGER_NESTLEVEL",
    "UPDATE",
    // ChangeTracking
    "CHANGETABLE",
    "CHANGE_TRACKING_CONTEXT",
    "CHANGE_TRACKING_CURRENT_VERSION",
    "CHANGE_TRACKING_IS_COLUMN_IN_MASK",
    "CHANGE_TRACKING_MIN_VALID_VERSION",
    // FullTextSearch
    "CONTAINSTABLE",
    "FREETEXTTABLE",
    // SemanticTextSearch
    "SEMANTICKEYPHRASETABLE",
    "SEMANTICSIMILARITYDETAILSTABLE",
    "SEMANTICSIMILARITYTABLE",
    // FileStream
    "FILETABLEROOTPATH",
    "GETFILENAMESPACEPATH",
    "GETPATHLOCATOR",
    "PATHNAME",
    // ServiceBroker
    "GET_TRANSMISSION_STATUS"
  ],
  builtinVariables: [
    // Configuration
    "@@DATEFIRST",
    "@@DBTS",
    "@@LANGID",
    "@@LANGUAGE",
    "@@LOCK_TIMEOUT",
    "@@MAX_CONNECTIONS",
    "@@MAX_PRECISION",
    "@@NESTLEVEL",
    "@@OPTIONS",
    "@@REMSERVER",
    "@@SERVERNAME",
    "@@SERVICENAME",
    "@@SPID",
    "@@TEXTSIZE",
    "@@VERSION",
    // Cursor
    "@@CURSOR_ROWS",
    "@@FETCH_STATUS",
    // Datetime
    "@@DATEFIRST",
    // Metadata
    "@@PROCID",
    // System
    "@@ERROR",
    "@@IDENTITY",
    "@@ROWCOUNT",
    "@@TRANCOUNT",
    // Stats
    "@@CONNECTIONS",
    "@@CPU_BUSY",
    "@@IDLE",
    "@@IO_BUSY",
    "@@PACKET_ERRORS",
    "@@PACK_RECEIVED",
    "@@PACK_SENT",
    "@@TIMETICKS",
    "@@TOTAL_ERRORS",
    "@@TOTAL_READ",
    "@@TOTAL_WRITE"
  ],
  pseudoColumns: ["$ACTION", "$IDENTITY", "$ROWGUID", "$PARTITION"],
  tokenizer: {
    root: [
      { include: "@templateVariables" },
      { include: "@macros" },
      { include: "@comments" },
      { include: "@whitespace" },
      { include: "@pseudoColumns" },
      { include: "@numbers" },
      { include: "@strings" },
      { include: "@complexIdentifiers" },
      { include: "@scopes" },
      { include: "@schemaTable" },
      [/[;,.]/, "delimiter"],
      [/[()]/, "@brackets"],
      [
        /[\w@#$|<|>|=|!|%|&|+|\|-|*|/|~|^]+/,
        {
          cases: {
            "@operators": "operator",
            "@comparisonOperators": "operator",
            "@logicalOperators": "operator",
            "@builtinVariables": "predefined",
            "@builtinFunctions": "predefined",
            "@keywords": "keyword",
            "@default": "identifier"
          }
        }
      ]
    ],
    templateVariables: [[/\$[a-zA-Z0-9]+/, "variable"]],
    macros: [[/\$__[a-zA-Z0-9-_]+/, "type"]],
    schemaTable: [
      [/(\w+)\./, "identifier"],
      [/(\w+\.\w+)/, "identifier"]
    ],
    whitespace: [[/\s+/, "white"]],
    comments: [
      [/--+.*/, "comment"],
      [/\/\*/, { token: "comment.quote", next: "@comment" }]
    ],
    comment: [
      [/[^*/]+/, "comment"],
      // Not supporting nested comments, as nested comments seem to not be standard?
      // i.e. http://stackoverflow.com/questions/728172/are-there-multiline-comment-delimiters-in-sql-that-are-vendor-agnostic
      // [/\/\*/, { token: 'comment.quote', next: '@push' }],    // nested comment not allowed :-(
      [/\*\//, { token: "comment.quote", next: "@pop" }],
      [/./, "comment"]
    ],
    pseudoColumns: [
      [
        /[$][A-Za-z_][\w@#$]*/,
        {
          cases: {
            "@pseudoColumns": "predefined",
            "@default": "identifier"
          }
        }
      ]
    ],
    numbers: [
      [/0[xX][0-9a-fA-F]*/, "number"],
      [/[$][+-]*\d*(\.\d*)?/, "number"],
      [/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/, "number"]
    ],
    strings: [
      [/N'/, { token: "string", next: "@string" }],
      [/'/, { token: "string", next: "@string" }]
    ],
    string: [
      [/[^']+/, "string"],
      [/''/, "string"],
      [/'/, { token: "string", next: "@pop" }]
    ],
    complexIdentifiers: [
      [/\[/, { token: "identifier.quote", next: "@bracketedIdentifier" }],
      [/"/, { token: "identifier.quote", next: "@quotedIdentifier" }]
    ],
    bracketedIdentifier: [
      [/[^\]]+/, "identifier"],
      [/]]/, "identifier"],
      [/]/, { token: "identifier.quote", next: "@pop" }]
    ],
    quotedIdentifier: [
      [/[^"]+/, "identifier"],
      [/""/, "identifier"],
      [/"/, { token: "identifier.quote", next: "@pop" }]
    ],
    scopes: [
      [/BEGIN\s+(DISTRIBUTED\s+)?TRAN(SACTION)?\b/i, "keyword"],
      [/BEGIN\s+TRY\b/i, { token: "keyword.try" }],
      [/END\s+TRY\b/i, { token: "keyword.try" }],
      [/BEGIN\s+CATCH\b/i, { token: "keyword.catch" }],
      [/END\s+CATCH\b/i, { token: "keyword.catch" }],
      [/(BEGIN|CASE)\b/i, { token: "keyword.block" }],
      [/END\b/i, { token: "keyword.block" }],
      [/WHEN\b/i, { token: "keyword.choice" }],
      [/THEN\b/i, { token: "keyword.choice" }]
    ]
  }
};

var language$1 = /*#__PURE__*/Object.freeze({
  __proto__: null,
  AND: AND,
  AS: AS,
  ASC: ASC,
  BY: BY,
  COMPARISON_OPERATORS: COMPARISON_OPERATORS,
  DESC: DESC,
  EQUALS: EQUALS,
  FROM: FROM,
  GROUP: GROUP,
  LIMIT: LIMIT,
  LOGICAL_OPERATORS: LOGICAL_OPERATORS,
  NOT_EQUALS: NOT_EQUALS,
  OR: OR,
  ORDER: ORDER,
  SCHEMA: SCHEMA,
  SELECT: SELECT,
  STD_OPERATORS: STD_OPERATORS,
  WHERE: WHERE,
  WITH: WITH,
  conf: conf,
  language: language
});

const getSelectToken = (currentToken) => {
  var _a;
  return (_a = currentToken == null ? undefined : currentToken.getPreviousOfType(TokenType.Keyword, SELECT)) != null ? _a : null;
};
const getFromKeywordToken = (currentToken) => {
  const selectToken = getSelectToken(currentToken);
  return selectToken == null ? undefined : selectToken.getNextOfType(TokenType.Keyword, FROM);
};
const getTableToken = (currentToken) => {
  var _a;
  const fromToken = getFromKeywordToken(currentToken);
  const nextNonWhiteSpace = fromToken == null ? undefined : fromToken.getNextNonWhiteSpaceToken();
  if (nextNonWhiteSpace == null ? undefined : nextNonWhiteSpace.isVariable()) {
    return null;
  } else if ((nextNonWhiteSpace == null ? undefined : nextNonWhiteSpace.isKeyword()) && ((_a = nextNonWhiteSpace.next) == null ? undefined : _a.is(TokenType.Parenthesis, "("))) {
    return null;
  } else {
    return nextNonWhiteSpace;
  }
};
const defaultTableNameParser = (token) => {
  const parts = token == null ? undefined : token.value.split(".");
  if ((parts == null ? undefined : parts.length) === 1) {
    return { table: parts[0] };
  } else if ((parts == null ? undefined : parts.length) === 2) {
    return { schema: parts[0], table: parts[1] };
  } else if ((parts == null ? undefined : parts.length) === 3) {
    return { catalog: parts[0], schema: parts[1], table: parts[2] };
  }
  return null;
};

const TRIGGER_SUGGEST = {
  id: "editor.action.triggerSuggest",
  title: ""
};

const initStandardSuggestions = (functions, operators, macros) => () => [
  {
    id: SuggestionKind.SelectKeyword,
    name: SuggestionKind.SelectKeyword,
    suggestions: (_, m) => Promise.resolve([
      {
        label: `SELECT <column>`,
        insertText: `SELECT $0`,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet,
        kind: CompletionItemKind.Snippet,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.Medium
      },
      {
        label: `SELECT <column> FROM <table>`,
        insertText: `SELECT $2 FROM $1`,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet,
        kind: CompletionItemKind.Snippet,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.Medium
      }
    ])
  },
  {
    id: SuggestionKind.TemplateVariables,
    name: SuggestionKind.TemplateVariables,
    suggestions: (_, m) => {
      const templateSrv = runtime.getTemplateSrv();
      if (!templateSrv) {
        return Promise.resolve([]);
      }
      return Promise.resolve(
        templateSrv.getVariables().map((variable) => {
          const label = `$${variable.name}`;
          const val = templateSrv.replace(label);
          return {
            label,
            detail: `(Template Variable) ${val}`,
            kind: CompletionItemKind.Snippet,
            documentation: `(Template Variable) ${val}`,
            insertText: `\\$${variable.name} `,
            insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet,
            command: TRIGGER_SUGGEST,
            sortText: CompletionItemPriority.Low
          };
        })
      );
    }
  },
  {
    id: SuggestionKind.SelectMacro,
    name: SuggestionKind.SelectMacro,
    suggestions: (_, m) => Promise.resolve([
      ...macros.list().filter((m2) => m2.type === MacroType.Value || m2.type === MacroType.Column).map(createMacroSuggestionItem)
    ])
  },
  {
    id: SuggestionKind.TableMacro,
    name: SuggestionKind.TableMacro,
    suggestions: (_, m) => Promise.resolve([
      ...macros.list().filter((m2) => m2.type === MacroType.Table).map(createMacroSuggestionItem)
    ])
  },
  {
    id: SuggestionKind.GroupMacro,
    name: SuggestionKind.GroupMacro,
    suggestions: (_, m) => Promise.resolve([
      ...macros.list().filter((m2) => m2.type === MacroType.Group).map(createMacroSuggestionItem)
    ])
  },
  {
    id: SuggestionKind.FilterMacro,
    name: SuggestionKind.FilterMacro,
    suggestions: (_, m) => Promise.resolve([
      ...macros.list().filter((m2) => m2.type === MacroType.Filter).map(createMacroSuggestionItem)
    ])
  },
  {
    id: SuggestionKind.WithKeyword,
    name: SuggestionKind.WithKeyword,
    suggestions: (_, m) => Promise.resolve([
      {
        label: `WITH <alias> AS ( ... )`,
        insertText: `WITH $1  AS ( $2 )`,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet,
        kind: CompletionItemKind.Snippet,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.Medium
      }
    ])
  },
  {
    id: SuggestionKind.StarWildCard,
    name: SuggestionKind.StarWildCard,
    suggestions: (_, m) => Promise.resolve([
      {
        label: "*",
        insertText: `* $0`,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet,
        kind: CompletionItemKind.Field,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.High
      }
    ])
  },
  {
    id: SuggestionKind.FunctionsWithArguments,
    name: SuggestionKind.FunctionsWithArguments,
    suggestions: (_, m) => Promise.resolve([
      ...functions.list().map((f) => ({
        label: f.name,
        insertText: `${f.name}($0)`,
        documentation: f.description,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet,
        kind: CompletionItemKind.Function,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.MediumLow
      }))
    ])
  },
  {
    id: SuggestionKind.FunctionsWithoutArguments,
    name: SuggestionKind.FunctionsWithoutArguments,
    suggestions: (_, m) => Promise.resolve([
      ...functions.list().map((f) => ({
        label: f.name,
        insertText: `${f.name}()`,
        documentation: f.description,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet,
        kind: CompletionItemKind.Function,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.MediumHigh
      }))
    ])
  },
  {
    id: SuggestionKind.FromKeyword,
    name: SuggestionKind.FromKeyword,
    suggestions: (_, m) => Promise.resolve([
      {
        label: "FROM",
        insertText: `FROM $0`,
        command: TRIGGER_SUGGEST,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet,
        kind: CompletionItemKind.Keyword
      }
    ])
  },
  {
    id: SuggestionKind.Schemas,
    name: SuggestionKind.Schemas,
    suggestions: (_, m) => Promise.resolve([])
  },
  {
    id: SuggestionKind.Tables,
    name: SuggestionKind.Tables,
    suggestions: (_, m) => Promise.resolve([])
  },
  {
    id: SuggestionKind.Columns,
    name: SuggestionKind.Columns,
    suggestions: (_, m) => Promise.resolve([])
  },
  {
    id: SuggestionKind.LogicalOperators,
    name: SuggestionKind.LogicalOperators,
    suggestions: (_, m) => Promise.resolve(
      operators.list().filter((o) => o.type === OperatorType.Logical).map((o) => ({
        label: o.operator,
        insertText: `${o.operator} `,
        documentation: o.description,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.MediumHigh,
        kind: CompletionItemKind.Operator
      }))
    )
  },
  {
    id: SuggestionKind.WhereKeyword,
    name: SuggestionKind.WhereKeyword,
    suggestions: (_, m) => Promise.resolve([
      {
        label: "WHERE",
        insertText: `WHERE `,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.MediumHigh,
        kind: CompletionItemKind.Keyword
      }
    ])
  },
  {
    id: SuggestionKind.ComparisonOperators,
    name: SuggestionKind.ComparisonOperators,
    suggestions: (_, m) => Promise.resolve([
      ...operators.list().filter((o) => o.type === OperatorType.Comparison).map((o) => ({
        label: o.operator,
        insertText: `${o.operator} `,
        documentation: o.description,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.MediumHigh,
        kind: CompletionItemKind.Operator
      })),
      {
        label: "IN (...)",
        insertText: `IN ( $0 )`,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.Medium,
        kind: CompletionItemKind.Operator,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet
      },
      {
        label: "NOT IN (...)",
        insertText: `NOT IN ( $0 )`,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.Medium,
        kind: CompletionItemKind.Operator,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet
      },
      {
        label: "IS",
        insertText: `IS`,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.Medium,
        kind: CompletionItemKind.Operator
      },
      {
        label: "IS NOT",
        insertText: `IS NOT`,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.Medium,
        kind: CompletionItemKind.Operator
      }
    ])
  },
  {
    id: SuggestionKind.GroupByKeywords,
    name: SuggestionKind.GroupByKeywords,
    suggestions: (_, m) => Promise.resolve([
      {
        label: "GROUP BY",
        insertText: `GROUP BY `,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.MediumHigh,
        kind: CompletionItemKind.Keyword
      }
    ])
  },
  {
    id: SuggestionKind.OrderByKeywords,
    name: SuggestionKind.OrderByKeywords,
    suggestions: (_, m) => Promise.resolve([
      {
        label: "ORDER BY",
        insertText: `ORDER BY `,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.Medium,
        kind: CompletionItemKind.Keyword
      },
      {
        label: "ORDER BY(ascending)",
        insertText: `ORDER BY $1 ASC `,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.MediumLow,
        kind: CompletionItemKind.Snippet,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet
      },
      {
        label: "ORDER BY(descending)",
        insertText: `ORDER BY $1 DESC`,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.MediumLow,
        kind: CompletionItemKind.Snippet,
        insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet
      }
    ])
  },
  {
    id: SuggestionKind.LimitKeyword,
    name: SuggestionKind.LimitKeyword,
    suggestions: (_, m) => Promise.resolve([
      {
        label: "LIMIT",
        insertText: `LIMIT `,
        command: TRIGGER_SUGGEST,
        sortText: CompletionItemPriority.MediumLow,
        kind: CompletionItemKind.Keyword
      }
    ])
  },
  {
    id: SuggestionKind.SortOrderDirectionKeyword,
    name: SuggestionKind.SortOrderDirectionKeyword,
    suggestions: (_, m) => Promise.resolve(
      [ASC, DESC].map((o) => ({
        label: o,
        insertText: `${o} `,
        command: TRIGGER_SUGGEST,
        kind: CompletionItemKind.Keyword
      }))
    )
  },
  {
    id: SuggestionKind.NotKeyword,
    name: SuggestionKind.NotKeyword,
    suggestions: () => Promise.resolve([
      {
        label: "NOT",
        insertText: "NOT",
        command: TRIGGER_SUGGEST,
        kind: CompletionItemKind.Keyword,
        sortText: CompletionItemPriority.High
      }
    ])
  },
  {
    id: SuggestionKind.BoolValues,
    name: SuggestionKind.BoolValues,
    suggestions: () => Promise.resolve(
      ["TRUE", "FALSE"].map((o) => ({
        label: o,
        insertText: `${o}`,
        command: TRIGGER_SUGGEST,
        kind: CompletionItemKind.Keyword,
        sortText: CompletionItemPriority.Medium
      }))
    )
  },
  {
    id: SuggestionKind.NullValue,
    name: SuggestionKind.NullValue,
    suggestions: () => Promise.resolve(
      ["NULL"].map((o) => ({
        label: o,
        insertText: `${o}`,
        command: TRIGGER_SUGGEST,
        kind: CompletionItemKind.Keyword,
        sortText: CompletionItemPriority.Low
      }))
    )
  }
];
function createMacroSuggestionItem(m) {
  return {
    label: m.name,
    insertText: `${"\\" + m.text}${argsString(m.args)} `,
    insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet,
    kind: CompletionItemKind.Snippet,
    documentation: m.description,
    command: TRIGGER_SUGGEST
  };
}
function argsString(args) {
  if (!args) {
    return "()";
  }
  return "(".concat(args.map((t, i) => `\${${i}:${t}}`).join(", ")).concat(")");
}

function initStatementPositionResolvers() {
  return [
    {
      id: StatementPosition.SelectKeyword,
      name: StatementPosition.SelectKeyword,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => Boolean(
        currentToken === null || currentToken.isWhiteSpace() && currentToken.previous === null || currentToken.is(TokenType.Keyword, SELECT) || currentToken.is(TokenType.Keyword, SELECT) && currentToken.previous === null || previousIsSlash || currentToken.isIdentifier() && (previousIsSlash || (currentToken == null ? undefined : currentToken.previous) === null) || currentToken.isIdentifier() && SELECT.startsWith(currentToken.value.toLowerCase())
      )
    },
    {
      id: StatementPosition.WithKeyword,
      name: StatementPosition.WithKeyword,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => Boolean(
        currentToken === null || currentToken.isWhiteSpace() && currentToken.previous === null || currentToken.is(TokenType.Keyword, WITH) && currentToken.previous === null || currentToken.isIdentifier() && WITH.toLowerCase().startsWith(currentToken.value.toLowerCase())
      )
    },
    {
      id: StatementPosition.AfterSelectKeyword,
      name: StatementPosition.AfterSelectKeyword,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => Boolean((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.value.toLowerCase()) === SELECT)
    },
    {
      id: StatementPosition.AfterSelectArguments,
      name: StatementPosition.AfterSelectArguments,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        return Boolean((previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === SELECT && (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.value) === ",");
      }
    },
    {
      id: StatementPosition.AfterSelectFuncFirstArgument,
      name: StatementPosition.AfterSelectFuncFirstArgument,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        return Boolean(
          ((previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === SELECT || (previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === AS) && ((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Parenthesis, "(")) || (currentToken == null ? undefined : currentToken.is(TokenType.Parenthesis, "()")))
        );
      }
    },
    {
      id: StatementPosition.AfterWhereFunctionArgument,
      name: StatementPosition.AfterWhereFunctionArgument,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        return Boolean(
          (previousKeyword == null ? undefined : previousKeyword.is(TokenType.Keyword, WHERE)) && ((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Parenthesis, "(")) || (currentToken == null ? undefined : currentToken.is(TokenType.Parenthesis, "()")))
        );
      }
    },
    {
      id: StatementPosition.AfterGroupBy,
      name: StatementPosition.AfterGroupBy,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        var _a;
        return Boolean(
          (previousKeyword == null ? undefined : previousKeyword.is(TokenType.Keyword, BY)) && ((_a = previousKeyword == null ? undefined : previousKeyword.getPreviousKeyword()) == null ? undefined : _a.is(TokenType.Keyword, GROUP)) && ((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isIdentifier()) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isDoubleQuotedString()) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Parenthesis, ")")) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Parenthesis, "()")))
        );
      }
    },
    {
      id: StatementPosition.SelectAlias,
      name: StatementPosition.SelectAlias,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        if ((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.value) === "," && (previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === AS) {
          return true;
        }
        return false;
      }
    },
    {
      id: StatementPosition.FromKeyword,
      name: StatementPosition.FromKeyword,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        return Boolean(
          (previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === SELECT && (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.value) !== "," || ((currentToken == null ? undefined : currentToken.isKeyword()) || (currentToken == null ? undefined : currentToken.isIdentifier())) && FROM.toLowerCase().startsWith(currentToken.value.toLowerCase())
        );
      }
    },
    {
      id: StatementPosition.AfterFromKeyword,
      name: StatementPosition.AfterFromKeyword,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => Boolean(!(currentToken == null ? undefined : currentToken.value.includes(".")) && (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.value.toLowerCase()) === FROM)
    },
    {
      id: StatementPosition.AfterSchema,
      name: StatementPosition.AfterSchema,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        if ((currentToken == null ? undefined : currentToken.isWhiteSpace()) && (currentToken == null ? undefined : currentToken.next)) {
          currentToken = currentToken == null ? undefined : currentToken.previous;
          previousNonWhiteSpace = currentToken.getPreviousNonWhiteSpaceToken();
        }
        return Boolean(
          (currentToken == null ? undefined : currentToken.isIdentifier()) && (currentToken == null ? undefined : currentToken.value.endsWith(".")) && (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.value.toLowerCase()) === FROM
        );
      }
    },
    {
      id: StatementPosition.AfterFrom,
      name: StatementPosition.AfterFrom,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => Boolean(
        (previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === FROM && (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isDoubleQuotedString()) || (previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === FROM && (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isIdentifier()) || (previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === FROM && (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isVariable())
        //  cloudwatch specific
        // (previousKeyword?.value === SCHEMA && previousNonWhiteSpace?.is(TokenType.Parenthesis, ')'))
      )
    },
    {
      id: StatementPosition.AfterTable,
      name: StatementPosition.AfterTable,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        return Boolean(
          (previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === FROM && ((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isVariable()) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.value) !== "" && (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.value.toLowerCase()) !== FROM)
        );
      }
    },
    {
      id: StatementPosition.WhereKeyword,
      name: StatementPosition.WhereKeyword,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => Boolean(
        (previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === WHERE && ((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isKeyword()) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Parenthesis, "(")) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Operator, AND)))
      )
    },
    {
      id: StatementPosition.WhereComparisonOperator,
      name: StatementPosition.WhereComparisonOperator,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        var _a;
        return Boolean(
          (previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === WHERE && !((_a = previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.getPreviousNonWhiteSpaceToken()) == null ? undefined : _a.isOperator()) && !(currentToken == null ? undefined : currentToken.is(TokenType.Delimiter, ".")) && !(currentToken == null ? undefined : currentToken.isParenthesis()) && ((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isIdentifier()) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isDoubleQuotedString()))
        );
      }
    },
    {
      id: StatementPosition.WhereValue,
      name: StatementPosition.WhereValue,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => Boolean((previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === WHERE && (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isOperator()))
    },
    {
      id: StatementPosition.AfterWhereValue,
      name: StatementPosition.AfterWhereValue,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        var _a, _b, _c;
        return Boolean(
          (previousKeyword == null ? undefined : previousKeyword.value.toLowerCase()) === WHERE && ((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Operator, "and")) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Operator, "or")) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isString()) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isNumber()) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Parenthesis, ")")) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Parenthesis, "()")) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.isTemplateVariable()) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.IdentifierQuote)) && ((_a = previousNonWhiteSpace.getPreviousNonWhiteSpaceToken()) == null ? undefined : _a.is(TokenType.Identifier)) && ((_c = (_b = previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.getPreviousNonWhiteSpaceToken()) == null ? undefined : _b.getPreviousNonWhiteSpaceToken()) == null ? undefined : _c.is(TokenType.IdentifierQuote)))
        );
      }
    },
    {
      id: StatementPosition.AfterGroupByKeywords,
      name: StatementPosition.AfterGroupByKeywords,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        var _a;
        return Boolean(
          (previousKeyword == null ? undefined : previousKeyword.is(TokenType.Keyword, BY)) && ((_a = previousKeyword == null ? undefined : previousKeyword.getPreviousKeyword()) == null ? undefined : _a.is(TokenType.Keyword, GROUP)) && ((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Keyword, BY)) || (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Delimiter, ",")))
        );
      }
    },
    {
      id: StatementPosition.AfterGroupByFunctionArgument,
      name: StatementPosition.AfterGroupByFunctionArgument,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        var _a;
        return Boolean(
          (previousKeyword == null ? undefined : previousKeyword.is(TokenType.Keyword, BY)) && ((_a = previousKeyword == null ? undefined : previousKeyword.getPreviousKeyword()) == null ? undefined : _a.is(TokenType.Keyword, GROUP)) && ((previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Parenthesis, "(")) || (currentToken == null ? undefined : currentToken.is(TokenType.Parenthesis, "()")))
        );
      }
    },
    {
      id: StatementPosition.AfterOrderByKeywords,
      name: StatementPosition.AfterOrderByKeywords,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        var _a;
        return Boolean(
          (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Keyword, BY)) && ((_a = previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.getPreviousKeyword()) == null ? undefined : _a.is(TokenType.Keyword, ORDER))
        );
      }
    },
    {
      id: StatementPosition.AfterOrderByFunction,
      name: StatementPosition.AfterOrderByFunction,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        var _a, _b;
        return Boolean(
          (previousKeyword == null ? undefined : previousKeyword.is(TokenType.Keyword, BY)) && ((_a = previousKeyword == null ? undefined : previousKeyword.getPreviousKeyword()) == null ? undefined : _a.is(TokenType.Keyword, ORDER)) && (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Parenthesis)) && ((_b = previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.getPreviousNonWhiteSpaceToken()) == null ? undefined : _b.is(TokenType.Function))
        );
      }
    },
    {
      id: StatementPosition.AfterOrderByDirection,
      name: StatementPosition.AfterOrderByDirection,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => Boolean((previousKeyword == null ? undefined : previousKeyword.is(TokenType.Keyword, DESC)) || (previousKeyword == null ? undefined : previousKeyword.is(TokenType.Keyword, ASC)))
    },
    {
      id: StatementPosition.AfterIsOperator,
      name: StatementPosition.AfterIsOperator,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        return Boolean(previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Operator, "IS"));
      }
    },
    {
      id: StatementPosition.AfterIsNotOperator,
      name: StatementPosition.AfterIsNotOperator,
      resolve: (currentToken, previousKeyword, previousNonWhiteSpace, previousIsSlash) => {
        var _a;
        return Boolean(
          (previousNonWhiteSpace == null ? undefined : previousNonWhiteSpace.is(TokenType.Operator, "NOT")) && ((_a = previousNonWhiteSpace.getPreviousNonWhiteSpaceToken()) == null ? undefined : _a.is(TokenType.Operator, "IS"))
        );
      }
    }
  ];
}

let sqlEditorLogger = { logger: () => {
} };
let sqlEditorLog = () => {
};
if (ui.attachDebugger && ui.createLogger) {
  sqlEditorLogger = ui.createLogger("SQLEditor");
  sqlEditorLog = sqlEditorLogger.logger;
  ui.attachDebugger("sqleditor", undefined, sqlEditorLogger);
}

const COLUMN = "column", RELATIVE_TIME_STRING = "'5m'";
const MACROS = [
  {
    id: "$__timeFilter(dateColumn)",
    name: "$__timeFilter(dateColumn)",
    text: "$__timeFilter",
    args: [COLUMN],
    type: MacroType.Filter,
    description: "Will be replaced by a time range filter using the specified column name. For example, dateColumn BETWEEN FROM_UNIXTIME(1494410783) AND FROM_UNIXTIME(1494410983)"
  },
  {
    id: "$__timeFrom()",
    name: "$__timeFrom()",
    text: "$__timeFrom",
    args: [],
    type: MacroType.Filter,
    description: "Will be replaced by the start of the currently active time selection. For example, FROM_UNIXTIME(1494410783)"
  },
  {
    id: "$__timeTo()",
    name: "$__timeTo()",
    text: "$__timeTo",
    args: [],
    type: MacroType.Filter,
    description: "Will be replaced by the end of the currently active time selection. For example, FROM_UNIXTIME(1494410983)"
  },
  {
    id: "$__timeGroup(dateColumn, '5m')",
    name: "$__timeGroup(dateColumn, '5m')",
    text: "$__timeGroup",
    args: [COLUMN, RELATIVE_TIME_STRING],
    type: MacroType.Value,
    description: "Will be replaced by an expression usable in GROUP BY clause. For example, *cast(cast(UNIX_TIMESTAMP(dateColumn)/(300) as signed)*300 as signed),*"
  },
  {
    id: "$__table",
    name: "$__table",
    text: "$__table",
    args: [],
    type: MacroType.Table,
    description: "Will be replaced by the query table."
  },
  {
    id: "$__column",
    name: "$__column",
    text: "$__column",
    args: [],
    type: MacroType.Column,
    description: "Will be replaced by the query column."
  }
];

function getStandardSQLCompletionProvider(monaco, language) {
  var _a, _b, _c;
  const provider = { triggerCharacters: [".", " ", "$", ",", "(", "'"] };
  if (language && Array.isArray(language.builtinFunctions)) {
    provider.supportedFunctions = () => language.builtinFunctions.map((f) => ({ id: f, name: f }));
  }
  const operators = [];
  if ((_a = language == null ? undefined : language.comparisonOperators) == null ? undefined : _a.length) {
    operators.push(
      ...language.comparisonOperators.map((f) => ({
        id: f.toLocaleLowerCase(),
        operator: f,
        type: OperatorType.Comparison
      }))
    );
  }
  language.logicalOperators = (_b = language.logicalOperators) != null ? _b : language.operators;
  if ((_c = language == null ? undefined : language.logicalOperators) == null ? undefined : _c.length) {
    operators.push(
      ...language.logicalOperators.map((f) => ({ id: f.toLocaleLowerCase(), operator: f, type: OperatorType.Logical }))
    );
  }
  provider.supportedOperators = () => operators;
  provider.supportedMacros = () => MACROS;
  return provider;
}

const standardSQLLanguageDefinition = {
  id: "standardSql",
  extensions: [".sql"],
  aliases: ["sql"],
  mimetypes: [],
  loader: () => Promise.resolve().then(function () { return language$1; }),
  completionProvider: getStandardSQLCompletionProvider
};

function useLatestCallback(callback) {
  const ref = React.useRef(callback);
  React.useEffect(() => {
    ref.current = callback;
  });
  const hasCallback = Boolean(callback);
  return React.useMemo(
    () => hasCallback ? (...args) => ref.current(...args) : undefined,
    [hasCallback]
  );
}

const STANDARD_SQL_LANGUAGE = "sql";
const LANGUAGES_CACHE = /* @__PURE__ */ new Map();
const INSTANCE_CACHE = /* @__PURE__ */ new Map();
const SQLEditor = ({
  children,
  onBlur,
  onChange,
  query,
  language = { id: STANDARD_SQL_LANGUAGE },
  width,
  height
}) => {
  const monacoRef = React.useRef(null);
  const langUid = React.useRef();
  const stableOnChange = useLatestCallback(onChange);
  const id = React.useMemo(() => {
    const uid = uuid.v4();
    const id2 = `${language.id}-${uid}`;
    langUid.current = id2;
    return id2;
  }, [language.id]);
  React.useEffect(() => {
    return () => {
      if (langUid.current) {
        INSTANCE_CACHE.delete(langUid.current);
      }
      sqlEditorLog(`Removing instance cache ${langUid.current}`, false, INSTANCE_CACHE);
    };
  }, []);
  const formatQuery = React.useCallback(() => {
    if (monacoRef.current) {
      monacoRef.current.getAction("editor.action.formatDocument").run();
    }
  }, []);
  const onSqlBlur = (text) => {
    stableOnChange && stableOnChange(text, false);
    onBlur && onBlur(text);
  };
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { width }, children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.CodeEditor,
      {
        height: height || "240px",
        width: width ? `${width - 2}px` : undefined,
        language: id,
        value: query,
        onBlur: onSqlBlur,
        showMiniMap: false,
        showLineNumbers: true,
        onEditorDidMount: (editor, m) => {
          monacoRef.current = editor;
          editor.onDidChangeModelContent((e) => {
            const text = editor.getValue();
            if (stableOnChange) {
              stableOnChange(text, false);
            }
          });
          editor.addCommand(m.KeyMod.CtrlCmd | m.KeyCode.Enter, () => {
            const text = editor.getValue();
            if (stableOnChange) {
              stableOnChange(text, true);
            }
          });
          editor.onKeyUp((e) => {
            if (e.keyCode === 84) {
              editor.trigger(TRIGGER_SUGGEST.id, TRIGGER_SUGGEST.id, {});
            }
          });
          registerLanguageAndSuggestions(m, language, id);
        }
      }
    ),
    children && children({ formatQuery })
  ] });
};
const resolveLanguage = (monaco, languageDefinitionProp) => {
  if ((languageDefinitionProp == null ? undefined : languageDefinitionProp.id) !== STANDARD_SQL_LANGUAGE && !languageDefinitionProp.loader) {
    sqlEditorLog(`Loading language '${languageDefinitionProp == null ? undefined : languageDefinitionProp.id}' from Monaco registry`, false);
    const allLangs = monaco.languages.getLanguages();
    const custom = allLangs.find(({ id }) => id === (languageDefinitionProp == null ? undefined : languageDefinitionProp.id));
    if (!custom) {
      throw Error(`Unknown Monaco language ${languageDefinitionProp == null ? undefined : languageDefinitionProp.id}`);
    }
    return { completionProvider: getStandardSQLCompletionProvider, ...custom, ...languageDefinitionProp };
  }
  return {
    ...standardSQLLanguageDefinition,
    ...languageDefinitionProp
  };
};
const registerLanguageAndSuggestions = async (monaco, l, lid) => {
  const languageDefinition = resolveLanguage(monaco, l);
  if (!languageDefinition.loader) {
    return;
  }
  const { language, conf } = await languageDefinition.loader(monaco);
  monaco.languages.register({ id: lid });
  monaco.languages.setMonarchTokensProvider(lid, { ...language });
  monaco.languages.setLanguageConfiguration(lid, { ...conf });
  if (languageDefinition.formatter) {
    monaco.languages.registerDocumentFormattingEditProvider(lid, {
      provideDocumentFormattingEdits: (model) => {
        var _a;
        const formatted = (_a = l.formatter) == null ? undefined : _a.call(l, model.getValue());
        return [
          {
            range: model.getFullModelRange(),
            text: formatted || ""
          }
        ];
      }
    });
  }
  if (languageDefinition.completionProvider) {
    const customProvider = languageDefinition.completionProvider(monaco, language);
    extendStandardRegistries(l.id, lid, customProvider);
    const languageSuggestionsRegistries = LANGUAGES_CACHE.get(l.id);
    const instanceSuggestionsRegistry = INSTANCE_CACHE.get(lid);
    const completionProvider = async (model, position, context, token) => {
      const currentToken = linkedTokenBuilder(monaco, model, position, lid);
      const statementPosition = getStatementPosition(currentToken, languageSuggestionsRegistries.positionResolvers);
      const kind = getSuggestionKinds(statementPosition, languageSuggestionsRegistries.suggestionKinds);
      sqlEditorLog("Statement position", false, statementPosition);
      sqlEditorLog("Suggestion kinds", false, kind);
      const ctx = {
        position,
        currentToken,
        statementPosition,
        kind,
        range: monaco.Range.fromPositions(position)
      };
      const stdSuggestions = await getStandardSuggestions(monaco, currentToken, kind, ctx, instanceSuggestionsRegistry);
      return {
        suggestions: stdSuggestions
      };
    };
    monaco.languages.registerCompletionItemProvider(lid, {
      ...customProvider,
      provideCompletionItems: completionProvider
    });
  }
};
function extendStandardRegistries(id, lid, customProvider) {
  var _a;
  if (!LANGUAGES_CACHE.has(id)) {
    initializeLanguageRegistries(id);
  }
  const languageRegistries = LANGUAGES_CACHE.get(id);
  if (!INSTANCE_CACHE.has(lid)) {
    INSTANCE_CACHE.set(
      lid,
      new data.Registry(
        initStandardSuggestions(languageRegistries.functions, languageRegistries.operators, languageRegistries.macros)
      )
    );
  }
  const instanceSuggestionsRegistry = INSTANCE_CACHE.get(lid);
  if (customProvider.supportedFunctions) {
    for (const func of customProvider.supportedFunctions()) {
      const exists = languageRegistries.functions.getIfExists(func.id);
      if (!exists) {
        languageRegistries.functions.register(func);
      }
    }
  }
  if (customProvider.supportedOperators) {
    for (const op of customProvider.supportedOperators()) {
      const exists = languageRegistries.operators.getIfExists(op.id);
      if (!exists) {
        languageRegistries.operators.register({ ...op, name: op.id });
      }
    }
  }
  if (customProvider.supportedMacros) {
    for (const macro of customProvider.supportedMacros()) {
      const exists = languageRegistries.macros.getIfExists(macro.id);
      if (!exists) {
        languageRegistries.macros.register({ ...macro, name: macro.id });
      }
    }
  }
  if (customProvider.customStatementPlacement) {
    for (const placement of customProvider.customStatementPlacement()) {
      const exists = languageRegistries.positionResolvers.getIfExists(placement.id);
      if (!exists) {
        languageRegistries.positionResolvers.register({
          ...placement,
          id: placement.id,
          name: placement.id
        });
        languageRegistries.suggestionKinds.register({
          id: placement.id,
          name: placement.id,
          kind: []
        });
      } else {
        const origResolve = exists.resolve;
        exists.resolve = (...args) => {
          const ext = placement.resolve(...args);
          if (placement.overrideDefault) {
            return ext;
          }
          const orig = origResolve(...args);
          return orig || ext;
        };
      }
    }
  }
  if (customProvider.customSuggestionKinds) {
    for (const kind of customProvider.customSuggestionKinds()) {
      (_a = kind.applyTo) == null ? undefined : _a.forEach((applyTo) => {
        const exists = languageRegistries.suggestionKinds.getIfExists(applyTo);
        if (exists) {
          if (exists.kind.indexOf(kind.id) === -1) {
            exists.kind.push(kind.id);
          }
        }
      });
      if (kind.overrideDefault) {
        const stbBehavior = instanceSuggestionsRegistry.get(kind.id);
        if (stbBehavior !== undefined) {
          stbBehavior.suggestions = kind.suggestionsResolver;
          continue;
        }
      }
      instanceSuggestionsRegistry.register({
        id: kind.id,
        name: kind.id,
        suggestions: kind.suggestionsResolver
      });
    }
  }
  if (customProvider.schemas) {
    const stbBehavior = instanceSuggestionsRegistry.get(SuggestionKind.Schemas);
    const s = stbBehavior.suggestions;
    stbBehavior.suggestions = async (ctx, m) => {
      const standardSchemas = await s(ctx, m);
      if (!customProvider.schemas) {
        return [...standardSchemas];
      }
      const customSchemas = await customProvider.schemas.resolve();
      const customSchemaCompletionItems = customSchemas.map((x) => {
        var _a2;
        return {
          label: x.name,
          insertText: `${(_a2 = x.completion) != null ? _a2 : x.name}.`,
          command: TRIGGER_SUGGEST,
          kind: CompletionItemKind.Module,
          // it's nice to differentiate schemas from tables
          sortText: CompletionItemPriority.High
        };
      });
      return [...standardSchemas, ...customSchemaCompletionItems];
    };
  }
  if (customProvider.tables) {
    const stbBehavior = instanceSuggestionsRegistry.get(SuggestionKind.Tables);
    const s = stbBehavior.suggestions;
    stbBehavior.suggestions = async (ctx, m) => {
      var _a2, _b, _c, _d, _e;
      const o = await s(ctx, m);
      const tableToken = getTableToken(ctx.currentToken);
      const tableNameParser = (_b = (_a2 = customProvider.tables) == null ? undefined : _a2.parseName) != null ? _b : defaultTableNameParser;
      const tableIdentifier = tableNameParser(tableToken);
      const oo = ((_e = await ((_d = (_c = customProvider.tables) == null ? undefined : _c.resolve) == null ? undefined : _d.call(_c, tableIdentifier))) != null ? _e : []).map((x) => {
        var _a3;
        return {
          label: x.name,
          // if no custom completion is provided it's safe to move cursor further in the statement
          insertText: `${(_a3 = x.completion) != null ? _a3 : x.name}${x.completion === x.name ? " $0" : ""}`,
          insertTextRules: CompletionItemInsertTextRule.InsertAsSnippet,
          command: TRIGGER_SUGGEST,
          kind: CompletionItemKind.Field,
          sortText: CompletionItemPriority.MediumHigh
        };
      });
      return [...o, ...oo];
    };
  }
  if (customProvider.columns) {
    const stbBehavior = instanceSuggestionsRegistry.get(SuggestionKind.Columns);
    const s = stbBehavior.suggestions;
    stbBehavior.suggestions = async (ctx, m) => {
      var _a2, _b, _c;
      const o = await s(ctx, m);
      const tableToken = getTableToken(ctx.currentToken);
      let tableIdentifier;
      const tableNameParser = (_b = (_a2 = customProvider.tables) == null ? undefined : _a2.parseName) != null ? _b : defaultTableNameParser;
      if (tableToken && tableToken.value) {
        tableIdentifier = tableNameParser(tableToken);
      }
      let oo = [];
      if (tableIdentifier) {
        const columns = await ((_c = customProvider.columns) == null ? undefined : _c.resolve(tableIdentifier));
        oo = columns ? columns.map((x) => {
          var _a3;
          return {
            label: x.name,
            insertText: (_a3 = x.completion) != null ? _a3 : x.name,
            kind: CompletionItemKind.Field,
            sortText: CompletionItemPriority.High,
            detail: x.type,
            documentation: x.description
          };
        }) : [];
      }
      return [...o, ...oo];
    };
  }
}
function initializeLanguageRegistries(id) {
  if (!LANGUAGES_CACHE.has(id)) {
    LANGUAGES_CACHE.set(id, {
      functions: new data.Registry(),
      operators: new data.Registry(),
      suggestionKinds: new data.Registry(initSuggestionsKindRegistry),
      positionResolvers: new data.Registry(initStatementPositionResolvers),
      macros: new data.Registry()
    });
  }
  return LANGUAGES_CACHE.get(id);
}

const singleLineFullQuery = {
  query: `SELECT column1, FROM table1 WHERE column1 = "value1" GROUP BY column1 ORDER BY column1 DESC LIMIT 10`,
  tokens: [
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 7,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 14,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 15,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 16,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 20,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 21,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 27,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 28,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 33,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 34,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 41,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 42,
        type: "operator.sql",
        language: "sql"
      },
      {
        offset: 43,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 44,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 45,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 51,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 52,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 53,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 58,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 59,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 61,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 62,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 69,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 70,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 75,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 76,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 78,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 79,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 86,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 87,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 91,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 92,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 97,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 98,
        type: "number.sql",
        language: "sql"
      },
      {
        offset: 100,
        type: "delimiter.sql",
        language: "sql"
      }
    ]
  ]
};

const singleLineFullQueryWithAggregation = {
  query: 'SELECT count(column1), FROM table1 WHERE column1 = "value1" GROUP BY column1 ORDER BY column1 DESC LIMIT 10;',
  tokens: [
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 7,
        type: "predefined.sql",
        language: "sql"
      },
      {
        offset: 12,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 13,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 20,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 21,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 22,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 23,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 27,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 28,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 34,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 35,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 40,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 41,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 48,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 49,
        type: "operator.sql",
        language: "sql"
      },
      {
        offset: 50,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 51,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 52,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 58,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 59,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 60,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 65,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 66,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 68,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 69,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 76,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 77,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 82,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 83,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 85,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 86,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 93,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 94,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 98,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 99,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 104,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 105,
        type: "number.sql",
        language: "sql"
      },
      {
        offset: 107,
        type: "delimiter.sql",
        language: "sql"
      }
    ]
  ]
};

const multiLineFullQuery = {
  query: `SELECT column1,
  FROM table1

  WHERE column1 = "value1"
  GROUP BY column1 ORDER BY column1 DESC
  LIMIT 10;`,
  tokens: [
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 7,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 14,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 15,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 4,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 11,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 13,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 14,
        type: "operator.sql",
        language: "sql"
      },
      {
        offset: 15,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 16,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 17,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 23,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 24,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 8,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 9,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 16,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 17,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 22,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 23,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 25,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 26,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 33,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 34,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 38,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "number.sql",
        language: "sql"
      },
      {
        offset: 8,
        type: "delimiter.sql",
        language: "sql"
      }
    ]
  ]
};

const multiLineFullQueryWithAggregation = {
  query: `SELECT count(column1),
  FROM table1

  WHERE column1 = "value1"
  GROUP BY column1 ORDER BY column1 DESC
  LIMIT 10;`,
  tokens: [
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 7,
        type: "predefined.sql",
        language: "sql"
      },
      {
        offset: 12,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 13,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 20,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 21,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 22,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 4,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 11,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 13,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 14,
        type: "operator.sql",
        language: "sql"
      },
      {
        offset: 15,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 16,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 17,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 23,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 24,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 8,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 9,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 16,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 17,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 22,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 23,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 25,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 26,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 33,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 34,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 38,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "number.sql",
        language: "sql"
      },
      {
        offset: 8,
        type: "delimiter.sql",
        language: "sql"
      }
    ]
  ]
};

const singleLineEmptyQuery = {
  query: "",
  tokens: []
};

const singleLineTwoQueries = {
  query: 'SELECT column1, FROM table1 WHERE column1 = "value1" GROUP BY column1 ORDER BY column1 DESC LIMIT 10; SELECT column2, FROM table2 WHERE column2 = "value2" GROUP BY column1 ORDER BY column2 DESC LIMIT 10;',
  tokens: [
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 7,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 14,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 15,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 16,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 20,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 21,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 27,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 28,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 33,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 34,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 41,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 42,
        type: "operator.sql",
        language: "sql"
      },
      {
        offset: 43,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 44,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 45,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 51,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 52,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 53,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 58,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 59,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 61,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 62,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 69,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 70,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 75,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 76,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 78,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 79,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 86,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 87,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 91,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 92,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 97,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 98,
        type: "number.sql",
        language: "sql"
      },
      {
        offset: 100,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 101,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 102,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 108,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 109,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 116,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 117,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 118,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 122,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 123,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 129,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 130,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 135,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 136,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 143,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 144,
        type: "operator.sql",
        language: "sql"
      },
      {
        offset: 145,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 146,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 147,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 153,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 154,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 155,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 160,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 161,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 163,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 164,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 171,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 172,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 177,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 178,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 180,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 181,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 188,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 189,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 193,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 194,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 199,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 200,
        type: "number.sql",
        language: "sql"
      },
      {
        offset: 202,
        type: "delimiter.sql",
        language: "sql"
      }
    ]
  ]
};

const singleLineTwoQueriesWithAggregation = {
  query: 'SELECT count(column1), FROM table1 WHERE column1 = "value1" GROUP BY column1 ORDER BY column1 DESC LIMIT 10; SELECT count(column2), FROM table2 WHERE column2 = "value2" GROUP BY column1 ORDER BY column2 DESC LIMIT 10;',
  tokens: [
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 7,
        type: "predefined.sql",
        language: "sql"
      },
      {
        offset: 12,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 13,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 20,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 21,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 22,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 23,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 27,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 28,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 34,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 35,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 40,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 41,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 48,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 49,
        type: "operator.sql",
        language: "sql"
      },
      {
        offset: 50,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 51,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 52,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 58,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 59,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 60,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 65,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 66,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 68,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 69,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 76,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 77,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 82,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 83,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 85,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 86,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 93,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 94,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 98,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 99,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 104,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 105,
        type: "number.sql",
        language: "sql"
      },
      {
        offset: 107,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 108,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 109,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 115,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 116,
        type: "predefined.sql",
        language: "sql"
      },
      {
        offset: 121,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 122,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 129,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 130,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 131,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 132,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 136,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 137,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 143,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 144,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 149,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 150,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 157,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 158,
        type: "operator.sql",
        language: "sql"
      },
      {
        offset: 159,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 160,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 161,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 167,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 168,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 169,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 174,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 175,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 177,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 178,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 185,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 186,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 191,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 192,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 194,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 195,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 202,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 203,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 207,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 208,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 213,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 214,
        type: "number.sql",
        language: "sql"
      },
      {
        offset: 216,
        type: "delimiter.sql",
        language: "sql"
      }
    ]
  ]
};

const singleLineMultipleColumns = {
  query: 'SELECT count(column1), column2 FROM table1 WHERE column1 = "value1" GROUP BY column1 ORDER BY column1, avg(column2) DESC LIMIT 10;',
  tokens: [
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 7,
        type: "predefined.sql",
        language: "sql"
      },
      {
        offset: 12,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 13,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 20,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 21,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 22,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 23,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 30,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 31,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 35,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 36,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 42,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 43,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 48,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 49,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 56,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 57,
        type: "operator.sql",
        language: "sql"
      },
      {
        offset: 58,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 59,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 60,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 66,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 67,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 68,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 73,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 74,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 76,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 77,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 84,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 85,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 90,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 91,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 93,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 94,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 101,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 102,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 103,
        type: "predefined.sql",
        language: "sql"
      },
      {
        offset: 106,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 107,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 114,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 115,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 116,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 120,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 121,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 126,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 127,
        type: "number.sql",
        language: "sql"
      },
      {
        offset: 129,
        type: "delimiter.sql",
        language: "sql"
      }
    ]
  ]
};

const multiLineMultipleColumns = {
  query: `SELECT count(column1), column2
  FROM table1

  WHERE column1 = "value1"
  GROUP BY column1 ORDER BY column1, avg(column2) DESC
  LIMIT 10;`,
  tokens: [
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 7,
        type: "predefined.sql",
        language: "sql"
      },
      {
        offset: 12,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 13,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 20,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 21,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 22,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 23,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 30,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 4,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 11,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 13,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 14,
        type: "operator.sql",
        language: "sql"
      },
      {
        offset: 15,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 16,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 17,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 23,
        type: "identifier.quote.sql",
        language: "sql"
      },
      {
        offset: 24,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 8,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 9,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 16,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 17,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 22,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 23,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 25,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 26,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 33,
        type: "delimiter.sql",
        language: "sql"
      },
      {
        offset: 34,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 35,
        type: "predefined.sql",
        language: "sql"
      },
      {
        offset: 38,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 39,
        type: "identifier.sql",
        language: "sql"
      },
      {
        offset: 46,
        type: "delimiter.parenthesis.sql",
        language: "sql"
      },
      {
        offset: 47,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 48,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 52,
        type: "white.sql",
        language: "sql"
      }
    ],
    [
      {
        offset: 0,
        type: "keyword.sql",
        language: "sql"
      },
      {
        offset: 5,
        type: "white.sql",
        language: "sql"
      },
      {
        offset: 6,
        type: "number.sql",
        language: "sql"
      },
      {
        offset: 8,
        type: "delimiter.sql",
        language: "sql"
      }
    ]
  ]
};

var testData = /*#__PURE__*/Object.freeze({
  __proto__: null,
  multiLineFullQuery: multiLineFullQuery,
  multiLineFullQueryWithAggregation: multiLineFullQueryWithAggregation,
  multiLineMultipleColumns: multiLineMultipleColumns,
  singleLineEmptyQuery: singleLineEmptyQuery,
  singleLineFullQuery: singleLineFullQuery,
  singleLineFullQueryWithAggregation: singleLineFullQueryWithAggregation,
  singleLineMultipleColumns: singleLineMultipleColumns,
  singleLineTwoQueries: singleLineTwoQueries,
  singleLineTwoQueriesWithAggregation: singleLineTwoQueriesWithAggregation
});

const getMonacoMock = (testData) => ({
  editor: {
    tokenize: (value, languageId) => testData.get(value)
  },
  Range: {
    containsPosition: (range, position) => {
      return position.lineNumber >= range.startLineNumber && position.lineNumber <= range.endLineNumber && position.column >= range.startColumn && position.column <= range.endColumn;
    }
  },
  languages: {
    CompletionItemKind: { Snippet: 2, Function: 1, Keyword: 3 },
    CompletionItemInsertTextRule: { InsertAsSnippet: 2 }
  }
});

function TextModel(value) {
  return {
    getValue: function(eol, preserveBOM) {
      return value;
    },
    getValueInRange: function(range, eol) {
      const lines = value.split("\n");
      const line = lines[range.startLineNumber - 1];
      return line.trim().slice(range.startColumn === 0 ? 0 : range.startColumn - 1, range.endColumn - 1);
    },
    getLineLength: function(lineNumber) {
      const lines = value.split("\n");
      return lines[lineNumber - 1].trim().length;
    }
  };
}

function assertPosition(query, position, expected, monacoMock, resolversRegistry) {
  const testModel = TextModel(query);
  const current = linkedTokenBuilder(monacoMock, testModel, position);
  const statementPosition = getStatementPosition(current, resolversRegistry);
  expect(statementPosition).toContain(expected);
}
const testStatementPosition = (expected, cases, resolvers) => {
  describe(`${expected}`, () => {
    let MonacoMock;
    let statementPositionResolversRegistry;
    beforeEach(() => {
      const mockQueries = /* @__PURE__ */ new Map();
      cases.forEach((c) => mockQueries.set(c.query.query, c.query.tokens));
      MonacoMock = getMonacoMock(mockQueries);
      statementPositionResolversRegistry = new data.Registry(() => {
        return resolvers().map((r) => ({
          id: r.id,
          name: r.name || r.id,
          resolve: r.resolve
        }));
      });
    });
    cases.forEach((c) => {
      test(`${c.query.query}`, () => {
        assertPosition(
          c.query.query,
          { lineNumber: c.position.line, column: c.position.column },
          expected,
          MonacoMock,
          statementPositionResolversRegistry
        );
      });
    });
  });
};

const SQLEditorTestUtils = {
  testData,
  testStatementPosition
};

var _a;
var QueryFormat = /* @__PURE__ */ ((QueryFormat2) => {
  QueryFormat2[QueryFormat2["Timeseries"] = 0] = "Timeseries";
  QueryFormat2[QueryFormat2["Table"] = 1] = "Table";
  QueryFormat2[QueryFormat2["Logs"] = 2] = "Logs";
  QueryFormat2[QueryFormat2["Trace"] = 3] = "Trace";
  QueryFormat2[QueryFormat2["OptionMulti"] = 4] = "OptionMulti";
  return QueryFormat2;
})(QueryFormat || {});
var EditorMode = /* @__PURE__ */ ((EditorMode2) => {
  EditorMode2["Builder"] = "builder";
  EditorMode2["Code"] = "code";
  return EditorMode2;
})(EditorMode || {});
const QUERY_FORMAT_OPTIONS = [
  { label: "Time series", value: 0 /* Timeseries */ },
  { label: "Table", value: 1 /* Table */ }
];
const backWardToOption = (value) => ({ label: value, value });
const toOption = (_a = data.toOption) != null ? _a : backWardToOption;

const EditorStack = ({ children, wrap: wrapItems = true, ...props }) => {
  var _a, _b;
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { wrap: wrapItems ? "wrap" : undefined, direction: (_a = props.direction) != null ? _a : "row", gap: (_b = props.gap) != null ? _b : 2, ...props, children });
};

const EditorList = React.forwardRef(function EditorList2({ items, renderItem, onChange }, ref) {
  const onAddItem = () => {
    const newItems = [...items, {}];
    onChange(newItems);
  };
  const onChangeItem = (itemIndex, newItem) => {
    const newItems = [...items];
    newItems[itemIndex] = newItem;
    onChange(newItems);
  };
  const onDeleteItem = (itemIndex) => {
    const newItems = [...items];
    newItems.splice(itemIndex, 1);
    onChange(newItems);
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(EditorStack, { children: [
    items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: renderItem(
      item,
      (newItem) => onChangeItem(index, newItem),
      () => onDeleteItem(index)
    ) }, index)),
    /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { ref, onClick: onAddItem, variant: "secondary", size: "md", icon: "plus", "aria-label": "Add", type: "button" })
  ] });
});

const AccessoryButton = ({ className, ...props }) => {
  const styles = ui.useStyles2(getButtonStyles);
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { ...props, className: css.cx(className, styles.button) });
};
const getButtonStyles = (theme) => ({
  button: css.css({
    paddingLeft: theme.spacing(3 / 2),
    paddingRight: theme.spacing(3 / 2)
  })
});

const InputGroup = ({ children }) => {
  const styles = ui.useStyles2(getStyles$n);
  const modifiedChildren = React.Children.map(children, (child) => {
    if (React.isValidElement(child) && child.props.invalid) {
      return React.cloneElement(child, { className: css.cx(child.props.className, styles.invalidChild) });
    }
    return child;
  });
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.root, children: modifiedChildren });
};
const borderPriority = [
  "",
  // lowest priority
  "base",
  "hovered",
  "invalid",
  "focused"
  // highest priority
];
const getStyles$n = () => ({
  root: css.css({
    display: "flex",
    // Style the direct children of the component
    "> *": {
      "&:not(:first-child)": {
        // Negative margin hides the double-border on adjacent selects
        marginLeft: -1
      },
      "&:first-child": {
        borderTopRightRadius: 0,
        borderBottomRightRadius: 0
      },
      "&:last-child": {
        borderTopLeftRadius: 0,
        borderBottomLeftRadius: 0
      },
      "&:not(:first-child):not(:last-child)": {
        borderRadius: 0
      },
      //
      position: "relative",
      zIndex: borderPriority.indexOf("base"),
      // Adjacent borders are overlapping, so raise children up when hovering etc
      // so all that child's borders are visible.
      "&:hover": {
        zIndex: borderPriority.indexOf("hovered")
      },
      "&:focus-within": {
        zIndex: borderPriority.indexOf("focused")
      }
    }
  }),
  invalidChild: css.css({
    zIndex: borderPriority.indexOf("invalid")
  })
});

function GroupByRow({ sql, columns, onSqlChange }) {
  const onGroupByChange = React.useCallback(
    (item) => {
      const cleaned = item.map((v) => {
        var _a;
        return setGroupByField((_a = v.property) == null ? undefined : _a.name);
      });
      const newSql = { ...sql, groupBy: cleaned };
      onSqlChange(newSql);
    },
    [onSqlChange, sql]
  );
  return /* @__PURE__ */ jsxRuntime.jsx(
    EditorList,
    {
      items: sql.groupBy,
      onChange: onGroupByChange,
      renderItem: makeRenderColumn({
        options: columns
      })
    }
  );
}
function makeRenderColumn({ options }) {
  const renderColumn = function(item, onChangeItem, onDeleteItem) {
    var _a;
    return /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        ui.Select,
        {
          value: ((_a = item.property) == null ? undefined : _a.name) ? data.toOption(item.property.name) : null,
          "aria-label": "Group by",
          options,
          menuShouldPortal: true,
          onChange: ({ value }) => value && onChangeItem(setGroupByField(value))
        }
      ),
      /* @__PURE__ */ jsxRuntime.jsx(AccessoryButton, { "aria-label": "Remove group by column", icon: "times", variant: "secondary", onClick: onDeleteItem })
    ] });
  };
  return renderColumn;
}

const EditorFieldGroup = ({ children }) => {
  return /* @__PURE__ */ jsxRuntime.jsx(EditorStack, { gap: 1, children });
};

const EditorHeader = ({ children }) => {
  const styles = ui.useStyles2(getStyles$m);
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.root, children });
};
const getStyles$m = (theme) => ({
  root: css.css({
    display: "flex",
    flexWrap: "wrap",
    alignItems: "center",
    gap: theme.spacing(3),
    minHeight: theme.spacing(4)
  })
});

const EditorField$1 = (props) => {
  var _a;
  const { label, optional, tooltip, tooltipInteractive, children, width, ...fieldProps } = props;
  const styles = ui.useStyles2(getStyles$l, width);
  const childInputId = (fieldProps == null ? undefined : fieldProps.htmlFor) || ((_a = ui.ReactUtils) == null ? undefined : _a.getChildId(children));
  const labelEl = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsxs("label", { className: styles.label, htmlFor: childInputId, children: [
      label,
      optional && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.optional, children: " - optional" }),
      tooltip && /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { placement: "top", content: tooltip, theme: "info", interactive: tooltipInteractive, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { tabIndex: 0, name: "info-circle", size: "sm", className: styles.icon }) })
    ] }),
    /* @__PURE__ */ jsxRuntime.jsx(ui.Space, { v: 0.5 })
  ] });
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.root, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Field, { className: styles.field, label: labelEl, ...fieldProps, children }) });
};
const getStyles$l = (theme, width) => {
  return {
    root: css.css({
      minWidth: theme.spacing(width != null ? width : 0)
    }),
    label: css.css({
      fontSize: 12,
      fontWeight: theme.typography.fontWeightMedium
    }),
    optional: css.css({
      fontStyle: "italic",
      color: theme.colors.text.secondary
    }),
    field: css.css({
      marginBottom: 0
      // GrafanaUI/Field has a bottom margin which we must remove
    }),
    icon: css.css({
      color: theme.colors.text.secondary,
      marginLeft: theme.spacing(1),
      ":hover": {
        color: theme.colors.text.primary
      }
    })
  };
};

const EditorRow$1 = ({ children }) => {
  const styles = ui.useStyles2(getStyles$k);
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.root, children: /* @__PURE__ */ jsxRuntime.jsx(EditorStack, { gap: 2, children }) });
};
const getStyles$k = (theme) => {
  return {
    root: css.css({
      padding: theme.spacing(1),
      backgroundColor: theme.colors.background.secondary,
      borderRadius: theme.shape.radius.default
    })
  };
};

const EditorRows$1 = ({ children }) => {
  return /* @__PURE__ */ jsxRuntime.jsx(EditorStack, { gap: 0.5, direction: "column", children });
};

const EditorSwitch = (props) => {
  const styles = getStyles$j();
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.switch, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { ...props }) });
};
const getStyles$j = () => {
  return {
    switch: css.css({
      display: "flex",
      alignItems: "center",
      minHeight: 30
    })
  };
};

const FlexItem = ({ grow, shrink }) => {
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "block", flexGrow: grow, flexShrink: shrink } });
};

function getDefaultExportFromCjs (x) {
	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}

function InlineSelect({ label: labelProp, ...props }) {
  const [id] = React.useState(() => Math.random().toString(16).slice(2));
  const styles = ui.useStyles2(getSelectStyles);
  const components = {
    SelectContainer,
    ValueContainer,
    SingleValue: ValueContainer
  };
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.root, children: [
    labelProp && /* @__PURE__ */ jsxRuntime.jsxs("label", { className: styles.label, htmlFor: id, children: [
      labelProp,
      ":",
      "\xA0"
    ] }),
    /* @__PURE__ */ jsxRuntime.jsx(ui.Select, { openMenuOnFocus: true, inputId: id, ...props, components })
  ] });
}
const SelectContainer = (props) => {
  const { children } = props;
  const styles = ui.useStyles2(getSelectStyles);
  return /* @__PURE__ */ jsxRuntime.jsx(ui.SelectContainer, { ...props, className: css.cx(props.className, styles.container), children });
};
const ValueContainer = (props) => {
  const { className, children } = props;
  const styles = ui.useStyles2(getSelectStyles);
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: css.cx(className, styles.valueContainer), children });
};
const getSelectStyles = (theme) => ({
  root: css.css({
    display: "flex",
    fontSize: 12,
    alignItems: "center"
  }),
  label: css.css({
    color: theme.colors.text.secondary,
    whiteSpace: "nowrap"
  }),
  container: css.css({
    background: "none",
    borderColor: "transparent"
  }),
  valueContainer: css.css({
    display: "flex",
    alignItems: "center",
    flex: "initial",
    color: theme.colors.text.secondary,
    fontSize: 12
  })
});

const Space = (props) => {
  const theme = ui.useTheme2();
  const styles = getStyles$i(theme, props);
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: css.cx(styles.wrapper) });
};
Space.defaultProps = {
  v: 0,
  h: 0,
  layout: "block"
};
const getStyles$i = ui.stylesFactory((theme, props) => {
  var _a, _b;
  return {
    wrapper: css.css([
      {
        paddingRight: theme.spacing((_a = props.h) != null ? _a : 0),
        paddingBottom: theme.spacing((_b = props.v) != null ? _b : 0)
      },
      props.layout === "inline" && {
        display: "inline-block"
      },
      props.layout === "block" && {
        display: "block"
      }
    ])
  };
});

function ConfirmModal({ isOpen, onCancel, onDiscard, onCopy }) {
  const buttonRef = React.useRef(null);
  React.useEffect(() => {
    var _a;
    if (isOpen) {
      (_a = buttonRef.current) == null ? undefined : _a.focus();
    }
  }, [isOpen]);
  return /* @__PURE__ */ jsxRuntime.jsxs(
    ui.Modal,
    {
      title: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "modal-header-title", children: [
        /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { name: "exclamation-triangle", size: "lg" }),
        /* @__PURE__ */ jsxRuntime.jsx("span", { className: "p-l-1", children: "Warning" })
      ] }),
      onDismiss: onCancel,
      isOpen,
      children: [
        /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Builder mode does not display changes made in code. The query builder will display the last changes you made in builder mode." }),
        /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Do you want to copy your code to the clipboard?" }),
        /* @__PURE__ */ jsxRuntime.jsxs(ui.Modal.ButtonRow, { children: [
          /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "button", variant: "secondary", onClick: onCancel, fill: "outline", children: "Cancel" }),
          /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "destructive", type: "button", onClick: onDiscard, ref: buttonRef, children: "Discard code and switch" }),
          /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "primary", onClick: onCopy, children: "Copy code and switch" })
        ] })
      ]
    }
  );
}

const DatasetSelector = ({
  db,
  dataset,
  catalog,
  value,
  onChange,
  disabled,
  className,
  applyDefault,
  inputId,
  enableCatalogs,
  "data-testid": dataTestId
}) => {
  const state = reactUse.useAsync(async () => {
    if (dataset) {
      onChange(toOption(dataset));
      return [toOption(dataset)];
    }
    const datasets = await db.datasets(catalog);
    return datasets.map(toOption);
  }, [catalog]);
  React.useEffect(() => {
    if (!applyDefault) {
      return;
    }
    if (!value) {
      if (state.value && state.value[0]) {
        onChange(state.value[0]);
      }
    } else {
      if (state.value && state.value.find((v) => v.value === value) === undefined) {
        if (state.value.length > 0) {
          onChange(state.value[0]);
        }
      }
    }
  }, [state.value, value, applyDefault, onChange]);
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.Select,
    {
      inputId,
      className,
      "aria-label": "Dataset selector",
      value,
      options: state.value,
      onChange,
      disabled,
      isLoading: state.loading,
      menuShouldPortal: true,
      "data-testid": dataTestId,
      placeholder: enableCatalogs ? "Select schema" : "Select dataset"
    }
  );
};

const CatalogSelector = ({ db, inputId, value, onChange }) => {
  const [catalogs, setCatalogs] = React.useState([]);
  const [isLoading, setIsLoading] = React.useState(false);
  const loadCatalogs = React.useCallback(async () => {
    if (!db.catalogs) {
      return;
    }
    setIsLoading(true);
    try {
      const catalogList = await db.catalogs();
      const catalogOptions = catalogList.map((catalog) => ({
        label: catalog,
        value: catalog
      }));
      setCatalogs(catalogOptions);
    } catch (error) {
      console.error("Error loading catalogs:", error);
      setCatalogs([]);
    } finally {
      setIsLoading(false);
    }
  }, [db]);
  React.useEffect(() => {
    loadCatalogs();
  }, [db, loadCatalogs]);
  const handleChange = (selectable) => {
    onChange((selectable == null ? undefined : selectable.value) || null);
  };
  const selectedValue = catalogs.find((catalog) => catalog.value === value) || null;
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.Select,
    {
      inputId,
      options: catalogs,
      value: selectedValue,
      onChange: handleChange,
      isLoading,
      placeholder: "Select catalog",
      isClearable: true,
      allowCustomValue: true,
      menuShouldPortal: true
    }
  );
};

const TableSelector = ({
  db,
  dataset,
  catalog,
  value,
  className,
  onChange,
  inputId,
  enableCatalogs
}) => {
  const state = reactUse.useAsync(async () => {
    if (!dataset && !catalog) {
      return [];
    }
    if (enableCatalogs && (!catalog || !dataset)) {
      return [];
    }
    const tables = await db.tables(dataset, catalog);
    return tables.map(data.toOption);
  }, [dataset, catalog, enableCatalogs]);
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.Select,
    {
      inputId,
      className,
      "aria-label": "Table selector",
      value,
      options: state.value,
      onChange,
      isLoading: state.loading,
      menuShouldPortal: true,
      placeholder: state.loading ? "Loading tables" : "Select table"
    }
  );
};

const RunQueryButton = ({
  ariaLabel = "Query editor Run button",
  queryRunning = false,
  queryInvalid = false,
  invalidQueryTooltip,
  disabled = false,
  onClick,
  dataTestId
}) => {
  let icon = queryInvalid ? "exclamation-triangle" : undefined;
  if (queryRunning) {
    icon = "fa fa-spinner";
  }
  const RunButton = /* @__PURE__ */ jsxRuntime.jsx(
    ui.Button,
    {
      "aria-label": ariaLabel,
      size: "sm",
      variant: "secondary",
      icon,
      disabled: disabled || queryRunning,
      onClick,
      "data-testid": dataTestId,
      children: "Run query"
    }
  );
  return queryInvalid ? /* @__PURE__ */ jsxRuntime.jsx(
    ui.Tooltip,
    {
      theme: "error",
      placement: "top",
      content: invalidQueryTooltip != null ? invalidQueryTooltip : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
        "Your query is invalid. Check below for details. ",
        /* @__PURE__ */ jsxRuntime.jsx("br", {}),
        "However, you can still run this query."
      ] }),
      children: RunButton
    }
  ) : RunButton;
};

const editorModes$1 = [
  { label: "Builder", value: EditorMode.Builder },
  { label: "Code", value: EditorMode.Code }
];
function QueryHeader({
  db,
  defaultDataset,
  enableDatasets,
  enableCatalogs,
  query,
  queryRowFilter,
  onChange,
  onRunQuery,
  onQueryRowChange,
  isQueryRunnable,
  labels = /* @__PURE__ */ new Map([["dataset", "Dataset"]])
}) {
  const { editorMode } = query;
  const [_, copyToClipboard] = reactUse.useCopyToClipboard();
  const [showConfirm, setShowConfirm] = React.useState(false);
  const toRawSql = getRawSqlFn(db);
  const htmlId = React.useId();
  const catalogsEnabled = enableCatalogs != null ? enableCatalogs : db.disableCatalogs === false;
  const effectiveEnableDatasets = catalogsEnabled ? true : enableDatasets;
  const onEditorModeChange = React.useCallback(
    (newEditorMode) => {
      if (editorMode === EditorMode.Code) {
        setShowConfirm(true);
        return;
      }
      onChange({ ...query, editorMode: newEditorMode });
    },
    [editorMode, onChange, query]
  );
  const onFormatChange = (e) => {
    const next = { ...query, format: e.value !== undefined ? e.value : QueryFormat.Table };
    onChange(next);
  };
  const onDatasetChange = (e) => {
    const datasetValue = e.value || undefined;
    if (datasetValue === query.dataset) {
      return;
    }
    const next = {
      ...query,
      dataset: datasetValue,
      table: undefined,
      sql: undefined,
      rawSql: ""
    };
    onChange(next);
  };
  const onCatalogChange = (catalog) => {
    const catalogValue = catalog || undefined;
    if (catalogValue === query.catalog) {
      return;
    }
    const next = {
      ...query,
      catalog: catalogValue,
      dataset: undefined,
      // Reset dataset (which acts as schema when catalog is present)
      table: undefined,
      sql: undefined,
      rawSql: ""
    };
    onChange(next);
  };
  const onTableChange = (e) => {
    if (e.value === query.table) {
      return;
    }
    const next = {
      ...query,
      table: e.value,
      sql: undefined,
      rawSql: ""
    };
    onChange(next);
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsxs(EditorHeader, { children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        InlineSelect,
        {
          label: "Format",
          value: query.format,
          placeholder: "Select format",
          menuShouldPortal: true,
          onChange: onFormatChange,
          options: QUERY_FORMAT_OPTIONS
        }
      ),
      editorMode === EditorMode.Builder && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.InlineSwitch,
          {
            id: `sql-filter-${htmlId}`,
            label: "Filter",
            transparent: true,
            showLabel: true,
            value: queryRowFilter.filter,
            onChange: (ev) => ev.target instanceof HTMLInputElement && onQueryRowChange({ ...queryRowFilter, filter: ev.target.checked })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.InlineSwitch,
          {
            id: `sql-group-${htmlId}`,
            label: "Group",
            transparent: true,
            showLabel: true,
            value: queryRowFilter.group,
            onChange: (ev) => ev.target instanceof HTMLInputElement && onQueryRowChange({ ...queryRowFilter, group: ev.target.checked })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.InlineSwitch,
          {
            id: `sql-order-${htmlId}`,
            label: "Order",
            transparent: true,
            showLabel: true,
            value: queryRowFilter.order,
            onChange: (ev) => ev.target instanceof HTMLInputElement && onQueryRowChange({ ...queryRowFilter, order: ev.target.checked })
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.InlineSwitch,
          {
            id: `sql-preview-${htmlId}`,
            label: "Preview",
            transparent: true,
            showLabel: true,
            value: queryRowFilter.preview,
            onChange: (ev) => ev.target instanceof HTMLInputElement && onQueryRowChange({ ...queryRowFilter, preview: ev.target.checked })
          }
        )
      ] }),
      /* @__PURE__ */ jsxRuntime.jsx(FlexItem, { grow: 1 }),
      /* @__PURE__ */ jsxRuntime.jsx(RunQueryButton, { queryInvalid: !isQueryRunnable, onClick: () => onRunQuery() }),
      /* @__PURE__ */ jsxRuntime.jsx(ui.RadioButtonGroup, { options: editorModes$1, size: "sm", value: editorMode, onChange: onEditorModeChange }),
      /* @__PURE__ */ jsxRuntime.jsx(
        ConfirmModal,
        {
          isOpen: showConfirm,
          onCopy: () => {
            setShowConfirm(false);
            copyToClipboard(query.rawSql);
            onChange({
              ...query,
              rawSql: toRawSql(query),
              editorMode: EditorMode.Builder
            });
          },
          onDiscard: () => {
            setShowConfirm(false);
            onChange({
              ...query,
              rawSql: toRawSql(query),
              editorMode: EditorMode.Builder
            });
          },
          onCancel: () => setShowConfirm(false)
        }
      )
    ] }),
    editorMode === EditorMode.Builder && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
      /* @__PURE__ */ jsxRuntime.jsx(Space, { v: 0.5 }),
      /* @__PURE__ */ jsxRuntime.jsxs(EditorRow$1, { children: [
        catalogsEnabled && /* @__PURE__ */ jsxRuntime.jsx(EditorField$1, { label: labels.get("catalog") || "Catalog", width: 25, children: /* @__PURE__ */ jsxRuntime.jsx(
          CatalogSelector,
          {
            db,
            inputId: `sql-catalog-${htmlId}`,
            value: query.catalog === undefined ? null : query.catalog,
            onChange: onCatalogChange
          }
        ) }),
        effectiveEnableDatasets && /* @__PURE__ */ jsxRuntime.jsx(
          EditorField$1,
          {
            label: catalogsEnabled ? labels.get("schema") || "Schema" : labels.get("dataset") || "Dataset",
            width: 25,
            children: /* @__PURE__ */ jsxRuntime.jsx(
              DatasetSelector,
              {
                db,
                inputId: catalogsEnabled ? `sql-schema-${htmlId}` : `sql-dataset-${htmlId}`,
                "data-testid": catalogsEnabled ? "schema-selector" : "dataset-selector",
                dataset: catalogsEnabled ? undefined : defaultDataset,
                value: query.dataset === undefined ? null : query.dataset,
                onChange: onDatasetChange,
                catalog: catalogsEnabled ? query.catalog : undefined
              }
            )
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(EditorField$1, { label: labels.get("table") || "Table", width: 25, children: /* @__PURE__ */ jsxRuntime.jsx(
          TableSelector,
          {
            db,
            inputId: `sql-table-${htmlId}`,
            dataset: query.dataset || (catalogsEnabled ? undefined : defaultDataset),
            catalog: catalogsEnabled ? query.catalog : undefined,
            query,
            value: query.table === undefined ? null : query.table,
            onChange: onTableChange,
            enableCatalogs: catalogsEnabled,
            applyDefault: true
          }
        ) })
      ] })
    ] })
  ] });
}

function formatSQL(q) {
  return sqlFormatter__default.default.format(q).replace(/(\$ \{ .* \})|(\$ __)|(\$ \w+)/g, (m) => {
    return m.replace(/\s/g, "");
  });
}

function QueryEditorRaw({ children, onChange, query, width, height, completionProvider }) {
  const queryRef = React.useRef(query);
  React.useEffect(() => {
    queryRef.current = query;
  }, [query]);
  const onRawQueryChange = React.useCallback(
    (rawSql, processQuery) => {
      const newQuery = {
        ...queryRef.current,
        rawQuery: true,
        rawSql
      };
      onChange(newQuery, processQuery);
    },
    [onChange]
  );
  return /* @__PURE__ */ jsxRuntime.jsx(
    SQLEditor,
    {
      width,
      height,
      query: query.rawSql,
      onChange: onRawQueryChange,
      language: { id: "sql", completionProvider, formatter: formatSQL },
      children
    }
  );
}

function QueryValidator({ db, query, onValidate, range }) {
  var _a;
  const [validationResult, setValidationResult] = React.useState();
  const theme = ui.useTheme2();
  const valueFormatter = React.useMemo(() => data.getValueFormat("bytes"), []);
  const styles = React.useMemo(() => {
    return {
      error: css.css`
        color: ${theme.colors.error.text};
        font-size: ${theme.typography.bodySmall.fontSize};
        font-family: ${theme.typography.fontFamilyMonospace};
      `,
      valid: css.css`
        color: ${theme.colors.success.text};
      `,
      info: css.css`
        color: ${theme.colors.text.secondary};
      `
    };
  }, [theme]);
  const [state, validateQuery] = reactUse.useAsyncFn(
    async (q) => {
      var _a2;
      if (((_a2 = q.rawSql) == null ? undefined : _a2.trim()) === "") {
        return null;
      }
      return await db.validateQuery(q, range);
    },
    [db]
  );
  reactUse.useDebounce(
    async () => {
      const result = await validateQuery(query);
      if (result) {
        setValidationResult(result);
      }
      return null;
    },
    1e3,
    [query, validateQuery]
  );
  React.useEffect(() => {
    if (validationResult == null ? undefined : validationResult.isError) {
      onValidate(false);
    }
    if (validationResult == null ? undefined : validationResult.isValid) {
      onValidate(true);
    }
  }, [validationResult, onValidate]);
  if (!state.value && !state.loading) {
    return null;
  }
  const error = ((_a = state.value) == null ? undefined : _a.error) ? processErrorMessage(state.value.error) : "";
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    state.loading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.info, children: [
      /* @__PURE__ */ jsxRuntime.jsx(ui.Spinner, { inline: true, size: 12 }),
      " Validating query..."
    ] }),
    !state.loading && state.value && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
      /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: state.value.isValid && state.value.statistics && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.valid, children: [
        /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { name: "check" }),
        " This query will process",
        " ",
        /* @__PURE__ */ jsxRuntime.jsx("strong", { children: data.formattedValueToString(valueFormatter(state.value.statistics.TotalBytesProcessed)) }),
        " ",
        "when run."
      ] }) }),
      /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: state.value.isError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.error, children: error }) })
    ] })
  ] });
}
function processErrorMessage(error) {
  const splat = error.split(":");
  if (splat.length > 2) {
    return splat.slice(2).join(":");
  }
  return error;
}

function QueryToolbox({ showTools, onFormatCode, onExpand, isExpanded, ...validatorProps }) {
  const theme = ui.useTheme2();
  const [validationResult, setValidationResult] = React.useState();
  const styles = React.useMemo(() => {
    return {
      container: css.css`
        border: 1px solid ${theme.colors.border.medium};
        border-top: none;
        padding: ${theme.spacing(0.5, 0.5, 0.5, 0.5)};
        display: flex;
        flex-grow: 1;
        justify-content: space-between;
        font-size: ${theme.typography.bodySmall.fontSize};
      `,
      error: css.css`
        color: ${theme.colors.error.text};
        font-size: ${theme.typography.bodySmall.fontSize};
        font-family: ${theme.typography.fontFamilyMonospace};
      `,
      valid: css.css`
        color: ${theme.colors.success.text};
      `,
      info: css.css`
        color: ${theme.colors.text.secondary};
      `,
      hint: css.css`
        color: ${theme.colors.text.disabled};
        white-space: nowrap;
        cursor: help;
      `
    };
  }, [theme]);
  let style = {};
  if (!showTools && validationResult === undefined) {
    style = { height: 0, padding: 0, visibility: "hidden" };
  }
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.container, style, children: [
    /* @__PURE__ */ jsxRuntime.jsx("div", { children: validatorProps.onValidate && /* @__PURE__ */ jsxRuntime.jsx(
      QueryValidator,
      {
        ...validatorProps,
        onValidate: (result) => {
          setValidationResult(result);
          validatorProps.onValidate(result);
        }
      }
    ) }),
    showTools && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.HorizontalGroup, { spacing: "sm", children: [
      onFormatCode && /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { onClick: onFormatCode, name: "brackets-curly", size: "xs", tooltip: "Format query" }),
      onExpand && /* @__PURE__ */ jsxRuntime.jsx(
        ui.IconButton,
        {
          onClick: () => onExpand(!isExpanded),
          name: isExpanded ? "angle-up" : "angle-down",
          size: "xs",
          tooltip: isExpanded ? "Collapse editor" : "Expand editor"
        }
      ),
      /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: "Hit CTRL/CMD+Return to run query", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { className: styles.hint, name: "keyboard" }) })
    ] }) })
  ] });
}

function RawEditor({ db, query, onChange, onRunQuery, onValidate, queryToValidate, range }) {
  const theme = ui.useTheme2();
  const styles = ui.useStyles2(getStyles$h);
  const [isExpanded, setIsExpanded] = React.useState(false);
  const [toolboxRef, toolboxMeasure] = reactUse.useMeasure();
  const [editorRef, editorMeasure] = reactUse.useMeasure();
  const completionProvider = React.useMemo(() => db.getSqlCompletionProvider(), [db]);
  const renderQueryEditor = (width, height) => {
    return /* @__PURE__ */ jsxRuntime.jsx(
      QueryEditorRaw,
      {
        completionProvider,
        query,
        width,
        height: height ? height - toolboxMeasure.height : undefined,
        onChange,
        children: ({ formatQuery }) => {
          return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: toolboxRef, children: /* @__PURE__ */ jsxRuntime.jsx(
            QueryToolbox,
            {
              db,
              query: queryToValidate,
              onValidate,
              onFormatCode: formatQuery,
              showTools: true,
              range,
              onExpand: setIsExpanded,
              isExpanded
            }
          ) });
        }
      }
    );
  };
  const renderEditor = (standalone = false) => {
    return standalone ? /* @__PURE__ */ jsxRuntime.jsx(AutoSizer__default.default, { children: ({ width, height }) => {
      return renderQueryEditor(width, height);
    } }) : /* @__PURE__ */ jsxRuntime.jsx("div", { ref: editorRef, children: renderQueryEditor() });
  };
  const renderPlaceholder = () => {
    return /* @__PURE__ */ jsxRuntime.jsx(
      "div",
      {
        style: {
          width: editorMeasure.width,
          height: editorMeasure.height,
          background: theme.colors.background.primary,
          display: "flex",
          alignItems: "center",
          justifyContent: "center"
        },
        children: "Editing in expanded code editor"
      }
    );
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    isExpanded ? renderPlaceholder() : renderEditor(),
    isExpanded && /* @__PURE__ */ jsxRuntime.jsx(
      ui.Modal,
      {
        title: `Query ${query.refId}`,
        closeOnBackdropClick: false,
        closeOnEscape: false,
        className: styles.modal,
        contentClassName: styles.modalContent,
        isOpen: isExpanded,
        onDismiss: () => {
          setIsExpanded(false);
        },
        children: renderEditor(true)
      }
    )
  ] });
}
function getStyles$h(theme) {
  return {
    modal: css.css`
      width: 95vw;
      height: 95vh;
    `,
    modalContent: css.css`
      height: 100%;
      padding-top: 0;
    `
  };
}

function Preview({ rawSql }) {
  const [_, copyToClipboard] = reactUse.useCopyToClipboard();
  const styles = ui.useStyles2(getStyles$g);
  const labelElement = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.labelWrapper, children: [
    /* @__PURE__ */ jsxRuntime.jsx("label", { className: styles.label, children: "Preview" }),
    /* @__PURE__ */ jsxRuntime.jsx(ui.IconButton, { tooltip: "Copy to clipboard", onClick: () => copyToClipboard(rawSql), name: "copy" })
  ] });
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Field, { label: labelElement, className: styles.grow, children: /* @__PURE__ */ jsxRuntime.jsx(
    ui.CodeEditor,
    {
      language: "sql",
      height: 80,
      value: formatSQL(rawSql),
      monacoOptions: { scrollbar: { vertical: "hidden" }, scrollBeyondLastLine: false },
      readOnly: true,
      showMiniMap: false
    }
  ) });
}
function getStyles$g(theme) {
  return {
    grow: css.css({ flexGrow: 1 }),
    label: css.css({ fontSize: 12, fontWeight: theme.typography.fontWeightMedium }),
    labelWrapper: css.css({ display: "flex", justifyContent: "space-between", paddingBottom: theme.spacing(0.5) })
  };
}

function useSqlChange({ query, onQueryChange, db }) {
  const onSqlChange = React.useCallback(
    (sql) => {
      const toRawSql = getRawSqlFn(db);
      const rawSql = toRawSql({
        sql,
        catalog: query.catalog,
        dataset: query.dataset,
        table: query.table,
        refId: query.refId
      });
      const newQuery = { ...query, sql, rawSql };
      onQueryChange(newQuery);
    },
    [db, onQueryChange, query]
  );
  return { onSqlChange };
}

function SQLGroupByRow({ fields, query, onQueryChange, db }) {
  const { onSqlChange } = useSqlChange({ query, onQueryChange, db });
  return /* @__PURE__ */ jsxRuntime.jsx(GroupByRow, { columns: fields, sql: query.sql, onSqlChange });
}

const sortOrderOptions = [
  { description: "Sort by ascending", value: "ASC", icon: "sort-amount-up" },
  { description: "Sort by descending", value: "DESC", icon: "sort-amount-down" }
];
function OrderByRow({ sql, onSqlChange, columns, showOffset }) {
  var _a, _b;
  const onSortOrderChange = React.useCallback(
    (item) => {
      const newSql = { ...sql, orderByDirection: item };
      onSqlChange(newSql);
    },
    [onSqlChange, sql]
  );
  const onLimitChange = React.useCallback(
    (event) => {
      const newSql = { ...sql, limit: Number.parseInt(event.currentTarget.value, 10) };
      onSqlChange(newSql);
    },
    [onSqlChange, sql]
  );
  const onOffsetChange = React.useCallback(
    (event) => {
      const newSql = { ...sql, offset: Number.parseInt(event.currentTarget.value, 10) };
      onSqlChange(newSql);
    },
    [onSqlChange, sql]
  );
  const onOrderByChange = React.useCallback(
    (item) => {
      const newSql = { ...sql, orderBy: setPropertyField(item == null ? undefined : item.value) };
      if (item === null) {
        newSql.orderByDirection = undefined;
      }
      onSqlChange(newSql);
    },
    [onSqlChange, sql]
  );
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(EditorField$1, { label: "Order by", width: 25, children: /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { children: [
      /* @__PURE__ */ jsxRuntime.jsx(
        ui.Select,
        {
          "aria-label": "Order by",
          options: columns,
          value: ((_a = sql.orderBy) == null ? undefined : _a.property.name) ? data.toOption(sql.orderBy.property.name) : null,
          isClearable: true,
          menuShouldPortal: true,
          onChange: onOrderByChange
        }
      ),
      /* @__PURE__ */ jsxRuntime.jsx(Space, { h: 1.5 }),
      /* @__PURE__ */ jsxRuntime.jsx(
        ui.RadioButtonGroup,
        {
          options: sortOrderOptions,
          disabled: !((_b = sql == null ? undefined : sql.orderBy) == null ? undefined : _b.property.name),
          value: sql.orderByDirection,
          onChange: onSortOrderChange
        }
      )
    ] }) }),
    /* @__PURE__ */ jsxRuntime.jsx(EditorField$1, { label: "Limit", optional: true, width: 25, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { type: "number", min: 0, id: lodash.uniqueId("limit-"), value: sql.limit || "", onChange: onLimitChange }) }),
    showOffset && /* @__PURE__ */ jsxRuntime.jsx(EditorField$1, { label: "Offset", optional: true, width: 25, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Input, { type: "number", id: lodash.uniqueId("offset-"), value: sql.offset || "", onChange: onOffsetChange }) })
  ] });
}

function SQLOrderByRow({ fields, query, onQueryChange, db }) {
  var _a, _b;
  const { onSqlChange } = useSqlChange({ query, onQueryChange, db });
  let columnsWithIndices = [];
  if (fields) {
    const options = (_b = (_a = query.sql) == null ? undefined : _a.columns) == null ? undefined : _b.map((c, i) => {
      var _a2, _b2;
      const value = c.name ? `${c.name}(${(_a2 = c.parameters) == null ? undefined : _a2.map((p) => p.name)})` : (_b2 = c.parameters) == null ? undefined : _b2.map((p) => p.name);
      return {
        value,
        label: `${i + 1} - ${value}`
      };
    });
    columnsWithIndices = [
      {
        value: "",
        label: "Selected columns",
        options,
        expanded: true
      },
      ...fields
    ];
  }
  return /* @__PURE__ */ jsxRuntime.jsx(OrderByRow, { sql: query.sql, onSqlChange, columns: columnsWithIndices });
}

const asteriskValue = { label: "*", value: "*" };
function SelectRow({ sql, columns, onSqlChange, functions }) {
  var _a;
  const styles = ui.useStyles2(getStyles$f);
  const columnsWithAsterisk = [asteriskValue, ...columns || []];
  const onColumnChange = React.useCallback(
    (item, index) => (column) => {
      var _a2, _b;
      let modifiedItem = { ...item };
      if (!((_a2 = item.parameters) == null ? undefined : _a2.length)) {
        modifiedItem.parameters = [{ type: QueryEditorExpressionType.FunctionParameter, name: column.value }];
      } else {
        modifiedItem.parameters = item.parameters.map(
          (p) => p.type === QueryEditorExpressionType.FunctionParameter ? { ...p, name: column.value } : p
        );
      }
      const newSql = {
        ...sql,
        columns: (_b = sql.columns) == null ? undefined : _b.map((c, i) => i === index ? modifiedItem : c)
      };
      onSqlChange(newSql);
    },
    [onSqlChange, sql]
  );
  const onAggregationChange = React.useCallback(
    (item, index) => (aggregation) => {
      var _a2;
      const newItem = {
        ...item,
        name: aggregation == null ? undefined : aggregation.value
      };
      const newSql = {
        ...sql,
        columns: (_a2 = sql.columns) == null ? undefined : _a2.map((c, i) => i === index ? newItem : c)
      };
      onSqlChange(newSql);
    },
    [onSqlChange, sql]
  );
  const removeColumn = React.useCallback(
    (index) => () => {
      const clone = [...sql.columns];
      clone.splice(index, 1);
      const newSql = {
        ...sql,
        columns: clone
      };
      onSqlChange(newSql);
    },
    [onSqlChange, sql]
  );
  const addColumn = React.useCallback(() => {
    const newSql = { ...sql, columns: [...sql.columns, createFunctionField()] };
    onSqlChange(newSql);
  }, [onSqlChange, sql]);
  return /* @__PURE__ */ jsxRuntime.jsxs(EditorStack, { gap: 2, alignItems: "end", direction: "column", children: [
    (_a = sql.columns) == null ? undefined : _a.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(EditorStack, { gap: 2, alignItems: "end", children: [
      /* @__PURE__ */ jsxRuntime.jsx(EditorField$1, { label: "Column", width: 25, children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Select,
        {
          value: getColumnValue(item),
          options: columnsWithAsterisk,
          inputId: `select-column-${index}-${lodash.uniqueId()}`,
          menuShouldPortal: true,
          allowCustomValue: true,
          onChange: onColumnChange(item, index)
        }
      ) }),
      /* @__PURE__ */ jsxRuntime.jsx(EditorField$1, { label: "Aggregation", optional: true, width: 25, children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Select,
        {
          value: item.name ? data.toOption(item.name) : null,
          inputId: `select-aggregation-${index}-${lodash.uniqueId()}`,
          isClearable: true,
          menuShouldPortal: true,
          allowCustomValue: true,
          options: functions,
          onChange: onAggregationChange(item, index)
        }
      ) }),
      /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          "aria-label": "Remove",
          type: "button",
          icon: "trash-alt",
          variant: "secondary",
          size: "md",
          onClick: removeColumn(index)
        }
      )
    ] }) }, index)),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        type: "button",
        onClick: addColumn,
        variant: "secondary",
        size: "md",
        icon: "plus",
        "aria-label": "Add",
        className: styles.addButton
      }
    )
  ] });
}
const getStyles$f = () => {
  return { addButton: css.css({ alignSelf: "flex-start" }) };
};
function getColumnValue({ parameters }) {
  const column = parameters == null ? undefined : parameters.find((p) => p.type === QueryEditorExpressionType.FunctionParameter);
  if (column == null ? undefined : column.name) {
    return data.toOption(column.name);
  }
  return null;
}

function SQLSelectRow({ fields, query, onQueryChange, db }) {
  const { onSqlChange } = useSqlChange({ query, onQueryChange, db });
  const state = reactUse.useAsync(async () => {
    const functions = await db.functions();
    return functions.map((f) => data.toOption(f.name));
  }, [db]);
  return /* @__PURE__ */ jsxRuntime.jsx(SelectRow, { columns: fields, sql: query.sql, functions: state.value, onSqlChange });
}

const buttonLabels = {
  add: "Add",
  remove: "Remove"
};
({
  id: ui$1.Utils.uuid(),
  type: "group",
  children1: [
    {
      id: ui$1.Utils.uuid(),
      type: "rule",
      properties: {
        field: null,
        operator: null,
        value: [],
        valueSrc: []
      }
    }
  ]
});
const emptyInitTree = {
  id: ui$1.Utils.uuid(),
  type: "group",
  children1: [
    {
      id: ui$1.Utils.uuid(),
      type: "rule",
      properties: {
        field: null,
        operator: null,
        value: [],
        valueSrc: []
      }
    }
  ]
};
const widgets = {
  ...ui$1.BasicConfig.widgets,
  text: {
    ...ui$1.BasicConfig.widgets.text,
    factory: function TextInput(props) {
      return /* @__PURE__ */ jsxRuntime.jsx(
        ui.Input,
        {
          value: (props == null ? undefined : props.value) || "",
          placeholder: props == null ? undefined : props.placeholder,
          onChange: (e) => props == null ? undefined : props.setValue(e.currentTarget.value)
        }
      );
    }
  },
  number: {
    ...ui$1.BasicConfig.widgets.number,
    factory: function NumberInput(props) {
      return /* @__PURE__ */ jsxRuntime.jsx(
        ui.Input,
        {
          value: props == null ? undefined : props.value,
          placeholder: props == null ? undefined : props.placeholder,
          type: "number",
          onChange: (e) => props == null ? undefined : props.setValue(Number.parseInt(e.currentTarget.value, 10))
        }
      );
    }
  },
  datetime: {
    ...ui$1.BasicConfig.widgets.datetime,
    factory: function DateTimeInput(props) {
      return /* @__PURE__ */ jsxRuntime.jsx(
        ui.DateTimePicker,
        {
          onChange: (e) => {
            props == null ? undefined : props.setValue(e == null ? undefined : e.format(ui$1.BasicConfig.widgets.datetime.valueFormat));
          },
          date: data.dateTime(props == null ? undefined : props.value).utc()
        }
      );
    }
  }
};
const settings = {
  ...ui$1.BasicConfig.settings,
  canRegroup: false,
  maxNesting: 1,
  canReorder: false,
  showNot: false,
  addRuleLabel: buttonLabels.add,
  deleteLabel: buttonLabels.remove,
  renderConjs: function Conjunctions(conjProps) {
    return /* @__PURE__ */ jsxRuntime.jsx(
      ui.Select,
      {
        id: conjProps == null ? undefined : conjProps.id,
        "aria-label": "Conjunction",
        menuShouldPortal: true,
        options: (conjProps == null ? undefined : conjProps.conjunctionOptions) ? Object.keys(conjProps == null ? undefined : conjProps.conjunctionOptions).map(data.toOption) : undefined,
        value: conjProps == null ? undefined : conjProps.selectedConjunction,
        onChange: (val) => conjProps == null ? undefined : conjProps.setConjunction(val.value)
      }
    );
  },
  renderField: function Field(fieldProps) {
    var _a;
    const fields = ((_a = fieldProps == null ? undefined : fieldProps.config) == null ? undefined : _a.fields) || {};
    return /* @__PURE__ */ jsxRuntime.jsx(
      ui.Select,
      {
        id: fieldProps == null ? undefined : fieldProps.id,
        width: 25,
        "aria-label": "Field",
        menuShouldPortal: true,
        options: fieldProps == null ? undefined : fieldProps.items.map((f) => {
          var _a2, _b;
          const icon = (_b = (_a2 = fields[f.key].mainWidgetProps) == null ? undefined : _a2.customProps) == null ? undefined : _b.icon;
          return {
            label: f.label,
            value: f.key,
            icon
          };
        }),
        value: fieldProps == null ? undefined : fieldProps.selectedKey,
        onChange: (val) => {
          fieldProps == null ? undefined : fieldProps.setField(val.label);
        }
      }
    );
  },
  renderButton: function RAQBButton(buttonProps) {
    return /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        type: "button",
        title: `${buttonProps == null ? undefined : buttonProps.label} filter`,
        onClick: buttonProps == null ? undefined : buttonProps.onClick,
        variant: "secondary",
        size: "md",
        icon: (buttonProps == null ? undefined : buttonProps.label) === buttonLabels.add ? "plus" : "times"
      }
    );
  },
  renderOperator: function Operator(operatorProps) {
    return /* @__PURE__ */ jsxRuntime.jsx(
      ui.Select,
      {
        options: operatorProps == null ? undefined : operatorProps.items.map((op) => ({ label: op.label, value: op.key })),
        "aria-label": "Operator",
        menuShouldPortal: true,
        value: operatorProps == null ? undefined : operatorProps.selectedKey,
        onChange: (val) => {
          operatorProps == null ? undefined : operatorProps.setField(val.value || "");
        }
      }
    );
  }
};
const customOperators = getCustomOperators(ui$1.BasicConfig);
const textWidget = ui$1.BasicConfig.types.text.widgets.text;
const opers = [...textWidget.operators || [], "select_any_in" /* IN */, "select_not_any_in" /* NOT_IN */];
const customTextWidget = {
  ...textWidget,
  operators: opers
};
const customTypes = {
  ...ui$1.BasicConfig.types,
  text: {
    ...ui$1.BasicConfig.types.text,
    widgets: {
      ...ui$1.BasicConfig.types.text.widgets,
      text: customTextWidget
    }
  }
};
const raqbConfig = {
  ...ui$1.BasicConfig,
  widgets,
  settings,
  operators: customOperators,
  types: customTypes
};
function getCustomOperators(config) {
  const { ...supportedOperators } = config.operators;
  const noop = () => "";
  const sqlFormatInOp = supportedOperators["select_any_in" /* IN */].sqlFormatOp || noop;
  const customSqlInFormatter = (field, op, value, valueSrc, valueType, opDef, operatorOptions, fieldDef) => sqlFormatInOp.call(
    config.ctx,
    field,
    op,
    splitIfString(value),
    valueSrc,
    valueType,
    opDef,
    operatorOptions,
    fieldDef
  );
  const sqlFormatNotInOp = supportedOperators["select_not_any_in" /* NOT_IN */].sqlFormatOp || noop;
  const customSqlNotInFormatter = (field, op, value, valueSrc, valueType, opDef, operatorOptions, fieldDef) => sqlFormatNotInOp.call(
    config.ctx,
    field,
    op,
    splitIfString(value),
    valueSrc,
    valueType,
    opDef,
    operatorOptions,
    fieldDef
  );
  const customOperators2 = {
    ...supportedOperators,
    ["select_any_in" /* IN */]: {
      ...supportedOperators["select_any_in" /* IN */],
      sqlFormatOp: customSqlInFormatter
    },
    ["select_not_any_in" /* NOT_IN */]: {
      ...supportedOperators["select_not_any_in" /* NOT_IN */],
      sqlFormatOp: customSqlNotInFormatter
    }
  };
  return customOperators2;
}
function splitIfString(value) {
  if (lodash.isString(value)) {
    return value.split(",");
  }
  return value;
}

function WhereRow({ sql, config, onSqlChange }) {
  const [tree, setTree] = React.useState();
  const configWithDefaults = React.useMemo(() => ({ ...raqbConfig, ...config }), [config]);
  React.useEffect(() => {
    var _a;
    if (!tree) {
      const initTree = ui$1.Utils.checkTree(ui$1.Utils.loadTree((_a = sql.whereJsonTree) != null ? _a : emptyInitTree), configWithDefaults);
      setTree(initTree);
    }
  }, [configWithDefaults, sql.whereJsonTree, tree]);
  React.useEffect(() => {
    if (!sql.whereJsonTree) {
      setTree(ui$1.Utils.checkTree(ui$1.Utils.loadTree(emptyInitTree), configWithDefaults));
    }
  }, [configWithDefaults, sql.whereJsonTree]);
  const onTreeChange = React.useCallback(
    (changedTree, config2) => {
      setTree(changedTree);
      const newSql = {
        ...sql,
        whereJsonTree: ui$1.Utils.getTree(changedTree),
        whereString: ui$1.Utils.sqlFormat(changedTree, config2)
      };
      onSqlChange(newSql);
    },
    [onSqlChange, sql]
  );
  if (!tree) {
    return null;
  }
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui$1.Query,
    {
      ...configWithDefaults,
      value: tree,
      onChange: onTreeChange,
      renderBuilder: (props) => /* @__PURE__ */ jsxRuntime.jsx(ui$1.Builder, { ...props })
    }
  );
}
function flex(direction) {
  return `
    display: flex;
    gap: 8px;
    flex-direction: ${direction};`;
}
css.injectGlobal`
  .group--header {
    ${flex("row")}
  }

  .group-or-rule {
    ${flex("column")}
    .rule {
      flex-direction: row;
    }
  }

  .rule--body {
    ${flex("row")}
  }

  .group--children {
    ${flex("column")}
  }

  .group--conjunctions:empty {
    display: none;
  }
`;

function SQLWhereRow({ query, fields, onQueryChange, db }) {
  const state = reactUse.useAsync(async () => {
    return mapFieldsToTypes(fields);
  }, [fields]);
  const { onSqlChange } = useSqlChange({ query, onQueryChange, db });
  return /* @__PURE__ */ jsxRuntime.jsx(
    WhereRow,
    {
      config: { fields: state.value || {} },
      sql: query.sql,
      onSqlChange: (val) => {
        onSqlChange(val);
      }
    },
    JSON.stringify(state.value)
  );
}
function mapFieldsToTypes(columns) {
  const fields = {};
  for (const col of columns) {
    fields[col.value] = {
      type: col.raqbFieldType || "text",
      valueSources: ["value"],
      mainWidgetProps: { customProps: { icon: col.icon } }
    };
  }
  return fields;
}

const EditorRow = ({ children }) => {
  const styles = ui.useStyles2(getStyles$e);
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.root, children: /* @__PURE__ */ jsxRuntime.jsx(EditorStack, { gap: 2, children }) });
};
const getStyles$e = (theme) => {
  return {
    root: css.css({
      padding: theme.spacing(1),
      backgroundColor: theme.colors.background.secondary,
      borderRadius: theme.shape.borderRadius(1)
    })
  };
};

const EditorField = (props) => {
  var _a;
  const { label, optional, tooltip, children, width, ...fieldProps } = props;
  const theme = ui.useTheme2();
  const styles = getStyles$d(theme, width);
  const childInputId = (fieldProps == null ? undefined : fieldProps.htmlFor) || ((_a = ui.ReactUtils) == null ? undefined : _a.getChildId(children));
  const labelEl = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsxs("label", { className: styles.label, htmlFor: childInputId, children: [
      label,
      optional && /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.optional, children: " - optional" }),
      tooltip && /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { placement: "top", content: tooltip, theme: "info", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { name: "info-circle", size: "sm", className: styles.icon }) })
    ] }),
    /* @__PURE__ */ jsxRuntime.jsx(Space, { v: 0.5 })
  ] });
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.root, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Field, { className: styles.field, label: labelEl, ...fieldProps, children }) });
};
const getStyles$d = ui.stylesFactory((theme, width) => {
  return {
    root: css.css({
      minWidth: theme.spacing(width != null ? width : 0)
    }),
    label: css.css({
      fontSize: 12,
      fontWeight: theme.typography.fontWeightMedium
    }),
    optional: css.css({
      fontStyle: "italic",
      color: theme.colors.text.secondary
    }),
    field: css.css({
      marginBottom: 0
      // GrafanaUI/Field has a bottom margin which we must remove
    }),
    icon: css.css({
      color: theme.colors.text.secondary,
      marginLeft: theme.spacing(1),
      ":hover": {
        color: theme.colors.text.primary
      }
    })
  };
});

const EditorRows = ({ children }) => {
  return /* @__PURE__ */ jsxRuntime.jsx(EditorStack, { gap: 0.5, direction: "column", children });
};

const VisualEditor = ({ query, db, queryRowFilter, onChange, onValidate, range }) => {
  const state = reactUse.useAsync(async () => {
    const fields = await db.fields(query);
    return fields;
  }, [db, query.dataset, query.table]);
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsxs(EditorRows, { children: [
      /* @__PURE__ */ jsxRuntime.jsx(EditorRow, { children: /* @__PURE__ */ jsxRuntime.jsx(SQLSelectRow, { fields: state.value || [], query, onQueryChange: onChange, db }) }),
      queryRowFilter.filter && /* @__PURE__ */ jsxRuntime.jsx(EditorRow, { children: /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Filter by column value", optional: true, children: /* @__PURE__ */ jsxRuntime.jsx(SQLWhereRow, { fields: state.value || [], query, onQueryChange: onChange, db }) }) }),
      queryRowFilter.group && /* @__PURE__ */ jsxRuntime.jsx(EditorRow, { children: /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Group by column", children: /* @__PURE__ */ jsxRuntime.jsx(SQLGroupByRow, { fields: state.value || [], query, onQueryChange: onChange, db }) }) }),
      queryRowFilter.order && /* @__PURE__ */ jsxRuntime.jsx(EditorRow, { children: /* @__PURE__ */ jsxRuntime.jsx(SQLOrderByRow, { fields: state.value || [], query, onQueryChange: onChange, db }) }),
      queryRowFilter.preview && query.rawSql && /* @__PURE__ */ jsxRuntime.jsx(EditorRow, { children: /* @__PURE__ */ jsxRuntime.jsx(Preview, { rawSql: query.rawSql }) })
    ] }),
    /* @__PURE__ */ jsxRuntime.jsx(QueryToolbox, { db, query, onValidate, range })
  ] });
};

const MACRO_NAMES = [
  "$__time",
  "$__timeEpoch",
  "$__timeFilter",
  "$__timeFrom",
  "$__timeTo",
  "$__timeGroup",
  "$__timeGroupAlias",
  "$__unixEpochFilter",
  "$__unixEpochNanoFilter",
  "$__unixEpochNanoFrom",
  "$__unixEpochNanoTo",
  "$__unixEpochGroup",
  "$__unixEpochGroupAlias"
];

var __defProp$3 = Object.defineProperty;
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
class SqlDatasource extends runtime.DataSourceWithBackend {
  constructor(instanceSettings, templateSrv = runtime.getTemplateSrv()) {
    super(instanceSettings);
    this.templateSrv = templateSrv;
    __publicField$3(this, "id");
    __publicField$3(this, "name");
    __publicField$3(this, "interval");
    __publicField$3(this, "db");
    __publicField$3(this, "dataset");
    __publicField$3(this, "annotations", {});
    __publicField$3(this, "interpolateVariable", (value, variable) => {
      if (typeof value === "string") {
        if (variable.multi || variable.includeAll) {
          const result = this.getQueryModel().quoteLiteral(value);
          return result;
        } else {
          return value;
        }
      }
      if (typeof value === "number") {
        return value;
      }
      if (Array.isArray(value)) {
        const quotedValues = value.map((v) => this.getQueryModel().quoteLiteral(v));
        return quotedValues.join(",");
      }
      return value;
    });
    this.name = instanceSettings.name;
    this.id = instanceSettings.id;
    const settingsData = instanceSettings.jsonData || {};
    this.interval = settingsData.timeInterval || "1m";
    this.db = this.getDB();
  }
  interpolateVariablesInQueries(queries, scopedVars) {
    let expandedQueries = queries;
    if (queries && queries.length > 0) {
      expandedQueries = queries.map((query) => {
        const expandedQuery = {
          ...query,
          datasource: this.getRef(),
          rawSql: this.templateSrv.replace(query.rawSql, scopedVars, this.interpolateVariable),
          rawQuery: true
        };
        return expandedQuery;
      });
    }
    return expandedQueries;
  }
  filterQuery(query) {
    return !query.hide;
  }
  applyTemplateVariables(target, scopedVars) {
    const queryModel = this.getQueryModel(target, this.templateSrv, scopedVars);
    const rawSql = this.clean(queryModel.interpolate());
    return {
      refId: target.refId,
      datasource: this.getRef(),
      rawSql,
      format: target.format
    };
  }
  clean(value) {
    return value.replace(/''/g, "'");
  }
  async metricFindQuery(query, optionalOptions) {
    const rawSql = this.templateSrv.replace(
      query,
      getSearchFilterScopedVar({ query, wildcardChar: "%", options: optionalOptions }),
      this.interpolateVariable
    );
    const interpolatedQuery = {
      refId: "tempvar",
      datasource: this.getRef(),
      rawSql,
      format: QueryFormat.Table
    };
    const response = await this.runMetaQuery(interpolatedQuery, optionalOptions);
    return this.getResponseParser().transformMetricFindResponse(response);
  }
  async runSql(query, options) {
    const frame = await this.runMetaQuery({ rawSql: query, format: QueryFormat.Table, refId: options == null ? undefined : options.refId }, options);
    return new data.DataFrameView(frame);
  }
  runMetaQuery(request, options) {
    var _a, _b;
    const refId = request.refId || "meta";
    const queries = [{ ...request, datasource: request.datasource || this.getRef(), refId }];
    return rxjs.lastValueFrom(
      runtime.getBackendSrv().fetch({
        url: "/api/ds/query",
        method: "POST",
        data: {
          from: (_a = options == null ? undefined : options.range) == null ? undefined : _a.from.valueOf().toString(),
          to: (_b = options == null ? undefined : options.range) == null ? undefined : _b.to.valueOf().toString(),
          queries
        },
        requestId: refId
      }).pipe(
        operators$1.map((res) => {
          const rsp = runtime.toDataQueryResponse(res, queries);
          return rsp.data[0];
        })
      )
    );
  }
  testDatasource() {
    return rxjs.lastValueFrom(
      runtime.getBackendSrv().fetch({
        url: "/api/ds/query",
        method: "POST",
        data: {
          from: "5m",
          to: "now",
          queries: [
            {
              refId: "A",
              intervalMs: 1,
              maxDataPoints: 1,
              datasource: this.getRef(),
              datasourceId: this.id,
              rawSql: "SELECT 1",
              format: "table"
            }
          ]
        }
      }).pipe(
        operators$1.map(() => ({ status: "success", message: "Database Connection OK" })),
        operators$1.catchError((err) => {
          return rxjs.of(err);
        })
      )
    );
  }
  targetContainsTemplate(target) {
    let queryWithoutMacros = target.rawSql;
    MACRO_NAMES.forEach((value) => {
      queryWithoutMacros = (queryWithoutMacros == null ? undefined : queryWithoutMacros.replace(value, "")) || "";
    });
    return this.templateSrv.containsTemplate(queryWithoutMacros);
  }
}
const SEARCH_FILTER_VARIABLE = "__searchFilter";
const containsSearchFilter = (query) => query && typeof query === "string" ? query.indexOf(SEARCH_FILTER_VARIABLE) !== -1 : false;
const getSearchFilterScopedVar = (args) => {
  const { query, wildcardChar } = args;
  if (!containsSearchFilter(query)) {
    return {};
  }
  let { options } = args;
  options = options || { searchFilter: "" };
  const value = options.searchFilter ? `${options.searchFilter}${wildcardChar}` : `${wildcardChar}`;
  return {
    __searchFilter: {
      value,
      text: ""
    }
  };
};

function SqlQueryEditor({ datasource, query, onChange, onRunQuery, range }) {
  var _a, _b, _c, _d, _e, _f, _g;
  const [isQueryRunnable, setIsQueryRunnable] = React.useState(true);
  const db = datasource.getDB();
  const defaultDataset = datasource.dataset;
  const { loading, error } = reactUse.useAsync(async () => {
    return () => {
      if (datasource.getDB(datasource.id).init !== undefined) {
        datasource.getDB(datasource.id).init();
      }
    };
  }, [datasource]);
  const queryWithDefaults = applyQueryDefaults(query);
  const [queryRowFilter, setQueryRowFilter] = React.useState({
    filter: !!((_a = queryWithDefaults.sql) == null ? undefined : _a.whereString),
    group: !!((_d = (_c = (_b = queryWithDefaults.sql) == null ? undefined : _b.groupBy) == null ? undefined : _c[0]) == null ? undefined : _d.property.name),
    order: !!((_f = (_e = queryWithDefaults.sql) == null ? undefined : _e.orderBy) == null ? undefined : _f.property.name),
    preview: true
  });
  const [queryToValidate, setQueryToValidate] = React.useState(queryWithDefaults);
  React.useEffect(() => {
    return () => {
      if (datasource.getDB(datasource.id).dispose !== undefined) {
        datasource.getDB(datasource.id).dispose();
      }
    };
  }, [datasource]);
  const processQuery = React.useCallback(
    (q) => {
      if (isQueryValid(q) && onRunQuery) {
        onRunQuery();
      }
    },
    [onRunQuery]
  );
  const onQueryChange = (q, process = true) => {
    var _a2, _b2;
    setQueryToValidate(q);
    onChange(q);
    if (haveColumns((_a2 = q.sql) == null ? undefined : _a2.columns) && ((_b2 = q.sql) == null ? undefined : _b2.columns.some((c) => c.name)) && !queryRowFilter.group) {
      setQueryRowFilter({ ...queryRowFilter, group: true });
    }
    if (process) {
      processQuery(q);
    }
  };
  const onQueryHeaderChange = (q) => {
    setQueryToValidate(q);
    onChange(q);
  };
  if (loading || error) {
    return null;
  }
  const catalogsEnabled = db.disableCatalogs === false;
  const datasetsEnabled = !db.disableDatasets;
  const effectiveEnableDatasets = catalogsEnabled ? true : datasetsEnabled;
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      QueryHeader,
      {
        db,
        defaultDataset: defaultDataset || "",
        enableDatasets: effectiveEnableDatasets,
        enableCatalogs: catalogsEnabled,
        onChange: onQueryHeaderChange,
        onRunQuery,
        onQueryRowChange: setQueryRowFilter,
        queryRowFilter,
        query: queryWithDefaults,
        isQueryRunnable,
        labels: (_g = datasource.getDB(datasource.id)) == null ? undefined : _g.labels
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(Space, { v: 0.5 }),
    queryWithDefaults.editorMode !== EditorMode.Code && /* @__PURE__ */ jsxRuntime.jsx(
      VisualEditor,
      {
        db,
        query: queryWithDefaults,
        onChange: (q) => onQueryChange(q, false),
        queryRowFilter,
        onValidate: setIsQueryRunnable,
        range
      }
    ),
    queryWithDefaults.editorMode === EditorMode.Code && /* @__PURE__ */ jsxRuntime.jsx(
      RawEditor,
      {
        db,
        query: queryWithDefaults,
        queryToValidate,
        onChange: onQueryChange,
        onRunQuery,
        onValidate: setIsQueryRunnable,
        range
      }
    )
  ] });
}
const isQueryValid = (q) => {
  return Boolean(q.rawSql);
};

const SecureSocksProxyToggle = ({ labelWidth = 10, ...props }) => {
  const { dataSourceConfig, onChange } = props;
  const handleSwitchChange = (e) => {
    onChange({
      ...dataSourceConfig,
      jsonData: {
        ...dataSourceConfig.jsonData,
        enableSecureSocksProxy: e.target.checked
      }
    });
  };
  return runtime.config.secureSocksDSProxyEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gf-form", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gf-form gf-form-inline", children: /* @__PURE__ */ jsxRuntime.jsx(
    ui.InlineField,
    {
      htmlFor: "secureSocksProxyEnabled",
      label: "Secure Socks Proxy Enabled",
      labelWidth,
      tooltip: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
        "Proxy the datasource connection through the secure socks proxy to a different network. To learn more about configuring the datasource connection proxy,",
        " ",
        /* @__PURE__ */ jsxRuntime.jsx(
          "a",
          {
            href: "https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/proxy/",
            target: "_blank",
            rel: "noopener noreferrer",
            children: "click here."
          }
        )
      ] }),
      children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.InlineSwitch,
        {
          id: "secureSocksProxyEnabled",
          value: dataSourceConfig.jsonData.enableSecureSocksProxy,
          onChange: handleSwitchChange
        }
      )
    }
  ) }) }) });
};

const DataSourceDescription = ({ dataSourceName, docsLink, hasRequiredFields = true, className }) => {
  const theme = ui.useTheme2();
  const styles = {
    container: css.css({
      p: {
        margin: 0
      },
      "p + p": {
        marginTop: theme.spacing(2)
      }
    }),
    text: css.css({
      ...theme.typography.body,
      color: theme.colors.text.secondary,
      a: css.css({
        color: theme.colors.text.link,
        textDecoration: "underline",
        "&:hover": {
          textDecoration: "none"
        }
      })
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: css.cx(styles.container, className), children: [
    /* @__PURE__ */ jsxRuntime.jsxs("p", { className: styles.text, children: [
      "Before you can use the ",
      dataSourceName,
      " data source, you must configure it below or in the config file. For detailed instructions,",
      " ",
      /* @__PURE__ */ jsxRuntime.jsx("a", { href: docsLink, target: "_blank", rel: "noreferrer", children: "view the documentation" }),
      "."
    ] }),
    hasRequiredFields && /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles.text, children: /* @__PURE__ */ jsxRuntime.jsx("i", { children: "Fields marked with * are required" }) })
  ] });
};

const GenericConfigSection = ({
  children,
  title,
  description,
  isCollapsible = false,
  isInitiallyOpen = true,
  kind = "section",
  className
}) => {
  const { colors, typography, spacing } = ui.useTheme2();
  const [isOpen, setIsOpen] = React.useState(isCollapsible ? isInitiallyOpen : true);
  const iconName = isOpen ? "angle-up" : "angle-down";
  const isSubSection = kind === "sub-section";
  const collapsibleButtonAriaLabel = `${isOpen ? "Collapse" : "Expand"} section ${title}`;
  const styles = {
    header: css.css({
      display: "flex",
      justifyContent: "space-between",
      alignItems: "center"
    }),
    title: css.css({
      margin: 0
    }),
    subtitle: css.css({
      margin: 0,
      fontWeight: typography.fontWeightRegular
    }),
    descriptionText: css.css({
      marginTop: spacing(isSubSection ? 0.25 : 0.5),
      marginBottom: 0,
      ...typography.bodySmall,
      color: colors.text.secondary
    }),
    content: css.css({
      marginTop: spacing(2)
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
    /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.header, children: [
      kind === "section" ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: styles.title, children: title }) : /* @__PURE__ */ jsxRuntime.jsx("h6", { className: styles.subtitle, children: title }),
      isCollapsible && /* @__PURE__ */ jsxRuntime.jsx(
        ui.IconButton,
        {
          name: iconName,
          onClick: () => setIsOpen(!isOpen),
          type: "button",
          size: "xl",
          "aria-label": collapsibleButtonAriaLabel
        }
      )
    ] }),
    description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles.descriptionText, children: description }),
    isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.content, children })
  ] });
};

const ConfigSection = ({ children, ...props }) => {
  return /* @__PURE__ */ jsxRuntime.jsx(GenericConfigSection, { ...props, kind: "section", children });
};

const ConfigSubSection = ({ children, ...props }) => {
  return /* @__PURE__ */ jsxRuntime.jsx(GenericConfigSection, { ...props, kind: "sub-section", children });
};

function ConfigDescriptionLink(props) {
  const { description, suffix, feature } = props;
  const text = `Learn more about ${feature}`;
  const styles = ui.useStyles2(getStyles$c);
  return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles.container, children: [
    description,
    /* @__PURE__ */ jsxRuntime.jsx(
      "a",
      {
        "aria-label": text,
        href: `https://grafana.com/docs/grafana/next/datasources/${suffix}`,
        rel: "noreferrer",
        target: "_blank",
        children: text
      }
    )
  ] });
}
const getStyles$c = (theme) => {
  return {
    container: css.css({
      color: theme.colors.text.secondary,
      a: css.css({
        color: theme.colors.text.link,
        textDecoration: "underline",
        marginLeft: "5px",
        "&:hover": {
          textDecoration: "none"
        }
      })
    })
  };
};

var AuthMethod = /* @__PURE__ */ ((AuthMethod2) => {
  AuthMethod2["NoAuth"] = "NoAuth";
  AuthMethod2["BasicAuth"] = "BasicAuth";
  AuthMethod2["OAuthForward"] = "OAuthForward";
  AuthMethod2["CrossSiteCredentials"] = "CrossSiteCredentials";
  return AuthMethod2;
})(AuthMethod || {});

const useCommonStyles = () => {
  return {
    inlineFieldNoMarginRight: css.css({
      marginRight: 0
    }),
    // This is dirty hack to make configured secret input grow
    inlineFieldWithSecret: css.css({
      '[class$="layoutChildrenWrapper"]:first-child': {
        flexGrow: 1
      }
    })
  };
};

const BasicAuth = ({
  user,
  passwordConfigured,
  userLabel = "User",
  userTooltip = "The username of the data source account",
  userPlaceholder = "User",
  passwordLabel = "Password",
  passwordTooltip = "The password of the data source account",
  passwordPlaceholder = "Password",
  onUserChange,
  onPasswordChange,
  onPasswordReset,
  readOnly
}) => {
  const commonStyles = useCommonStyles();
  const styles = {
    lastInlineField: css.css({
      marginBottom: 0
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.InlineField,
      {
        className: commonStyles.inlineFieldNoMarginRight,
        label: userLabel,
        labelWidth: 24,
        tooltip: userTooltip,
        required: true,
        htmlFor: "basic-auth-user-input",
        interactive: true,
        grow: true,
        disabled: readOnly,
        children: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Input,
          {
            id: "basic-auth-user-input",
            placeholder: userPlaceholder,
            value: user,
            onChange: (e) => onUserChange(e.currentTarget.value),
            required: true
          }
        )
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.InlineField,
      {
        className: css.cx(
          commonStyles.inlineFieldNoMarginRight,
          commonStyles.inlineFieldWithSecret,
          styles.lastInlineField
        ),
        label: passwordLabel,
        labelWidth: 24,
        tooltip: passwordTooltip,
        required: true,
        htmlFor: "basic-auth-password-input",
        interactive: true,
        grow: true,
        disabled: readOnly,
        children: /* @__PURE__ */ jsxRuntime.jsx(
          ui.SecretInput,
          {
            id: "basic-auth-password-input",
            isConfigured: passwordConfigured,
            onReset: readOnly ? () => {
            } : onPasswordReset,
            placeholder: passwordPlaceholder,
            onChange: (e) => onPasswordChange(e.currentTarget.value),
            required: true
          }
        )
      }
    )
  ] });
};

const defaultOptions = {
  [AuthMethod.BasicAuth]: {
    label: "Basic authentication",
    value: AuthMethod.BasicAuth,
    description: "Authenticate with your data source username and password"
  },
  [AuthMethod.CrossSiteCredentials]: {
    label: "Enable cross-site access control requests",
    value: AuthMethod.CrossSiteCredentials,
    description: "Allow cross-site Access-Control requests with your existing credentials and cookies. This enables the server to authenticate the user and perform authorized requests on their behalf on other domains."
  },
  [AuthMethod.OAuthForward]: {
    label: "Forward OAuth Identity",
    value: AuthMethod.OAuthForward,
    description: "Forward the OAuth access token (and if available: the OIDC ID token) of the user querying to the data source"
  },
  [AuthMethod.NoAuth]: {
    label: "No Authentication",
    value: AuthMethod.NoAuth,
    description: "Data source is available without authentication"
  }
};
const AuthMethodSettings = ({
  selectedMethod,
  mostCommonMethod,
  visibleMethods: visibleMethodsFromProps,
  defaultOptionsOverrides,
  customMethods,
  onAuthMethodSelect,
  basicAuth,
  readOnly
}) => {
  var _a, _b, _c, _d;
  const [authMethodChanged, setAuthMethodChanged] = React.useState(false);
  const { colors, spacing } = ui.useTheme2();
  const visibleMethods = React.useMemo(
    () => {
      var _a2;
      return visibleMethodsFromProps != null ? visibleMethodsFromProps : [
        AuthMethod.BasicAuth,
        AuthMethod.OAuthForward,
        AuthMethod.NoAuth,
        ...(_a2 = customMethods == null ? undefined : customMethods.map((m) => m.id)) != null ? _a2 : []
      ];
    },
    [customMethods, visibleMethodsFromProps]
  );
  const hasSelect = visibleMethods.length > 1;
  const preparedOptions = React.useMemo(() => {
    var _a2;
    const customOptions = (_a2 = customMethods == null ? undefined : customMethods.reduce((acc, method) => {
      acc[method.id] = {
        label: method.label,
        value: method.id,
        description: method.description
      };
      return acc;
    }, {})) != null ? _a2 : {};
    const preparedDefaultOptions = {};
    let k;
    for (k in defaultOptions) {
      preparedDefaultOptions[k] = {
        ...defaultOptions[k],
        ...defaultOptionsOverrides == null ? undefined : defaultOptionsOverrides[k]
      };
    }
    const allOptions = {
      ...customOptions,
      ...preparedDefaultOptions
    };
    return visibleMethods.filter((method) => Boolean(allOptions[method])).map((method) => {
      const option = allOptions[method];
      if (method === mostCommonMethod && hasSelect) {
        return {
          ...option,
          label: `${option.label} (most common)`
        };
      }
      return option;
    });
  }, [visibleMethods, customMethods, defaultOptionsOverrides, mostCommonMethod, hasSelect]);
  let selected = selectedMethod;
  if (!hasSelect) {
    selected = visibleMethods[0];
  } else if (selectedMethod === AuthMethod.NoAuth && mostCommonMethod && !authMethodChanged) {
    selected = mostCommonMethod;
  }
  let AuthFieldsComponent = null;
  if (selected === AuthMethod.BasicAuth && basicAuth) {
    AuthFieldsComponent = /* @__PURE__ */ jsxRuntime.jsx(BasicAuth, { ...basicAuth, readOnly });
  } else if (selected.startsWith("custom-")) {
    AuthFieldsComponent = (_b = (_a = customMethods == null ? undefined : customMethods.find((m) => m.id === selected)) == null ? undefined : _a.component) != null ? _b : null;
  }
  const title = hasSelect ? "Authentication methods" : (_c = preparedOptions[0].label) != null ? _c : "";
  const description = hasSelect ? "Choose an authentication method to access the data source" : (_d = preparedOptions[0].description) != null ? _d : "";
  const styles = {
    authMethods: css.css({
      marginTop: spacing(2.5),
      ...hasSelect && {
        padding: spacing(2),
        border: `1px solid ${colors.border.weak}`
      }
    }),
    selectedMethodFields: css.css({
      marginTop: spacing(1.5)
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsx(ConfigSubSection, { title, description, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.authMethods, children: [
    hasSelect && /* @__PURE__ */ jsxRuntime.jsx(ui.Field, { label: "Authentication method", children: /* @__PURE__ */ jsxRuntime.jsx(
      ui.Select,
      {
        inputId: "auth-method-select",
        options: preparedOptions,
        value: selected,
        onChange: (option) => {
          setAuthMethodChanged(true);
          onAuthMethodSelect(option.value);
        },
        disabled: readOnly
      }
    ) }),
    AuthFieldsComponent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.selectedMethodFields, children: AuthFieldsComponent })
  ] }) });
};

const TLSSettingsSection = ({
  children,
  enabled,
  label,
  tooltipText,
  onToggle,
  readOnly
}) => {
  const { colors, spacing } = ui.useTheme2();
  const styles = {
    container: css.css({
      marginTop: 3
    }),
    checkboxContainer: css.css({
      display: "flex",
      alignItems: "center"
    }),
    infoIcon: css.css({
      marginTop: -2,
      marginLeft: 5,
      color: colors.text.secondary
    }),
    content: css.css({
      margin: spacing(1, 0, 2, 3)
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.container, children: [
    /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.checkboxContainer, children: [
      /* @__PURE__ */ jsxRuntime.jsx(ui.Checkbox, { value: enabled, label, onChange: () => onToggle(!enabled), disabled: readOnly }),
      /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { placement: "top", content: tooltipText, interactive: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { name: "info-circle", className: styles.infoIcon, size: "sm" }) })
    ] }),
    enabled && children && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.content, children })
  ] });
};

const SelfSignedCertificate = ({
  enabled,
  certificateConfigured,
  onToggle,
  onCertificateChange,
  onCertificateReset,
  tooltips,
  readOnly
}) => {
  var _a;
  const commonStyles = useCommonStyles();
  return /* @__PURE__ */ jsxRuntime.jsx(
    TLSSettingsSection,
    {
      enabled,
      label: "Add self-signed certificate",
      tooltipText: "Add your own Certificate Authority (CA) certificate on top of one generated by the certificate authorities for additional security measures",
      onToggle: (newEnabled) => onToggle(newEnabled),
      readOnly,
      children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.InlineField,
        {
          label: "CA Certificate",
          labelWidth: 24,
          tooltip: (_a = tooltips == null ? undefined : tooltips.certificateLabel) != null ? _a : "Your self-signed certificate",
          required: true,
          htmlFor: "self-signed-certificate-input",
          interactive: true,
          grow: true,
          className: css.cx(commonStyles.inlineFieldNoMarginRight, commonStyles.inlineFieldWithSecret),
          disabled: readOnly,
          children: /* @__PURE__ */ jsxRuntime.jsx(
            ui.SecretTextArea,
            {
              id: "self-signed-certificate-input",
              isConfigured: certificateConfigured,
              onChange: (e) => onCertificateChange(e.currentTarget.value),
              onReset: readOnly ? () => {
              } : onCertificateReset,
              placeholder: "Begins with --- BEGIN CERTIFICATE ---",
              rows: 6,
              required: true
            }
          )
        }
      )
    }
  );
};

const TLSClientAuth = ({
  enabled,
  serverName,
  clientCertificateConfigured,
  clientKeyConfigured,
  onToggle,
  onServerNameChange,
  onClientCertificateChange,
  onClientKeyChange,
  onClientCertificateReset,
  onClientKeyReset,
  tooltips,
  readOnly
}) => {
  var _a, _b, _c;
  const commonStyles = useCommonStyles();
  return /* @__PURE__ */ jsxRuntime.jsxs(
    TLSSettingsSection,
    {
      enabled,
      label: "TLS Client Authentication",
      tooltipText: "Validate using TLS client authentication, in which the server authenticates the client",
      onToggle: (newEnabled) => onToggle(newEnabled),
      readOnly,
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.InlineField,
          {
            label: "ServerName",
            labelWidth: 24,
            tooltip: (_a = tooltips == null ? undefined : tooltips.serverNameLabel) != null ? _a : "A Servername is used to verify the hostname on the returned certificate",
            required: true,
            htmlFor: "client-auth-servername-input",
            interactive: true,
            grow: true,
            className: commonStyles.inlineFieldNoMarginRight,
            disabled: readOnly,
            children: /* @__PURE__ */ jsxRuntime.jsx(
              ui.Input,
              {
                id: "client-auth-servername-input",
                placeholder: "domain.example.com",
                value: serverName,
                onChange: (e) => onServerNameChange(e.currentTarget.value),
                required: true
              }
            )
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.InlineField,
          {
            label: "Client Certificate",
            labelWidth: 24,
            tooltip: (_b = tooltips == null ? undefined : tooltips.certificateLabel) != null ? _b : "The client certificate can be generated from a Certificate Authority or be self-signed",
            required: true,
            htmlFor: "client-auth-client-certificate-input",
            interactive: true,
            grow: true,
            className: css.cx(commonStyles.inlineFieldNoMarginRight, commonStyles.inlineFieldWithSecret),
            disabled: readOnly,
            children: /* @__PURE__ */ jsxRuntime.jsx(
              ui.SecretTextArea,
              {
                id: "client-auth-client-certificate-input",
                isConfigured: clientCertificateConfigured,
                onChange: (e) => onClientCertificateChange(e.currentTarget.value),
                onReset: readOnly ? () => {
                } : onClientCertificateReset,
                placeholder: "Begins with --- BEGIN CERTIFICATE ---",
                rows: 6,
                required: true
              }
            )
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.InlineField,
          {
            label: "Client Key",
            labelWidth: 24,
            tooltip: (_c = tooltips == null ? undefined : tooltips.keyLabel) != null ? _c : "The client key can be generated from a Certificate Authority or be self-signed",
            required: true,
            htmlFor: "client-auth-client-key-input",
            interactive: true,
            grow: true,
            className: css.cx(commonStyles.inlineFieldNoMarginRight, commonStyles.inlineFieldWithSecret),
            disabled: readOnly,
            children: /* @__PURE__ */ jsxRuntime.jsx(
              ui.SecretTextArea,
              {
                id: "client-auth-client-key-input",
                isConfigured: clientKeyConfigured,
                onChange: (e) => onClientKeyChange(e.currentTarget.value),
                onReset: readOnly ? () => {
                } : onClientKeyReset,
                placeholder: `Begins with --- RSA PRIVATE KEY CERTIFICATE ---`,
                rows: 6,
                required: true
              }
            )
          }
        )
      ]
    }
  );
};

const SkipTLSVerification = ({ enabled, onToggle, readOnly }) => {
  return /* @__PURE__ */ jsxRuntime.jsx(
    TLSSettingsSection,
    {
      enabled,
      label: "Skip TLS certificate validation",
      tooltipText: "Skipping TLS certificate validation is not recommended unless absolutely necessary or for testing",
      onToggle: (newEnabled) => onToggle(newEnabled),
      readOnly
    }
  );
};

const TLSSettings = ({ selfSignedCertificate, TLSClientAuth: TLSClientAuth$1, skipTLSVerification, readOnly }) => {
  const { spacing } = ui.useTheme2();
  const styles = {
    container: css.css({
      marginTop: spacing(3)
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(
    ConfigSubSection,
    {
      className: styles.container,
      title: "TLS settings",
      description: "Additional security measures that can be applied on top of authentication",
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(SelfSignedCertificate, { ...selfSignedCertificate, readOnly }),
        /* @__PURE__ */ jsxRuntime.jsx(TLSClientAuth, { ...TLSClientAuth$1, readOnly }),
        /* @__PURE__ */ jsxRuntime.jsx(SkipTLSVerification, { ...skipTLSVerification, readOnly })
      ]
    }
  );
};

const CustomHeader = ({ header, onChange, onBlur, onDelete, readOnly }) => {
  const { spacing } = ui.useTheme2();
  const commonStyles = useCommonStyles();
  const styles = {
    container: css.css({
      alignItems: "center"
    }),
    input: css.css({
      minWidth: "100%"
    }),
    headerNameField: css.css({
      width: "40%",
      marginRight: 0,
      paddingRight: spacing(1)
    }),
    headerValueField: css.css({
      width: "45%",
      marginRight: 0
    }),
    removeHeaderBtn: css.css({
      margin: `0 0 3px 10px`
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.InlineFieldRow, { className: styles.container, children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.InlineField,
      {
        label: "Header",
        labelWidth: 9,
        grow: true,
        className: styles.headerNameField,
        htmlFor: `custom-header-${header.id}-name-input`,
        disabled: readOnly,
        children: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Input,
          {
            id: `custom-header-${header.id}-name-input`,
            placeholder: "X-Custom-Header",
            value: header.name,
            width: 12,
            onChange: (e) => onChange({ ...header, name: e.currentTarget.value }),
            onBlur,
            className: styles.input
          }
        )
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.InlineField,
      {
        label: "Value",
        labelWidth: 9,
        grow: true,
        className: css.cx(commonStyles.inlineFieldWithSecret, styles.headerValueField),
        htmlFor: `custom-header-${header.id}-value-input`,
        disabled: readOnly,
        children: /* @__PURE__ */ jsxRuntime.jsx(
          ui.SecretInput,
          {
            id: `custom-header-${header.id}-value-input`,
            isConfigured: header.configured,
            placeholder: "Header value",
            value: header.value,
            width: 12,
            onChange: (e) => onChange({ ...header, value: e.currentTarget.value }),
            onReset: readOnly ? () => {
            } : () => onChange({ ...header, configured: false, value: "" }),
            onBlur,
            className: styles.input
          }
        )
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.IconButton,
      {
        name: "trash-alt",
        tooltip: "Remove header",
        tooltipPlacement: "top",
        className: styles.removeHeaderBtn,
        onClick: onDelete,
        type: "button",
        disabled: readOnly
      }
    )
  ] }) });
};

const CustomHeaders = ({ headers: headersFromProps, onChange, readOnly }) => {
  const { spacing } = ui.useTheme2();
  const [headers, setHeaders] = React.useState(
    headersFromProps.map((header) => ({
      ...header,
      id: uniqueId(),
      value: ""
    }))
  );
  React.useEffect(() => {
    setHeaders((headers2) => {
      let changed = false;
      const newHeaders = headers2.map((header) => {
        var _a;
        const configured = (_a = headersFromProps.find((h) => h.name === header.name)) == null ? undefined : _a.configured;
        if (typeof configured !== "undefined" && header.configured !== configured) {
          changed = true;
          return { ...header, configured };
        }
        return header;
      });
      if (changed) {
        return newHeaders;
      }
      return headers2;
    });
  }, [headersFromProps]);
  const onHeaderAdd = () => {
    setHeaders([...headers, { id: uniqueId(), name: "", value: "", configured: false }]);
  };
  const onHeaderChange = (id, header) => {
    setHeaders(headers.map((h) => h.id === id ? { ...header } : h));
  };
  const onHeaderDelete = (id) => {
    const index = headers.findIndex((h) => h.id === id);
    if (index === -1) {
      return;
    }
    const newHeaders = [...headers];
    newHeaders.splice(index, 1);
    setHeaders(newHeaders);
    onChange(
      newHeaders.map(({ name, value, configured }) => ({
        name,
        value,
        configured
      }))
    );
  };
  const onBlur = () => {
    onChange(
      headers.map(({ name, value, configured }) => ({
        name,
        value,
        configured
      }))
    );
  };
  const styles = {
    container: css.css({
      marginTop: spacing(3)
    }),
    addHeaderButton: css.css({
      marginTop: spacing(1.5)
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.container, children: /* @__PURE__ */ jsxRuntime.jsxs(
    ConfigSubSection,
    {
      title: "HTTP headers",
      description: "Pass along additional context and metadata about the request/response",
      isCollapsible: true,
      isInitiallyOpen: headers.length > 0,
      children: [
        /* @__PURE__ */ jsxRuntime.jsx("div", { children: headers.map((header) => /* @__PURE__ */ jsxRuntime.jsx(
          CustomHeader,
          {
            header,
            onChange: (header2) => onHeaderChange(header2.id, header2),
            onDelete: () => onHeaderDelete(header.id),
            onBlur,
            readOnly
          },
          header.id
        )) }),
        /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.addHeaderButton, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { icon: "plus", variant: "secondary", fill: "outline", onClick: onHeaderAdd, disabled: readOnly, children: headers.length === 0 ? "Add header" : "Add another header" }) })
      ]
    }
  ) });
};
function uniqueId() {
  return Math.random().toString(16).slice(2);
}

const Auth = ({
  selectedMethod,
  mostCommonMethod,
  visibleMethods,
  defaultOptionsOverrides,
  customMethods,
  onAuthMethodSelect,
  basicAuth,
  TLS,
  customHeaders,
  readOnly = false
}) => {
  const styles = {
    container: css.css({
      maxWidth: 578
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.container, children: /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Authentication", children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      AuthMethodSettings,
      {
        selectedMethod,
        mostCommonMethod,
        customMethods,
        visibleMethods,
        defaultOptionsOverrides,
        onAuthMethodSelect,
        basicAuth,
        readOnly
      }
    ),
    TLS && /* @__PURE__ */ jsxRuntime.jsx(TLSSettings, { ...TLS, readOnly }),
    customHeaders && /* @__PURE__ */ jsxRuntime.jsx(CustomHeaders, { ...customHeaders, readOnly })
  ] }) });
};

const headerNamePrefix = "httpHeaderName";
const headerValuePrefix = "httpHeaderValue";
function convertLegacyAuthProps({
  config,
  onChange
}) {
  const props = {
    selectedMethod: getSelectedMethod(config),
    onAuthMethodSelect: getOnAuthMethodSelectHandler(config, onChange),
    basicAuth: getBasicAuthProps(config, onChange),
    TLS: getTLSProps(config, onChange),
    customHeaders: getCustomHeaders(config, onChange),
    readOnly: config.readOnly
  };
  return props;
}
function getSelectedMethod(config) {
  if (config.basicAuth) {
    return AuthMethod.BasicAuth;
  }
  if (config.withCredentials) {
    return AuthMethod.CrossSiteCredentials;
  }
  if (config.jsonData.oauthPassThru) {
    return AuthMethod.OAuthForward;
  }
  return AuthMethod.NoAuth;
}
function getOnAuthMethodSelectHandler(config, onChange) {
  return (method) => {
    onChange({
      ...config,
      basicAuth: method === AuthMethod.BasicAuth,
      withCredentials: method === AuthMethod.CrossSiteCredentials,
      jsonData: {
        ...config.jsonData,
        oauthPassThru: method === AuthMethod.OAuthForward
      }
    });
  };
}
function getBasicAuthProps(config, onChange) {
  return {
    user: config.basicAuthUser,
    passwordConfigured: config.secureJsonFields.basicAuthPassword,
    onUserChange: (user) => onChange({ ...config, basicAuthUser: user }),
    onPasswordChange: (password) => onChange({
      ...config,
      secureJsonData: {
        ...config.secureJsonData,
        basicAuthPassword: password
      }
    }),
    onPasswordReset: () => onChange({
      ...config,
      secureJsonData: { ...config.secureJsonData, basicAuthPassword: "" },
      secureJsonFields: {
        ...config.secureJsonFields,
        basicAuthPassword: false
      }
    })
  };
}
function getTLSProps(config, onChange) {
  var _a, _b, _c;
  return {
    selfSignedCertificate: {
      enabled: Boolean(config.jsonData.tlsAuthWithCACert),
      certificateConfigured: !!((_a = config.secureJsonFields) == null ? undefined : _a.tlsCACert),
      onToggle: (enabled) => enabled ? onChange({
        ...config,
        jsonData: { ...config.jsonData, tlsAuthWithCACert: enabled }
      }) : onChange({
        ...config,
        jsonData: { ...config.jsonData, tlsAuthWithCACert: enabled },
        secureJsonData: { ...config.secureJsonData, tlsCACert: "" },
        secureJsonFields: { ...config.secureJsonFields, tlsCACert: false }
      }),
      onCertificateChange: (certificate) => onChange({
        ...config,
        secureJsonData: { ...config.secureJsonData, tlsCACert: certificate }
      }),
      onCertificateReset: () => onChange({
        ...config,
        secureJsonData: { ...config.secureJsonData, tlsCACert: "" },
        secureJsonFields: { ...config.secureJsonFields, tlsCACert: false }
      })
    },
    TLSClientAuth: {
      enabled: config.jsonData.tlsAuth,
      serverName: config.jsonData.serverName,
      clientCertificateConfigured: !!((_b = config.secureJsonFields) == null ? undefined : _b.tlsClientCert),
      clientKeyConfigured: !!((_c = config.secureJsonFields) == null ? undefined : _c.tlsClientKey),
      onToggle: (enabled) => enabled ? onChange({
        ...config,
        jsonData: { ...config.jsonData, tlsAuth: enabled }
      }) : onChange({
        ...config,
        jsonData: { ...config.jsonData, tlsAuth: enabled, serverName: "" },
        secureJsonData: { ...config.secureJsonData, tlsClientCert: "", tlsClientKey: "" },
        secureJsonFields: { ...config.secureJsonFields, tlsClientCert: false, tlsClientKey: false }
      }),
      onServerNameChange: (serverName) => onChange({
        ...config,
        jsonData: { ...config.jsonData, serverName }
      }),
      onClientCertificateChange: (clientCertificate) => onChange({
        ...config,
        secureJsonData: {
          ...config.secureJsonData,
          tlsClientCert: clientCertificate
        }
      }),
      onClientCertificateReset: () => onChange({
        ...config,
        secureJsonData: {
          ...config.secureJsonData,
          tlsClientCert: ""
        },
        secureJsonFields: {
          ...config.secureJsonFields,
          tlsClientCert: false
        }
      }),
      onClientKeyChange: (clientKey) => onChange({
        ...config,
        secureJsonData: {
          ...config.secureJsonData,
          tlsClientKey: clientKey
        }
      }),
      onClientKeyReset: () => onChange({
        ...config,
        secureJsonData: {
          ...config.secureJsonData,
          tlsClientKey: ""
        },
        secureJsonFields: {
          ...config.secureJsonFields,
          tlsClientKey: false
        }
      })
    },
    skipTLSVerification: {
      enabled: config.jsonData.tlsSkipVerify,
      onToggle: (enabled) => onChange({
        ...config,
        jsonData: { ...config.jsonData, tlsSkipVerify: enabled }
      })
    }
  };
}
function getCustomHeaders(config, onChange) {
  const headers = Object.keys(config.jsonData).filter((key) => key.startsWith(headerNamePrefix)).sort().map((key) => {
    var _a;
    const index = key.slice(headerNamePrefix.length);
    return {
      name: config.jsonData[key],
      configured: (_a = config.secureJsonFields[`${headerValuePrefix}${index}`]) != null ? _a : false
    };
  });
  return {
    headers,
    onChange: (headers2) => {
      const newJsonData = Object.fromEntries(
        Object.entries(config.jsonData).filter(([key]) => !key.startsWith(headerNamePrefix))
      );
      const newSecureJsonData = Object.fromEntries(
        Object.entries(config.secureJsonData || {}).filter(([key]) => !key.startsWith(headerValuePrefix))
      );
      const newSecureJsonFields = Object.fromEntries(
        Object.entries(config.secureJsonFields).filter(([key]) => !key.startsWith(headerValuePrefix))
      );
      headers2.forEach((header, index) => {
        newJsonData[`${headerNamePrefix}${index + 1}`] = header.name;
        if (header.configured) {
          newSecureJsonFields[`${headerValuePrefix}${index + 1}`] = true;
        } else {
          newSecureJsonData[`${headerValuePrefix}${index + 1}`] = header.value;
        }
      });
      onChange({
        ...config,
        jsonData: newJsonData,
        secureJsonData: newSecureJsonData,
        secureJsonFields: newSecureJsonFields
      });
    }
  };
}

const ConnectionSettings = ({
  config,
  onChange,
  description,
  urlPlaceholder,
  urlTooltip,
  urlLabel,
  className
}) => {
  const isValidUrl = config.url !== undefined && /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/.test(config.url);
  const styles = {
    container: css.css({
      maxWidth: 578
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Connection", description, className: css.cx(styles.container, className), children: /* @__PURE__ */ jsxRuntime.jsx(
    ui.InlineField,
    {
      htmlFor: "connection-url",
      label: urlLabel || "URL",
      labelWidth: 24,
      tooltip: urlTooltip || /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
        "Specify a complete HTTP URL",
        /* @__PURE__ */ jsxRuntime.jsx("br", {}),
        "(for example https://example.com:8080)"
      ] }),
      grow: true,
      disabled: config.readOnly,
      required: true,
      invalid: !isValidUrl && !config.readOnly,
      error: isValidUrl ? "" : "Please enter a valid URL",
      interactive: true,
      children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Input,
        {
          id: "connection-url",
          "aria-label": "Data source connection URL",
          onChange: (event) => onChange({
            ...config,
            url: event.currentTarget.value
          }),
          value: config.url || "",
          placeholder: urlPlaceholder || "URL"
        }
      )
    }
  ) }) });
};

const AdvancedHttpSettings = ({
  config,
  onChange,
  className
}) => {
  const onCookiesChange = (cookies) => {
    onChange({
      ...config,
      jsonData: {
        ...config.jsonData,
        keepCookies: cookies
      }
    });
  };
  const onTimeoutChange = (event) => {
    onChange({
      ...config,
      jsonData: {
        ...config.jsonData,
        timeout: parseInt(event.currentTarget.value, 10)
      }
    });
  };
  const styles = {
    container: css.css({
      maxWidth: 578
    })
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSubSection, { title: "Advanced HTTP settings", className: css.cx(styles.container, className), children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.InlineField,
      {
        htmlFor: "advanced-http-cookies",
        label: "Allowed cookies",
        labelWidth: 24,
        tooltip: "Grafana proxy deletes forwarded cookies by default. Specify cookies by name that should be forwarded to the data source.",
        disabled: config.readOnly,
        grow: true,
        children: /* @__PURE__ */ jsxRuntime.jsx(
          ui.TagsInput,
          {
            id: "advanced-http-cookies",
            placeholder: "New cookie (hit enter to add)",
            tags: config.jsonData.keepCookies,
            onChange: onCookiesChange
          }
        )
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.InlineField,
      {
        htmlFor: "advanced-http-timeout",
        label: "Timeout",
        labelWidth: 24,
        tooltip: "HTTP request timeout in seconds",
        disabled: config.readOnly,
        grow: true,
        children: /* @__PURE__ */ jsxRuntime.jsx(
          ui.Input,
          {
            id: "advanced-http-timeout",
            type: "number",
            min: 0,
            placeholder: "Timeout in seconds",
            "aria-label": "Timeout in seconds",
            value: config.jsonData.timeout,
            onChange: onTimeoutChange
          }
        )
      }
    )
  ] });
};

var __defProp$2 = Object.defineProperty;
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
const getCustomHeaderRowStyles = ui.stylesFactory(() => {
  return {
    layout: css.css`
      display: flex;
      align-items: center;
      margin-bottom: 4px;
      > * {
        margin-left: 4px;
        margin-bottom: 0;
        height: 100%;
        &:first-child,
        &:last-child {
          margin-left: 0;
        }
      }
    `
  };
});
const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }) => {
  const styles = getCustomHeaderRowStyles();
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.layout, children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.LegacyForms.FormField,
      {
        label: "Header",
        name: "name",
        placeholder: "X-Custom-Header",
        labelWidth: 5,
        value: header.name || "",
        onChange: (e) => onChange({ ...header, name: e.target.value }),
        onBlur
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.LegacyForms.SecretFormField,
      {
        label: "Value",
        "aria-label": "Value",
        name: "value",
        isConfigured: header.configured,
        value: header.value,
        labelWidth: 5,
        inputWidth: header.configured ? 11 : 12,
        placeholder: "Header Value",
        onReset: () => onReset(header.id),
        onChange: (e) => onChange({ ...header, value: e.target.value }),
        onBlur
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        type: "button",
        "aria-label": "Remove header",
        variant: "secondary",
        size: "xs",
        onClick: (_e) => onRemove(header.id),
        children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { name: "trash-alt" })
      }
    )
  ] });
};
CustomHeaderRow.displayName = "CustomHeaderRow";
class CustomHeadersSettings extends React.PureComponent {
  constructor(props) {
    super(props);
    __publicField$2(this, "state", {
      headers: []
    });
    __publicField$2(this, "updateSettings", () => {
      const { headers } = this.state;
      const newJsonData = Object.fromEntries(
        Object.entries(this.props.dataSourceConfig.jsonData).filter(([key, val]) => !key.startsWith("httpHeaderName"))
      );
      const newSecureJsonData = Object.fromEntries(
        Object.entries(this.props.dataSourceConfig.secureJsonData || {}).filter(
          ([key, val]) => !key.startsWith("httpHeaderValue")
        )
      );
      for (const [index, header] of headers.entries()) {
        newJsonData[`httpHeaderName${index + 1}`] = header.name;
        if (!header.configured) {
          newSecureJsonData[`httpHeaderValue${index + 1}`] = header.value;
        }
      }
      this.props.onChange({
        ...this.props.dataSourceConfig,
        jsonData: newJsonData,
        secureJsonData: newSecureJsonData
      });
    });
    __publicField$2(this, "onHeaderAdd", () => {
      this.setState((prevState) => {
        return {
          headers: [...prevState.headers, { id: lodash.uniqueId(), name: "", value: "", configured: false }]
        };
      });
    });
    __publicField$2(this, "onHeaderChange", (headerIndex, value) => {
      this.setState(({ headers }) => {
        return {
          headers: headers.map((item, index) => {
            if (headerIndex !== index) {
              return item;
            }
            return { ...value };
          })
        };
      });
    });
    __publicField$2(this, "onHeaderReset", (headerId) => {
      this.setState(({ headers }) => {
        return {
          headers: headers.map((h, i) => {
            if (h.id !== headerId) {
              return h;
            }
            return {
              ...h,
              value: "",
              configured: false
            };
          })
        };
      });
    });
    __publicField$2(this, "onHeaderRemove", (headerId) => {
      this.setState(
        ({ headers }) => ({
          headers: headers.filter((h) => h.id !== headerId)
        }),
        this.updateSettings
      );
    });
    const { jsonData, secureJsonData, secureJsonFields } = this.props.dataSourceConfig;
    this.state = {
      headers: Object.keys(jsonData).sort().filter((key) => key.startsWith("httpHeaderName")).map((key, index) => {
        return {
          id: lodash.uniqueId(),
          name: jsonData[key],
          value: secureJsonData !== undefined ? secureJsonData[key] : "",
          configured: secureJsonFields && secureJsonFields[`httpHeaderValue${index + 1}`] || false
        };
      })
    };
  }
  render() {
    const { headers } = this.state;
    return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gf-form-group", children: [
      /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gf-form", children: /* @__PURE__ */ jsxRuntime.jsx("h6", { children: "Custom HTTP Headers" }) }),
      /* @__PURE__ */ jsxRuntime.jsx("div", { children: headers.map((header, i) => /* @__PURE__ */ jsxRuntime.jsx(
        CustomHeaderRow,
        {
          header,
          onChange: (h) => {
            this.onHeaderChange(i, h);
          },
          onBlur: this.updateSettings,
          onRemove: this.onHeaderRemove,
          onReset: this.onHeaderReset
        },
        header.id
      )) }),
      /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gf-form", children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Button,
        {
          variant: "secondary",
          icon: "plus",
          type: "button",
          onClick: (e) => {
            this.onHeaderAdd();
          },
          children: "Add header"
        }
      ) })
    ] });
  }
}

var QueryEditorMode = /* @__PURE__ */ ((QueryEditorMode2) => {
  QueryEditorMode2["Code"] = "code";
  QueryEditorMode2["Builder"] = "builder";
  return QueryEditorMode2;
})(QueryEditorMode || {});
const BINARY_OPERATIONS_KEY = "Binary operations";

var __defProp$1 = Object.defineProperty;
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
class QueryModellerBase {
  constructor(operationDefinitions, innerQueryPlaceholder) {
    __publicField$1(this, "operationsRegistry");
    __publicField$1(this, "categories", []);
    __publicField$1(this, "innerQueryPlaceholder");
    this.operationsRegistry = new data.Registry(() => operationDefinitions);
    this.innerQueryPlaceholder = innerQueryPlaceholder || "<query>";
  }
  setOperationCategories(categories) {
    this.categories = categories;
  }
  getOperationsForCategory(category) {
    return this.operationsRegistry.list().filter((op) => op.category === category && !op.hideFromList);
  }
  getAlternativeOperations(key) {
    return this.operationsRegistry.list().filter((op) => op.alternativesKey && op.alternativesKey === key);
  }
  getCategories() {
    return this.categories;
  }
  getOperationDefinition(id) {
    return this.operationsRegistry.getIfExists(id);
  }
  hasBinaryOp(query) {
    return query.operations.find((op) => {
      const def = this.getOperationDefinition(op.id);
      return (def == null ? undefined : def.category) === BINARY_OPERATIONS_KEY;
    }) !== undefined;
  }
}

const CONFLICTING_LABEL_FILTER_ERROR_MESSAGE = "You have conflicting label filters";
function LabelFilterItem({
  item,
  items,
  defaultOp,
  onChange,
  onDelete,
  onGetLabelNames,
  onGetLabelValues,
  invalidLabel,
  invalidValue,
  multiValueSeparator = "|"
}) {
  var _a;
  const [state, setState] = React.useState({});
  const [labelNamesMenuOpen, setLabelNamesMenuOpen] = React.useState(false);
  const [labelValuesMenuOpen, setLabelValuesMenuOpen] = React.useState(false);
  const isMultiSelect = (operator = item.op) => {
    var _a2;
    return (_a2 = operators.find((op) => op.label === operator)) == null ? undefined : _a2.isMultiValue;
  };
  const getSelectOptionsFromString = (item2) => {
    if (item2) {
      if (item2.indexOf(multiValueSeparator) > 0) {
        return item2.split(multiValueSeparator);
      }
      return [item2];
    }
    return [];
  };
  const getOptions = () => {
    const labelValues = state.labelValues ? [...state.labelValues] : [];
    const selectedOptions = getSelectOptionsFromString(item == null ? undefined : item.value).map(data.toOption);
    return lodash.uniqBy([...selectedOptions, ...labelValues], "value");
  };
  const isConflicting = isConflictingLabelFilter(item, items);
  const { current: id } = React.useRef(uuid.v4());
  return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": "visual-query-builder-dimensions-filter-item", children: /* @__PURE__ */ jsxRuntime.jsx(ui.InlineField, { error: CONFLICTING_LABEL_FILTER_ERROR_MESSAGE, invalid: isConflicting ? true : undefined, children: /* @__PURE__ */ jsxRuntime.jsxs(InputGroup, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Select,
      {
        placeholder: "Select label",
        "data-testid": e2eSelectors.selectors.components.QueryBuilder.labelSelect,
        inputId: `visual-query-builder-dimensions-filter-item-key-${id}`,
        width: "auto",
        value: item.label ? data.toOption(item.label) : null,
        allowCustomValue: true,
        onOpenMenu: async () => {
          setState({ isLoadingLabelNames: true });
          const labelNames = await onGetLabelNames(item);
          setLabelNamesMenuOpen(true);
          setState({ labelNames, isLoadingLabelNames: undefined });
        },
        onCloseMenu: () => {
          setLabelNamesMenuOpen(false);
        },
        isOpen: labelNamesMenuOpen,
        isLoading: state.isLoadingLabelNames,
        options: state.labelNames,
        onChange: (change) => {
          var _a2;
          if (change.value) {
            onChange({
              ...item,
              op: (_a2 = item.op) != null ? _a2 : defaultOp,
              label: change.value
            });
          }
        },
        invalid: isConflicting || invalidLabel
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Select,
      {
        "data-testid": e2eSelectors.selectors.components.QueryBuilder.matchOperatorSelect,
        value: data.toOption((_a = item.op) != null ? _a : defaultOp),
        options: operators,
        width: "auto",
        onChange: (change) => {
          if (change.value) {
            onChange({
              ...item,
              op: change.value,
              value: isMultiSelect(change.value) ? item.value : getSelectOptionsFromString(item == null ? undefined : item.value)[0]
            });
          }
        },
        invalid: isConflicting
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Select,
      {
        placeholder: "Select value",
        "data-testid": e2eSelectors.selectors.components.QueryBuilder.valueSelect,
        inputId: `visual-query-builder-dimensions-filter-item-value-${id}`,
        width: "auto",
        value: isMultiSelect() ? getSelectOptionsFromString(item == null ? undefined : item.value).map(data.toOption) : getSelectOptionsFromString(item == null ? undefined : item.value).map(data.toOption)[0],
        allowCustomValue: true,
        onOpenMenu: async () => {
          setState({ isLoadingLabelValues: true });
          const labelValues = await onGetLabelValues(item);
          setState({
            ...state,
            labelValues,
            isLoadingLabelValues: undefined
          });
          setLabelValuesMenuOpen(true);
        },
        onCloseMenu: () => {
          setLabelValuesMenuOpen(false);
        },
        isOpen: labelValuesMenuOpen,
        isMulti: isMultiSelect(),
        isLoading: state.isLoadingLabelValues,
        options: getOptions(),
        onChange: (change) => {
          var _a2, _b;
          if (change.value) {
            onChange({
              ...item,
              value: change.value,
              op: (_a2 = item.op) != null ? _a2 : defaultOp
            });
          } else {
            const changes = change.map((change2) => {
              if (change2.value) {
                return change2.value;
              } else {
                return undefined;
              }
            }).filter((val) => val !== undefined).join(multiValueSeparator);
            onChange({ ...item, value: changes, op: (_b = item.op) != null ? _b : defaultOp });
          }
        },
        invalid: isConflicting || invalidValue
      }
    ),
    /* @__PURE__ */ jsxRuntime.jsx(AccessoryButton, { "aria-label": "remove", icon: "times", variant: "secondary", onClick: onDelete })
  ] }) }) });
}
const operators = [
  { label: "=", value: "=", description: "Equals", isMultiValue: false },
  { label: "!=", value: "!=", description: "Does not equal", isMultiValue: false },
  { label: "=~", value: "=~", description: "Matches regex", isMultiValue: true },
  { label: "!~", value: "!~", description: "Does not match regex", isMultiValue: true }
];
function isConflictingLabelFilter(newLabel, labels) {
  if (!newLabel.label || !newLabel.op || !newLabel.value) {
    return false;
  }
  if (labels.length < 2) {
    return false;
  }
  const operationIsNegative = newLabel.op.toString().startsWith("!");
  const candidates = labels.filter(
    (label) => label.label === newLabel.label && label.value === newLabel.value && label.op !== newLabel.op
  );
  const conflict = candidates.some((candidate) => {
    var _a, _b;
    if (operationIsNegative && ((_a = candidate == null ? undefined : candidate.op) == null ? undefined : _a.toString().startsWith("!")) === false) {
      return true;
    }
    if (operationIsNegative === false && ((_b = candidate == null ? undefined : candidate.op) == null ? undefined : _b.toString().startsWith("!"))) {
      return true;
    }
    return false;
  });
  return conflict;
}

const MISSING_LABEL_FILTER_ERROR_MESSAGE = "Select at least 1 label filter (label and value)";
function LabelFilters({
  labelsFilters,
  onChange,
  onGetLabelNames,
  onGetLabelValues,
  labelFilterRequired,
  multiValueSeparator
}) {
  const defaultOp = "=";
  const [items, setItems] = React.useState([{ op: defaultOp }]);
  React.useEffect(() => {
    if (labelsFilters.length > 0) {
      setItems(labelsFilters);
    } else {
      setItems([{ op: defaultOp }]);
    }
  }, [labelsFilters]);
  const onLabelsChange = (newItems) => {
    setItems(newItems);
    const newLabels = newItems.filter(
      (item) => item.label !== undefined && item.value !== undefined
    );
    if (!lodash.isEqual(newLabels, labelsFilters)) {
      onChange(newLabels);
    }
  };
  const hasLabelFilter = items.some((item) => item.label && item.value);
  return /* @__PURE__ */ jsxRuntime.jsx(EditorFieldGroup, { children: /* @__PURE__ */ jsxRuntime.jsx(
    EditorField$1,
    {
      label: "Label filters",
      error: MISSING_LABEL_FILTER_ERROR_MESSAGE,
      invalid: labelFilterRequired && !hasLabelFilter,
      children: /* @__PURE__ */ jsxRuntime.jsx(
        EditorList,
        {
          items,
          onChange: onLabelsChange,
          renderItem: (item, onChangeItem, onDelete) => /* @__PURE__ */ jsxRuntime.jsx(
            LabelFilterItem,
            {
              item,
              items,
              defaultOp,
              onChange: onChangeItem,
              onDelete,
              onGetLabelNames,
              onGetLabelValues,
              invalidLabel: labelFilterRequired && !item.label,
              invalidValue: labelFilterRequired && !item.value,
              multiValueSeparator
            }
          )
        }
      )
    }
  ) });
}

function OperationExplainedBox({ title, stepNumber, markdown, children }) {
  const styles = ui.useStyles2(getStyles$b);
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.box, children: [
    stepNumber !== undefined && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.stepNumber, children: stepNumber }),
    /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.boxInner, children: [
      title && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.header, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: title }) }),
      /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.body, children: [
        markdown && /* @__PURE__ */ jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: data.renderMarkdown(markdown) } }),
        children
      ] })
    ] })
  ] });
}
const getStyles$b = (theme) => {
  return {
    box: css.css({
      background: theme.colors.background.secondary,
      padding: theme.spacing(1),
      borderRadius: theme.shape.radius.default,
      position: "relative"
    }),
    boxInner: css.css({
      marginLeft: theme.spacing(4)
    }),
    stepNumber: css.css({
      fontWeight: theme.typography.fontWeightMedium,
      background: theme.colors.secondary.main,
      width: "20px",
      height: "20px",
      borderRadius: theme.shape.radius.circle,
      display: "flex",
      alignItems: "center",
      justifyContent: "center",
      position: "absolute",
      top: "10px",
      left: "11px",
      fontSize: theme.typography.bodySmall.fontSize
    }),
    header: css.css({
      paddingBottom: theme.spacing(0.5),
      display: "flex",
      alignItems: "center",
      fontFamily: theme.typography.fontFamilyMonospace
    }),
    body: css.css({
      color: theme.colors.text.secondary,
      "p:last-child": {
        margin: 0
      },
      a: {
        color: theme.colors.text.link,
        textDecoration: "underline"
      }
    })
  };
};

const OperationInfoButton = React.memo(({ definition, operation, innerQueryPlaceholder }) => {
  const styles = ui.useStyles2(getStyles$a);
  const [show, setShow] = React.useState(false);
  const { getTooltipProps, setTooltipRef, setTriggerRef, visible } = reactPopperTooltip.usePopperTooltip({
    placement: "top",
    visible: show,
    offset: [0, 16],
    onVisibleChange: setShow,
    interactive: true,
    trigger: ["click"]
  });
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        title: "Click to show description",
        ref: setTriggerRef,
        icon: "info-circle",
        size: "sm",
        variant: "secondary",
        fill: "text"
      }
    ),
    visible && /* @__PURE__ */ jsxRuntime.jsx(ui.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: setTooltipRef, ...getTooltipProps(), className: styles.docBox, children: [
      /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.docBoxHeader, children: [
        /* @__PURE__ */ jsxRuntime.jsx("span", { children: definition.renderer(operation, definition, innerQueryPlaceholder) }),
        /* @__PURE__ */ jsxRuntime.jsx(FlexItem, { grow: 1 }),
        /* @__PURE__ */ jsxRuntime.jsx(
          ui.Button,
          {
            icon: "times",
            onClick: () => setShow(false),
            fill: "text",
            variant: "secondary",
            title: "Remove operation"
          }
        )
      ] }),
      /* @__PURE__ */ jsxRuntime.jsx(
        "div",
        {
          className: styles.docBoxBody,
          dangerouslySetInnerHTML: { __html: getOperationDocs(definition, operation) }
        }
      )
    ] }) })
  ] });
});
OperationInfoButton.displayName = "OperationDocs";
const getStyles$a = (theme) => {
  return {
    docBox: css.css({
      overflow: "hidden",
      background: theme.colors.background.primary,
      border: `1px solid ${theme.colors.border.strong}`,
      boxShadow: theme.shadows.z3,
      maxWidth: "600px",
      padding: theme.spacing(1),
      borderRadius: theme.shape.radius.default,
      zIndex: theme.zIndex.tooltip
    }),
    docBoxHeader: css.css({
      fontSize: theme.typography.h5.fontSize,
      fontFamily: theme.typography.fontFamilyMonospace,
      paddingBottom: theme.spacing(1),
      display: "flex",
      alignItems: "center"
    }),
    docBoxBody: css.css({
      // The markdown paragraph has a marginBottom this removes it
      marginBottom: theme.spacing(-1),
      color: theme.colors.text.secondary
    }),
    signature: css.css({
      fontSize: theme.typography.bodySmall.fontSize,
      fontFamily: theme.typography.fontFamilyMonospace
    }),
    dropdown: css.css({
      opacity: 0,
      color: theme.colors.text.secondary
    })
  };
};
function getOperationDocs(def, op) {
  var _a;
  return data.renderMarkdown(def.explainHandler ? def.explainHandler(op, def) : (_a = def.documentation) != null ? _a : "no docs");
}

const OperationHeader = React.memo(
  ({ operation, definition, index, onChange, onRemove, onToggle, queryModeller, dragHandleProps }) => {
    var _a;
    const styles = ui.useStyles2(getStyles$9);
    const [state, setState] = React.useState({});
    const onToggleSwitcher = () => {
      if (state.isOpen) {
        setState({ ...state, isOpen: false });
      } else {
        const alternatives = queryModeller.getAlternativeOperations(definition.alternativesKey).map((alt) => ({ label: alt.name, value: alt }));
        setState({ isOpen: true, alternatives });
      }
    };
    return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.header, children: [
      !state.isOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
        /* @__PURE__ */ jsxRuntime.jsx("div", { ...dragHandleProps, children: (_a = definition.name) != null ? _a : definition.id }),
        /* @__PURE__ */ jsxRuntime.jsx(FlexItem, { grow: 1 }),
        /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles.operationHeaderButtons} operation-header-show-on-hover`, children: [
          /* @__PURE__ */ jsxRuntime.jsx(
            ui.Button,
            {
              icon: "angle-down",
              size: "sm",
              onClick: onToggleSwitcher,
              fill: "text",
              variant: "secondary",
              title: "Click to view alternative operations"
            }
          ),
          /* @__PURE__ */ jsxRuntime.jsx(
            OperationInfoButton,
            {
              definition,
              operation,
              innerQueryPlaceholder: queryModeller.innerQueryPlaceholder
            }
          ),
          definition.toggleable && /* @__PURE__ */ jsxRuntime.jsx(
            ui.Button,
            {
              icon: operation.disabled ? "eye-slash" : "eye",
              size: "sm",
              onClick: () => onToggle(index),
              fill: "text",
              variant: "secondary",
              title: operation.disabled ? "Enable operation" : "Disable operation"
            }
          ),
          /* @__PURE__ */ jsxRuntime.jsx(
            ui.Button,
            {
              icon: "times",
              size: "sm",
              onClick: () => onRemove(index),
              fill: "text",
              variant: "secondary",
              title: "Remove operation"
            }
          )
        ] })
      ] }),
      state.isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.selectWrapper, children: /* @__PURE__ */ jsxRuntime.jsx(
        ui.Select,
        {
          autoFocus: true,
          openMenuOnFocus: true,
          placeholder: "Replace with",
          options: state.alternatives,
          isOpen: true,
          onCloseMenu: onToggleSwitcher,
          onChange: (value) => {
            if (value.value) {
              const newDef = queryModeller.getOperationDefinition(value.value.id);
              const newParams = [...newDef.defaultParams];
              for (let i = 0; i < Math.min(operation.params.length, newParams.length); i++) {
                if (newDef.params[i].type === definition.params[i].type) {
                  newParams[i] = operation.params[i];
                }
              }
              const changedOp = { ...operation, params: newParams, id: value.value.id };
              onChange(
                index,
                definition.changeTypeHandler ? definition.changeTypeHandler(changedOp, newDef) : changedOp
              );
            }
          }
        }
      ) })
    ] });
  }
);
OperationHeader.displayName = "OperationHeader";
const getStyles$9 = (theme) => {
  return {
    header: css.css({
      borderBottom: `1px solid ${theme.colors.border.medium}`,
      padding: theme.spacing(0.5, 0.5, 0.5, 1),
      display: "flex",
      alignItems: "center"
    }),
    operationHeaderButtons: css.css({
      opacity: 1
    }),
    selectWrapper: css.css({
      paddingRight: theme.spacing(2)
    })
  };
};

function getOperationParamEditor(paramDef) {
  if (paramDef.editor) {
    return paramDef.editor;
  }
  if (paramDef.options) {
    return SelectInputParamEditor;
  }
  switch (paramDef.type) {
    case "boolean":
      return BoolInputParamEditor;
    case "number":
    case "string":
    default:
      return SimpleInputParamEditor;
  }
}
function SimpleInputParamEditor(props) {
  var _a;
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.AutoSizeInput,
    {
      id: getOperationParamId(props.operationId, props.index),
      defaultValue: (_a = props.value) == null ? undefined : _a.toString(),
      minWidth: props.paramDef.minWidth,
      placeholder: props.paramDef.placeholder,
      title: props.paramDef.description,
      maxWidth: (props.paramDef.minWidth || 20) * 3,
      onCommitChange: (evt) => {
        props.onChange(props.index, evt.currentTarget.value);
        if (props.paramDef.runQueryOnEnter && evt.type === "keydown") {
          props.onRunQuery();
        }
      }
    }
  );
}
function BoolInputParamEditor(props) {
  return /* @__PURE__ */ jsxRuntime.jsx(
    ui.Checkbox,
    {
      id: getOperationParamId(props.operationId, props.index),
      value: Boolean(props.value),
      onChange: (evt) => props.onChange(props.index, evt.currentTarget.checked)
    }
  );
}
function SelectInputParamEditor({
  paramDef,
  value,
  index,
  operationId,
  onChange
}) {
  var _a, _b;
  const styles = ui.useStyles2(getStyles$8);
  let selectOptions = paramDef.options;
  if (!((_a = selectOptions[0]) == null ? undefined : _a.label)) {
    selectOptions = paramDef.options.map((option) => ({
      label: option.toString(),
      value: option
    }));
  }
  let valueOption = (_b = selectOptions.find((x) => x.value === value)) != null ? _b : data.toOption(value);
  if (!value && paramDef.optional) {
    return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.optionalParam, children: /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        size: "sm",
        variant: "secondary",
        title: `Add ${paramDef.name}`,
        icon: "plus",
        onClick: () => onChange(index, selectOptions[0].value),
        children: paramDef.name
      }
    ) });
  }
  return /* @__PURE__ */ jsxRuntime.jsxs(EditorStack, { gap: 0.5, direction: "row", alignItems: "center", children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Select,
      {
        id: getOperationParamId(operationId, index),
        value: valueOption,
        options: selectOptions,
        placeholder: paramDef.placeholder,
        allowCustomValue: true,
        onChange: (value2) => onChange(index, value2.value),
        width: paramDef.minWidth || "auto"
      }
    ),
    paramDef.optional && /* @__PURE__ */ jsxRuntime.jsx(
      ui.Button,
      {
        "data-testid": `operations.${index}.remove-param`,
        size: "sm",
        fill: "text",
        icon: "times",
        variant: "secondary",
        title: `Remove ${paramDef.name}`,
        onClick: () => onChange(index, "")
      }
    )
  ] });
}
const getStyles$8 = (theme) => {
  return {
    optionalParam: css.css({
      marginTop: theme.spacing(1)
    })
  };
};
function getOperationParamId(operationId, paramIndex) {
  return `operations.${operationId}.param.${paramIndex}`;
}

function OperationEditorBody({
  provided,
  flash,
  isConflicting,
  highlight,
  index,
  queryModeller,
  onChange,
  onRemove,
  onToggle,
  operation,
  definition,
  query,
  timeRange,
  onRunQuery,
  datasource
}) {
  const theme = ui.useTheme2();
  const styles = getStyles$7(theme, isConflicting);
  const shouldFlash = useFlash(flash);
  const { current: id } = React.useRef(uuid.v4());
  const onParamValueChanged = (paramIdx, value) => {
    const update = { ...operation, params: [...operation.params] };
    update.params[paramIdx] = value;
    callParamChangedThenOnChange(definition, update, index, paramIdx, onChange);
  };
  const onAddRestParam = () => {
    const update = { ...operation, params: [...operation.params, ""] };
    callParamChangedThenOnChange(definition, update, index, operation.params.length, onChange);
  };
  const onRemoveRestParam = (paramIdx) => {
    const update = {
      ...operation,
      params: [...operation.params.slice(0, paramIdx), ...operation.params.slice(paramIdx + 1)]
    };
    callParamChangedThenOnChange(definition, update, index, paramIdx, onChange);
  };
  let restParam;
  if (definition.params.length > 0) {
    const lastParamDef = definition.params[definition.params.length - 1];
    if (lastParamDef.restParam) {
      restParam = renderAddRestParamButton(lastParamDef, onAddRestParam, index, operation.params.length, styles);
    }
  }
  return /* @__PURE__ */ jsxRuntime.jsxs(
    "div",
    {
      className: css.cx(styles.card, {
        [styles.cardHighlight]: shouldFlash || highlight,
        [styles.cardError]: isConflicting,
        [styles.disabled]: operation.disabled
      }),
      ref: provided.innerRef,
      ...provided.draggableProps,
      "data-testid": `operations.${index}.wrapper`,
      children: [
        /* @__PURE__ */ jsxRuntime.jsx(
          OperationHeader,
          {
            operation,
            dragHandleProps: provided.dragHandleProps,
            definition,
            index,
            onChange,
            onRemove,
            onToggle,
            queryModeller
          }
        ),
        /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.body, children: operation.params.map((param, paramIndex) => {
          const paramDef = definition.params[Math.min(definition.params.length - 1, paramIndex)];
          const Editor = getOperationParamEditor(paramDef);
          return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.paramRow, children: [
            !paramDef.hideName && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.paramName, children: [
              /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: getOperationParamId(id, paramIndex), children: paramDef.name }),
              paramDef.description && /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { placement: "top", content: paramDef.description, theme: "info", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { name: "info-circle", size: "sm", className: styles.infoIcon }) })
            ] }),
            /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.paramValue, children: /* @__PURE__ */ jsxRuntime.jsxs(EditorStack, { gap: 0.5, direction: "row", alignItems: "center", wrap: false, children: [
              /* @__PURE__ */ jsxRuntime.jsx(
                Editor,
                {
                  index: paramIndex,
                  paramDef,
                  value: operation.params[paramIndex],
                  operation,
                  operationId: id,
                  onChange: onParamValueChanged,
                  onRunQuery,
                  query,
                  datasource,
                  timeRange,
                  queryModeller
                }
              ),
              paramDef.restParam && (operation.params.length > definition.params.length || paramDef.optional) && /* @__PURE__ */ jsxRuntime.jsx(
                ui.Button,
                {
                  "data-testid": `operations.${index}.remove-rest-param`,
                  size: "sm",
                  fill: "text",
                  icon: "times",
                  variant: "secondary",
                  title: `Remove ${paramDef.name}`,
                  onClick: () => onRemoveRestParam(paramIndex)
                }
              )
            ] }) })
          ] }, `${paramIndex}-1`);
        }) }),
        restParam,
        index < query.operations.length - 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.arrow, children: [
          /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.arrowLine }),
          /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.arrowArrow })
        ] })
      ]
    }
  );
}
const getStyles$7 = (theme, isConflicting) => {
  return {
    cardWrapper: css.css({
      alignItems: "stretch"
    }),
    error: css.css({
      marginBottom: theme.spacing(1)
    }),
    card: css.css({
      background: theme.colors.background.primary,
      border: `1px solid ${theme.colors.border.medium}`,
      cursor: "grab",
      borderRadius: theme.shape.radius.default,
      position: "relative",
      transition: "all 0.5s ease-in 0s",
      height: isConflicting ? "auto" : "100%"
    }),
    disabled: css.css({
      opacity: 0.5,
      transition: "none"
    }),
    cardError: css.css({
      boxShadow: `0px 0px 4px 0px ${theme.colors.warning.main}`,
      border: `1px solid ${theme.colors.warning.main}`
    }),
    cardHighlight: css.css({
      boxShadow: `0px 0px 4px 0px ${theme.colors.primary.border}`,
      border: `1px solid ${theme.colors.primary.border}`
    }),
    infoIcon: css.css({
      marginLeft: theme.spacing(0.5),
      color: theme.colors.text.secondary,
      ":hover": {
        color: theme.colors.text.primary
      }
    }),
    body: css.css({
      margin: theme.spacing(1, 1, 0.5, 1),
      display: "table"
    }),
    paramRow: css.css({
      label: "paramRow",
      display: "table-row",
      verticalAlign: "middle"
    }),
    paramName: css.css({
      display: "table-cell",
      padding: theme.spacing(0, 1, 0, 0),
      fontSize: theme.typography.bodySmall.fontSize,
      fontWeight: theme.typography.fontWeightMedium,
      verticalAlign: "middle",
      height: "32px"
    }),
    paramValue: css.css({
      label: "paramValue",
      display: "table-cell",
      verticalAlign: "middle"
    }),
    restParam: css.css({
      padding: theme.spacing(0, 1, 1, 1)
    }),
    arrow: css.css({
      position: "absolute",
      top: "0",
      right: "-18px",
      display: "flex"
    }),
    arrowLine: css.css({
      height: "2px",
      width: "8px",
      backgroundColor: theme.colors.border.strong,
      position: "relative",
      top: "14px"
    }),
    arrowArrow: css.css({
      width: 0,
      height: 0,
      borderTop: `5px solid transparent`,
      borderBottom: `5px solid transparent`,
      borderLeft: `7px solid ${theme.colors.border.strong}`,
      position: "relative",
      top: "10px"
    })
  };
};
function useFlash(flash) {
  const [keepFlash, setKeepFlash] = React.useState(true);
  React.useEffect(() => {
    let t;
    if (flash) {
      t = setTimeout(() => {
        setKeepFlash(false);
      }, 1e3);
    } else {
      setKeepFlash(true);
    }
    return () => clearTimeout(t);
  }, [flash]);
  return keepFlash && flash;
}
function callParamChangedThenOnChange(def, operation, operationIndex, paramIndex, onChange) {
  if (def.paramChangedHandler) {
    onChange(operationIndex, def.paramChangedHandler(paramIndex, operation, def));
  } else {
    onChange(operationIndex, operation);
  }
}
function renderAddRestParamButton(paramDef, onAddRestParam, operationIndex, paramIndex, styles) {
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.restParam, children: /* @__PURE__ */ jsxRuntime.jsx(
    ui.Button,
    {
      size: "sm",
      icon: "plus",
      title: `Add ${paramDef.name}`.trimEnd(),
      variant: "secondary",
      onClick: onAddRestParam,
      "data-testid": `operations.${operationIndex}.add-rest-param`,
      children: paramDef.name
    }
  ) }, `${paramIndex}-2`);
}

function OperationEditor({
  operation,
  index,
  onRemove,
  onToggle,
  onChange,
  onRunQuery,
  queryModeller,
  query,
  datasource,
  flash,
  highlight,
  timeRange,
  isConflictingOperation
}) {
  const def = queryModeller.getOperationDefinition(operation.id);
  const theme = ui.useTheme2();
  const isConflicting = isConflictingOperation ? isConflictingOperation(operation, query.operations) : false;
  const styles = getStyles$6(theme);
  if (!def) {
    return /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
      "Operation ",
      operation.id,
      " not found"
    ] });
  }
  const isInvalid = (isDragging) => {
    if (isDragging) {
      return undefined;
    }
    return isConflicting ? true : undefined;
  };
  return /* @__PURE__ */ jsxRuntime.jsx(dnd.Draggable, { draggableId: `operation-${index}`, index, children: (provided, snapshot) => /* @__PURE__ */ jsxRuntime.jsx(
    ui.InlineField,
    {
      error: "You have conflicting label filters",
      invalid: isInvalid(snapshot.isDragging),
      className: css.cx(styles.error, styles.cardWrapper),
      children: /* @__PURE__ */ jsxRuntime.jsx(
        OperationEditorBody,
        {
          provided,
          flash,
          highlight,
          isConflicting,
          index,
          operation,
          definition: def,
          onChange,
          onRemove,
          onToggle,
          queryModeller,
          query,
          timeRange,
          onRunQuery,
          datasource
        }
      )
    }
  ) });
}
const getStyles$6 = (theme, isConflicting) => {
  return {
    cardWrapper: css.css({
      alignItems: "stretch"
    }),
    error: css.css({
      marginBottom: theme.spacing(1)
    })
  };
};

function OperationList({
  query,
  datasource,
  queryModeller,
  onChange,
  onRunQuery,
  highlightedOp,
  timeRange,
  isConflictingOperation
}) {
  const styles = ui.useStyles2(getStyles$5);
  const { operations } = query;
  const opsToHighlight = useOperationsHighlight(operations);
  const [cascaderOpen, setCascaderOpen] = React.useState(false);
  const onOperationChange = (index, update) => {
    const updatedList = [...operations];
    updatedList.splice(index, 1, update);
    onChange({ ...query, operations: updatedList });
  };
  const onRemove = (index) => {
    const updatedList = [...operations.slice(0, index), ...operations.slice(index + 1)];
    onChange({ ...query, operations: updatedList });
  };
  const onToggle = (index) => {
    onOperationChange(index, { ...operations[index], disabled: !operations[index].disabled });
  };
  const addOptions = queryModeller.getCategories().map((category) => {
    return {
      value: category,
      label: category,
      items: queryModeller.getOperationsForCategory(category).map((operation) => ({
        value: operation.id,
        label: operation.name,
        isLeaf: true
      }))
    };
  });
  const onAddOperation = (value) => {
    const operationDef = queryModeller.getOperationDefinition(value);
    if (!operationDef) {
      return;
    }
    onChange(operationDef.addOperationHandler(operationDef, query, queryModeller));
    setCascaderOpen(false);
  };
  const onDragEnd = (result) => {
    if (!result.destination) {
      return;
    }
    const updatedList = [...operations];
    const element = updatedList[result.source.index];
    updatedList.splice(result.source.index, 1);
    updatedList.splice(result.destination.index, 0, element);
    onChange({ ...query, operations: updatedList });
  };
  const onCascaderBlur = () => {
    setCascaderOpen(false);
  };
  return /* @__PURE__ */ jsxRuntime.jsx(EditorStack, { gap: 1, direction: "column", children: /* @__PURE__ */ jsxRuntime.jsxs(EditorStack, { gap: 1, children: [
    operations.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(dnd.DragDropContext, { onDragEnd, children: /* @__PURE__ */ jsxRuntime.jsx(dnd.Droppable, { droppableId: "sortable-field-mappings", direction: "horizontal", children: (provided) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.operationList, ref: provided.innerRef, ...provided.droppableProps, children: [
      operations.map((op, index) => {
        return /* @__PURE__ */ jsxRuntime.jsx(
          OperationEditor,
          {
            queryModeller,
            index,
            operation: op,
            query,
            datasource,
            onChange: onOperationChange,
            onRemove,
            onToggle,
            onRunQuery,
            flash: opsToHighlight[index],
            highlight: highlightedOp === op,
            timeRange,
            isConflictingOperation
          },
          op.id + JSON.stringify(op.params) + index
        );
      }),
      provided.placeholder
    ] }) }) }),
    /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.addButton, children: cascaderOpen ? /* @__PURE__ */ jsxRuntime.jsx(
      ui.Cascader,
      {
        options: addOptions,
        onSelect: onAddOperation,
        onBlur: onCascaderBlur,
        autoFocus: true,
        alwaysOpen: true,
        hideActiveLevelLabel: true,
        placeholder: "Search"
      }
    ) : /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { icon: "plus", variant: "secondary", onClick: () => setCascaderOpen(true), title: "Add operation", children: "Operations" }) })
  ] }) });
}
function useOperationsHighlight(operations) {
  const isMounted = reactUse.useMountedState();
  const prevOperations = reactUse.usePrevious(operations);
  if (!isMounted()) {
    return operations.map(() => false);
  }
  if (!prevOperations) {
    return operations.map(() => true);
  }
  let newOps = [];
  if (prevOperations.length - 1 === operations.length && operations.every((op) => prevOperations.includes(op))) {
    return operations.map(() => false);
  }
  if (prevOperations.length + 1 === operations.length && prevOperations.every((op) => operations.includes(op))) {
    const newOp = operations.find((op) => !prevOperations.includes(op));
    newOps = operations.map((op) => {
      return op === newOp;
    });
  } else {
    newOps = operations.map((op, index) => {
      var _a;
      return !isSameOp(op.id, (_a = prevOperations[index]) == null ? undefined : _a.id);
    });
  }
  return newOps;
}
function isSameOp(op1, op2) {
  return op1 === op2 || `__${op1}_by` === op2 || op1 === `__${op2}_by`;
}
const getStyles$5 = (theme) => {
  return {
    heading: css.css({
      label: "heading",
      fontSize: 12,
      fontWeight: theme.typography.fontWeightMedium,
      marginBottom: 0
    }),
    operationList: css.css({
      label: "operationList",
      display: "flex",
      flexWrap: "wrap",
      gap: theme.spacing(2)
    }),
    addButton: css.css({
      label: "addButton",
      width: 126,
      paddingBottom: theme.spacing(1)
    })
  };
};

function RawQuery({ query, language, className }) {
  const theme = ui.useTheme2();
  const styles = getStyles$4(theme);
  const highlighted = Prism__default.default.highlight(query, language.grammar, language.name);
  return /* @__PURE__ */ jsxRuntime.jsx(
    "div",
    {
      className: css.cx(styles.editorField, "prism-syntax-highlight", className),
      "aria-label": "selector",
      dangerouslySetInnerHTML: { __html: data.textUtil.sanitize(highlighted) }
    }
  );
}
const getStyles$4 = (theme) => {
  return {
    editorField: css.css({
      fontFamily: theme.typography.fontFamilyMonospace,
      fontSize: theme.typography.bodySmall.fontSize
    })
  };
};

function OperationListExplained({
  query,
  queryModeller,
  stepNumber,
  language,
  onMouseEnter,
  onMouseLeave
}) {
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: query.operations.map((op, index) => {
    var _a;
    const def = queryModeller.getOperationDefinition(op.id);
    if (!def) {
      return `Operation ${op.id} not found`;
    }
    const title = def.renderer(op, def, queryModeller.innerQueryPlaceholder);
    const body = def.explainHandler ? def.explainHandler(op, def) : (_a = def.documentation) != null ? _a : "no docs";
    return /* @__PURE__ */ jsxRuntime.jsx(
      "div",
      {
        onMouseEnter: () => onMouseEnter == null ? undefined : onMouseEnter(op, index),
        onMouseLeave: () => onMouseLeave == null ? undefined : onMouseLeave(op, index),
        children: /* @__PURE__ */ jsxRuntime.jsx(
          OperationExplainedBox,
          {
            stepNumber: index + stepNumber,
            title: /* @__PURE__ */ jsxRuntime.jsx(RawQuery, { query: title, language }),
            markdown: body
          }
        )
      },
      index
    );
  }) });
}

function OperationsEditorRow({ children }) {
  const styles = ui.useStyles2(getStyles$3);
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.root, children: /* @__PURE__ */ jsxRuntime.jsx(EditorStack, { gap: 1, children }) });
}
const getStyles$3 = (theme) => {
  return {
    root: css.css({
      padding: theme.spacing(1, 1, 0, 1),
      backgroundColor: theme.colors.background.secondary,
      borderRadius: theme.shape.radius.default
    })
  };
};

const QueryBuilderHints = ({
  datasource,
  query: visualQuery,
  onChange,
  data,
  queryModeller,
  buildVisualQueryFromString,
  buildDataQueryFromQueryString,
  buildQueryStringFromDataQuery
}) => {
  const styles = ui.useStyles2(getStyles$2);
  const hints = React.useMemo(() => {
    var _a;
    const dataQuery = buildDataQueryFromQueryString(queryModeller.renderQuery(visualQuery));
    const hints2 = (_a = datasource.getQueryHints) == null ? undefined : _a.call(datasource, dataQuery, (data == null ? undefined : data.series) || []).filter((hint) => {
      var _a2;
      return (_a2 = hint.fix) == null ? undefined : _a2.action;
    });
    return hints2 != null ? hints2 : [];
  }, [datasource, visualQuery, data, queryModeller, buildDataQueryFromQueryString]);
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: hints.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.container, children: hints.map((hint) => {
    var _a, _b, _c, _d;
    return /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: `${hint.label} ${(_a = hint.fix) == null ? undefined : _a.label}`, children: /* @__PURE__ */ jsxRuntime.jsxs(
      ui.Button,
      {
        onClick: () => {
          var _a2, _b2, _c2;
          runtime.reportInteraction("grafana_query_builder_hints_clicked", {
            hint: hint.type,
            datasourceType: datasource.type
          });
          if ((_a2 = hint == null ? undefined : hint.fix) == null ? undefined : _a2.action) {
            const dataQuery = buildDataQueryFromQueryString(queryModeller.renderQuery(visualQuery));
            const newQuery = (_b2 = datasource.modifyQuery) == null ? undefined : _b2.call(datasource, dataQuery, hint.fix.action);
            if (newQuery) {
              const newVisualQuery = buildVisualQueryFromString(
                (_c2 = buildQueryStringFromDataQuery(newQuery)) != null ? _c2 : ""
              );
              return onChange(newVisualQuery.query);
            }
          }
        },
        fill: "outline",
        size: "sm",
        className: styles.hint,
        children: [
          "hint: ",
          ((_b = hint.fix) == null ? undefined : _b.title) || ((_d = (_c = hint.fix) == null ? undefined : _c.action) == null ? undefined : _d.type.toLowerCase().replace("_", " "))
        ]
      }
    ) }, hint.type);
  }) }) });
};
QueryBuilderHints.displayName = "QueryBuilderHints";
const getStyles$2 = (theme) => {
  return {
    container: css.css`
      display: flex;
      align-items: start;
    `,
    hint: css.css`
      margin-right: ${theme.spacing(1)};
    `
  };
};

const editorModes = [
  { label: "Builder", value: QueryEditorMode.Builder },
  { label: "Code", value: QueryEditorMode.Code }
];
function QueryEditorModeToggle({ mode, onChange }) {
  return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": "QueryEditorModeToggle", children: /* @__PURE__ */ jsxRuntime.jsx(ui.RadioButtonGroup, { options: editorModes, size: "sm", value: mode, onChange }) });
}

function QueryHeaderSwitch({ label, ...inputProps }) {
  const dashedLabel = label.replace(" ", "-");
  const switchIdRef = React.useRef(lodash.uniqueId(`switch-${dashedLabel}`));
  const styles = ui.useStyles2(getStyles$1);
  return /* @__PURE__ */ jsxRuntime.jsxs(EditorStack, { gap: 1, children: [
    /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: switchIdRef.current, className: styles.switchLabel, children: label }),
    /* @__PURE__ */ jsxRuntime.jsx(ui.Switch, { ...inputProps, id: switchIdRef.current })
  ] });
}
const getStyles$1 = (theme) => {
  return {
    switchLabel: css.css({
      color: theme.colors.text.secondary,
      cursor: "pointer",
      fontSize: theme.typography.bodySmall.fontSize,
      "&:hover": {
        color: theme.colors.text.primary
      }
    })
  };
};

function QueryOptionGroup({ title, children, collapsedInfo, queryStats }) {
  const [isOpen, toggleOpen] = reactUse.useToggle(false);
  const styles = ui.useStyles2(getStyles);
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.wrapper, children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      ui.Collapse,
      {
        className: styles.collapse,
        collapsible: true,
        isOpen,
        onToggle: toggleOpen,
        label: /* @__PURE__ */ jsxRuntime.jsxs(EditorStack, { gap: 0, children: [
          /* @__PURE__ */ jsxRuntime.jsx("h6", { className: styles.title, children: title }),
          !isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.description, children: collapsedInfo.map((x, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { children: x }, i)) })
        ] }),
        children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.body, children })
      }
    ),
    queryStats && runtime.config.featureToggles.lokiQuerySplitting && /* @__PURE__ */ jsxRuntime.jsx(ui.Tooltip, { content: "Note: the query will be split into multiple parts and executed in sequence. Query limits will only apply each individual part.", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { tabIndex: 0, name: "info-circle", className: styles.tooltip, size: "sm" }) }),
    queryStats && /* @__PURE__ */ jsxRuntime.jsx("p", { className: styles.stats, children: generateQueryStats(queryStats) })
  ] });
}
const getStyles = (theme) => {
  return {
    collapse: css.css({
      backgroundColor: "unset",
      border: "unset",
      marginBottom: 0,
      ["> button"]: {
        padding: theme.spacing(0, 1)
      }
    }),
    wrapper: css.css({
      width: "100%",
      display: "flex",
      justifyContent: "space-between",
      alignItems: "baseline"
    }),
    title: css.css({
      flexGrow: 1,
      overflow: "hidden",
      fontSize: theme.typography.bodySmall.fontSize,
      fontWeight: theme.typography.fontWeightMedium,
      margin: 0
    }),
    description: css.css({
      color: theme.colors.text.secondary,
      fontSize: theme.typography.bodySmall.fontSize,
      fontWeight: theme.typography.bodySmall.fontWeight,
      paddingLeft: theme.spacing(2),
      gap: theme.spacing(2),
      display: "flex"
    }),
    body: css.css({
      display: "flex",
      gap: theme.spacing(2),
      flexWrap: "wrap"
    }),
    stats: css.css({
      margin: "0px",
      color: theme.colors.text.secondary,
      fontSize: theme.typography.bodySmall.fontSize
    }),
    tooltip: css.css({
      marginRight: theme.spacing(0.25)
    })
  };
};
const generateQueryStats = (queryStats) => {
  if (queryStats.message) {
    return queryStats.message;
  }
  return `This query will process approximately ${convertUnits(queryStats)}.`;
};
const convertUnits = (queryStats) => {
  const { text, suffix } = data.getValueFormat("bytes")(queryStats.bytes, 1);
  return text + suffix;
};

var chance$1 = {exports: {}};

var hasRequiredChance;

function requireChance () {
	if (hasRequiredChance) return chance$1.exports;
	hasRequiredChance = 1;
	(function (module, exports) {
		//  Chance.js 1.1.12
		//  https://chancejs.com
		//  (c) 2013 Victor Quinn
		//  Chance may be freely distributed or modified under the MIT license.

		(function () {

		    // Constants
		    var MAX_INT = 9007199254740992;
		    var MIN_INT = -9007199254740992;
		    var NUMBERS = '0123456789';
		    var CHARS_LOWER = 'abcdefghijklmnopqrstuvwxyz';
		    var CHARS_UPPER = CHARS_LOWER.toUpperCase();
		    var HEX_POOL = NUMBERS + "abcdef";

		    // Errors
		    function UnsupportedError(message) {
		        this.name = 'UnsupportedError';
		        this.message = message || 'This feature is not supported on this platform';
		    }

		    UnsupportedError.prototype = new Error();
		    UnsupportedError.prototype.constructor = UnsupportedError;

		    // Cached array helpers
		    var slice = Array.prototype.slice;

		    // Constructor
		    function Chance (seed) {
		        if (!(this instanceof Chance)) {
		            if (!seed) { seed = null; } // handle other non-truthy seeds, as described in issue #322
		            return seed === null ? new Chance() : new Chance(seed);
		        }

		        // if user has provided a function, use that as the generator
		        if (typeof seed === 'function') {
		            this.random = seed;
		            return this;
		        }

		        if (arguments.length) {
		            // set a starting value of zero so we can add to it
		            this.seed = 0;
		        }

		        // otherwise, leave this.seed blank so that MT will receive a blank

		        for (var i = 0; i < arguments.length; i++) {
		            var seedling = 0;
		            if (Object.prototype.toString.call(arguments[i]) === '[object String]') {
		                for (var j = 0; j < arguments[i].length; j++) {
		                    // create a numeric hash for each argument, add to seedling
		                    var hash = 0;
		                    for (var k = 0; k < arguments[i].length; k++) {
		                        hash = arguments[i].charCodeAt(k) + (hash << 6) + (hash << 16) - hash;
		                    }
		                    seedling += hash;
		                }
		            } else {
		                seedling = arguments[i];
		            }
		            this.seed += (arguments.length - i) * seedling;
		        }

		        // If no generator function was provided, use our MT
		        this.mt = this.mersenne_twister(this.seed);
		        this.bimd5 = this.blueimp_md5();
		        this.random = function () {
		            return this.mt.random(this.seed);
		        };

		        return this;
		    }

		    Chance.prototype.VERSION = "1.1.12";

		    // Random helper functions
		    function initOptions(options, defaults) {
		        options = options || {};

		        if (defaults) {
		            for (var i in defaults) {
		                if (typeof options[i] === 'undefined') {
		                    options[i] = defaults[i];
		                }
		            }
		        }

		        return options;
		    }

		    function range(size) {
		        return Array.apply(null, Array(size)).map(function (_, i) {return i;});
		    }

		    function testRange(test, errorMessage) {
		        if (test) {
		            throw new RangeError(errorMessage);
		        }
		    }

		    /**
		     * Encode the input string with Base64.
		     */
		    var base64 = function() {
		        throw new Error('No Base64 encoder available.');
		    };

		    // Select proper Base64 encoder.
		    (function determineBase64Encoder() {
		        if (typeof btoa === 'function') {
		            base64 = btoa;
		        } else if (typeof Buffer === 'function') {
		            base64 = function(input) {
		                return new Buffer(input).toString('base64');
		            };
		        }
		    })();

		    // -- Basics --

		    /**
		     *  Return a random bool, either true or false
		     *
		     *  @param {Object} [options={ likelihood: 50 }] alter the likelihood of
		     *    receiving a true or false value back.
		     *  @throws {RangeError} if the likelihood is out of bounds
		     *  @returns {Bool} either true or false
		     */
		    Chance.prototype.bool = function (options) {
		        // likelihood of success (true)
		        options = initOptions(options, {likelihood : 50});

		        // Note, we could get some minor perf optimizations by checking range
		        // prior to initializing defaults, but that makes code a bit messier
		        // and the check more complicated as we have to check existence of
		        // the object then existence of the key before checking constraints.
		        // Since the options initialization should be minor computationally,
		        // decision made for code cleanliness intentionally. This is mentioned
		        // here as it's the first occurrence, will not be mentioned again.
		        testRange(
		            options.likelihood < 0 || options.likelihood > 100,
		            "Chance: Likelihood accepts values from 0 to 100."
		        );

		        return this.random() * 100 < options.likelihood;
		    };

		    Chance.prototype.falsy = function (options) {
		        // return a random falsy value
		        options = initOptions(options, {pool: [false, null, 0, NaN, '', undefined]});
		        var pool = options.pool,
		            index = this.integer({min: 0, max: pool.length - 1}),
		            value = pool[index];

		        return value;
		    };

		    Chance.prototype.animal = function (options){
		      //returns a random animal
		      options = initOptions(options);

		      if(typeof options.type !== 'undefined'){
		        //if user does not put in a valid animal type, user will get an error
		        testRange(
		           !this.get("animals")[options.type.toLowerCase()],
		           "Please pick from desert, ocean, grassland, forest, zoo, pets, farm."
		         );
		         //if user does put in valid animal type, will return a random animal of that type
		          return this.pick(this.get("animals")[options.type.toLowerCase()]);
		      }
		       //if user does not put in any animal type, will return a random animal regardless
		      var animalTypeArray = ["desert","forest","ocean","zoo","farm","pet","grassland"];
		      return this.pick(this.get("animals")[this.pick(animalTypeArray)]);
		    };

		    /**
		     *  Return a random character.
		     *
		     *  @param {Object} [options={}] can specify a character pool or alpha,
		     *    numeric, symbols and casing (lower or upper)
		     *  @returns {String} a single random character
		     */
		    Chance.prototype.character = function (options) {
		        options = initOptions(options);

		        var symbols = "!@#$%^&*()[]",
		            letters, pool;

		        if (options.casing === 'lower') {
		            letters = CHARS_LOWER;
		        } else if (options.casing === 'upper') {
		            letters = CHARS_UPPER;
		        } else {
		            letters = CHARS_LOWER + CHARS_UPPER;
		        }

		        if (options.pool) {
		            pool = options.pool;
		        } else {
		            pool = '';
		            if (options.alpha) {
		                pool += letters;
		            }
		            if (options.numeric) {
		                pool += NUMBERS;
		            }
		            if (options.symbols) {
		                pool += symbols;
		            }
		            if (!pool) {
		                pool = letters + NUMBERS + symbols;
		            }
		        }

		        return pool.charAt(this.natural({max: (pool.length - 1)}));
		    };

		    // Note, wanted to use "float" or "double" but those are both JS reserved words.

		    // Note, fixed means N OR LESS digits after the decimal. This because
		    // It could be 14.9000 but in JavaScript, when this is cast as a number,
		    // the trailing zeroes are dropped. Left to the consumer if trailing zeroes are
		    // needed
		    /**
		     *  Return a random floating point number
		     *
		     *  @param {Object} [options={}] can specify a fixed precision, min, max
		     *  @returns {Number} a single floating point number
		     *  @throws {RangeError} Can only specify fixed or precision, not both. Also
		     *    min cannot be greater than max
		     */
		    Chance.prototype.floating = function (options) {
		        options = initOptions(options, {fixed : 4});
		        testRange(
		            options.fixed && options.precision,
		            "Chance: Cannot specify both fixed and precision."
		        );

		        var num;
		        var fixed = Math.pow(10, options.fixed);

		        var max = MAX_INT / fixed;
		        var min = -max;

		        testRange(
		            options.min && options.fixed && options.min < min,
		            "Chance: Min specified is out of range with fixed. Min should be, at least, " + min
		        );
		        testRange(
		            options.max && options.fixed && options.max > max,
		            "Chance: Max specified is out of range with fixed. Max should be, at most, " + max
		        );

		        options = initOptions(options, { min : min, max : max });

		        // Todo - Make this work!
		        // options.precision = (typeof options.precision !== "undefined") ? options.precision : false;

		        num = this.integer({min: options.min * fixed, max: options.max * fixed});
		        var num_fixed = (num / fixed).toFixed(options.fixed);

		        return parseFloat(num_fixed);
		    };

		    /**
		     *  Return a random integer
		     *
		     *  NOTE the max and min are INCLUDED in the range. So:
		     *  chance.integer({min: 1, max: 3});
		     *  would return either 1, 2, or 3.
		     *
		     *  @param {Object} [options={}] can specify a min and/or max
		     *  @returns {Number} a single random integer number
		     *  @throws {RangeError} min cannot be greater than max
		     */
		    Chance.prototype.integer = function (options) {
		        // 9007199254740992 (2^53) is the max integer number in JavaScript
		        // See: http://vq.io/132sa2j
		        options = initOptions(options, {min: MIN_INT, max: MAX_INT});
		        testRange(options.min > options.max, "Chance: Min cannot be greater than Max.");

		        return Math.floor(this.random() * (options.max - options.min + 1) + options.min);
		    };

		    /**
		     *  Return a random natural
		     *
		     *  NOTE the max and min are INCLUDED in the range. So:
		     *  chance.natural({min: 1, max: 3});
		     *  would return either 1, 2, or 3.
		     *
		     *  @param {Object} [options={}] can specify a min and/or max or a numerals count.
		     *  @returns {Number} a single random integer number
		     *  @throws {RangeError} min cannot be greater than max
		     */
		    Chance.prototype.natural = function (options) {
		        options = initOptions(options, {min: 0, max: MAX_INT});
		        if (typeof options.numerals === 'number'){
		          testRange(options.numerals < 1, "Chance: Numerals cannot be less than one.");
		          options.min = Math.pow(10, options.numerals - 1);
		          options.max = Math.pow(10, options.numerals) - 1;
		        }
		        testRange(options.min < 0, "Chance: Min cannot be less than zero.");

		        if (options.exclude) {
		            testRange(!Array.isArray(options.exclude), "Chance: exclude must be an array.");

		            for (var exclusionIndex in options.exclude) {
		                testRange(!Number.isInteger(options.exclude[exclusionIndex]), "Chance: exclude must be numbers.");
		            }

		            var random = options.min + this.natural({max: options.max - options.min - options.exclude.length});
		            var sortedExclusions = options.exclude.sort();
		            for (var sortedExclusionIndex in sortedExclusions) {
		                if (random < sortedExclusions[sortedExclusionIndex]) {
		                    break
		                }
		                random++;
		            }
		            return random
		        }
		        return this.integer(options);
		    };

		    /**
		     *  Return a random prime number
		     *
		     *  NOTE the max and min are INCLUDED in the range.
		     *
		     *  @param {Object} [options={}] can specify a min and/or max
		     *  @returns {Number} a single random prime number
		     *  @throws {RangeError} min cannot be greater than max nor negative
		     */
		    Chance.prototype.prime = function (options) {
		        options = initOptions(options, {min: 0, max: 10000});
		        testRange(options.min < 0, "Chance: Min cannot be less than zero.");
		        testRange(options.min > options.max, "Chance: Min cannot be greater than Max.");

		        var lastPrime = data.primes[data.primes.length - 1];
		        if (options.max > lastPrime) {
		            for (var i = lastPrime + 2; i <= options.max; ++i) {
		                if (this.is_prime(i)) {
		                    data.primes.push(i);
		                }
		            }
		        }
		        var targetPrimes = data.primes.filter(function (prime) {
		            return prime >= options.min && prime <= options.max;
		        });
		        return this.pick(targetPrimes);
		    };

		    /**
		     * Determine whether a given number is prime or not.
		     */
		    Chance.prototype.is_prime = function (n) {
		        if (n % 1 || n < 2) {
		            return false;
		        }
		        if (n % 2 === 0) {
		            return n === 2;
		        }
		        if (n % 3 === 0) {
		            return n === 3;
		        }
		        var m = Math.sqrt(n);
		        for (var i = 5; i <= m; i += 6) {
		            if (n % i === 0 || n % (i + 2) === 0) {
		                return false;
		            }
		        }
		        return true;
		    };

		    /**
		     *  Return a random hex number as string
		     *
		     *  NOTE the max and min are INCLUDED in the range. So:
		     *  chance.hex({min: '9', max: 'B'});
		     *  would return either '9', 'A' or 'B'.
		     *
		     *  @param {Object} [options={}] can specify a min and/or max and/or casing
		     *  @returns {String} a single random string hex number
		     *  @throws {RangeError} min cannot be greater than max
		     */
		    Chance.prototype.hex = function (options) {
		        options = initOptions(options, {min: 0, max: MAX_INT, casing: 'lower'});
		        testRange(options.min < 0, "Chance: Min cannot be less than zero.");
				var integer = this.natural({min: options.min, max: options.max});
				if (options.casing === 'upper') {
					return integer.toString(16).toUpperCase();
				}
				return integer.toString(16);
		    };

		    Chance.prototype.letter = function(options) {
		        options = initOptions(options, {casing: 'lower'});
		        var pool = "abcdefghijklmnopqrstuvwxyz";
		        var letter = this.character({pool: pool});
		        if (options.casing === 'upper') {
		            letter = letter.toUpperCase();
		        }
		        return letter;
		    };

		    /**
		     *  Return a random string
		     *
		     *  @param {Object} [options={}] can specify a length or min and max
		     *  @returns {String} a string of random length
		     *  @throws {RangeError} length cannot be less than zero
		     */
		    Chance.prototype.string = function (options) {
		        options = initOptions(options, { min: 5, max: 20 });

		        if (options.length !== 0 && !options.length) {
		            options.length = this.natural({ min: options.min, max: options.max });
		        }

		        testRange(options.length < 0, "Chance: Length cannot be less than zero.");
		        var length = options.length,
		            text = this.n(this.character, length, options);

		        return text.join("");
		    };

		    function CopyToken(c) {
		        this.c = c;
		    }

		    CopyToken.prototype = {
		        substitute: function () {
		            return this.c
		        }
		    };

		    function EscapeToken(c) {
		        this.c = c;
		    }

		    EscapeToken.prototype = {
		        substitute: function () {
		            if (!/[{}\\]/.test(this.c)) {
		                throw new Error('Invalid escape sequence: "\\' + this.c + '".')
		            }
		            return this.c
		        }
		    };

		    function ReplaceToken(c) {
		        this.c = c;
		    }

		    ReplaceToken.prototype = {
		        replacers: {
		            '#': function (chance) { return chance.character({ pool: NUMBERS }) },
		            'A': function (chance) { return chance.character({ pool: CHARS_UPPER }) },
		            'a': function (chance) { return chance.character({ pool: CHARS_LOWER }) },
		        },

		        substitute: function (chance) {
		            var replacer = this.replacers[this.c];
		            if (!replacer) {
		                throw new Error('Invalid replacement character: "' + this.c + '".')
		            }
		            return replacer(chance)
		        }
		    };

		    function parseTemplate(template) {
		        var tokens = [];
		        var mode = 'identity';
		        for (var i = 0; i<template.length; i++) {
		            var c = template[i];
		            switch (mode) {
		                case 'escape':
		                    tokens.push(new EscapeToken(c));
		                    mode = 'identity';
		                    break
		                case 'identity':
		                    if (c === '{') {
		                        mode = 'replace';
		                    } else if (c === '\\') {
		                        mode = 'escape';
		                    } else {
		                        tokens.push(new CopyToken(c));
		                    }
		                    break
		                case 'replace':
		                    if (c === '}') {
		                        mode = 'identity';
		                    } else {
		                        tokens.push(new ReplaceToken(c));
		                    }
		                    break
		            }
		        }
		        return tokens
		    }

		    /**
		     *  Return a random string matching the given template.
		     *
		     *  The template consists of any number of "character replacement" and
		     *  "character literal" sequences. A "character replacement" sequence
		     *  starts with a left brace, has any number of special replacement
		     *  characters, and ends with a right brace. A character literal can be any
		     *  character except a brace or a backslash. A literal brace or backslash
		     *  character can be included in the output by escaping with a backslash.
		     *
		     *  The following replacement characters can be used in a replacement
		     *  sequence:
		     *
		     *      "#": a random digit
		     *      "a": a random lower case letter
		     *      "A": a random upper case letter
		     *
		     *  Example: chance.template('{AA###}-{##}')
		     *
		     *  @param {String} template string.
		     *  @returns {String} a random string matching the template.
		     */
		    Chance.prototype.template = function (template) {
		        if (!template) {
		            throw new Error('Template string is required')
		        }
		        var self = this;
		        return parseTemplate(template)
		            .map(function (token) { return token.substitute(self) })
		            .join('');
		    };


		    /**
		     *  Return a random buffer
		     *
		     *  @param {Object} [options={}] can specify a length
		     *  @returns {Buffer} a buffer of random length
		     *  @throws {RangeError} length cannot be less than zero
		     */
		    Chance.prototype.buffer = function (options) {
		        if (typeof Buffer === 'undefined') {
		            throw new UnsupportedError('Sorry, the buffer() function is not supported on your platform');
		        }
		        options = initOptions(options, { length: this.natural({min: 5, max: 20}) });
		        testRange(options.length < 0, "Chance: Length cannot be less than zero.");
		        var length = options.length;
		        var content = this.n(this.character, length, options);

		        return Buffer.from(content);
		    };

		    // -- End Basics --

		    // -- Helpers --

		    Chance.prototype.capitalize = function (word) {
		        return word.charAt(0).toUpperCase() + word.substr(1);
		    };

		    Chance.prototype.mixin = function (obj) {
		        for (var func_name in obj) {
		            this[func_name] = obj[func_name];
		        }
		        return this;
		    };

		    /**
		     *  Given a function that generates something random and a number of items to generate,
		     *    return an array of items where none repeat.
		     *
		     *  @param {Function} fn the function that generates something random
		     *  @param {Number} num number of terms to generate
		     *  @param {Object} options any options to pass on to the generator function
		     *  @returns {Array} an array of length `num` with every item generated by `fn` and unique
		     *
		     *  There can be more parameters after these. All additional parameters are provided to the given function
		     */
		    Chance.prototype.unique = function(fn, num, options) {
		        testRange(
		            typeof fn !== "function",
		            "Chance: The first argument must be a function."
		        );

		        var comparator = function(arr, val) { return arr.indexOf(val) !== -1; };

		        if (options) {
		            comparator = options.comparator || comparator;
		        }

		        var arr = [], count = 0, result, MAX_DUPLICATES = num * 50, params = slice.call(arguments, 2);

		        while (arr.length < num) {
		            var clonedParams = JSON.parse(JSON.stringify(params));
		            result = fn.apply(this, clonedParams);
		            if (!comparator(arr, result)) {
		                arr.push(result);
		                // reset count when unique found
		                count = 0;
		            }

		            if (++count > MAX_DUPLICATES) {
		                throw new RangeError("Chance: num is likely too large for sample set");
		            }
		        }
		        return arr;
		    };

		    /**
		     *  Gives an array of n random terms
		     *
		     *  @param {Function} fn the function that generates something random
		     *  @param {Number} n number of terms to generate
		     *  @returns {Array} an array of length `n` with items generated by `fn`
		     *
		     *  There can be more parameters after these. All additional parameters are provided to the given function
		     */
		    Chance.prototype.n = function(fn, n) {
		        testRange(
		            typeof fn !== "function",
		            "Chance: The first argument must be a function."
		        );

		        if (typeof n === 'undefined') {
		            n = 1;
		        }
		        var i = n, arr = [], params = slice.call(arguments, 2);

		        // Providing a negative count should result in a noop.
		        i = Math.max( 0, i );

		        for (null; i--; null) {
		            arr.push(fn.apply(this, params));
		        }

		        return arr;
		    };

		    // H/T to SO for this one: http://vq.io/OtUrZ5
		    Chance.prototype.pad = function (number, width, pad) {
		        // Default pad to 0 if none provided
		        pad = pad || '0';
		        // Convert number to a string
		        number = number + '';
		        return number.length >= width ? number : new Array(width - number.length + 1).join(pad) + number;
		    };

		    // DEPRECATED on 2015-10-01
		    Chance.prototype.pick = function (arr, count) {
		        if (arr.length === 0) {
		            throw new RangeError("Chance: Cannot pick() from an empty array");
		        }
		        if (!count || count === 1) {
		            return arr[this.natural({max: arr.length - 1})];
		        } else {
		            return this.shuffle(arr).slice(0, count);
		        }
		    };

		    // Given an array, returns a single random element
		    Chance.prototype.pickone = function (arr) {
		        if (arr.length === 0) {
		          throw new RangeError("Chance: Cannot pickone() from an empty array");
		        }
		        return arr[this.natural({max: arr.length - 1})];
		    };

		    // Given an array, returns a random set with 'count' elements
		    Chance.prototype.pickset = function (arr, count) {
		        if (count === 0) {
		            return [];
		        }
		        if (arr.length === 0) {
		            throw new RangeError("Chance: Cannot pickset() from an empty array");
		        }
		        if (count < 0) {
		            throw new RangeError("Chance: Count must be a positive number");
		        }
		        if (!count || count === 1) {
		            return [ this.pickone(arr) ];
		        } else {
		            var array = arr.slice(0);
		            var end = array.length;

		            return this.n(function () {
		                var index = this.natural({max: --end});
		                var value = array[index];
		                array[index] = array[end];
		                return value;
		            }, Math.min(end, count));
		        }
		    };

		    Chance.prototype.shuffle = function (arr) {
		        var new_array = [],
		            j = 0,
		            length = Number(arr.length),
		            source_indexes = range(length),
		            last_source_index = length - 1,
		            selected_source_index;

		        for (var i = 0; i < length; i++) {
		            // Pick a random index from the array
		            selected_source_index = this.natural({max: last_source_index});
		            j = source_indexes[selected_source_index];

		            // Add it to the new array
		            new_array[i] = arr[j];

		            // Mark the source index as used
		            source_indexes[selected_source_index] = source_indexes[last_source_index];
		            last_source_index -= 1;
		        }

		        return new_array;
		    };

		    // Returns a single item from an array with relative weighting of odds
		    Chance.prototype.weighted = function (arr, weights, trim) {
		        if (arr.length !== weights.length) {
		            throw new RangeError("Chance: Length of array and weights must match");
		        }

		        // scan weights array and sum valid entries
		        var sum = 0;
		        var val;
		        for (var weightIndex = 0; weightIndex < weights.length; ++weightIndex) {
		            val = weights[weightIndex];
		            if (isNaN(val)) {
		                throw new RangeError("Chance: All weights must be numbers");
		            }

		            if (val > 0) {
		                sum += val;
		            }
		        }

		        if (sum === 0) {
		            throw new RangeError("Chance: No valid entries in array weights");
		        }

		        // select a value within range
		        var selected = this.random() * sum;

		        // find array entry corresponding to selected value
		        var total = 0;
		        var lastGoodIdx = -1;
		        var chosenIdx;
		        for (weightIndex = 0; weightIndex < weights.length; ++weightIndex) {
		            val = weights[weightIndex];
		            total += val;
		            if (val > 0) {
		                if (selected <= total) {
		                    chosenIdx = weightIndex;
		                    break;
		                }
		                lastGoodIdx = weightIndex;
		            }

		            // handle any possible rounding error comparison to ensure something is picked
		            if (weightIndex === (weights.length - 1)) {
		                chosenIdx = lastGoodIdx;
		            }
		        }

		        var chosen = arr[chosenIdx];
		        trim = (typeof trim === 'undefined') ? false : trim;
		        if (trim) {
		            arr.splice(chosenIdx, 1);
		            weights.splice(chosenIdx, 1);
		        }

		        return chosen;
		    };

		    // -- End Helpers --

		    // -- Text --

		    Chance.prototype.paragraph = function (options) {
		        options = initOptions(options);

		        var sentences = options.sentences || this.natural({min: 3, max: 7}),
		            sentence_array = this.n(this.sentence, sentences),
		            separator = options.linebreak === true ? '\n' : ' ';

		        return sentence_array.join(separator);
		    };

		    // Could get smarter about this than generating random words and
		    // chaining them together. Such as: http://vq.io/1a5ceOh
		    Chance.prototype.sentence = function (options) {
		        options = initOptions(options);

		        var words = options.words || this.natural({min: 12, max: 18}),
		            punctuation = options.punctuation,
		            text, word_array = this.n(this.word, words);

		        text = word_array.join(' ');

		        // Capitalize first letter of sentence
		        text = this.capitalize(text);

		        // Make sure punctuation has a usable value
		        if (punctuation !== false && !/^[.?;!:]$/.test(punctuation)) {
		            punctuation = '.';
		        }

		        // Add punctuation mark
		        if (punctuation) {
		            text += punctuation;
		        }

		        return text;
		    };

		    Chance.prototype.syllable = function (options) {
		        options = initOptions(options);

		        var length = options.length || this.natural({min: 2, max: 3}),
		            consonants = 'bcdfghjklmnprstvwz', // consonants except hard to speak ones
		            vowels = 'aeiou', // vowels
		            all = consonants + vowels, // all
		            text = '',
		            chr;

		        // I'm sure there's a more elegant way to do this, but this works
		        // decently well.
		        for (var i = 0; i < length; i++) {
		            if (i === 0) {
		                // First character can be anything
		                chr = this.character({pool: all});
		            } else if (consonants.indexOf(chr) === -1) {
		                // Last character was a vowel, now we want a consonant
		                chr = this.character({pool: consonants});
		            } else {
		                // Last character was a consonant, now we want a vowel
		                chr = this.character({pool: vowels});
		            }

		            text += chr;
		        }

		        if (options.capitalize) {
		            text = this.capitalize(text);
		        }

		        return text;
		    };

		    Chance.prototype.word = function (options) {
		        options = initOptions(options);

		        testRange(
		            options.syllables && options.length,
		            "Chance: Cannot specify both syllables AND length."
		        );

		        var syllables = options.syllables || this.natural({min: 1, max: 3}),
		            text = '';

		        if (options.length) {
		            // Either bound word by length
		            do {
		                text += this.syllable();
		            } while (text.length < options.length);
		            text = text.substring(0, options.length);
		        } else {
		            // Or by number of syllables
		            for (var i = 0; i < syllables; i++) {
		                text += this.syllable();
		            }
		        }

		        if (options.capitalize) {
		            text = this.capitalize(text);
		        }

		        return text;
		    };

		    Chance.prototype.emoji = function (options) {
		        options = initOptions(options, { category: "all", length: 1 });

		        testRange(
		            options.length < 1 || BigInt(options.length) > BigInt(MAX_INT),
		            "Chance: length must be between 1 and " + String(MAX_INT)
		        );

		        var emojis = this.get("emojis");

		        if (options.category === "all") {
		            options.category = this.pickone(Object.keys(emojis));
		        }

		        var emojisForCategory = emojis[options.category];

		        testRange(
		            emojisForCategory === undefined,
		            "Chance: Unrecognised emoji category: [" + options.category + "]."
		        );

		        return this.pickset(emojisForCategory, options.length)
		            .map(function (codePoint) {
		                return String.fromCodePoint(codePoint);
		            }).join("");
		    };

		    // -- End Text --

		    // -- Person --

		    Chance.prototype.age = function (options) {
		        options = initOptions(options);
		        var ageRange;

		        switch (options.type) {
		            case 'child':
		                ageRange = {min: 0, max: 12};
		                break;
		            case 'teen':
		                ageRange = {min: 13, max: 19};
		                break;
		            case 'adult':
		                ageRange = {min: 18, max: 65};
		                break;
		            case 'senior':
		                ageRange = {min: 65, max: 100};
		                break;
		            case 'all':
		                ageRange = {min: 0, max: 100};
		                break;
		            default:
		                ageRange = {min: 18, max: 65};
		                break;
		        }

		        return this.natural(ageRange);
		    };

		    Chance.prototype.birthday = function (options) {
		        var age = this.age(options);
		        var now = new Date();
		        var currentYear = now.getFullYear();

		        if (options && options.type) {
		            var min = new Date();
		            var max = new Date();
		            min.setFullYear(currentYear - age - 1);
		            max.setFullYear(currentYear - age);

		            options = initOptions(options, {
		                min: min,
		                max: max
		            });
		        } else if (options && ((options.minAge !== undefined) || (options.maxAge !== undefined))) {
		            testRange(options.minAge < 0, "Chance: MinAge cannot be less than zero.");
		            testRange(options.minAge > options.maxAge, "Chance: MinAge cannot be greater than MaxAge.");

		            var minAge = options.minAge !== undefined ? options.minAge : 0;
		            var maxAge = options.maxAge !== undefined ? options.maxAge : 100;

		            var minDate = new Date(currentYear - maxAge - 1, now.getMonth(), now.getDate());
		            var maxDate = new Date(currentYear - minAge, now.getMonth(), now.getDate());

		            minDate.setDate(minDate.getDate() +1);

		            maxDate.setDate(maxDate.getDate() +1);
		            maxDate.setMilliseconds(maxDate.getMilliseconds() -1);

		            options = initOptions(options, {
		                min: minDate,
		                max: maxDate
		          });
		        } else {
		            options = initOptions(options, {
		                year: currentYear - age
		            });
		        }

		        return this.date(options);
		    };

		    // CPF; ID to identify taxpayers in Brazil
		    Chance.prototype.cpf = function (options) {
		        options = initOptions(options, {
		            formatted: true
		        });

		        var n = this.n(this.natural, 9, { max: 9 });
		        var d1 = n[8]*2+n[7]*3+n[6]*4+n[5]*5+n[4]*6+n[3]*7+n[2]*8+n[1]*9+n[0]*10;
		        d1 = 11 - (d1 % 11);
		        if (d1>=10) {
		            d1 = 0;
		        }
		        var d2 = d1*2+n[8]*3+n[7]*4+n[6]*5+n[5]*6+n[4]*7+n[3]*8+n[2]*9+n[1]*10+n[0]*11;
		        d2 = 11 - (d2 % 11);
		        if (d2>=10) {
		            d2 = 0;
		        }
		        var cpf = ''+n[0]+n[1]+n[2]+'.'+n[3]+n[4]+n[5]+'.'+n[6]+n[7]+n[8]+'-'+d1+d2;
		        return options.formatted ? cpf : cpf.replace(/\D/g,'');
		    };

		    // CNPJ: ID to identify companies in Brazil
		    Chance.prototype.cnpj = function (options) {
		        options = initOptions(options, {
		            formatted: true
		        });

		        var n = this.n(this.natural, 12, { max: 12 });
		        var d1 = n[11]*2+n[10]*3+n[9]*4+n[8]*5+n[7]*6+n[6]*7+n[5]*8+n[4]*9+n[3]*2+n[2]*3+n[1]*4+n[0]*5;
		        d1 = 11 - (d1 % 11);
		        if (d1<2) {
		            d1 = 0;
		        }
		        var d2 = d1*2+n[11]*3+n[10]*4+n[9]*5+n[8]*6+n[7]*7+n[6]*8+n[5]*9+n[4]*2+n[3]*3+n[2]*4+n[1]*5+n[0]*6;
		        d2 = 11 - (d2 % 11);
		        if (d2<2) {
		            d2 = 0;
		        }
		        var cnpj = ''+n[0]+n[1]+'.'+n[2]+n[3]+n[4]+'.'+n[5]+n[6]+n[7]+'/'+n[8]+n[9]+n[10]+n[11]+'-'+d1+d2;
		        return options.formatted ? cnpj : cnpj.replace(/\D/g,'');
		    };

		    Chance.prototype.first = function (options) {
		        options = initOptions(options, {gender: this.gender(), nationality: 'en'});
		        return this.pick(this.get("firstNames")[options.gender.toLowerCase()][options.nationality.toLowerCase()]);
		    };

		    Chance.prototype.profession = function (options) {
		        options = initOptions(options);
		        if(options.rank){
		            return this.pick(['Apprentice ', 'Junior ', 'Senior ', 'Lead ']) + this.pick(this.get("profession"));
		        } else {
		            return this.pick(this.get("profession"));
		        }
		    };

		    Chance.prototype.company = function (){
		        return this.pick(this.get("company"));
		    };

		    Chance.prototype.gender = function (options) {
		        options = initOptions(options, {extraGenders: []});
		        return this.pick(['Male', 'Female'].concat(options.extraGenders));
		    };

		    Chance.prototype.last = function (options) {
		      options = initOptions(options, {nationality: '*'});
		      if (options.nationality === "*") {
		        var allLastNames = [];
		        var lastNames = this.get("lastNames");
		        Object.keys(lastNames).forEach(function(key){
		          allLastNames = allLastNames.concat(lastNames[key]);
		        });
		        return this.pick(allLastNames)
		      }
		      else {
		        return this.pick(this.get("lastNames")[options.nationality.toLowerCase()]);
		      }

		    };

		    Chance.prototype.israelId=function(){
		        var x=this.string({pool: '0123456789',length:8});
		        var y=0;
		        for (var i=0;i<x.length;i++){
		            var thisDigit=  x[i] *  (i/2===parseInt(i/2) ? 1 : 2);
		            thisDigit=this.pad(thisDigit,2).toString();
		            thisDigit=parseInt(thisDigit[0]) + parseInt(thisDigit[1]);
		            y=y+thisDigit;
		        }
		        x=x+(10-parseInt(y.toString().slice(-1))).toString().slice(-1);
		        return x;
		    };

		    Chance.prototype.mrz = function (options) {
		        var checkDigit = function (input) {
		            var alpha = "<ABCDEFGHIJKLMNOPQRSTUVWXYXZ".split(''),
		                multipliers = [ 7, 3, 1 ],
		                runningTotal = 0;

		            if (typeof input !== 'string') {
		                input = input.toString();
		            }

		            input.split('').forEach(function(character, idx) {
		                var pos = alpha.indexOf(character);

		                if(pos !== -1) {
		                    character = pos === 0 ? 0 : pos + 9;
		                } else {
		                    character = parseInt(character, 10);
		                }
		                character *= multipliers[idx % multipliers.length];
		                runningTotal += character;
		            });
		            return runningTotal % 10;
		        };
		        var generate = function (opts) {
		            var pad = function (length) {
		                return new Array(length + 1).join('<');
		            };
		            var number = [ 'P<',
		                           opts.issuer,
		                           opts.last.toUpperCase(),
		                           '<<',
		                           opts.first.toUpperCase(),
		                           pad(39 - (opts.last.length + opts.first.length + 2)),
		                           opts.passportNumber,
		                           checkDigit(opts.passportNumber),
		                           opts.nationality,
		                           opts.dob,
		                           checkDigit(opts.dob),
		                           opts.gender,
		                           opts.expiry,
		                           checkDigit(opts.expiry),
		                           pad(14),
		                           checkDigit(pad(14)) ].join('');

		            return number +
		                (checkDigit(number.substr(44, 10) +
		                            number.substr(57, 7) +
		                            number.substr(65, 7)));
		        };

		        var that = this;

		        options = initOptions(options, {
		            first: this.first(),
		            last: this.last(),
		            passportNumber: this.integer({min: 100000000, max: 999999999}),
		            dob: (function () {
		                var date = that.birthday({type: 'adult'});
		                return [date.getFullYear().toString().substr(2),
		                        that.pad(date.getMonth() + 1, 2),
		                        that.pad(date.getDate(), 2)].join('');
		            }()),
		            expiry: (function () {
		                var date = new Date();
		                return [(date.getFullYear() + 5).toString().substr(2),
		                        that.pad(date.getMonth() + 1, 2),
		                        that.pad(date.getDate(), 2)].join('');
		            }()),
		            gender: this.gender() === 'Female' ? 'F': 'M',
		            issuer: 'GBR',
		            nationality: 'GBR'
		        });
		        return generate (options);
		    };

		    Chance.prototype.name = function (options) {
		        options = initOptions(options);

		        var first = this.first(options),
		            last = this.last(options),
		            name;

		        if (options.middle) {
		            name = first + ' ' + this.first(options) + ' ' + last;
		        } else if (options.middle_initial) {
		            name = first + ' ' + this.character({alpha: true, casing: 'upper'}) + '. ' + last;
		        } else {
		            name = first + ' ' + last;
		        }

		        if (options.prefix) {
		            name = this.prefix(options) + ' ' + name;
		        }

		        if (options.suffix) {
		            name = name + ' ' + this.suffix(options);
		        }

		        return name;
		    };

		    // Return the list of available name prefixes based on supplied gender.
		    // @todo introduce internationalization
		    Chance.prototype.name_prefixes = function (gender) {
		        gender = gender || "all";
		        gender = gender.toLowerCase();

		        var prefixes = [
		            { name: 'Doctor', abbreviation: 'Dr.' }
		        ];

		        if (gender === "male" || gender === "all") {
		            prefixes.push({ name: 'Mister', abbreviation: 'Mr.' });
		        }

		        if (gender === "female" || gender === "all") {
		            prefixes.push({ name: 'Miss', abbreviation: 'Miss' });
		            prefixes.push({ name: 'Misses', abbreviation: 'Mrs.' });
		        }

		        return prefixes;
		    };

		    // Alias for name_prefix
		    Chance.prototype.prefix = function (options) {
		        return this.name_prefix(options);
		    };

		    Chance.prototype.name_prefix = function (options) {
		        options = initOptions(options, { gender: "all" });
		        return options.full ?
		            this.pick(this.name_prefixes(options.gender)).name :
		            this.pick(this.name_prefixes(options.gender)).abbreviation;
		    };
		    //Hungarian ID number
		    Chance.prototype.HIDN= function(){
		     //Hungarian ID nuber structure: XXXXXXYY (X=number,Y=Capital Latin letter)
		      var idn_pool="0123456789";
		      var idn_chrs="ABCDEFGHIJKLMNOPQRSTUVWXYXZ";
		      var idn="";
		        idn+=this.string({pool:idn_pool,length:6});
		        idn+=this.string({pool:idn_chrs,length:2});
		        return idn;
		    };


		    Chance.prototype.ssn = function (options) {
		        options = initOptions(options, {ssnFour: false, dashes: true});
		        var ssn_pool = "1234567890",
		            ssn,
		            dash = options.dashes ? '-' : '';

		        if(!options.ssnFour) {
		            ssn = this.string({pool: ssn_pool, length: 3}) + dash +
		            this.string({pool: ssn_pool, length: 2}) + dash +
		            this.string({pool: ssn_pool, length: 4});
		        } else {
		            ssn = this.string({pool: ssn_pool, length: 4});
		        }
		        return ssn;
		    };

		    // Aadhar is similar to ssn, used in India to uniquely identify a person
		    Chance.prototype.aadhar = function (options) {
		        options = initOptions(options, {onlyLastFour: false, separatedByWhiteSpace: true});
		        var aadhar_pool = "1234567890",
		            aadhar,
		            whiteSpace = options.separatedByWhiteSpace ? ' ' : '';

		        if(!options.onlyLastFour) {
		            aadhar = this.string({pool: aadhar_pool, length: 4}) + whiteSpace +
		            this.string({pool: aadhar_pool, length: 4}) + whiteSpace +
		            this.string({pool: aadhar_pool, length: 4});
		        } else {
		            aadhar = this.string({pool: aadhar_pool, length: 4});
		        }
		        return aadhar;
		    };

		    // Return the list of available name suffixes
		    // @todo introduce internationalization
		    Chance.prototype.name_suffixes = function () {
		        var suffixes = [
		            { name: 'Doctor of Osteopathic Medicine', abbreviation: 'D.O.' },
		            { name: 'Doctor of Philosophy', abbreviation: 'Ph.D.' },
		            { name: 'Esquire', abbreviation: 'Esq.' },
		            { name: 'Junior', abbreviation: 'Jr.' },
		            { name: 'Juris Doctor', abbreviation: 'J.D.' },
		            { name: 'Master of Arts', abbreviation: 'M.A.' },
		            { name: 'Master of Business Administration', abbreviation: 'M.B.A.' },
		            { name: 'Master of Science', abbreviation: 'M.S.' },
		            { name: 'Medical Doctor', abbreviation: 'M.D.' },
		            { name: 'Senior', abbreviation: 'Sr.' },
		            { name: 'The Third', abbreviation: 'III' },
		            { name: 'The Fourth', abbreviation: 'IV' },
		            { name: 'Bachelor of Engineering', abbreviation: 'B.E' },
		            { name: 'Bachelor of Technology', abbreviation: 'B.TECH' }
		        ];
		        return suffixes;
		    };

		    // Alias for name_suffix
		    Chance.prototype.suffix = function (options) {
		        return this.name_suffix(options);
		    };

		    Chance.prototype.name_suffix = function (options) {
		        options = initOptions(options);
		        return options.full ?
		            this.pick(this.name_suffixes()).name :
		            this.pick(this.name_suffixes()).abbreviation;
		    };

		    Chance.prototype.nationalities = function () {
		        return this.get("nationalities");
		    };

		    // Generate random nationality based on json list
		    Chance.prototype.nationality = function () {
		        var nationality = this.pick(this.nationalities());
		        return nationality.name;
		    };

		     // Generate random zodiac sign
		     Chance.prototype.zodiac = function () {
		        const zodiacSymbols = ["Aries","Taurus","Gemini","Cancer","Leo","Virgo","Libra","Scorpio","Sagittarius","Capricorn","Aquarius","Pisces"];
		        return this.pickone(zodiacSymbols);
		    };


		    // -- End Person --

		    // -- Mobile --
		    // Android GCM Registration ID
		    Chance.prototype.android_id = function () {
		        return "APA91" + this.string({ pool: "0123456789abcefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_", length: 178 });
		    };

		    // Apple Push Token
		    Chance.prototype.apple_token = function () {
		        return this.string({ pool: "abcdef1234567890", length: 64 });
		    };

		    // Windows Phone 8 ANID2
		    Chance.prototype.wp8_anid2 = function () {
		        return base64( this.hash( { length : 32 } ) );
		    };

		    // Windows Phone 7 ANID
		    Chance.prototype.wp7_anid = function () {
		        return 'A=' + this.guid().replace(/-/g, '').toUpperCase() + '&E=' + this.hash({ length:3 }) + '&W=' + this.integer({ min:0, max:9 });
		    };

		    // BlackBerry Device PIN
		    Chance.prototype.bb_pin = function () {
		        return this.hash({ length: 8 });
		    };

		    // -- End Mobile --

		    // -- Web --
		    Chance.prototype.avatar = function (options) {
		        var url = null;
		        var URL_BASE = '//www.gravatar.com/avatar/';
		        var PROTOCOLS = {
		            http: 'http',
		            https: 'https'
		        };
		        var FILE_TYPES = {
		            bmp: 'bmp',
		            gif: 'gif',
		            jpg: 'jpg',
		            png: 'png'
		        };
		        var FALLBACKS = {
		            '404': '404', // Return 404 if not found
		            mm: 'mm', // Mystery man
		            identicon: 'identicon', // Geometric pattern based on hash
		            monsterid: 'monsterid', // A generated monster icon
		            wavatar: 'wavatar', // A generated face
		            retro: 'retro', // 8-bit icon
		            blank: 'blank' // A transparent png
		        };
		        var RATINGS = {
		            g: 'g',
		            pg: 'pg',
		            r: 'r',
		            x: 'x'
		        };
		        var opts = {
		            protocol: null,
		            email: null,
		            fileExtension: null,
		            size: null,
		            fallback: null,
		            rating: null
		        };

		        if (!options) {
		            // Set to a random email
		            opts.email = this.email();
		            options = {};
		        }
		        else if (typeof options === 'string') {
		            opts.email = options;
		            options = {};
		        }
		        else if (typeof options !== 'object') {
		            return null;
		        }
		        else if (options.constructor === 'Array') {
		            return null;
		        }

		        opts = initOptions(options, opts);

		        if (!opts.email) {
		            // Set to a random email
		            opts.email = this.email();
		        }

		        // Safe checking for params
		        opts.protocol = PROTOCOLS[opts.protocol] ? opts.protocol + ':' : '';
		        opts.size = parseInt(opts.size, 0) ? opts.size : '';
		        opts.rating = RATINGS[opts.rating] ? opts.rating : '';
		        opts.fallback = FALLBACKS[opts.fallback] ? opts.fallback : '';
		        opts.fileExtension = FILE_TYPES[opts.fileExtension] ? opts.fileExtension : '';

		        url =
		            opts.protocol +
		            URL_BASE +
		            this.bimd5.md5(opts.email) +
		            (opts.fileExtension ? '.' + opts.fileExtension : '') +
		            (opts.size || opts.rating || opts.fallback ? '?' : '') +
		            (opts.size ? '&s=' + opts.size.toString() : '') +
		            (opts.rating ? '&r=' + opts.rating : '') +
		            (opts.fallback ? '&d=' + opts.fallback : '')
		            ;

		        return url;
		    };

		    /**
		     * #Description:
		     * ===============================================
		     * Generate random color value base on color type:
		     * -> hex
		     * -> rgb
		     * -> rgba
		     * -> 0x
		     * -> named color
		     *
		     * #Examples:
		     * ===============================================
		     * * Geerate random hex color
		     * chance.color() => '#79c157' / 'rgb(110,52,164)' / '0x67ae0b' / '#e2e2e2' / '#29CFA7'
		     *
		     * * Generate Hex based color value
		     * chance.color({format: 'hex'})    => '#d67118'
		     *
		     * * Generate simple rgb value
		     * chance.color({format: 'rgb'})    => 'rgb(110,52,164)'
		     *
		     * * Generate Ox based color value
		     * chance.color({format: '0x'})     => '0x67ae0b'
		     *
		     * * Generate graiscale based value
		     * chance.color({grayscale: true})  => '#e2e2e2'
		     *
		     * * Return valide color name
		     * chance.color({format: 'name'})   => 'red'
		     *
		     * * Make color uppercase
		     * chance.color({casing: 'upper'})  => '#29CFA7'
		     *
		     * * Min Max values for RGBA
		     * var light_red = chance.color({format: 'hex', min_red: 200, max_red: 255, max_green: 0, max_blue: 0, min_alpha: .2, max_alpha: .3});
		     *
		     * @param  [object] options
		     * @return [string] color value
		     */
		    Chance.prototype.color = function (options) {
		        function gray(value, delimiter) {
		            return [value, value, value].join(delimiter || '');
		        }

		        function rgb(hasAlpha) {
		            var rgbValue     = (hasAlpha)    ? 'rgba' : 'rgb';
		            var alphaChannel = (hasAlpha)    ? (',' + this.floating({min:min_alpha, max:max_alpha})) : "";
		            var colorValue   = (isGrayscale) ? (gray(this.natural({min: min_rgb, max: max_rgb}), ',')) : (this.natural({min: min_green, max: max_green}) + ',' + this.natural({min: min_blue, max: max_blue}) + ',' + this.natural({max: 255}));
		            return rgbValue + '(' + colorValue + alphaChannel + ')';
		        }

		        function hex(start, end, withHash) {
		            var symbol = (withHash) ? "#" : "";
		            var hexstring = "";

		            if (isGrayscale) {
		                hexstring = gray(this.pad(this.hex({min: min_rgb, max: max_rgb}), 2));
		                if (options.format === "shorthex") {
		                    hexstring = gray(this.hex({min: 0, max: 15}));
		                }
		            }
		            else {
		                if (options.format === "shorthex") {
		                    hexstring = this.pad(this.hex({min: Math.floor(min_red / 16), max: Math.floor(max_red / 16)}), 1) + this.pad(this.hex({min: Math.floor(min_green / 16), max: Math.floor(max_green / 16)}), 1) + this.pad(this.hex({min: Math.floor(min_blue / 16), max: Math.floor(max_blue / 16)}), 1);
		                }
		                else if (min_red !== undefined || max_red !== undefined || min_green !== undefined || max_green !== undefined || min_blue !== undefined || max_blue !== undefined) {
		                    hexstring = this.pad(this.hex({min: min_red, max: max_red}), 2) + this.pad(this.hex({min: min_green, max: max_green}), 2) + this.pad(this.hex({min: min_blue, max: max_blue}), 2);
		                }
		                else {
		                    hexstring = this.pad(this.hex({min: min_rgb, max: max_rgb}), 2) + this.pad(this.hex({min: min_rgb, max: max_rgb}), 2) + this.pad(this.hex({min: min_rgb, max: max_rgb}), 2);
		                }
		            }

		            return symbol + hexstring;
		        }

		        options = initOptions(options, {
		            format: this.pick(['hex', 'shorthex', 'rgb', 'rgba', '0x', 'name']),
		            grayscale: false,
		            casing: 'lower',
		            min: 0,
		            max: 255,
		            min_red: undefined,
		            max_red: undefined,
		            min_green: undefined,
		            max_green: undefined,
		            min_blue: undefined,
		            max_blue: undefined,
		            min_alpha: 0,
		            max_alpha: 1
		        });

		        var isGrayscale = options.grayscale;
		        var min_rgb = options.min;
		        var max_rgb = options.max;
		        var min_red = options.min_red;
		        var max_red = options.max_red;
		        var min_green = options.min_green;
		        var max_green = options.max_green;
		        var min_blue = options.min_blue;
		        var max_blue = options.max_blue;
		        var min_alpha = options.min_alpha;
		        var max_alpha = options.max_alpha;
		        if (options.min_red === undefined) { min_red = min_rgb; }
		        if (options.max_red === undefined) { max_red = max_rgb; }
		        if (options.min_green === undefined) { min_green = min_rgb; }
		        if (options.max_green === undefined) { max_green = max_rgb; }
		        if (options.min_blue === undefined) { min_blue = min_rgb; }
		        if (options.max_blue === undefined) { max_blue = max_rgb; }
		        if (options.min_alpha === undefined) { min_alpha = 0; }
		        if (options.max_alpha === undefined) { max_alpha = 1; }
		        if (isGrayscale && min_rgb === 0 && max_rgb === 255 && min_red !== undefined && max_red !== undefined) {
		            min_rgb = ((min_red + min_green + min_blue) / 3);
		            max_rgb = ((max_red + max_green + max_blue) / 3);
		        }
		        var colorValue;

		        if (options.format === 'hex') {
		            colorValue = hex.call(this, 2, 6, true);
		        }
		        else if (options.format === 'shorthex') {
		            colorValue = hex.call(this, 1, 3, true);
		        }
		        else if (options.format === 'rgb') {
		            colorValue = rgb.call(this, false);
		        }
		        else if (options.format === 'rgba') {
		            colorValue = rgb.call(this, true);
		        }
		        else if (options.format === '0x') {
		            colorValue = '0x' + hex.call(this, 2, 6);
		        }
		        else if(options.format === 'name') {
		            return this.pick(this.get("colorNames"));
		        }
		        else {
		            throw new RangeError('Invalid format provided. Please provide one of "hex", "shorthex", "rgb", "rgba", "0x" or "name".');
		        }

		        if (options.casing === 'upper' ) {
		            colorValue = colorValue.toUpperCase();
		        }

		        return colorValue;
		    };

		    Chance.prototype.domain = function (options) {
		        options = initOptions(options);
		        return this.word() + '.' + (options.tld || this.tld());
		    };

		    Chance.prototype.email = function (options) {
		        options = initOptions(options);
		        return this.word({length: options.length}) + '@' + (options.domain || this.domain());
		    };

		    /**
		     * #Description:
		     * ===============================================
		     * Generate a random Facebook id, aka fbid.
		     *
		     * NOTE: At the moment (Sep 2017), Facebook ids are
		     * "numeric strings" of length 16.
		     * However, Facebook Graph API documentation states that
		     * "it is extremely likely to change over time".
		     * @see https://developers.facebook.com/docs/graph-api/overview/
		     *
		     * #Examples:
		     * ===============================================
		     * chance.fbid() => '1000035231661304'
		     *
		     * @return [string] facebook id
		     */
		    Chance.prototype.fbid = function () {
		        return '10000' + this.string({pool: "1234567890", length: 11});
		    };

		    Chance.prototype.google_analytics = function () {
		        var account = this.pad(this.natural({max: 999999}), 6);
		        var property = this.pad(this.natural({max: 99}), 2);

		        return 'UA-' + account + '-' + property;
		    };

		    Chance.prototype.hashtag = function () {
		        return '#' + this.word();
		    };

		    Chance.prototype.ip = function () {
		        // Todo: This could return some reserved IPs. See http://vq.io/137dgYy
		        // this should probably be updated to account for that rare as it may be
		        return this.natural({min: 1, max: 254}) + '.' +
		               this.natural({max: 255}) + '.' +
		               this.natural({max: 255}) + '.' +
		               this.natural({min: 1, max: 254});
		    };

		    Chance.prototype.ipv6 = function () {
		        var ip_addr = this.n(this.hash, 8, {length: 4});

		        return ip_addr.join(":");
		    };

		    Chance.prototype.klout = function () {
		        return this.natural({min: 1, max: 99});
		    };

		    Chance.prototype.mac = function (options) {
		        // Todo: This could also be extended to EUI-64 based MACs
		        // (https://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml#ethernet-numbers-4)
		        // Todo: This can return some reserved MACs (similar to IP function)
		        // this should probably be updated to account for that rare as it may be
		        options = initOptions(options, { delimiter: ':' });
		        return this.pad(this.natural({max: 255}).toString(16),2) + options.delimiter +
		               this.pad(this.natural({max: 255}).toString(16),2) + options.delimiter +
		               this.pad(this.natural({max: 255}).toString(16),2) + options.delimiter +
		               this.pad(this.natural({max: 255}).toString(16),2) + options.delimiter +
		               this.pad(this.natural({max: 255}).toString(16),2) + options.delimiter +
		               this.pad(this.natural({max: 255}).toString(16),2);
		    };

		    Chance.prototype.semver = function (options) {
		        options = initOptions(options, { include_prerelease: true });

		        var range = this.pickone(["^", "~", "<", ">", "<=", ">=", "="]);
		        if (options.range) {
		            range = options.range;
		        }

		        var prerelease = "";
		        if (options.include_prerelease) {
		            prerelease = this.weighted(["", "-dev", "-beta", "-alpha"], [50, 10, 5, 1]);
		        }
		        return range + this.rpg('3d10').join('.') + prerelease;
		    };

		    Chance.prototype.tlds = function () {
		        return ['com', 'org', 'edu', 'gov', 'co.uk', 'net', 'io', 'ac', 'ad', 'ae', 'af', 'ag', 'ai', 'al', 'am', 'ao', 'aq', 'ar', 'as', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb', 'bd', 'be', 'bf', 'bg', 'bh', 'bi', 'bj', 'bm', 'bn', 'bo', 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cc', 'cd', 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'cr', 'cu', 'cv', 'cw', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'ee', 'eg', 'eh', 'er', 'es', 'et', 'eu', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr', 'ga', 'gb', 'gd', 'ge', 'gf', 'gg', 'gh', 'gi', 'gl', 'gm', 'gn', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu', 'gw', 'gy', 'hk', 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il', 'im', 'in', 'io', 'iq', 'ir', 'is', 'it', 'je', 'jm', 'jo', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', 'kr', 'kw', 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu', 'lv', 'ly', 'ma', 'mc', 'md', 'me', 'mg', 'mh', 'mk', 'ml', 'mm', 'mn', 'mo', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'nc', 'ne', 'nf', 'ng', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'pa', 'pe', 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'ps', 'pt', 'pw', 'py', 'qa', 're', 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sr', 'ss', 'st', 'su', 'sv', 'sx', 'sy', 'sz', 'tc', 'td', 'tf', 'tg', 'th', 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tr', 'tt', 'tv', 'tw', 'tz', 'ua', 'ug', 'uk', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', 'ye', 'yt', 'za', 'zm', 'zw'];
		    };

		    Chance.prototype.tld = function () {
		        return this.pick(this.tlds());
		    };

		    Chance.prototype.twitter = function () {
		        return '@' + this.word();
		    };

		    Chance.prototype.url = function (options) {
		        options = initOptions(options, { protocol: "http", domain: this.domain(options), domain_prefix: "", path: this.word(), extensions: []});

		        var extension = options.extensions.length > 0 ? "." + this.pick(options.extensions) : "";
		        var domain = options.domain_prefix ? options.domain_prefix + "." + options.domain : options.domain;

		        return options.protocol + "://" + domain + "/" + options.path + extension;
		    };

		    Chance.prototype.port = function() {
		        return this.integer({min: 0, max: 65535});
		    };

		    Chance.prototype.locale = function (options) {
		        options = initOptions(options);
		        if (options.region){
		          return this.pick(this.get("locale_regions"));
		        } else {
		          return this.pick(this.get("locale_languages"));
		        }
		    };

		    Chance.prototype.locales = function (options) {
		      options = initOptions(options);
		      if (options.region){
		        return this.get("locale_regions");
		      } else {
		        return this.get("locale_languages");
		      }
		    };

		    Chance.prototype.loremPicsum = function (options) {
		        options = initOptions(options, { width: 500, height: 500, greyscale: false, blurred: false });

		        var greyscale = options.greyscale ? 'g/' : '';
		        var query = options.blurred ? '/?blur' : '/?random';

		        return 'https://picsum.photos/' + greyscale + options.width + '/' + options.height + query;
		    };

		    // -- End Web --

		    // -- Location --

		    Chance.prototype.address = function (options) {
		        options = initOptions(options);
		        return this.natural({min: 5, max: 2000}) + ' ' + this.street(options);
		    };

		    Chance.prototype.altitude = function (options) {
		        options = initOptions(options, {fixed: 5, min: 0, max: 8848});
		        return this.floating({
		            min: options.min,
		            max: options.max,
		            fixed: options.fixed
		        });
		    };

		    Chance.prototype.areacode = function (options) {
		        options = initOptions(options, {parens : true});
		        // Don't want area codes to start with 1, or have a 9 as the second digit
		        var areacode = options.exampleNumber ?
		        "555" :
		        this.natural({min: 2, max: 9}).toString() +
		                this.natural({min: 0, max: 8}).toString() +
		                this.natural({min: 0, max: 9}).toString();

		        return options.parens ? '(' + areacode + ')' : areacode;
		    };

		    Chance.prototype.city = function () {
		        return this.capitalize(this.word({syllables: 3}));
		    };

		    Chance.prototype.coordinates = function (options) {
		        return this.latitude(options) + ', ' + this.longitude(options);
		    };

		    Chance.prototype.countries = function () {
		        return this.get("countries");
		    };

		    Chance.prototype.country = function (options) {
		        options = initOptions(options);
		        var country = this.pick(this.countries());
		        return options.raw ? country : options.full ? country.name : country.abbreviation;
		    };

		    Chance.prototype.depth = function (options) {
		        options = initOptions(options, {fixed: 5, min: -10994, max: 0});
		        return this.floating({
		            min: options.min,
		            max: options.max,
		            fixed: options.fixed
		        });
		    };

		    Chance.prototype.geohash = function (options) {
		        options = initOptions(options, { length: 7 });
		        return this.string({ length: options.length, pool: '0123456789bcdefghjkmnpqrstuvwxyz' });
		    };

		    Chance.prototype.geojson = function (options) {
		        return this.latitude(options) + ', ' + this.longitude(options) + ', ' + this.altitude(options);
		    };

		    Chance.prototype.latitude = function (options) {
		        // Constants - Formats
		        var [DDM, DMS, DD] = ['ddm', 'dms', 'dd'];

		        options = initOptions(
		options,
		            options && options.format && [DDM, DMS].includes(options.format.toLowerCase()) ?
		            {min: 0, max: 89, fixed: 4} :
		            {fixed: 5, min: -90, max: 90, format: DD}
		);

		        var format = options.format.toLowerCase();

		        if (format === DDM || format === DMS) {
		            testRange(options.min < 0 || options.min > 89, "Chance: Min specified is out of range. Should be between 0 - 89");
		            testRange(options.max < 0 || options.max > 89, "Chance: Max specified is out of range. Should be between 0 - 89");
		            testRange(options.fixed > 4, 'Chance: Fixed specified should be below or equal to 4');
		        }

		        switch (format) {
		            case DDM: {
		                return  this.integer({min: options.min, max: options.max}) + '°' +
		                        this.floating({min: 0, max: 59, fixed: options.fixed});
		            }
		            case DMS: {
		                return  this.integer({min: options.min, max: options.max}) + '°' +
		                        this.integer({min: 0, max: 59}) + '’' +
		                        this.floating({min: 0, max: 59, fixed: options.fixed}) + '”';
		            }
		            case DD:
		            default: {
		                return this.floating({min: options.min, max: options.max, fixed: options.fixed});
		            }
		        }
		    };

		    Chance.prototype.longitude = function (options) {
		        // Constants - Formats
		        var [DDM, DMS, DD] = ['ddm', 'dms', 'dd'];

		        options = initOptions(
		options,
		            options && options.format && [DDM, DMS].includes(options.format.toLowerCase()) ?
		            {min: 0, max: 179, fixed: 4} :
		            {fixed: 5, min: -180, max: 180, format: DD}
		);

		        var format = options.format.toLowerCase();

		        if (format === DDM || format === DMS) {
		            testRange(options.min < 0 || options.min > 179, "Chance: Min specified is out of range. Should be between 0 - 179");
		            testRange(options.max < 0 || options.max > 179, "Chance: Max specified is out of range. Should be between 0 - 179");
		            testRange(options.fixed > 4, 'Chance: Fixed specified should be below or equal to 4');
		        }

		        switch (format) {
		            case DDM: {
		                return  this.integer({min: options.min, max: options.max}) + '°' +
		                        this.floating({min: 0, max: 59.9999, fixed: options.fixed})
		            }
		            case DMS: {
		                return  this.integer({min: options.min, max: options.max}) + '°' +
		                        this.integer({min: 0, max: 59}) + '’' +
		                        this.floating({min: 0, max: 59.9999, fixed: options.fixed}) + '”';
		            }
		            case DD:
		            default: {
		                return this.floating({min: options.min, max: options.max, fixed: options.fixed});
		            }
		        }
		    };

		    Chance.prototype.phone = function (options) {
		        var self = this,
		            numPick,
		            ukNum = function (parts) {
		                var section = [];
		                //fills the section part of the phone number with random numbers.
		                parts.sections.forEach(function(n) {
		                    section.push(self.string({ pool: '0123456789', length: n}));
		                });
		                return parts.area + section.join(' ');
		            };
		        options = initOptions(options, {
		            formatted: true,
		            country: 'us',
		            mobile: false,
		            exampleNumber: false,
		        });
		        if (!options.formatted) {
		            options.parens = false;
		        }
		        var phone;
		        switch (options.country) {
		            case 'fr':
		                if (!options.mobile) {
		                    numPick = this.pick([
		                        // Valid zone and département codes.
		                        '01' + this.pick(['30', '34', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '53', '55', '56', '58', '60', '64', '69', '70', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83']) + self.string({ pool: '0123456789', length: 6}),
		                        '02' + this.pick(['14', '18', '22', '23', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '40', '41', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '56', '57', '61', '62', '69', '72', '76', '77', '78', '85', '90', '96', '97', '98', '99']) + self.string({ pool: '0123456789', length: 6}),
		                        '03' + this.pick(['10', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '39', '44', '45', '51', '52', '54', '55', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90']) + self.string({ pool: '0123456789', length: 6}),
		                        '04' + this.pick(['11', '13', '15', '20', '22', '26', '27', '30', '32', '34', '37', '42', '43', '44', '50', '56', '57', '63', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '88', '89', '90', '91', '92', '93', '94', '95', '97', '98']) + self.string({ pool: '0123456789', length: 6}),
		                        '05' + this.pick(['08', '16', '17', '19', '24', '31', '32', '33', '34', '35', '40', '45', '46', '47', '49', '53', '55', '56', '57', '58', '59', '61', '62', '63', '64', '65', '67', '79', '81', '82', '86', '87', '90', '94']) + self.string({ pool: '0123456789', length: 6}),
		                        '09' + self.string({ pool: '0123456789', length: 8}),
		                    ]);
		                    phone = options.formatted ? numPick.match(/../g).join(' ') : numPick;
		                } else {
		                    numPick = this.pick(['06', '07']) + self.string({ pool: '0123456789', length: 8});
		                    phone = options.formatted ? numPick.match(/../g).join(' ') : numPick;
		                }
		                break;
		            case 'uk':
		                if (!options.mobile) {
		                    numPick = this.pick([
		                        //valid area codes of major cities/counties followed by random numbers in required format.

		                        { area: '01' + this.character({ pool: '234569' }) + '1 ', sections: [3,4] },
		                        { area: '020 ' + this.character({ pool: '378' }), sections: [3,4] },
		                        { area: '023 ' + this.character({ pool: '89' }), sections: [3,4] },
		                        { area: '024 7', sections: [3,4] },
		                        { area: '028 ' + this.pick(['25','28','37','71','82','90','92','95']), sections: [2,4] },
		                        { area: '012' + this.pick(['04','08','54','76','97','98']) + ' ', sections: [6] },
		                        { area: '013' + this.pick(['63','64','84','86']) + ' ', sections: [6] },
		                        { area: '014' + this.pick(['04','20','60','61','80','88']) + ' ', sections: [6] },
		                        { area: '015' + this.pick(['24','27','62','66']) + ' ', sections: [6] },
		                        { area: '016' + this.pick(['06','29','35','47','59','95']) + ' ', sections: [6] },
		                        { area: '017' + this.pick(['26','44','50','68']) + ' ', sections: [6] },
		                        { area: '018' + this.pick(['27','37','84','97']) + ' ', sections: [6] },
		                        { area: '019' + this.pick(['00','05','35','46','49','63','95']) + ' ', sections: [6] }
		                    ]);
		                    phone = options.formatted ? ukNum(numPick) : ukNum(numPick).replace(' ', '', 'g');
		                } else {
		                    numPick = this.pick([
		                        { area: '07' + this.pick(['4','5','7','8','9']), sections: [2,6] },
		                        { area: '07624 ', sections: [6] }
		                    ]);
		                    phone = options.formatted ? ukNum(numPick) : ukNum(numPick).replace(' ', '');
		                }
		                break;
		            case 'za':
		                if (!options.mobile) {
		                    numPick = this.pick([
		                       '01' + this.pick(['0', '1', '2', '3', '4', '5', '6', '7', '8']) + self.string({ pool: '0123456789', length: 7}),
		                       '02' + this.pick(['1', '2', '3', '4', '7', '8']) + self.string({ pool: '0123456789', length: 7}),
		                       '03' + this.pick(['1', '2', '3', '5', '6', '9']) + self.string({ pool: '0123456789', length: 7}),
		                       '04' + this.pick(['1', '2', '3', '4', '5','6','7', '8','9']) + self.string({ pool: '0123456789', length: 7}),
		                       '05' + this.pick(['1', '3', '4', '6', '7', '8']) + self.string({ pool: '0123456789', length: 7}),
		                    ]);
		                    phone = options.formatted || numPick;
		                } else {
		                    numPick = this.pick([
		                        '060' + this.pick(['3','4','5','6','7','8','9']) + self.string({ pool: '0123456789', length: 6}),
		                        '061' + this.pick(['0','1','2','3','4','5','8']) + self.string({ pool: '0123456789', length: 6}),
		                        '06'  + self.string({ pool: '0123456789', length: 7}),
		                        '071' + this.pick(['0','1','2','3','4','5','6','7','8','9']) + self.string({ pool: '0123456789', length: 6}),
		                        '07'  + this.pick(['2','3','4','6','7','8','9']) + self.string({ pool: '0123456789', length: 7}),
		                        '08'  + this.pick(['0','1','2','3','4','5']) + self.string({ pool: '0123456789', length: 7}),
		                    ]);
		                    phone = options.formatted || numPick;
		                }
		                break;
		            case 'us':
		                var areacode = this.areacode(options).toString();
		                var exchange = this.natural({ min: 2, max: 9 }).toString() +
		                    this.natural({ min: 0, max: 9 }).toString() +
		                    this.natural({ min: 0, max: 9 }).toString();
		                var subscriber = this.natural({ min: 1000, max: 9999 }).toString(); // this could be random [0-9]{4}
		                phone = options.formatted ? areacode + ' ' + exchange + '-' + subscriber : areacode + exchange + subscriber;
		                break;
		            case 'br':
		                var areaCode = this.pick(["11", "12", "13", "14", "15", "16", "17", "18", "19", "21", "22", "24", "27", "28", "31", "32", "33", "34", "35", "37", "38", "41", "42", "43", "44", "45", "46", "47", "48", "49", "51", "53", "54", "55", "61", "62", "63", "64", "65", "66", "67", "68", "69", "71", "73", "74", "75", "77", "79", "81", "82", "83", "84", "85", "86", "87", "88", "89", "91", "92", "93", "94", "95", "96", "97", "98", "99"]);
		                var prefix;
		                if (options.mobile) {
		                    // Brasilian official reference (mobile): http://www.anatel.gov.br/setorregulado/plano-de-numeracao-brasileiro?id=330
		                    prefix = '9' + self.string({ pool: '0123456789', length: 4});
		                } else {
		                    // Brasilian official reference: http://www.anatel.gov.br/setorregulado/plano-de-numeracao-brasileiro?id=331
		                    prefix = this.natural({ min: 2000, max: 5999 }).toString();
		                }
		                var mcdu = self.string({ pool: '0123456789', length: 4});
		                phone = options.formatted ? '(' + areaCode + ') ' + prefix + '-' + mcdu : areaCode + prefix + mcdu;
		                break;
		        }
		        return phone;
		    };

		    Chance.prototype.postal = function () {
		        // Postal District
		        var pd = this.character({pool: "XVTSRPNKLMHJGECBA"});
		        // Forward Sortation Area (FSA)
		        var fsa = pd + this.natural({max: 9}) + this.character({alpha: true, casing: "upper"});
		        // Local Delivery Unut (LDU)
		        var ldu = this.natural({max: 9}) + this.character({alpha: true, casing: "upper"}) + this.natural({max: 9});

		        return fsa + " " + ldu;
		    };

		    Chance.prototype.postcode = function () {
		        // Area
		        var area = this.pick(this.get("postcodeAreas")).code;
		        // District
		        var district = this.natural({max: 9});
		        // Sub-District
		        var subDistrict = this.bool() ? this.character({alpha: true, casing: "upper"}) : "";
		        // Outward Code
		        var outward = area + district + subDistrict;
		        // Sector
		        var sector = this.natural({max: 9});
		        // Unit
		        var unit = this.character({alpha: true, casing: "upper"}) + this.character({alpha: true, casing: "upper"});
		        // Inward Code
		        var inward = sector + unit;

		        return outward + " " + inward;
		    };

		    Chance.prototype.counties = function (options) {
		        options = initOptions(options, { country: 'uk' });
		        return this.get("counties")[options.country.toLowerCase()];
		    };

		    Chance.prototype.county = function (options) {
		        return this.pick(this.counties(options)).name;
		    };

		    Chance.prototype.provinces = function (options) {
		        options = initOptions(options, { country: 'ca' });
		        return this.get("provinces")[options.country.toLowerCase()];
		    };

		    Chance.prototype.province = function (options) {
		        return (options && options.full) ?
		            this.pick(this.provinces(options)).name :
		            this.pick(this.provinces(options)).abbreviation;
		    };

		    Chance.prototype.state = function (options) {
		        return (options && options.full) ?
		            this.pick(this.states(options)).name :
		            this.pick(this.states(options)).abbreviation;
		    };

		    Chance.prototype.states = function (options) {
		        options = initOptions(options, { country: 'us', us_states_and_dc: true } );

		        var states;

		        switch (options.country.toLowerCase()) {
		            case 'us':
		                var us_states_and_dc = this.get("us_states_and_dc"),
		                    territories = this.get("territories"),
		                    armed_forces = this.get("armed_forces");

		                states = [];

		                if (options.us_states_and_dc) {
		                    states = states.concat(us_states_and_dc);
		                }
		                if (options.territories) {
		                    states = states.concat(territories);
		                }
		                if (options.armed_forces) {
		                    states = states.concat(armed_forces);
		                }
		                break;
		            case 'it':
		            case 'mx':
		                states = this.get("country_regions")[options.country.toLowerCase()];
		                break;
		            case 'uk':
		                states = this.get("counties")[options.country.toLowerCase()];
		                break;
		        }

		        return states;
		    };

		    Chance.prototype.street = function (options) {
		        options = initOptions(options, { country: 'us', syllables: 2 });
		        var     street;

		        switch (options.country.toLowerCase()) {
		            case 'us':
		                street = this.word({ syllables: options.syllables });
		                street = this.capitalize(street);
		                street += ' ';
		                street += options.short_suffix ?
		                    this.street_suffix(options).abbreviation :
		                    this.street_suffix(options).name;
		                break;
		            case 'it':
		                street = this.word({ syllables: options.syllables });
		                street = this.capitalize(street);
		                street = (options.short_suffix ?
		                    this.street_suffix(options).abbreviation :
		                    this.street_suffix(options).name) + " " + street;
		                break;
		        }
		        return street;
		    };

		    Chance.prototype.street_suffix = function (options) {
		        options = initOptions(options, { country: 'us' });
		        return this.pick(this.street_suffixes(options));
		    };

		    Chance.prototype.street_suffixes = function (options) {
		        options = initOptions(options, { country: 'us' });
		        // These are the most common suffixes.
		        return this.get("street_suffixes")[options.country.toLowerCase()];
		    };

		    // Note: only returning US zip codes, internationalization will be a whole
		    // other beast to tackle at some point.
		    Chance.prototype.zip = function (options) {
		        var zip = this.n(this.natural, 5, {max: 9});

		        if (options && options.plusfour === true) {
		            zip.push('-');
		            zip = zip.concat(this.n(this.natural, 4, {max: 9}));
		        }

		        return zip.join("");
		    };

		    // -- End Location --

		    // -- Time

		    Chance.prototype.ampm = function () {
		        return this.bool() ? 'am' : 'pm';
		    };

		    Chance.prototype.date = function (options) {
		        var date_string, date;

		        // If interval is specified we ignore preset
		        if(options && (options.min || options.max)) {
		            options = initOptions(options, {
		                american: true,
		                string: false
		            });
		            var min = typeof options.min !== "undefined" ? options.min.getTime() : 1;
		            // 100,000,000 days measured relative to midnight at the beginning of 01 January, 1970 UTC. http://es5.github.io/#x15.9.1.1
		            var max = typeof options.max !== "undefined" ? options.max.getTime() : 8640000000000000;

		            date = new Date(this.integer({min: min, max: max}));
		        } else {
		            var m = this.month({raw: true});
		            var daysInMonth = m.days;

		            if(options && options.month) {
		                // Mod 12 to allow months outside range of 0-11 (not encouraged, but also not prevented).
		                daysInMonth = this.get('months')[((options.month % 12) + 12) % 12].days;
		            }

		            options = initOptions(options, {
		                year: parseInt(this.year(), 10),
		                // Necessary to subtract 1 because Date() 0-indexes month but not day or year
		                // for some reason.
		                month: m.numeric - 1,
		                day: this.natural({min: 1, max: daysInMonth}),
		                hour: this.hour({twentyfour: true}),
		                minute: this.minute(),
		                second: this.second(),
		                millisecond: this.millisecond(),
		                american: true,
		                string: false
		            });

		            date = new Date(options.year, options.month, options.day, options.hour, options.minute, options.second, options.millisecond);
		        }

		        if (options.american) {
		            // Adding 1 to the month is necessary because Date() 0-indexes
		            // months but not day for some odd reason.
		            date_string = (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();
		        } else {
		            date_string = date.getDate() + '/' + (date.getMonth() + 1) + '/' + date.getFullYear();
		        }

		        return options.string ? date_string : date;
		    };

		    Chance.prototype.hammertime = function (options) {
		        return this.date(options).getTime();
		    };

		    Chance.prototype.hour = function (options) {
		        options = initOptions(options, {
		            min: options && options.twentyfour ? 0 : 1,
		            max: options && options.twentyfour ? 23 : 12
		        });

		        testRange(options.min < 0, "Chance: Min cannot be less than 0.");
		        testRange(options.twentyfour && options.max > 23, "Chance: Max cannot be greater than 23 for twentyfour option.");
		        testRange(!options.twentyfour && options.max > 12, "Chance: Max cannot be greater than 12.");
		        testRange(options.min > options.max, "Chance: Min cannot be greater than Max.");

		        return this.natural({min: options.min, max: options.max});
		    };

		    Chance.prototype.millisecond = function () {
		        return this.natural({max: 999});
		    };

		    Chance.prototype.minute = Chance.prototype.second = function (options) {
		        options = initOptions(options, {min: 0, max: 59});

		        testRange(options.min < 0, "Chance: Min cannot be less than 0.");
		        testRange(options.max > 59, "Chance: Max cannot be greater than 59.");
		        testRange(options.min > options.max, "Chance: Min cannot be greater than Max.");

		        return this.natural({min: options.min, max: options.max});
		    };

		    Chance.prototype.month = function (options) {
		        options = initOptions(options, {min: 1, max: 12});

		        testRange(options.min < 1, "Chance: Min cannot be less than 1.");
		        testRange(options.max > 12, "Chance: Max cannot be greater than 12.");
		        testRange(options.min > options.max, "Chance: Min cannot be greater than Max.");

		        var month = this.pick(this.months().slice(options.min - 1, options.max));
		        return options.raw ? month : month.name;
		    };

		    Chance.prototype.months = function () {
		        return this.get("months");
		    };

		    Chance.prototype.second = function () {
		        return this.natural({max: 59});
		    };

		    Chance.prototype.timestamp = function () {
		        return this.natural({min: 1, max: parseInt(new Date().getTime() / 1000, 10)});
		    };

		    Chance.prototype.weekday = function (options) {
		        options = initOptions(options, {weekday_only: false});
		        var weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"];
		        if (!options.weekday_only) {
		            weekdays.push("Saturday");
		            weekdays.push("Sunday");
		        }
		        return this.pickone(weekdays);
		    };

		    Chance.prototype.year = function (options) {
		        // Default to current year as min if none specified
		        options = initOptions(options, {min: new Date().getFullYear()});

		        // Default to one century after current year as max if none specified
		        options.max = (typeof options.max !== "undefined") ? options.max : options.min + 100;

		        return this.natural(options).toString();
		    };

		    // -- End Time

		    // -- Finance --

		    Chance.prototype.cc = function (options) {
		        options = initOptions(options);

		        var type, number, to_generate;

		        type = (options.type) ?
		                    this.cc_type({ name: options.type, raw: true }) :
		                    this.cc_type({ raw: true });

		        number = type.prefix.split("");
		        to_generate = type.length - type.prefix.length - 1;

		        // Generates n - 1 digits
		        number = number.concat(this.n(this.integer, to_generate, {min: 0, max: 9}));

		        // Generates the last digit according to Luhn algorithm
		        number.push(this.luhn_calculate(number.join("")));

		        return number.join("");
		    };

		    Chance.prototype.cc_types = function () {
		        // http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29
		        return this.get("cc_types");
		    };

		    Chance.prototype.cc_type = function (options) {
		        options = initOptions(options);
		        var types = this.cc_types(),
		            type = null;

		        if (options.name) {
		            for (var i = 0; i < types.length; i++) {
		                // Accept either name or short_name to specify card type
		                if (types[i].name === options.name || types[i].short_name === options.name) {
		                    type = types[i];
		                    break;
		                }
		            }
		            if (type === null) {
		                throw new RangeError("Chance: Credit card type '" + options.name + "' is not supported");
		            }
		        } else {
		            type = this.pick(types);
		        }

		        return options.raw ? type : type.name;
		    };

		    // return all world currency by ISO 4217
		    Chance.prototype.currency_types = function () {
		        return this.get("currency_types");
		    };

		    // return random world currency by ISO 4217
		    Chance.prototype.currency = function () {
		        return this.pick(this.currency_types());
		    };

		    // return all timezones available
		    Chance.prototype.timezones = function () {
		        return this.get("timezones");
		    };

		    // return random timezone
		    Chance.prototype.timezone = function () {
		        return this.pick(this.timezones());
		    };

		    //Return random correct currency exchange pair (e.g. EUR/USD) or array of currency code
		    Chance.prototype.currency_pair = function (returnAsString) {
		        var currencies = this.unique(this.currency, 2, {
		            comparator: function(arr, val) {

		                return arr.reduce(function(acc, item) {
		                    // If a match has been found, short circuit check and just return
		                    return acc || (item.code === val.code);
		                }, false);
		            }
		        });

		        if (returnAsString) {
		            return currencies[0].code + '/' + currencies[1].code;
		        } else {
		            return currencies;
		        }
		    };

		    Chance.prototype.dollar = function (options) {
		        // By default, a somewhat more sane max for dollar than all available numbers
		        options = initOptions(options, {max : 10000, min : 0});

		        var dollar = this.floating({min: options.min, max: options.max, fixed: 2}).toString(),
		            cents = dollar.split('.')[1];

		        if (cents === undefined) {
		            dollar += '.00';
		        } else if (cents.length < 2) {
		            dollar = dollar + '0';
		        }

		        if (dollar < 0) {
		            return '-$' + dollar.replace('-', '');
		        } else {
		            return '$' + dollar;
		        }
		    };

		    Chance.prototype.euro = function (options) {
		        return Number(this.dollar(options).replace("$", "")).toLocaleString() + "€";
		    };

		    Chance.prototype.exp = function (options) {
		        options = initOptions(options);
		        var exp = {};

		        exp.year = this.exp_year();

		        // If the year is this year, need to ensure month is greater than the
		        // current month or this expiration will not be valid
		        if (exp.year === (new Date().getFullYear()).toString()) {
		            exp.month = this.exp_month({future: true});
		        } else {
		            exp.month = this.exp_month();
		        }

		        return options.raw ? exp : exp.month + '/' + exp.year;
		    };

		    Chance.prototype.exp_month = function (options) {
		        options = initOptions(options);
		        var month, month_int,
		            // Date object months are 0 indexed
		            curMonth = new Date().getMonth() + 1;

		        if (options.future && (curMonth !== 12)) {
		            do {
		                month = this.month({raw: true}).numeric;
		                month_int = parseInt(month, 10);
		            } while (month_int <= curMonth);
		        } else {
		            month = this.month({raw: true}).numeric;
		        }

		        return month;
		    };

		    Chance.prototype.exp_year = function () {
		        var curMonth = new Date().getMonth() + 1,
		            curYear = new Date().getFullYear();

		        return this.year({min: ((curMonth === 12) ? (curYear + 1) : curYear), max: (curYear + 10)});
		    };

		    Chance.prototype.vat = function (options) {
		        options = initOptions(options, { country: 'it' });
		        switch (options.country.toLowerCase()) {
		            case 'it':
		                return this.it_vat();
		        }
		    };

		    /**
		     * Generate a string matching IBAN pattern (https://en.wikipedia.org/wiki/International_Bank_Account_Number).
		     * No country-specific formats support (yet)
		     */
		    Chance.prototype.iban = function () {
		        var alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
		        var alphanum = alpha + '0123456789';
		        var iban =
		            this.string({ length: 2, pool: alpha }) +
		            this.pad(this.integer({ min: 0, max: 99 }), 2) +
		            this.string({ length: 4, pool: alphanum }) +
		            this.pad(this.natural(), this.natural({ min: 6, max: 26 }));
		        return iban;
		    };

		    // -- End Finance

		    // -- Regional

		    Chance.prototype.it_vat = function () {
		        var it_vat = this.natural({min: 1, max: 1800000});

		        it_vat = this.pad(it_vat, 7) + this.pad(this.pick(this.provinces({ country: 'it' })).code, 3);
		        return it_vat + this.luhn_calculate(it_vat);
		    };

		    /*
		     * this generator is written following the official algorithm
		     * all data can be passed explicitely or randomized by calling chance.cf() without options
		     * the code does not check that the input data is valid (it goes beyond the scope of the generator)
		     *
		     * @param  [Object] options = { first: first name,
		     *                              last: last name,
		     *                              gender: female|male,
		                                    birthday: JavaScript date object,
		                                    city: string(4), 1 letter + 3 numbers
		                                   }
		     * @return [string] codice fiscale
		     *
		    */
		    Chance.prototype.cf = function (options) {
		        options = options || {};
		        var gender = !!options.gender ? options.gender : this.gender(),
		            first = !!options.first ? options.first : this.first( { gender: gender, nationality: 'it'} ),
		            last = !!options.last ? options.last : this.last( { nationality: 'it'} ),
		            birthday = !!options.birthday ? options.birthday : this.birthday(),
		            city = !!options.city ? options.city : this.pickone(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'L', 'M', 'Z']) + this.pad(this.natural({max:999}), 3),
		            cf = [],
		            name_generator = function(name, isLast) {
		                var temp,
		                    return_value = [];

		                if (name.length < 3) {
		                    return_value = name.split("").concat("XXX".split("")).splice(0,3);
		                }
		                else {
		                    temp = name.toUpperCase().split('').map(function(c){
		                        return ("BCDFGHJKLMNPRSTVWZ".indexOf(c) !== -1) ? c : undefined;
		                    }).join('');
		                    if (temp.length > 3) {
		                        if (isLast) {
		                            temp = temp.substr(0,3);
		                        } else {
		                            temp = temp[0] + temp.substr(2,2);
		                        }
		                    }
		                    if (temp.length < 3) {
		                        return_value = temp;
		                        temp = name.toUpperCase().split('').map(function(c){
		                            return ("AEIOU".indexOf(c) !== -1) ? c : undefined;
		                        }).join('').substr(0, 3 - return_value.length);
		                    }
		                    return_value = return_value + temp;
		                }

		                return return_value;
		            },
		            date_generator = function(birthday, gender, that) {
		                var lettermonths = ['A', 'B', 'C', 'D', 'E', 'H', 'L', 'M', 'P', 'R', 'S', 'T'];

		                return  birthday.getFullYear().toString().substr(2) +
		                        lettermonths[birthday.getMonth()] +
		                        that.pad(birthday.getDate() + ((gender.toLowerCase() === "female") ? 40 : 0), 2);
		            },
		            checkdigit_generator = function(cf) {
		                var range1 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
		                    range2 = "ABCDEFGHIJABCDEFGHIJKLMNOPQRSTUVWXYZ",
		                    evens  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
		                    odds   = "BAKPLCQDREVOSFTGUHMINJWZYX",
		                    digit  = 0;


		                for(var i = 0; i < 15; i++) {
		                    if (i % 2 !== 0) {
		                        digit += evens.indexOf(range2[range1.indexOf(cf[i])]);
		                    }
		                    else {
		                        digit +=  odds.indexOf(range2[range1.indexOf(cf[i])]);
		                    }
		                }
		                return evens[digit % 26];
		            };

		        cf = cf.concat(name_generator(last, true), name_generator(first), date_generator(birthday, gender, this), city.toUpperCase().split("")).join("");
		        cf += checkdigit_generator(cf.toUpperCase());

		        return cf.toUpperCase();
		    };

		    Chance.prototype.pl_pesel = function () {
		        var number = this.natural({min: 1, max: 9999999999});
		        var arr = this.pad(number, 10).split('');
		        for (var i = 0; i < arr.length; i++) {
		            arr[i] = parseInt(arr[i]);
		        }

		        var controlNumber = (1 * arr[0] + 3 * arr[1] + 7 * arr[2] + 9 * arr[3] + 1 * arr[4] + 3 * arr[5] + 7 * arr[6] + 9 * arr[7] + 1 * arr[8] + 3 * arr[9]) % 10;
		        if(controlNumber !== 0) {
		            controlNumber = 10 - controlNumber;
		        }

		        return arr.join('') + controlNumber;
		    };

		    Chance.prototype.pl_nip = function () {
		        var number = this.natural({min: 1, max: 999999999});
		        var arr = this.pad(number, 9).split('');
		        for (var i = 0; i < arr.length; i++) {
		            arr[i] = parseInt(arr[i]);
		        }

		        var controlNumber = (6 * arr[0] + 5 * arr[1] + 7 * arr[2] + 2 * arr[3] + 3 * arr[4] + 4 * arr[5] + 5 * arr[6] + 6 * arr[7] + 7 * arr[8]) % 11;
		        if(controlNumber === 10) {
		            return this.pl_nip();
		        }

		        return arr.join('') + controlNumber;
		    };

		    Chance.prototype.pl_regon = function () {
		        var number = this.natural({min: 1, max: 99999999});
		        var arr = this.pad(number, 8).split('');
		        for (var i = 0; i < arr.length; i++) {
		            arr[i] = parseInt(arr[i]);
		        }

		        var controlNumber = (8 * arr[0] + 9 * arr[1] + 2 * arr[2] + 3 * arr[3] + 4 * arr[4] + 5 * arr[5] + 6 * arr[6] + 7 * arr[7]) % 11;
		        if(controlNumber === 10) {
		            controlNumber = 0;
		        }

		        return arr.join('') + controlNumber;
		    };

		    // -- End Regional

		    // -- Music --

		    // Genre choices:
		    // Rock,Pop,Hip-Hop,Jazz,Classical,Electronic,Country,R&B,Reggae,
		    // Blues,Metal,Folk,Alternative,Punk,Disco,Funk,Techno,
		    // Indie,Gospel,Dance,Children's,World

		    Chance.prototype.music_genre = function (genre = 'general') {
		        if (!(genre.toLowerCase() in data.music_genres)) {
		            throw new Error(`Unsupported genre: ${genre}`);
		        }

		        const genres = data.music_genres[genre.toLowerCase()];
		        const randomIndex = this.integer({ min: 0, max: genres.length - 1 });

		        return genres[randomIndex];
		    };

		    Chance.prototype.note = function(options) {
		      // choices for 'notes' option:
		      // flatKey - chromatic scale with flat notes (default)
		      // sharpKey - chromatic scale with sharp notes
		      // flats - just flat notes
		      // sharps - just sharp notes
		      // naturals - just natural notes
		      // all - naturals, sharps and flats
		      options = initOptions(options, { notes : 'flatKey'});
		      var scales = {
		        naturals: ['C', 'D', 'E', 'F', 'G', 'A', 'B'],
		        flats: ['D♭', 'E♭', 'G♭', 'A♭', 'B♭'],
		        sharps: ['C♯', 'D♯', 'F♯', 'G♯', 'A♯']
		      };
		      scales.all = scales.naturals.concat(scales.flats.concat(scales.sharps));
		      scales.flatKey = scales.naturals.concat(scales.flats);
		      scales.sharpKey = scales.naturals.concat(scales.sharps);
		      return this.pickone(scales[options.notes]);
		    };

		    Chance.prototype.midi_note = function(options) {
		      var min = 0;
		      var max = 127;
		      options = initOptions(options, { min : min, max : max });
		      return this.integer({min: options.min, max: options.max});
		    };

		    Chance.prototype.chord_quality = function(options) {
		      options = initOptions(options, { jazz: true });
		      var chord_qualities = ['maj', 'min', 'aug', 'dim'];
		      if (options.jazz){
		        chord_qualities = [
		          'maj7',
		          'min7',
		          '7',
		          'sus',
		          'dim',
		          'ø'
		        ];
		      }
		      return this.pickone(chord_qualities);
		    };

		    Chance.prototype.chord = function (options) {
		      options = initOptions(options);
		      return this.note(options) + this.chord_quality(options);
		    };

		    Chance.prototype.tempo = function (options) {
		      var min = 40;
		      var max = 320;
		      options = initOptions(options, {min: min, max: max});
		      return this.integer({min: options.min, max: options.max});
		    };

		    // -- End Music

		    // -- Miscellaneous --

		    // Coin - Flip, flip, flipadelphia
		    Chance.prototype.coin = function() {
		      return this.bool() ? "heads" : "tails";
		    };

		    // Dice - For all the board game geeks out there, myself included ;)
		    function diceFn (range) {
		        return function () {
		            return this.natural(range);
		        };
		    }
		    Chance.prototype.d4 = diceFn({min: 1, max: 4});
		    Chance.prototype.d6 = diceFn({min: 1, max: 6});
		    Chance.prototype.d8 = diceFn({min: 1, max: 8});
		    Chance.prototype.d10 = diceFn({min: 1, max: 10});
		    Chance.prototype.d12 = diceFn({min: 1, max: 12});
		    Chance.prototype.d20 = diceFn({min: 1, max: 20});
		    Chance.prototype.d30 = diceFn({min: 1, max: 30});
		    Chance.prototype.d100 = diceFn({min: 1, max: 100});

		    Chance.prototype.rpg = function (thrown, options) {
		        options = initOptions(options);
		        if (!thrown) {
		            throw new RangeError("Chance: A type of die roll must be included");
		        } else {
		            var bits = thrown.toLowerCase().split("d"),
		                rolls = [];

		            if (bits.length !== 2 || !parseInt(bits[0], 10) || !parseInt(bits[1], 10)) {
		                throw new Error("Chance: Invalid format provided. Please provide #d# where the first # is the number of dice to roll, the second # is the max of each die");
		            }
		            for (var i = bits[0]; i > 0; i--) {
		                rolls[i - 1] = this.natural({min: 1, max: bits[1]});
		            }
		            return (typeof options.sum !== 'undefined' && options.sum) ? rolls.reduce(function (p, c) { return p + c; }) : rolls;
		        }
		    };

		    // Guid
		    Chance.prototype.guid = function (options) {
		        options = initOptions(options, { version: 5 });

		        var guid_pool = "abcdef1234567890",
		            variant_pool = "ab89",
		            guid = this.string({ pool: guid_pool, length: 8 }) + '-' +
		                   this.string({ pool: guid_pool, length: 4 }) + '-' +
		                   // The Version
		                   options.version +
		                   this.string({ pool: guid_pool, length: 3 }) + '-' +
		                   // The Variant
		                   this.string({ pool: variant_pool, length: 1 }) +
		                   this.string({ pool: guid_pool, length: 3 }) + '-' +
		                   this.string({ pool: guid_pool, length: 12 });
		        return guid;
		    };

		    // Hash
		    Chance.prototype.hash = function (options) {
		        options = initOptions(options, {length : 40, casing: 'lower'});
		        var pool = options.casing === 'upper' ? HEX_POOL.toUpperCase() : HEX_POOL;
		        return this.string({pool: pool, length: options.length});
		    };

		    Chance.prototype.luhn_check = function (num) {
		        var str = num.toString();
		        var checkDigit = +str.substring(str.length - 1);
		        return checkDigit === this.luhn_calculate(+str.substring(0, str.length - 1));
		    };

		    Chance.prototype.luhn_calculate = function (num) {
		        var digits = num.toString().split("").reverse();
		        var sum = 0;
		        var digit;

		        for (var i = 0, l = digits.length; l > i; ++i) {
		            digit = +digits[i];
		            if (i % 2 === 0) {
		                digit *= 2;
		                if (digit > 9) {
		                    digit -= 9;
		                }
		            }
		            sum += digit;
		        }
		        return (sum * 9) % 10;
		    };

		    // MD5 Hash
		    Chance.prototype.md5 = function(options) {
		        var opts = { str: '', key: null, raw: false };

		        if (!options) {
		            opts.str = this.string();
		            options = {};
		        }
		        else if (typeof options === 'string') {
		            opts.str = options;
		            options = {};
		        }
		        else if (typeof options !== 'object') {
		            return null;
		        }
		        else if(options.constructor === 'Array') {
		            return null;
		        }

		        opts = initOptions(options, opts);

		        if(!opts.str){
		            throw new Error('A parameter is required to return an md5 hash.');
		        }

		        return this.bimd5.md5(opts.str, opts.key, opts.raw);
		    };

		    /**
		     * #Description:
		     * =====================================================
		     * Generate random file name with extension
		     *
		     * The argument provide extension type
		     * -> raster
		     * -> vector
		     * -> 3d
		     * -> document
		     *
		     * If nothing is provided the function return random file name with random
		     * extension type of any kind
		     *
		     * The user can validate the file name length range
		     * If nothing provided the generated file name is random
		     *
		     * #Extension Pool :
		     * * Currently the supported extensions are
		     *  -> some of the most popular raster image extensions
		     *  -> some of the most popular vector image extensions
		     *  -> some of the most popular 3d image extensions
		     *  -> some of the most popular document extensions
		     *
		     * #Examples :
		     * =====================================================
		     *
		     * Return random file name with random extension. The file extension
		     * is provided by a predefined collection of extensions. More about the extension
		     * pool can be found in #Extension Pool section
		     *
		     * chance.file()
		     * => dsfsdhjf.xml
		     *
		     * In order to generate a file name with specific length, specify the
		     * length property and integer value. The extension is going to be random
		     *
		     * chance.file({length : 10})
		     * => asrtineqos.pdf
		     *
		     * In order to generate file with extension from some of the predefined groups
		     * of the extension pool just specify the extension pool category in fileType property
		     *
		     * chance.file({fileType : 'raster'})
		     * => dshgssds.psd
		     *
		     * You can provide specific extension for your files
		     * chance.file({extension : 'html'})
		     * => djfsd.html
		     *
		     * Or you could pass custom collection of extensions by array or by object
		     * chance.file({extensions : [...]})
		     * => dhgsdsd.psd
		     *
		     * chance.file({extensions : { key : [...], key : [...]}})
		     * => djsfksdjsd.xml
		     *
		     * @param  [collection] options
		     * @return [string]
		     *
		     */
		    Chance.prototype.file = function(options) {

		        var fileOptions = options || {};
		        var poolCollectionKey = "fileExtension";
		        var typeRange   = Object.keys(this.get("fileExtension"));//['raster', 'vector', '3d', 'document'];
		        var fileName;
		        var fileExtension;

		        // Generate random file name
		        fileName = this.word({length : fileOptions.length});

		        // Generate file by specific extension provided by the user
		        if(fileOptions.extension) {

		            fileExtension = fileOptions.extension;
		            return (fileName + '.' + fileExtension);
		        }

		        // Generate file by specific extension collection
		        if(fileOptions.extensions) {

		            if(Array.isArray(fileOptions.extensions)) {

		                fileExtension = this.pickone(fileOptions.extensions);
		                return (fileName + '.' + fileExtension);
		            }
		            else if(fileOptions.extensions.constructor === Object) {

		                var extensionObjectCollection = fileOptions.extensions;
		                var keys = Object.keys(extensionObjectCollection);

		                fileExtension = this.pickone(extensionObjectCollection[this.pickone(keys)]);
		                return (fileName + '.' + fileExtension);
		            }

		            throw new Error("Chance: Extensions must be an Array or Object");
		        }

		        // Generate file extension based on specific file type
		        if(fileOptions.fileType) {

		            var fileType = fileOptions.fileType;
		            if(typeRange.indexOf(fileType) !== -1) {

		                fileExtension = this.pickone(this.get(poolCollectionKey)[fileType]);
		                return (fileName + '.' + fileExtension);
		            }

		            throw new RangeError("Chance: Expect file type value to be 'raster', 'vector', '3d' or 'document'");
		        }

		        // Generate random file name if no extension options are passed
		        fileExtension = this.pickone(this.get(poolCollectionKey)[this.pickone(typeRange)]);
		        return (fileName + '.' + fileExtension);
		    };

		    /**
		     * Generates file data of random bytes using the chance.file method for the file name
		     *
		     * @param {object}
		     * fileName: String
		     * fileExtention: String
		     * fileSize: Number      <- in bytes
		     * @returns {object} fileName: String, fileData: Buffer
		     */
		    Chance.prototype.fileWithContent = function (options){
		            var fileOptions = options || {};
		            var fileName = 'fileName' in fileOptions ? fileOptions.fileName : this.file().split(".")[0];
		            fileName += "." + ('fileExtension' in fileOptions ? fileOptions.fileExtension : this.file().split(".")[1]);


		            if (typeof fileOptions.fileSize !== "number") {
		                throw new Error('File size must be an integer')
		            }
		            var file = {
		              fileData: this.buffer({length: fileOptions.fileSize}),
		              fileName: fileName,
		            };
		        return file;
		   };

		    var data = {

		        firstNames: {
		            "male": {
		                "en": ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Charles", "Thomas", "Christopher", "Daniel", "Matthew", "George", "Donald", "Anthony", "Paul", "Mark", "Edward", "Steven", "Kenneth", "Andrew", "Brian", "Joshua", "Kevin", "Ronald", "Timothy", "Jason", "Jeffrey", "Frank", "Gary", "Ryan", "Nicholas", "Eric", "Stephen", "Jacob", "Larry", "Jonathan", "Scott", "Raymond", "Justin", "Brandon", "Gregory", "Samuel", "Benjamin", "Patrick", "Jack", "Henry", "Walter", "Dennis", "Jerry", "Alexander", "Peter", "Tyler", "Douglas", "Harold", "Aaron", "Jose", "Adam", "Arthur", "Zachary", "Carl", "Nathan", "Albert", "Kyle", "Lawrence", "Joe", "Willie", "Gerald", "Roger", "Keith", "Jeremy", "Terry", "Harry", "Ralph", "Sean", "Jesse", "Roy", "Louis", "Billy", "Austin", "Bruce", "Eugene", "Christian", "Bryan", "Wayne", "Russell", "Howard", "Fred", "Ethan", "Jordan", "Philip", "Alan", "Juan", "Randy", "Vincent", "Bobby", "Dylan", "Johnny", "Phillip", "Victor", "Clarence", "Ernest", "Martin", "Craig", "Stanley", "Shawn", "Travis", "Bradley", "Leonard", "Earl", "Gabriel", "Jimmy", "Francis", "Todd", "Noah", "Danny", "Dale", "Cody", "Carlos", "Allen", "Frederick", "Logan", "Curtis", "Alex", "Joel", "Luis", "Norman", "Marvin", "Glenn", "Tony", "Nathaniel", "Rodney", "Melvin", "Alfred", "Steve", "Cameron", "Chad", "Edwin", "Caleb", "Evan", "Antonio", "Lee", "Herbert", "Jeffery", "Isaac", "Derek", "Ricky", "Marcus", "Theodore", "Elijah", "Luke", "Jesus", "Eddie", "Troy", "Mike", "Dustin", "Ray", "Adrian", "Bernard", "Leroy", "Angel", "Randall", "Wesley", "Ian", "Jared", "Mason", "Hunter", "Calvin", "Oscar", "Clifford", "Jay", "Shane", "Ronnie", "Barry", "Lucas", "Corey", "Manuel", "Leo", "Tommy", "Warren", "Jackson", "Isaiah", "Connor", "Don", "Dean", "Jon", "Julian", "Miguel", "Bill", "Lloyd", "Charlie", "Mitchell", "Leon", "Jerome", "Darrell", "Jeremiah", "Alvin", "Brett", "Seth", "Floyd", "Jim", "Blake", "Micheal", "Gordon", "Trevor", "Lewis", "Erik", "Edgar", "Vernon", "Devin", "Gavin", "Jayden", "Chris", "Clyde", "Tom", "Derrick", "Mario", "Brent", "Marc", "Herman", "Chase", "Dominic", "Ricardo", "Franklin", "Maurice", "Max", "Aiden", "Owen", "Lester", "Gilbert", "Elmer", "Gene", "Francisco", "Glen", "Cory", "Garrett", "Clayton", "Sam", "Jorge", "Chester", "Alejandro", "Jeff", "Harvey", "Milton", "Cole", "Ivan", "Andre", "Duane", "Landon"],
		                // Data taken from http://www.dati.gov.it/dataset/comune-di-firenze_0163
		                "it": ["Adolfo", "Alberto", "Aldo", "Alessandro", "Alessio", "Alfredo", "Alvaro", "Andrea", "Angelo", "Angiolo", "Antonino", "Antonio", "Attilio", "Benito", "Bernardo", "Bruno", "Carlo", "Cesare", "Christian", "Claudio", "Corrado", "Cosimo", "Cristian", "Cristiano", "Daniele", "Dario", "David", "Davide", "Diego", "Dino", "Domenico", "Duccio", "Edoardo", "Elia", "Elio", "Emanuele", "Emiliano", "Emilio", "Enrico", "Enzo", "Ettore", "Fabio", "Fabrizio", "Federico", "Ferdinando", "Fernando", "Filippo", "Francesco", "Franco", "Gabriele", "Giacomo", "Giampaolo", "Giampiero", "Giancarlo", "Gianfranco", "Gianluca", "Gianmarco", "Gianni", "Gino", "Giorgio", "Giovanni", "Giuliano", "Giulio", "Giuseppe", "Graziano", "Gregorio", "Guido", "Iacopo", "Jacopo", "Lapo", "Leonardo", "Lorenzo", "Luca", "Luciano", "Luigi", "Manuel", "Marcello", "Marco", "Marino", "Mario", "Massimiliano", "Massimo", "Matteo", "Mattia", "Maurizio", "Mauro", "Michele", "Mirko", "Mohamed", "Nello", "Neri", "Niccolò", "Nicola", "Osvaldo", "Otello", "Paolo", "Pier Luigi", "Piero", "Pietro", "Raffaele", "Remo", "Renato", "Renzo", "Riccardo", "Roberto", "Rolando", "Romano", "Salvatore", "Samuele", "Sandro", "Sergio", "Silvano", "Simone", "Stefano", "Thomas", "Tommaso", "Ubaldo", "Ugo", "Umberto", "Valerio", "Valter", "Vasco", "Vincenzo", "Vittorio"],
		                // Data taken from http://www.svbkindernamen.nl/int/nl/kindernamen/index.html
		                "nl": ["Aaron","Abel","Adam","Adriaan","Albert","Alexander","Ali","Arjen","Arno","Bart","Bas","Bastiaan","Benjamin","Bob", "Boris","Bram","Brent","Cas","Casper","Chris","Christiaan","Cornelis","Daan","Daley","Damian","Dani","Daniel","Daniël","David","Dean","Dirk","Dylan","Egbert","Elijah","Erik","Erwin","Evert","Ezra","Fabian","Fedde","Finn","Florian","Floris","Frank","Frans","Frederik","Freek","Geert","Gerard","Gerben","Gerrit","Gijs","Guus","Hans","Hendrik","Henk","Herman","Hidde","Hugo","Jaap","Jan Jaap","Jan-Willem","Jack","Jacob","Jan","Jason","Jasper","Jayden","Jelle","Jelte","Jens","Jeroen","Jesse","Jim","Job","Joep","Johannes","John","Jonathan","Joris","Joshua","Joël","Julian","Kees","Kevin","Koen","Lars","Laurens","Leendert","Lennard","Lodewijk","Luc","Luca","Lucas","Lukas","Luuk","Maarten","Marcus","Martijn","Martin","Matthijs","Maurits","Max","Mees","Melle","Mick","Mika","Milan","Mohamed","Mohammed","Morris","Muhammed","Nathan","Nick","Nico","Niek","Niels","Noah","Noud","Olivier","Oscar","Owen","Paul","Pepijn","Peter","Pieter","Pim","Quinten","Reinier","Rens","Robin","Ruben","Sam","Samuel","Sander","Sebastiaan","Sem","Sep","Sepp","Siem","Simon","Stan","Stef","Steven","Stijn","Sven","Teun","Thijmen","Thijs","Thomas","Tijn","Tim","Timo","Tobias","Tom","Victor","Vince","Willem","Wim","Wouter","Yusuf"],
		                // Data taken from https://fr.wikipedia.org/wiki/Liste_de_pr%C3%A9noms_fran%C3%A7ais_et_de_la_francophonie
		                "fr": ["Aaron","Abdon","Abel","Abélard","Abelin","Abondance","Abraham","Absalon","Acace","Achaire","Achille","Adalard","Adalbald","Adalbéron","Adalbert","Adalric","Adam","Adegrin","Adel","Adelin","Andelin","Adelphe","Adam","Adéodat","Adhémar","Adjutor","Adolphe","Adonis","Adon","Adrien","Agapet","Agathange","Agathon","Agilbert","Agénor","Agnan","Aignan","Agrippin","Aimable","Aimé","Alain","Alban","Albin","Aubin","Albéric","Albert","Albertet","Alcibiade","Alcide","Alcée","Alcime","Aldonce","Aldric","Aldéric","Aleaume","Alexandre","Alexis","Alix","Alliaume","Aleaume","Almine","Almire","Aloïs","Alphée","Alphonse","Alpinien","Alverède","Amalric","Amaury","Amandin","Amant","Ambroise","Amédée","Amélien","Amiel","Amour","Anaël","Anastase","Anatole","Ancelin","Andéol","Andoche","André","Andoche","Ange","Angelin","Angilbe","Anglebert","Angoustan","Anicet","Anne","Annibal","Ansbert","Anselme","Anthelme","Antheaume","Anthime","Antide","Antoine","Antonius","Antonin","Apollinaire","Apollon","Aquilin","Arcade","Archambaud","Archambeau","Archange","Archibald","Arian","Ariel","Ariste","Aristide","Armand","Armel","Armin","Arnould","Arnaud","Arolde","Arsène","Arsinoé","Arthaud","Arthème","Arthur","Ascelin","Athanase","Aubry","Audebert","Audouin","Audran","Audric","Auguste","Augustin","Aurèle","Aurélien","Aurian","Auxence","Axel","Aymard","Aymeric","Aymon","Aymond","Balthazar","Baptiste","Barnabé","Barthélemy","Bartimée","Basile","Bastien","Baudouin","Bénigne","Benjamin","Benoît","Bérenger","Bérard","Bernard","Bertrand","Blaise","Bon","Boniface","Bouchard","Brice","Brieuc","Bruno","Brunon","Calixte","Calliste","Camélien","Camille","Camillien","Candide","Caribert","Carloman","Cassandre","Cassien","Cédric","Céleste","Célestin","Célien","Césaire","César","Charles","Charlemagne","Childebert","Chilpéric","Chrétien","Christian","Christodule","Christophe","Chrysostome","Clarence","Claude","Claudien","Cléandre","Clément","Clotaire","Côme","Constance","Constant","Constantin","Corentin","Cyprien","Cyriaque","Cyrille","Cyril","Damien","Daniel","David","Delphin","Denis","Désiré","Didier","Dieudonné","Dimitri","Dominique","Dorian","Dorothée","Edgard","Edmond","Édouard","Éleuthère","Élie","Élisée","Émeric","Émile","Émilien","Emmanuel","Enguerrand","Épiphane","Éric","Esprit","Ernest","Étienne","Eubert","Eudes","Eudoxe","Eugène","Eusèbe","Eustache","Évariste","Évrard","Fabien","Fabrice","Falba","Félicité","Félix","Ferdinand","Fiacre","Fidèle","Firmin","Flavien","Flodoard","Florent","Florentin","Florestan","Florian","Fortuné","Foulques","Francisque","François","Français","Franciscus","Francs","Frédéric","Fulbert","Fulcran","Fulgence","Gabin","Gabriel","Gaël","Garnier","Gaston","Gaspard","Gatien","Gaud","Gautier","Gédéon","Geoffroy","Georges","Géraud","Gérard","Gerbert","Germain","Gervais","Ghislain","Gilbert","Gilles","Girart","Gislebert","Gondebaud","Gonthier","Gontran","Gonzague","Grégoire","Guérin","Gui","Guillaume","Gustave","Guy","Guyot","Hardouin","Hector","Hédelin","Hélier","Henri","Herbert","Herluin","Hervé","Hilaire","Hildebert","Hincmar","Hippolyte","Honoré","Hubert","Hugues","Innocent","Isabeau","Isidore","Jacques","Japhet","Jason","Jean","Jeannel","Jeannot","Jérémie","Jérôme","Joachim","Joanny","Job","Jocelyn","Joël","Johan","Jonas","Jonathan","Joseph","Josse","Josselin","Jourdain","Jude","Judicaël","Jules","Julien","Juste","Justin","Lambert","Landry","Laurent","Lazare","Léandre","Léon","Léonard","Léopold","Leu","Loup","Leufroy","Libère","Liétald","Lionel","Loïc","Longin","Lorrain","Lorraine","Lothaire","Louis","Loup","Luc","Lucas","Lucien","Ludolphe","Ludovic","Macaire","Malo","Mamert","Manassé","Marc","Marceau","Marcel","Marcelin","Marius","Marseille","Martial","Martin","Mathurin","Matthias","Mathias","Matthieu","Maugis","Maurice","Mauricet","Maxence","Maxime","Maximilien","Mayeul","Médéric","Melchior","Mence","Merlin","Mérovée","Michaël","Michel","Moïse","Morgan","Nathan","Nathanaël","Narcisse","Néhémie","Nestor","Nestor","Nicéphore","Nicolas","Noé","Noël","Norbert","Normand","Normands","Octave","Odilon","Odon","Oger","Olivier","Oury","Pacôme","Palémon","Parfait","Pascal","Paterne","Patrice","Paul","Pépin","Perceval","Philémon","Philibert","Philippe","Philothée","Pie","Pierre","Pierrick","Prosper","Quentin","Raoul","Raphaël","Raymond","Régis","Réjean","Rémi","Renaud","René","Reybaud","Richard","Robert","Roch","Rodolphe","Rodrigue","Roger","Roland","Romain","Romuald","Roméo","Rome","Ronan","Roselin","Salomon","Samuel","Savin","Savinien","Scholastique","Sébastien","Séraphin","Serge","Séverin","Sidoine","Sigebert","Sigismond","Silvère","Simon","Siméon","Sixte","Stanislas","Stéphane","Stephan","Sylvain","Sylvestre","Tancrède","Tanguy","Taurin","Théodore","Théodose","Théophile","Théophraste","Thibault","Thibert","Thierry","Thomas","Timoléon","Timothée","Titien","Tonnin","Toussaint","Trajan","Tristan","Turold","Tim","Ulysse","Urbain","Valentin","Valère","Valéry","Venance","Venant","Venceslas","Vianney","Victor","Victorien","Victorin","Vigile","Vincent","Vital","Vitalien","Vivien","Waleran","Wandrille","Xavier","Xénophon","Yves","Zacharie","Zaché","Zéphirin"]
		            },

		            "female": {
		                "en": ["Mary", "Emma", "Elizabeth", "Minnie", "Margaret", "Ida", "Alice", "Bertha", "Sarah", "Annie", "Clara", "Ella", "Florence", "Cora", "Martha", "Laura", "Nellie", "Grace", "Carrie", "Maude", "Mabel", "Bessie", "Jennie", "Gertrude", "Julia", "Hattie", "Edith", "Mattie", "Rose", "Catherine", "Lillian", "Ada", "Lillie", "Helen", "Jessie", "Louise", "Ethel", "Lula", "Myrtle", "Eva", "Frances", "Lena", "Lucy", "Edna", "Maggie", "Pearl", "Daisy", "Fannie", "Josephine", "Dora", "Rosa", "Katherine", "Agnes", "Marie", "Nora", "May", "Mamie", "Blanche", "Stella", "Ellen", "Nancy", "Effie", "Sallie", "Nettie", "Della", "Lizzie", "Flora", "Susie", "Maud", "Mae", "Etta", "Harriet", "Sadie", "Caroline", "Katie", "Lydia", "Elsie", "Kate", "Susan", "Mollie", "Alma", "Addie", "Georgia", "Eliza", "Lulu", "Nannie", "Lottie", "Amanda", "Belle", "Charlotte", "Rebecca", "Ruth", "Viola", "Olive", "Amelia", "Hannah", "Jane", "Virginia", "Emily", "Matilda", "Irene", "Kathryn", "Esther", "Willie", "Henrietta", "Ollie", "Amy", "Rachel", "Sara", "Estella", "Theresa", "Augusta", "Ora", "Pauline", "Josie", "Lola", "Sophia", "Leona", "Anne", "Mildred", "Ann", "Beulah", "Callie", "Lou", "Delia", "Eleanor", "Barbara", "Iva", "Louisa", "Maria", "Mayme", "Evelyn", "Estelle", "Nina", "Betty", "Marion", "Bettie", "Dorothy", "Luella", "Inez", "Lela", "Rosie", "Allie", "Millie", "Janie", "Cornelia", "Victoria", "Ruby", "Winifred", "Alta", "Celia", "Christine", "Beatrice", "Birdie", "Harriett", "Mable", "Myra", "Sophie", "Tillie", "Isabel", "Sylvia", "Carolyn", "Isabelle", "Leila", "Sally", "Ina", "Essie", "Bertie", "Nell", "Alberta", "Katharine", "Lora", "Rena", "Mina", "Rhoda", "Mathilda", "Abbie", "Eula", "Dollie", "Hettie", "Eunice", "Fanny", "Ola", "Lenora", "Adelaide", "Christina", "Lelia", "Nelle", "Sue", "Johanna", "Lilly", "Lucinda", "Minerva", "Lettie", "Roxie", "Cynthia", "Helena", "Hilda", "Hulda", "Bernice", "Genevieve", "Jean", "Cordelia", "Marian", "Francis", "Jeanette", "Adeline", "Gussie", "Leah", "Lois", "Lura", "Mittie", "Hallie", "Isabella", "Olga", "Phoebe", "Teresa", "Hester", "Lida", "Lina", "Winnie", "Claudia", "Marguerite", "Vera", "Cecelia", "Bess", "Emilie", "Rosetta", "Verna", "Myrtie", "Cecilia", "Elva", "Olivia", "Ophelia", "Georgie", "Elnora", "Violet", "Adele", "Lily", "Linnie", "Loretta", "Madge", "Polly", "Virgie", "Eugenia", "Lucile", "Lucille", "Mabelle", "Rosalie"],
		                // Data taken from http://www.dati.gov.it/dataset/comune-di-firenze_0162
		                "it": ["Ada", "Adriana", "Alessandra", "Alessia", "Alice", "Angela", "Anna", "Anna Maria", "Annalisa", "Annita", "Annunziata", "Antonella", "Arianna", "Asia", "Assunta", "Aurora", "Barbara", "Beatrice", "Benedetta", "Bianca", "Bruna", "Camilla", "Carla", "Carlotta", "Carmela", "Carolina", "Caterina", "Catia", "Cecilia", "Chiara", "Cinzia", "Clara", "Claudia", "Costanza", "Cristina", "Daniela", "Debora", "Diletta", "Dina", "Donatella", "Elena", "Eleonora", "Elisa", "Elisabetta", "Emanuela", "Emma", "Eva", "Federica", "Fernanda", "Fiorella", "Fiorenza", "Flora", "Franca", "Francesca", "Gabriella", "Gaia", "Gemma", "Giada", "Gianna", "Gina", "Ginevra", "Giorgia", "Giovanna", "Giulia", "Giuliana", "Giuseppa", "Giuseppina", "Grazia", "Graziella", "Greta", "Ida", "Ilaria", "Ines", "Iolanda", "Irene", "Irma", "Isabella", "Jessica", "Laura", "Lea", "Letizia", "Licia", "Lidia", "Liliana", "Lina", "Linda", "Lisa", "Livia", "Loretta", "Luana", "Lucia", "Luciana", "Lucrezia", "Luisa", "Manuela", "Mara", "Marcella", "Margherita", "Maria", "Maria Cristina", "Maria Grazia", "Maria Luisa", "Maria Pia", "Maria Teresa", "Marina", "Marisa", "Marta", "Martina", "Marzia", "Matilde", "Melissa", "Michela", "Milena", "Mirella", "Monica", "Natalina", "Nella", "Nicoletta", "Noemi", "Olga", "Paola", "Patrizia", "Piera", "Pierina", "Raffaella", "Rebecca", "Renata", "Rina", "Rita", "Roberta", "Rosa", "Rosanna", "Rossana", "Rossella", "Sabrina", "Sandra", "Sara", "Serena", "Silvana", "Silvia", "Simona", "Simonetta", "Sofia", "Sonia", "Stefania", "Susanna", "Teresa", "Tina", "Tiziana", "Tosca", "Valentina", "Valeria", "Vanda", "Vanessa", "Vanna", "Vera", "Veronica", "Vilma", "Viola", "Virginia", "Vittoria"],
		                // Data taken from http://www.svbkindernamen.nl/int/nl/kindernamen/index.html
		                "nl": ["Ada", "Arianne", "Afke", "Amanda", "Amber", "Amy", "Aniek", "Anita", "Anja", "Anna", "Anne", "Annelies", "Annemarie", "Annette", "Anouk", "Astrid", "Aukje", "Barbara", "Bianca", "Carla", "Carlijn", "Carolien", "Chantal", "Charlotte", "Claudia", "Daniëlle", "Debora", "Diane", "Dora", "Eline", "Elise", "Ella", "Ellen", "Emma", "Esmee", "Evelien", "Esther", "Erica", "Eva", "Femke", "Fleur", "Floor", "Froukje", "Gea", "Gerda", "Hanna", "Hanneke", "Heleen", "Hilde", "Ilona", "Ina", "Inge", "Ingrid", "Iris", "Isabel", "Isabelle", "Janneke", "Jasmijn", "Jeanine", "Jennifer", "Jessica", "Johanna", "Joke", "Julia", "Julie", "Karen", "Karin", "Katja", "Kim", "Lara", "Laura", "Lena", "Lianne", "Lieke", "Lilian", "Linda", "Lisa", "Lisanne", "Lotte", "Louise", "Maaike", "Manon", "Marga", "Maria", "Marissa", "Marit", "Marjolein", "Martine", "Marleen", "Melissa", "Merel", "Miranda", "Michelle", "Mirjam", "Mirthe", "Naomi", "Natalie", 'Nienke', "Nina", "Noortje", "Olivia", "Patricia", "Paula", "Paulien", "Ramona", "Ria", "Rianne", "Roos", "Rosanne", "Ruth", "Sabrina", "Sandra", "Sanne", "Sara", "Saskia", "Silvia", "Sofia", "Sophie", "Sonja", "Suzanne", "Tamara", "Tess", "Tessa", "Tineke", "Valerie", "Vanessa", "Veerle", "Vera", "Victoria", "Wendy", "Willeke", "Yvonne", "Zoë"],
		                // Data taken from https://fr.wikipedia.org/wiki/Liste_de_pr%C3%A9noms_fran%C3%A7ais_et_de_la_francophonie
		                "fr": ["Abdon","Abel","Abigaëlle","Abigaïl","Acacius","Acanthe","Adalbert","Adalsinde","Adegrine","Adélaïde","Adèle","Adélie","Adeline","Adeltrude","Adolphe","Adonis","Adrastée","Adrehilde","Adrienne","Agathe","Agilbert","Aglaé","Aignan","Agneflète","Agnès","Agrippine","Aimé","Alaine","Alaïs","Albane","Albérade","Alberte","Alcide","Alcine","Alcyone","Aldegonde","Aleth","Alexandrine","Alexine","Alice","Aliénor","Aliette","Aline","Alix","Alizé","Aloïse","Aloyse","Alphonsine","Althée","Amaliane","Amalthée","Amande","Amandine","Amant","Amarande","Amaranthe","Amaryllis","Ambre","Ambroisie","Amélie","Améthyste","Aminte","Anaël","Anaïs","Anastasie","Anatole","Ancelin","Andrée","Anémone","Angadrême","Angèle","Angeline","Angélique","Angilbert","Anicet","Annabelle","Anne","Annette","Annick","Annie","Annonciade","Ansbert","Anstrudie","Anthelme","Antigone","Antoinette","Antonine","Aphélie","Apolline","Apollonie","Aquiline","Arabelle","Arcadie","Archange","Argine","Ariane","Aricie","Ariel","Arielle","Arlette","Armance","Armande","Armandine","Armelle","Armide","Armelle","Armin","Arnaud","Arsène","Arsinoé","Artémis","Arthur","Ascelin","Ascension","Assomption","Astarté","Astérie","Astrée","Astrid","Athalie","Athanasie","Athina","Aube","Albert","Aude","Audrey","Augustine","Aure","Aurélie","Aurélien","Aurèle","Aurore","Auxence","Aveline","Abigaëlle","Avoye","Axelle","Aymard","Azalée","Adèle","Adeline","Barbe","Basilisse","Bathilde","Béatrice","Béatrix","Bénédicte","Bérengère","Bernadette","Berthe","Bertille","Beuve","Blanche","Blanc","Blandine","Brigitte","Brune","Brunehilde","Callista","Camille","Capucine","Carine","Caroline","Cassandre","Catherine","Cécile","Céleste","Célestine","Céline","Chantal","Charlène","Charline","Charlotte","Chloé","Christelle","Christiane","Christine","Claire","Clara","Claude","Claudine","Clarisse","Clémence","Clémentine","Cléo","Clio","Clotilde","Coline","Conception","Constance","Coralie","Coraline","Corentine","Corinne","Cyrielle","Daniel","Daniel","Daphné","Débora","Delphine","Denise","Diane","Dieudonné","Dominique","Doriane","Dorothée","Douce","Édith","Edmée","Éléonore","Éliane","Élia","Éliette","Élisabeth","Élise","Ella","Élodie","Éloïse","Elsa","Émeline","Émérance","Émérentienne","Émérencie","Émilie","Emma","Emmanuelle","Emmelie","Ernestine","Esther","Estelle","Eudoxie","Eugénie","Eulalie","Euphrasie","Eusébie","Évangéline","Eva","Ève","Évelyne","Fanny","Fantine","Faustine","Félicie","Fernande","Flavie","Fleur","Flore","Florence","Florie","Fortuné","France","Francia","Françoise","Francine","Gabrielle","Gaëlle","Garance","Geneviève","Georgette","Gerberge","Germaine","Gertrude","Gisèle","Guenièvre","Guilhemine","Guillemette","Gustave","Gwenael","Hélène","Héloïse","Henriette","Hermine","Hermione","Hippolyte","Honorine","Hortense","Huguette","Ines","Irène","Irina","Iris","Isabeau","Isabelle","Iseult","Isolde","Ismérie","Jacinthe","Jacqueline","Jade","Janine","Jeanne","Jocelyne","Joëlle","Joséphine","Judith","Julia","Julie","Jules","Juliette","Justine","Katy","Kathy","Katie","Laura","Laure","Laureline","Laurence","Laurene","Lauriane","Laurianne","Laurine","Léa","Léna","Léonie","Léon","Léontine","Lorraine","Lucie","Lucienne","Lucille","Ludivine","Lydie","Lydie","Megane","Madeleine","Magali","Maguelone","Mallaury","Manon","Marceline","Margot","Marguerite","Marianne","Marie","Myriam","Marie","Marine","Marion","Marlène","Marthe","Martine","Mathilde","Maud","Maureen","Mauricette","Maxime","Mélanie","Melissa","Mélissandre","Mélisande","Mélodie","Michel","Micheline","Mireille","Miriam","Moïse","Monique","Morgane","Muriel","Mylène","Nadège","Nadine","Nathalie","Nicole","Nicolette","Nine","Noël","Noémie","Océane","Odette","Odile","Olive","Olivia","Olympe","Ombline","Ombeline","Ophélie","Oriande","Oriane","Ozanne","Pascale","Pascaline","Paule","Paulette","Pauline","Priscille","Prisca","Prisque","Pécine","Pélagie","Pénélope","Perrine","Pétronille","Philippine","Philomène","Philothée","Primerose","Prudence","Pulchérie","Quentine","Quiéta","Quintia","Quintilla","Rachel","Raphaëlle","Raymonde","Rebecca","Régine","Réjeanne","René","Rita","Rita","Rolande","Romane","Rosalie","Rose","Roseline","Sabine","Salomé","Sandra","Sandrine","Sarah","Ségolène","Séverine","Sibylle","Simone","Sixt","Solange","Soline","Solène","Sophie","Stéphanie","Suzanne","Sylvain","Sylvie","Tatiana","Thaïs","Théodora","Thérèse","Tiphaine","Ursule","Valentine","Valérie","Véronique","Victoire","Victorine","Vinciane","Violette","Virginie","Viviane","Xavière","Yolande","Ysaline","Yvette","Yvonne","Zélie","Zita","Zoé"]
		            }
		        },

		        lastNames: {
		            "en": ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Davis', 'Miller', 'Wilson', 'Moore', 'Taylor', 'Anderson', 'Thomas', 'Jackson', 'White', 'Harris', 'Martin', 'Thompson', 'Garcia', 'Martinez', 'Robinson', 'Clark', 'Rodriguez', 'Lewis', 'Lee', 'Walker', 'Hall', 'Allen', 'Young', 'Hernandez', 'King', 'Wright', 'Lopez', 'Hill', 'Scott', 'Green', 'Adams', 'Baker', 'Gonzalez', 'Nelson', 'Carter', 'Mitchell', 'Perez', 'Roberts', 'Turner', 'Phillips', 'Campbell', 'Parker', 'Evans', 'Edwards', 'Collins', 'Stewart', 'Sanchez', 'Morris', 'Rogers', 'Reed', 'Cook', 'Morgan', 'Bell', 'Murphy', 'Bailey', 'Rivera', 'Cooper', 'Richardson', 'Cox', 'Howard', 'Ward', 'Torres', 'Peterson', 'Gray', 'Ramirez', 'James', 'Watson', 'Brooks', 'Kelly', 'Sanders', 'Price', 'Bennett', 'Wood', 'Barnes', 'Ross', 'Henderson', 'Coleman', 'Jenkins', 'Perry', 'Powell', 'Long', 'Patterson', 'Hughes', 'Flores', 'Washington', 'Butler', 'Simmons', 'Foster', 'Gonzales', 'Bryant', 'Alexander', 'Russell', 'Griffin', 'Diaz', 'Hayes', 'Myers', 'Ford', 'Hamilton', 'Graham', 'Sullivan', 'Wallace', 'Woods', 'Cole', 'West', 'Jordan', 'Owens', 'Reynolds', 'Fisher', 'Ellis', 'Harrison', 'Gibson', 'McDonald', 'Cruz', 'Marshall', 'Ortiz', 'Gomez', 'Murray', 'Freeman', 'Wells', 'Webb', 'Simpson', 'Stevens', 'Tucker', 'Porter', 'Hunter', 'Hicks', 'Crawford', 'Henry', 'Boyd', 'Mason', 'Morales', 'Kennedy', 'Warren', 'Dixon', 'Ramos', 'Reyes', 'Burns', 'Gordon', 'Shaw', 'Holmes', 'Rice', 'Robertson', 'Hunt', 'Black', 'Daniels', 'Palmer', 'Mills', 'Nichols', 'Grant', 'Knight', 'Ferguson', 'Rose', 'Stone', 'Hawkins', 'Dunn', 'Perkins', 'Hudson', 'Spencer', 'Gardner', 'Stephens', 'Payne', 'Pierce', 'Berry', 'Matthews', 'Arnold', 'Wagner', 'Willis', 'Ray', 'Watkins', 'Olson', 'Carroll', 'Duncan', 'Snyder', 'Hart', 'Cunningham', 'Bradley', 'Lane', 'Andrews', 'Ruiz', 'Harper', 'Fox', 'Riley', 'Armstrong', 'Carpenter', 'Weaver', 'Greene', 'Lawrence', 'Elliott', 'Chavez', 'Sims', 'Austin', 'Peters', 'Kelley', 'Franklin', 'Lawson', 'Fields', 'Gutierrez', 'Ryan', 'Schmidt', 'Carr', 'Vasquez', 'Castillo', 'Wheeler', 'Chapman', 'Oliver', 'Montgomery', 'Richards', 'Williamson', 'Johnston', 'Banks', 'Meyer', 'Bishop', 'McCoy', 'Howell', 'Alvarez', 'Morrison', 'Hansen', 'Fernandez', 'Garza', 'Harvey', 'Little', 'Burton', 'Stanley', 'Nguyen', 'George', 'Jacobs', 'Reid', 'Kim', 'Fuller', 'Lynch', 'Dean', 'Gilbert', 'Garrett', 'Romero', 'Welch', 'Larson', 'Frazier', 'Burke', 'Hanson', 'Day', 'Mendoza', 'Moreno', 'Bowman', 'Medina', 'Fowler', 'Brewer', 'Hoffman', 'Carlson', 'Silva', 'Pearson', 'Holland', 'Douglas', 'Fleming', 'Jensen', 'Vargas', 'Byrd', 'Davidson', 'Hopkins', 'May', 'Terry', 'Herrera', 'Wade', 'Soto', 'Walters', 'Curtis', 'Neal', 'Caldwell', 'Lowe', 'Jennings', 'Barnett', 'Graves', 'Jimenez', 'Horton', 'Shelton', 'Barrett', 'Obrien', 'Castro', 'Sutton', 'Gregory', 'McKinney', 'Lucas', 'Miles', 'Craig', 'Rodriquez', 'Chambers', 'Holt', 'Lambert', 'Fletcher', 'Watts', 'Bates', 'Hale', 'Rhodes', 'Pena', 'Beck', 'Newman', 'Haynes', 'McDaniel', 'Mendez', 'Bush', 'Vaughn', 'Parks', 'Dawson', 'Santiago', 'Norris', 'Hardy', 'Love', 'Steele', 'Curry', 'Powers', 'Schultz', 'Barker', 'Guzman', 'Page', 'Munoz', 'Ball', 'Keller', 'Chandler', 'Weber', 'Leonard', 'Walsh', 'Lyons', 'Ramsey', 'Wolfe', 'Schneider', 'Mullins', 'Benson', 'Sharp', 'Bowen', 'Daniel', 'Barber', 'Cummings', 'Hines', 'Baldwin', 'Griffith', 'Valdez', 'Hubbard', 'Salazar', 'Reeves', 'Warner', 'Stevenson', 'Burgess', 'Santos', 'Tate', 'Cross', 'Garner', 'Mann', 'Mack', 'Moss', 'Thornton', 'Dennis', 'McGee', 'Farmer', 'Delgado', 'Aguilar', 'Vega', 'Glover', 'Manning', 'Cohen', 'Harmon', 'Rodgers', 'Robbins', 'Newton', 'Todd', 'Blair', 'Higgins', 'Ingram', 'Reese', 'Cannon', 'Strickland', 'Townsend', 'Potter', 'Goodwin', 'Walton', 'Rowe', 'Hampton', 'Ortega', 'Patton', 'Swanson', 'Joseph', 'Francis', 'Goodman', 'Maldonado', 'Yates', 'Becker', 'Erickson', 'Hodges', 'Rios', 'Conner', 'Adkins', 'Webster', 'Norman', 'Malone', 'Hammond', 'Flowers', 'Cobb', 'Moody', 'Quinn', 'Blake', 'Maxwell', 'Pope', 'Floyd', 'Osborne', 'Paul', 'McCarthy', 'Guerrero', 'Lindsey', 'Estrada', 'Sandoval', 'Gibbs', 'Tyler', 'Gross', 'Fitzgerald', 'Stokes', 'Doyle', 'Sherman', 'Saunders', 'Wise', 'Colon', 'Gill', 'Alvarado', 'Greer', 'Padilla', 'Simon', 'Waters', 'Nunez', 'Ballard', 'Schwartz', 'McBride', 'Houston', 'Christensen', 'Klein', 'Pratt', 'Briggs', 'Parsons', 'McLaughlin', 'Zimmerman', 'French', 'Buchanan', 'Moran', 'Copeland', 'Roy', 'Pittman', 'Brady', 'McCormick', 'Holloway', 'Brock', 'Poole', 'Frank', 'Logan', 'Owen', 'Bass', 'Marsh', 'Drake', 'Wong', 'Jefferson', 'Park', 'Morton', 'Abbott', 'Sparks', 'Patrick', 'Norton', 'Huff', 'Clayton', 'Massey', 'Lloyd', 'Figueroa', 'Carson', 'Bowers', 'Roberson', 'Barton', 'Tran', 'Lamb', 'Harrington', 'Casey', 'Boone', 'Cortez', 'Clarke', 'Mathis', 'Singleton', 'Wilkins', 'Cain', 'Bryan', 'Underwood', 'Hogan', 'McKenzie', 'Collier', 'Luna', 'Phelps', 'McGuire', 'Allison', 'Bridges', 'Wilkerson', 'Nash', 'Summers', 'Atkins'],
		                // Data taken from http://www.dati.gov.it/dataset/comune-di-firenze_0164 (first 1000)
		            "it": ["Acciai", "Aglietti", "Agostini", "Agresti", "Ahmed", "Aiazzi", "Albanese", "Alberti", "Alessi", "Alfani", "Alinari", "Alterini", "Amato", "Ammannati", "Ancillotti", "Andrei", "Andreini", "Andreoni", "Angeli", "Anichini", "Antonelli", "Antonini", "Arena", "Ariani", "Arnetoli", "Arrighi", "Baccani", "Baccetti", "Bacci", "Bacherini", "Badii", "Baggiani", "Baglioni", "Bagni", "Bagnoli", "Baldassini", "Baldi", "Baldini", "Ballerini", "Balli", "Ballini", "Balloni", "Bambi", "Banchi", "Bandinelli", "Bandini", "Bani", "Barbetti", "Barbieri", "Barchielli", "Bardazzi", "Bardelli", "Bardi", "Barducci", "Bargellini", "Bargiacchi", "Barni", "Baroncelli", "Baroncini", "Barone", "Baroni", "Baronti", "Bartalesi", "Bartoletti", "Bartoli", "Bartolini", "Bartoloni", "Bartolozzi", "Basagni", "Basile", "Bassi", "Batacchi", "Battaglia", "Battaglini", "Bausi", "Becagli", "Becattini", "Becchi", "Becucci", "Bellandi", "Bellesi", "Belli", "Bellini", "Bellucci", "Bencini", "Benedetti", "Benelli", "Beni", "Benini", "Bensi", "Benucci", "Benvenuti", "Berlincioni", "Bernacchioni", "Bernardi", "Bernardini", "Berni", "Bernini", "Bertelli", "Berti", "Bertini", "Bessi", "Betti", "Bettini", "Biagi", "Biagini", "Biagioni", "Biagiotti", "Biancalani", "Bianchi", "Bianchini", "Bianco", "Biffoli", "Bigazzi", "Bigi", "Biliotti", "Billi", "Binazzi", "Bindi", "Bini", "Biondi", "Bizzarri", "Bocci", "Bogani", "Bolognesi", "Bonaiuti", "Bonanni", "Bonciani", "Boncinelli", "Bondi", "Bonechi", "Bongini", "Boni", "Bonini", "Borchi", "Boretti", "Borghi", "Borghini", "Borgioli", "Borri", "Borselli", "Boschi", "Bottai", "Bracci", "Braccini", "Brandi", "Braschi", "Bravi", "Brazzini", "Breschi", "Brilli", "Brizzi", "Brogelli", "Brogi", "Brogioni", "Brunelli", "Brunetti", "Bruni", "Bruno", "Brunori", "Bruschi", "Bucci", "Bucciarelli", "Buccioni", "Bucelli", "Bulli", "Burberi", "Burchi", "Burgassi", "Burroni", "Bussotti", "Buti", "Caciolli", "Caiani", "Calabrese", "Calamai", "Calamandrei", "Caldini", "Calo'", "Calonaci", "Calosi", "Calvelli", "Cambi", "Camiciottoli", "Cammelli", "Cammilli", "Campolmi", "Cantini", "Capanni", "Capecchi", "Caponi", "Cappelletti", "Cappelli", "Cappellini", "Cappugi", "Capretti", "Caputo", "Carbone", "Carboni", "Cardini", "Carlesi", "Carletti", "Carli", "Caroti", "Carotti", "Carrai", "Carraresi", "Carta", "Caruso", "Casalini", "Casati", "Caselli", "Casini", "Castagnoli", "Castellani", "Castelli", "Castellucci", "Catalano", "Catarzi", "Catelani", "Cavaciocchi", "Cavallaro", "Cavallini", "Cavicchi", "Cavini", "Ceccarelli", "Ceccatelli", "Ceccherelli", "Ceccherini", "Cecchi", "Cecchini", "Cecconi", "Cei", "Cellai", "Celli", "Cellini", "Cencetti", "Ceni", "Cenni", "Cerbai", "Cesari", "Ceseri", "Checcacci", "Checchi", "Checcucci", "Cheli", "Chellini", "Chen", "Cheng", "Cherici", "Cherubini", "Chiaramonti", "Chiarantini", "Chiarelli", "Chiari", "Chiarini", "Chiarugi", "Chiavacci", "Chiesi", "Chimenti", "Chini", "Chirici", "Chiti", "Ciabatti", "Ciampi", "Cianchi", "Cianfanelli", "Cianferoni", "Ciani", "Ciapetti", "Ciappi", "Ciardi", "Ciatti", "Cicali", "Ciccone", "Cinelli", "Cini", "Ciobanu", "Ciolli", "Cioni", "Cipriani", "Cirillo", "Cirri", "Ciucchi", "Ciuffi", "Ciulli", "Ciullini", "Clemente", "Cocchi", "Cognome", "Coli", "Collini", "Colombo", "Colzi", "Comparini", "Conforti", "Consigli", "Conte", "Conti", "Contini", "Coppini", "Coppola", "Corsi", "Corsini", "Corti", "Cortini", "Cosi", "Costa", "Costantini", "Costantino", "Cozzi", "Cresci", "Crescioli", "Cresti", "Crini", "Curradi", "D'Agostino", "D'Alessandro", "D'Amico", "D'Angelo", "Daddi", "Dainelli", "Dallai", "Danti", "Davitti", "De Angelis", "De Luca", "De Marco", "De Rosa", "De Santis", "De Simone", "De Vita", "Degl'Innocenti", "Degli Innocenti", "Dei", "Del Lungo", "Del Re", "Di Marco", "Di Stefano", "Dini", "Diop", "Dobre", "Dolfi", "Donati", "Dondoli", "Dong", "Donnini", "Ducci", "Dumitru", "Ermini", "Esposito", "Evangelisti", "Fabbri", "Fabbrini", "Fabbrizzi", "Fabbroni", "Fabbrucci", "Fabiani", "Facchini", "Faggi", "Fagioli", "Failli", "Faini", "Falciani", "Falcini", "Falcone", "Fallani", "Falorni", "Falsini", "Falugiani", "Fancelli", "Fanelli", "Fanetti", "Fanfani", "Fani", "Fantappie'", "Fantechi", "Fanti", "Fantini", "Fantoni", "Farina", "Fattori", "Favilli", "Fedi", "Fei", "Ferrante", "Ferrara", "Ferrari", "Ferraro", "Ferretti", "Ferri", "Ferrini", "Ferroni", "Fiaschi", "Fibbi", "Fiesoli", "Filippi", "Filippini", "Fini", "Fioravanti", "Fiore", "Fiorentini", "Fiorini", "Fissi", "Focardi", "Foggi", "Fontana", "Fontanelli", "Fontani", "Forconi", "Formigli", "Forte", "Forti", "Fortini", "Fossati", "Fossi", "Francalanci", "Franceschi", "Franceschini", "Franchi", "Franchini", "Franci", "Francini", "Francioni", "Franco", "Frassineti", "Frati", "Fratini", "Frilli", "Frizzi", "Frosali", "Frosini", "Frullini", "Fusco", "Fusi", "Gabbrielli", "Gabellini", "Gagliardi", "Galanti", "Galardi", "Galeotti", "Galletti", "Galli", "Gallo", "Gallori", "Gambacciani", "Gargani", "Garofalo", "Garuglieri", "Gashi", "Gasperini", "Gatti", "Gelli", "Gensini", "Gentile", "Gentili", "Geri", "Gerini", "Gheri", "Ghini", "Giachetti", "Giachi", "Giacomelli", "Gianassi", "Giani", "Giannelli", "Giannetti", "Gianni", "Giannini", "Giannoni", "Giannotti", "Giannozzi", "Gigli", "Giordano", "Giorgetti", "Giorgi", "Giovacchini", "Giovannelli", "Giovannetti", "Giovannini", "Giovannoni", "Giuliani", "Giunti", "Giuntini", "Giusti", "Gonnelli", "Goretti", "Gori", "Gradi", "Gramigni", "Grassi", "Grasso", "Graziani", "Grazzini", "Greco", "Grifoni", "Grillo", "Grimaldi", "Grossi", "Gualtieri", "Guarducci", "Guarino", "Guarnieri", "Guasti", "Guerra", "Guerri", "Guerrini", "Guidi", "Guidotti", "He", "Hoxha", "Hu", "Huang", "Iandelli", "Ignesti", "Innocenti", "Jin", "La Rosa", "Lai", "Landi", "Landini", "Lanini", "Lapi", "Lapini", "Lari", "Lascialfari", "Lastrucci", "Latini", "Lazzeri", "Lazzerini", "Lelli", "Lenzi", "Leonardi", "Leoncini", "Leone", "Leoni", "Lepri", "Li", "Liao", "Lin", "Linari", "Lippi", "Lisi", "Livi", "Lombardi", "Lombardini", "Lombardo", "Longo", "Lopez", "Lorenzi", "Lorenzini", "Lorini", "Lotti", "Lu", "Lucchesi", "Lucherini", "Lunghi", "Lupi", "Madiai", "Maestrini", "Maffei", "Maggi", "Maggini", "Magherini", "Magini", "Magnani", "Magnelli", "Magni", "Magnolfi", "Magrini", "Malavolti", "Malevolti", "Manca", "Mancini", "Manetti", "Manfredi", "Mangani", "Mannelli", "Manni", "Mannini", "Mannucci", "Manuelli", "Manzini", "Marcelli", "Marchese", "Marchetti", "Marchi", "Marchiani", "Marchionni", "Marconi", "Marcucci", "Margheri", "Mari", "Mariani", "Marilli", "Marinai", "Marinari", "Marinelli", "Marini", "Marino", "Mariotti", "Marsili", "Martelli", "Martinelli", "Martini", "Martino", "Marzi", "Masi", "Masini", "Masoni", "Massai", "Materassi", "Mattei", "Matteini", "Matteucci", "Matteuzzi", "Mattioli", "Mattolini", "Matucci", "Mauro", "Mazzanti", "Mazzei", "Mazzetti", "Mazzi", "Mazzini", "Mazzocchi", "Mazzoli", "Mazzoni", "Mazzuoli", "Meacci", "Mecocci", "Meini", "Melani", "Mele", "Meli", "Mengoni", "Menichetti", "Meoni", "Merlini", "Messeri", "Messina", "Meucci", "Miccinesi", "Miceli", "Micheli", "Michelini", "Michelozzi", "Migliori", "Migliorini", "Milani", "Miniati", "Misuri", "Monaco", "Montagnani", "Montagni", "Montanari", "Montelatici", "Monti", "Montigiani", "Montini", "Morandi", "Morandini", "Morelli", "Moretti", "Morganti", "Mori", "Morini", "Moroni", "Morozzi", "Mugnai", "Mugnaini", "Mustafa", "Naldi", "Naldini", "Nannelli", "Nanni", "Nannini", "Nannucci", "Nardi", "Nardini", "Nardoni", "Natali", "Ndiaye", "Nencetti", "Nencini", "Nencioni", "Neri", "Nesi", "Nesti", "Niccolai", "Niccoli", "Niccolini", "Nigi", "Nistri", "Nocentini", "Noferini", "Novelli", "Nucci", "Nuti", "Nutini", "Oliva", "Olivieri", "Olmi", "Orlandi", "Orlandini", "Orlando", "Orsini", "Ortolani", "Ottanelli", "Pacciani", "Pace", "Paci", "Pacini", "Pagani", "Pagano", "Paggetti", "Pagliai", "Pagni", "Pagnini", "Paladini", "Palagi", "Palchetti", "Palloni", "Palmieri", "Palumbo", "Pampaloni", "Pancani", "Pandolfi", "Pandolfini", "Panerai", "Panichi", "Paoletti", "Paoli", "Paolini", "Papi", "Papini", "Papucci", "Parenti", "Parigi", "Parisi", "Parri", "Parrini", "Pasquini", "Passeri", "Pecchioli", "Pecorini", "Pellegrini", "Pepi", "Perini", "Perrone", "Peruzzi", "Pesci", "Pestelli", "Petri", "Petrini", "Petrucci", "Pettini", "Pezzati", "Pezzatini", "Piani", "Piazza", "Piazzesi", "Piazzini", "Piccardi", "Picchi", "Piccini", "Piccioli", "Pieraccini", "Pieraccioni", "Pieralli", "Pierattini", "Pieri", "Pierini", "Pieroni", "Pietrini", "Pini", "Pinna", "Pinto", "Pinzani", "Pinzauti", "Piras", "Pisani", "Pistolesi", "Poggesi", "Poggi", "Poggiali", "Poggiolini", "Poli", "Pollastri", "Porciani", "Pozzi", "Pratellesi", "Pratesi", "Prosperi", "Pruneti", "Pucci", "Puccini", "Puccioni", "Pugi", "Pugliese", "Puliti", "Querci", "Quercioli", "Raddi", "Radu", "Raffaelli", "Ragazzini", "Ranfagni", "Ranieri", "Rastrelli", "Raugei", "Raveggi", "Renai", "Renzi", "Rettori", "Ricci", "Ricciardi", "Ridi", "Ridolfi", "Rigacci", "Righi", "Righini", "Rinaldi", "Risaliti", "Ristori", "Rizzo", "Rocchi", "Rocchini", "Rogai", "Romagnoli", "Romanelli", "Romani", "Romano", "Romei", "Romeo", "Romiti", "Romoli", "Romolini", "Rontini", "Rosati", "Roselli", "Rosi", "Rossetti", "Rossi", "Rossini", "Rovai", "Ruggeri", "Ruggiero", "Russo", "Sabatini", "Saccardi", "Sacchetti", "Sacchi", "Sacco", "Salerno", "Salimbeni", "Salucci", "Salvadori", "Salvestrini", "Salvi", "Salvini", "Sanesi", "Sani", "Sanna", "Santi", "Santini", "Santoni", "Santoro", "Santucci", "Sardi", "Sarri", "Sarti", "Sassi", "Sbolci", "Scali", "Scarpelli", "Scarselli", "Scopetani", "Secci", "Selvi", "Senatori", "Senesi", "Serafini", "Sereni", "Serra", "Sestini", "Sguanci", "Sieni", "Signorini", "Silvestri", "Simoncini", "Simonetti", "Simoni", "Singh", "Sodi", "Soldi", "Somigli", "Sorbi", "Sorelli", "Sorrentino", "Sottili", "Spina", "Spinelli", "Staccioli", "Staderini", "Stefanelli", "Stefani", "Stefanini", "Stella", "Susini", "Tacchi", "Tacconi", "Taddei", "Tagliaferri", "Tamburini", "Tanganelli", "Tani", "Tanini", "Tapinassi", "Tarchi", "Tarchiani", "Targioni", "Tassi", "Tassini", "Tempesti", "Terzani", "Tesi", "Testa", "Testi", "Tilli", "Tinti", "Tirinnanzi", "Toccafondi", "Tofanari", "Tofani", "Tognaccini", "Tonelli", "Tonini", "Torelli", "Torrini", "Tosi", "Toti", "Tozzi", "Trambusti", "Trapani", "Tucci", "Turchi", "Ugolini", "Ulivi", "Valente", "Valenti", "Valentini", "Vangelisti", "Vanni", "Vannini", "Vannoni", "Vannozzi", "Vannucchi", "Vannucci", "Ventura", "Venturi", "Venturini", "Vestri", "Vettori", "Vichi", "Viciani", "Vieri", "Vigiani", "Vignoli", "Vignolini", "Vignozzi", "Villani", "Vinci", "Visani", "Vitale", "Vitali", "Viti", "Viviani", "Vivoli", "Volpe", "Volpi", "Wang", "Wu", "Xu", "Yang", "Ye", "Zagli", "Zani", "Zanieri", "Zanobini", "Zecchi", "Zetti", "Zhang", "Zheng", "Zhou", "Zhu", "Zingoni", "Zini", "Zoppi"],
		            // http://www.voornamelijk.nl/meest-voorkomende-achternamen-in-nederland-en-amsterdam/
		            "nl":["Albers", "Alblas", "Appelman", "Baars", "Baas", "Bakker", "Blank", "Bleeker", "Blok", "Blom", "Boer", "Boers", "Boldewijn", "Boon", "Boot", "Bos", "Bosch", "Bosma", "Bosman", "Bouma", "Bouman", "Bouwman", "Brands", "Brouwer", "Burger", "Buijs", "Buitenhuis", "Ceder", "Cohen", "Dekker", "Dekkers", "Dijkman", "Dijkstra", "Driessen", "Drost", "Engel", "Evers", "Faber", "Franke", "Gerritsen", "Goedhart", "Goossens", "Groen", "Groenenberg", "Groot", "Haan", "Hart", "Heemskerk", "Hendriks", "Hermans", "Hoekstra", "Hofman", "Hopman", "Huisman", "Jacobs", "Jansen", "Janssen", "Jonker", "Jaspers", "Keijzer", "Klaassen", "Klein", "Koek", "Koenders", "Kok", "Kool", "Koopman", "Koopmans", "Koning", "Koster", "Kramer", "Kroon", "Kuijpers", "Kuiper", "Kuipers", "Kurt", "Koster", "Kwakman", "Los", "Lubbers", "Maas", "Markus", "Martens", "Meijer", "Mol", "Molenaar", "Mulder", "Nieuwenhuis", "Peeters", "Peters", "Pengel", "Pieters", "Pool", "Post", "Postma", "Prins", "Pronk", "Reijnders", "Rietveld", "Roest", "Roos", "Sanders", "Schaap", "Scheffer", "Schenk", "Schilder", "Schipper", "Schmidt", "Scholten", "Schouten", "Schut", "Schutte", "Schuurman", "Simons", "Smeets", "Smit", "Smits", "Snel", "Swinkels", "Tas", "Terpstra", "Timmermans", "Tol", "Tromp", "Troost", "Valk", "Veenstra", "Veldkamp", "Verbeek", "Verheul", "Verhoeven", "Vermeer", "Vermeulen", "Verweij", "Vink", "Visser", "Voorn", "Vos", "Wagenaar", "Wiersema", "Willems", "Willemsen", "Witteveen", "Wolff", "Wolters", "Zijlstra", "Zwart", "de Beer", "de Boer", "de Bruijn", "de Bruin", "de Graaf", "de Groot", "de Haan", "de Haas", "de Jager", "de Jong", "de Jonge", "de Koning", "de Lange", "de Leeuw", "de Ridder", "de Rooij", "de Ruiter", "de Vos", "de Vries", "de Waal", "de Wit", "de Zwart", "van Beek", "van Boven", "van Dam", "van Dijk", "van Dongen", "van Doorn", "van Egmond", "van Eijk", "van Es", "van Gelder", "van Gelderen", "van Houten", "van Hulst", "van Kempen", "van Kesteren", "van Leeuwen", "van Loon", "van Mill", "van Noord", "van Ommen", "van Ommeren", "van Oosten", "van Oostveen", "van Rijn", "van Schaik", "van Veen", "van Vliet", "van Wijk", "van Wijngaarden", "van den Poel", "van de Pol", "van den Ploeg", "van de Ven", "van den Berg", "van den Bosch", "van den Brink", "van den Broek", "van den Heuvel", "van der Heijden", "van der Horst", "van der Hulst", "van der Kroon", "van der Laan", "van der Linden", "van der Meer", "van der Meij", "van der Meulen", "van der Molen", "van der Sluis", "van der Spek", "van der Veen", "van der Velde", "van der Velden", "van der Vliet", "van der Wal"],
		            // https://surnames.behindthename.com/top/lists/england-wales/1991
		            "uk":["Smith","Jones","Williams","Taylor","Brown","Davies","Evans","Wilson","Thomas","Johnson","Roberts","Robinson","Thompson","Wright","Walker","White","Edwards","Hughes","Green","Hall","Lewis","Harris","Clarke","Patel","Jackson","Wood","Turner","Martin","Cooper","Hill","Ward","Morris","Moore","Clark","Lee","King","Baker","Harrison","Morgan","Allen","James","Scott","Phillips","Watson","Davis","Parker","Price","Bennett","Young","Griffiths","Mitchell","Kelly","Cook","Carter","Richardson","Bailey","Collins","Bell","Shaw","Murphy","Miller","Cox","Richards","Khan","Marshall","Anderson","Simpson","Ellis","Adams","Singh","Begum","Wilkinson","Foster","Chapman","Powell","Webb","Rogers","Gray","Mason","Ali","Hunt","Hussain","Campbell","Matthews","Owen","Palmer","Holmes","Mills","Barnes","Knight","Lloyd","Butler","Russell","Barker","Fisher","Stevens","Jenkins","Murray","Dixon","Harvey","Graham","Pearson","Ahmed","Fletcher","Walsh","Kaur","Gibson","Howard","Andrews","Stewart","Elliott","Reynolds","Saunders","Payne","Fox","Ford","Pearce","Day","Brooks","West","Lawrence","Cole","Atkinson","Bradley","Spencer","Gill","Dawson","Ball","Burton","O'brien","Watts","Rose","Booth","Perry","Ryan","Grant","Wells","Armstrong","Francis","Rees","Hayes","Hart","Hudson","Newman","Barrett","Webster","Hunter","Gregory","Carr","Lowe","Page","Marsh","Riley","Dunn","Woods","Parsons","Berry","Stone","Reid","Holland","Hawkins","Harding","Porter","Robertson","Newton","Oliver","Reed","Kennedy","Williamson","Bird","Gardner","Shah","Dean","Lane","Cooke","Bates","Henderson","Parry","Burgess","Bishop","Walton","Burns","Nicholson","Shepherd","Ross","Cross","Long","Freeman","Warren","Nicholls","Hamilton","Byrne","Sutton","Mcdonald","Yates","Hodgson","Robson","Curtis","Hopkins","O'connor","Harper","Coleman","Watkins","Moss","Mccarthy","Chambers","O'neill","Griffin","Sharp","Hardy","Wheeler","Potter","Osborne","Johnston","Gordon","Doyle","Wallace","George","Jordan","Hutchinson","Rowe","Burke","May","Pritchard","Gilbert","Willis","Higgins","Read","Miles","Stevenson","Stephenson","Hammond","Arnold","Buckley","Walters","Hewitt","Barber","Nelson","Slater","Austin","Sullivan","Whitehead","Mann","Frost","Lambert","Stephens","Blake","Akhtar","Lynch","Goodwin","Barton","Woodward","Thomson","Cunningham","Quinn","Barnett","Baxter","Bibi","Clayton","Nash","Greenwood","Jennings","Holt","Kemp","Poole","Gallagher","Bond","Stokes","Tucker","Davidson","Fowler","Heath","Norman","Middleton","Lawson","Banks","French","Stanley","Jarvis","Gibbs","Ferguson","Hayward","Carroll","Douglas","Dickinson","Todd","Barlow","Peters","Lucas","Knowles","Hartley","Miah","Simmons","Morton","Alexander","Field","Morrison","Norris","Townsend","Preston","Hancock","Thornton","Baldwin","Burrows","Briggs","Parkinson","Reeves","Macdonald","Lamb","Black","Abbott","Sanders","Thorpe","Holden","Tomlinson","Perkins","Ashton","Rhodes","Fuller","Howe","Bryant","Vaughan","Dale","Davey","Weston","Bartlett","Whittaker","Davison","Kent","Skinner","Birch","Morley","Daniels","Glover","Howell","Cartwright","Pugh","Humphreys","Goddard","Brennan","Wall","Kirby","Bowen","Savage","Bull","Wong","Dobson","Smart","Wilkins","Kirk","Fraser","Duffy","Hicks","Patterson","Bradshaw","Little","Archer","Warner","Waters","O'sullivan","Farrell","Brookes","Atkins","Kay","Dodd","Bentley","Flynn","John","Schofield","Short","Haynes","Wade","Butcher","Henry","Sanderson","Crawford","Sheppard","Bolton","Coates","Giles","Gould","Houghton","Gibbons","Pratt","Manning","Law","Hooper","Noble","Dyer","Rahman","Clements","Moran","Sykes","Chan","Doherty","Connolly","Joyce","Franklin","Hobbs","Coles","Herbert","Steele","Kerr","Leach","Winter","Owens","Duncan","Naylor","Fleming","Horton","Finch","Fitzgerald","Randall","Carpenter","Marsden","Browne","Garner","Pickering","Hale","Dennis","Vincent","Chadwick","Chandler","Sharpe","Nolan","Lyons","Hurst","Collier","Peacock","Howarth","Faulkner","Rice","Pollard","Welch","Norton","Gough","Sinclair","Blackburn","Bryan","Conway","Power","Cameron","Daly","Allan","Hanson","Gardiner","Boyle","Myers","Turnbull","Wallis","Mahmood","Sims","Swift","Iqbal","Pope","Brady","Chamberlain","Rowley","Tyler","Farmer","Metcalfe","Hilton","Godfrey","Holloway","Parkin","Bray","Talbot","Donnelly","Nixon","Charlton","Benson","Whitehouse","Barry","Hope","Lord","North","Storey","Connor","Potts","Bevan","Hargreaves","Mclean","Mistry","Bruce","Howells","Hyde","Parkes","Wyatt","Fry","Lees","O'donnell","Craig","Forster","Mckenzie","Humphries","Mellor","Carey","Ingram","Summers","Leonard"],
		            // https://surnames.behindthename.com/top/lists/germany/2017
		            "de": ["Müller","Schmidt","Schneider","Fischer","Weber","Meyer","Wagner","Becker","Schulz","Hoffmann","Schäfer","Koch","Bauer","Richter","Klein","Wolf","Schröder","Neumann","Schwarz","Zimmermann","Braun","Krüger","Hofmann","Hartmann","Lange","Schmitt","Werner","Schmitz","Krause","Meier","Lehmann","Schmid","Schulze","Maier","Köhler","Herrmann","König","Walter","Mayer","Huber","Kaiser","Fuchs","Peters","Lang","Scholz","Möller","Weiß","Jung","Hahn","Schubert","Vogel","Friedrich","Keller","Günther","Frank","Berger","Winkler","Roth","Beck","Lorenz","Baumann","Franke","Albrecht","Schuster","Simon","Ludwig","Böhm","Winter","Kraus","Martin","Schumacher","Krämer","Vogt","Stein","Jäger","Otto","Sommer","Groß","Seidel","Heinrich","Brandt","Haas","Schreiber","Graf","Schulte","Dietrich","Ziegler","Kuhn","Kühn","Pohl","Engel","Horn","Busch","Bergmann","Thomas","Voigt","Sauer","Arnold","Wolff","Pfeiffer"],
		            // http://www.japantimes.co.jp/life/2009/10/11/lifestyle/japans-top-100-most-common-family-names/
		            "jp": ["Sato","Suzuki","Takahashi","Tanaka","Watanabe","Ito","Yamamoto","Nakamura","Kobayashi","Kato","Yoshida","Yamada","Sasaki","Yamaguchi","Saito","Matsumoto","Inoue","Kimura","Hayashi","Shimizu","Yamazaki","Mori","Abe","Ikeda","Hashimoto","Yamashita","Ishikawa","Nakajima","Maeda","Fujita","Ogawa","Goto","Okada","Hasegawa","Murakami","Kondo","Ishii","Saito","Sakamoto","Endo","Aoki","Fujii","Nishimura","Fukuda","Ota","Miura","Fujiwara","Okamoto","Matsuda","Nakagawa","Nakano","Harada","Ono","Tamura","Takeuchi","Kaneko","Wada","Nakayama","Ishida","Ueda","Morita","Hara","Shibata","Sakai","Kudo","Yokoyama","Miyazaki","Miyamoto","Uchida","Takagi","Ando","Taniguchi","Ohno","Maruyama","Imai","Takada","Fujimoto","Takeda","Murata","Ueno","Sugiyama","Masuda","Sugawara","Hirano","Kojima","Otsuka","Chiba","Kubo","Matsui","Iwasaki","Sakurai","Kinoshita","Noguchi","Matsuo","Nomura","Kikuchi","Sano","Onishi","Sugimoto","Arai"],
		            // http://www.lowchensaustralia.com/names/popular-spanish-names.htm
		            "es": ["Garcia","Fernandez","Lopez","Martinez","Gonzalez","Rodriguez","Sanchez","Perez","Martin","Gomez","Ruiz","Diaz","Hernandez","Alvarez","Jimenez","Moreno","Munoz","Alonso","Romero","Navarro","Gutierrez","Torres","Dominguez","Gil","Vazquez","Blanco","Serrano","Ramos","Castro","Suarez","Sanz","Rubio","Ortega","Molina","Delgado","Ortiz","Morales","Ramirez","Marin","Iglesias","Santos","Castillo","Garrido","Calvo","Pena","Cruz","Cano","Nunez","Prieto","Diez","Lozano","Vidal","Pascual","Ferrer","Medina","Vega","Leon","Herrero","Vicente","Mendez","Guerrero","Fuentes","Campos","Nieto","Cortes","Caballero","Ibanez","Lorenzo","Pastor","Gimenez","Saez","Soler","Marquez","Carrasco","Herrera","Montero","Arias","Crespo","Flores","Andres","Aguilar","Hidalgo","Cabrera","Mora","Duran","Velasco","Rey","Pardo","Roman","Vila","Bravo","Merino","Moya","Soto","Izquierdo","Reyes","Redondo","Marcos","Carmona","Menendez"],
		            // Data taken from https://fr.wikipedia.org/wiki/Liste_des_noms_de_famille_les_plus_courants_en_France
		            "fr": ["Martin","Bernard","Thomas","Petit","Robert","Richard","Durand","Dubois","Moreau","Laurent","Simon","Michel","Lefèvre","Leroy","Roux","David","Bertrand","Morel","Fournier","Girard","Bonnet","Dupont","Lambert","Fontaine","Rousseau","Vincent","Müller","Lefèvre","Faure","André","Mercier","Blanc","Guérin","Boyer","Garnier","Chevalier","François","Legrand","Gauthier","Garcia","Perrin","Robin","Clément","Morin","Nicolas","Henry","Roussel","Matthieu","Gautier","Masson","Marchand","Duval","Denis","Dumont","Marie","Lemaire","Noël","Meyer","Dufour","Meunier","Brun","Blanchard","Giraud","Joly","Rivière","Lucas","Brunet","Gaillard","Barbier","Arnaud","Martínez","Gérard","Roche","Renard","Schmitt","Roy","Leroux","Colin","Vidal","Caron","Picard","Roger","Fabre","Aubert","Lemoine","Renaud","Dumas","Lacroix","Olivier","Philippe","Bourgeois","Pierre","Benoît","Rey","Leclerc","Payet","Rolland","Leclercq","Guillaume","Lecomte","López","Jean","Dupuy","Guillot","Hubert","Berger","Carpentier","Sánchez","Dupuis","Moulin","Louis","Deschamps","Huet","Vasseur","Perez","Boucher","Fleury","Royer","Klein","Jacquet","Adam","Paris","Poirier","Marty","Aubry","Guyot","Carré","Charles","Renault","Charpentier","Ménard","Maillard","Baron","Bertin","Bailly","Hervé","Schneider","Fernández","Le GallGall","Collet","Léger","Bouvier","Julien","Prévost","Millet","Perrot","Daniel","Le RouxRoux","Cousin","Germain","Breton","Besson","Langlois","Rémi","Le GoffGoff","Pelletier","Lévêque","Perrier","Leblanc","Barré","Lebrun","Marchal","Weber","Mallet","Hamon","Boulanger","Jacob","Monnier","Michaud","Rodríguez","Guichard","Gillet","Étienne","Grondin","Poulain","Tessier","Chevallier","Collin","Chauvin","Da SilvaSilva","Bouchet","Gay","Lemaître","Bénard","Maréchal","Humbert","Reynaud","Antoine","Hoarau","Perret","Barthélemy","Cordier","Pichon","Lejeune","Gilbert","Lamy","Delaunay","Pasquier","Carlier","LaporteLaporte"]
		        },

		        // Data taken from http://geoportal.statistics.gov.uk/datasets/ons-postcode-directory-latest-centroids
		        postcodeAreas: [{code: 'AB'}, {code: 'AL'}, {code: 'B'}, {code: 'BA'}, {code: 'BB'}, {code: 'BD'}, {code: 'BH'}, {code: 'BL'}, {code: 'BN'}, {code: 'BR'}, {code: 'BS'}, {code: 'BT'}, {code: 'CA'}, {code: 'CB'}, {code: 'CF'}, {code: 'CH'}, {code: 'CM'}, {code: 'CO'}, {code: 'CR'}, {code: 'CT'}, {code: 'CV'}, {code: 'CW'}, {code: 'DA'}, {code: 'DD'}, {code: 'DE'}, {code: 'DG'}, {code: 'DH'}, {code: 'DL'}, {code: 'DN'}, {code: 'DT'}, {code: 'DY'}, {code: 'E'}, {code: 'EC'}, {code: 'EH'}, {code: 'EN'}, {code: 'EX'}, {code: 'FK'}, {code: 'FY'}, {code: 'G'}, {code: 'GL'}, {code: 'GU'}, {code: 'GY'}, {code: 'HA'}, {code: 'HD'}, {code: 'HG'}, {code: 'HP'}, {code: 'HR'}, {code: 'HS'}, {code: 'HU'}, {code: 'HX'}, {code: 'IG'}, {code: 'IM'}, {code: 'IP'}, {code: 'IV'}, {code: 'JE'}, {code: 'KA'}, {code: 'KT'}, {code: 'KW'}, {code: 'KY'}, {code: 'L'}, {code: 'LA'}, {code: 'LD'}, {code: 'LE'}, {code: 'LL'}, {code: 'LN'}, {code: 'LS'}, {code: 'LU'}, {code: 'M'}, {code: 'ME'}, {code: 'MK'}, {code: 'ML'}, {code: 'N'}, {code: 'NE'}, {code: 'NG'}, {code: 'NN'}, {code: 'NP'}, {code: 'NR'}, {code: 'NW'}, {code: 'OL'}, {code: 'OX'}, {code: 'PA'}, {code: 'PE'}, {code: 'PH'}, {code: 'PL'}, {code: 'PO'}, {code: 'PR'}, {code: 'RG'}, {code: 'RH'}, {code: 'RM'}, {code: 'S'}, {code: 'SA'}, {code: 'SE'}, {code: 'SG'}, {code: 'SK'}, {code: 'SL'}, {code: 'SM'}, {code: 'SN'}, {code: 'SO'}, {code: 'SP'}, {code: 'SR'}, {code: 'SS'}, {code: 'ST'}, {code: 'SW'}, {code: 'SY'}, {code: 'TA'}, {code: 'TD'}, {code: 'TF'}, {code: 'TN'}, {code: 'TQ'}, {code: 'TR'}, {code: 'TS'}, {code: 'TW'}, {code: 'UB'}, {code: 'W'}, {code: 'WA'}, {code: 'WC'}, {code: 'WD'}, {code: 'WF'}, {code: 'WN'}, {code: 'WR'}, {code: 'WS'}, {code: 'WV'}, {code: 'YO'}, {code: 'ZE'}],

		        // Data taken from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
		        countries: [{"name":"Afghanistan","abbreviation":"AF"},{"name":"Åland Islands","abbreviation":"AX"},{"name":"Albania","abbreviation":"AL"},{"name":"Algeria","abbreviation":"DZ"},{"name":"American Samoa","abbreviation":"AS"},{"name":"Andorra","abbreviation":"AD"},{"name":"Angola","abbreviation":"AO"},{"name":"Anguilla","abbreviation":"AI"},{"name":"Antarctica","abbreviation":"AQ"},{"name":"Antigua and Barbuda","abbreviation":"AG"},{"name":"Argentina","abbreviation":"AR"},{"name":"Armenia","abbreviation":"AM"},{"name":"Aruba","abbreviation":"AW"},{"name":"Australia","abbreviation":"AU"},{"name":"Austria","abbreviation":"AT"},{"name":"Azerbaijan","abbreviation":"AZ"},{"name":"Bahamas","abbreviation":"BS"},{"name":"Bahrain","abbreviation":"BH"},{"name":"Bangladesh","abbreviation":"BD"},{"name":"Barbados","abbreviation":"BB"},{"name":"Belarus","abbreviation":"BY"},{"name":"Belgium","abbreviation":"BE"},{"name":"Belize","abbreviation":"BZ"},{"name":"Benin","abbreviation":"BJ"},{"name":"Bermuda","abbreviation":"BM"},{"name":"Bhutan","abbreviation":"BT"},{"name":"Plurinational State of Bolivia","abbreviation":"BO"},{"name":"Bonaire, Sint Eustatius and Saba","abbreviation":"BQ"},{"name":"Bosnia and Herzegovina","abbreviation":"BA"},{"name":"Botswana","abbreviation":"BW"},{"name":"Bouvet Island","abbreviation":"BV"},{"name":"Brazil","abbreviation":"BR"},{"name":"British Indian Ocean Territory","abbreviation":"IO"},{"name":"Brunei Darussalam","abbreviation":"BN"},{"name":"Bulgaria","abbreviation":"BG"},{"name":"Burkina Faso","abbreviation":"BF"},{"name":"Burundi","abbreviation":"BI"},{"name":"Cabo Verde","abbreviation":"CV"},{"name":"Cambodia","abbreviation":"KH"},{"name":"Cameroon","abbreviation":"CM"},{"name":"Canada","abbreviation":"CA"},{"name":"Cayman Islands","abbreviation":"KY"},{"name":"Central African Republic","abbreviation":"CF"},{"name":"Chad","abbreviation":"TD"},{"name":"Chile","abbreviation":"CL"},{"name":"China","abbreviation":"CN"},{"name":"Christmas Island","abbreviation":"CX"},{"name":"Cocos (Keeling) Islands","abbreviation":"CC"},{"name":"Colombia","abbreviation":"CO"},{"name":"Comoros","abbreviation":"KM"},{"name":"Congo","abbreviation":"CG"},{"name":"Democratic Republic of the Congo","abbreviation":"CD"},{"name":"Cook Islands","abbreviation":"CK"},{"name":"Costa Rica","abbreviation":"CR"},{"name":"Côte d'Ivoire","abbreviation":"CI"},{"name":"Croatia","abbreviation":"HR"},{"name":"Cuba","abbreviation":"CU"},{"name":"Curaçao","abbreviation":"CW"},{"name":"Cyprus","abbreviation":"CY"},{"name":"Czechia","abbreviation":"CZ"},{"name":"Denmark","abbreviation":"DK"},{"name":"Djibouti","abbreviation":"DJ"},{"name":"Dominica","abbreviation":"DM"},{"name":"Dominican Republic","abbreviation":"DO"},{"name":"Ecuador","abbreviation":"EC"},{"name":"Egypt","abbreviation":"EG"},{"name":"El Salvador","abbreviation":"SV"},{"name":"Equatorial Guinea","abbreviation":"GQ"},{"name":"Eritrea","abbreviation":"ER"},{"name":"Estonia","abbreviation":"EE"},{"name":"Eswatini","abbreviation":"SZ"},{"name":"Ethiopia","abbreviation":"ET"},{"name":"Falkland Islands (Malvinas)","abbreviation":"FK"},{"name":"Faroe Islands","abbreviation":"FO"},{"name":"Fiji","abbreviation":"FJ"},{"name":"Finland","abbreviation":"FI"},{"name":"France","abbreviation":"FR"},{"name":"French Guiana","abbreviation":"GF"},{"name":"French Polynesia","abbreviation":"PF"},{"name":"French Southern Territories","abbreviation":"TF"},{"name":"Gabon","abbreviation":"GA"},{"name":"Gambia","abbreviation":"GM"},{"name":"Georgia","abbreviation":"GE"},{"name":"Germany","abbreviation":"DE"},{"name":"Ghana","abbreviation":"GH"},{"name":"Gibraltar","abbreviation":"GI"},{"name":"Greece","abbreviation":"GR"},{"name":"Greenland","abbreviation":"GL"},{"name":"Grenada","abbreviation":"GD"},{"name":"Guadeloupe","abbreviation":"GP"},{"name":"Guam","abbreviation":"GU"},{"name":"Guatemala","abbreviation":"GT"},{"name":"Guernsey","abbreviation":"GG"},{"name":"Guinea","abbreviation":"GN"},{"name":"Guinea-Bissau","abbreviation":"GW"},{"name":"Guyana","abbreviation":"GY"},{"name":"Haiti","abbreviation":"HT"},{"name":"Heard Island and McDonald Islands","abbreviation":"HM"},{"name":"Holy See","abbreviation":"VA"},{"name":"Honduras","abbreviation":"HN"},{"name":"Hong Kong","abbreviation":"HK"},{"name":"Hungary","abbreviation":"HU"},{"name":"Iceland","abbreviation":"IS"},{"name":"India","abbreviation":"IN"},{"name":"Indonesia","abbreviation":"ID"},{"name":"Islamic Republic of Iran","abbreviation":"IR"},{"name":"Iraq","abbreviation":"IQ"},{"name":"Ireland","abbreviation":"IE"},{"name":"Isle of Man","abbreviation":"IM"},{"name":"Israel","abbreviation":"IL"},{"name":"Italy","abbreviation":"IT"},{"name":"Jamaica","abbreviation":"JM"},{"name":"Japan","abbreviation":"JP"},{"name":"Jersey","abbreviation":"JE"},{"name":"Jordan","abbreviation":"JO"},{"name":"Kazakhstan","abbreviation":"KZ"},{"name":"Kenya","abbreviation":"KE"},{"name":"Kiribati","abbreviation":"KI"},{"name":"Democratic People's Republic of Korea","abbreviation":"KP"},{"name":"Republic of Korea","abbreviation":"KR"},{"name":"Kuwait","abbreviation":"KW"},{"name":"Kyrgyzstan","abbreviation":"KG"},{"name":"Lao People's Democratic Republic","abbreviation":"LA"},{"name":"Latvia","abbreviation":"LV"},{"name":"Lebanon","abbreviation":"LB"},{"name":"Lesotho","abbreviation":"LS"},{"name":"Liberia","abbreviation":"LR"},{"name":"Libya","abbreviation":"LY"},{"name":"Liechtenstein","abbreviation":"LI"},{"name":"Lithuania","abbreviation":"LT"},{"name":"Luxembourg","abbreviation":"LU"},{"name":"Macao","abbreviation":"MO"},{"name":"Madagascar","abbreviation":"MG"},{"name":"Malawi","abbreviation":"MW"},{"name":"Malaysia","abbreviation":"MY"},{"name":"Maldives","abbreviation":"MV"},{"name":"Mali","abbreviation":"ML"},{"name":"Malta","abbreviation":"MT"},{"name":"Marshall Islands","abbreviation":"MH"},{"name":"Martinique","abbreviation":"MQ"},{"name":"Mauritania","abbreviation":"MR"},{"name":"Mauritius","abbreviation":"MU"},{"name":"Mayotte","abbreviation":"YT"},{"name":"Mexico","abbreviation":"MX"},{"name":"Federated States of Micronesia","abbreviation":"FM"},{"name":"Republic of Moldova","abbreviation":"MD"},{"name":"Monaco","abbreviation":"MC"},{"name":"Mongolia","abbreviation":"MN"},{"name":"Montenegro","abbreviation":"ME"},{"name":"Montserrat","abbreviation":"MS"},{"name":"Morocco","abbreviation":"MA"},{"name":"Mozambique","abbreviation":"MZ"},{"name":"Myanmar","abbreviation":"MM"},{"name":"Namibia","abbreviation":"NA"},{"name":"Nauru","abbreviation":"NR"},{"name":"Nepal","abbreviation":"NP"},{"name":"Kingdom of the Netherlands","abbreviation":"NL"},{"name":"New Caledonia","abbreviation":"NC"},{"name":"New Zealand","abbreviation":"NZ"},{"name":"Nicaragua","abbreviation":"NI"},{"name":"Niger","abbreviation":"NE"},{"name":"Nigeria","abbreviation":"NG"},{"name":"Niue","abbreviation":"NU"},{"name":"Norfolk Island","abbreviation":"NF"},{"name":"North Macedonia","abbreviation":"MK"},{"name":"Northern Mariana Islands","abbreviation":"MP"},{"name":"Norway","abbreviation":"NO"},{"name":"Oman","abbreviation":"OM"},{"name":"Pakistan","abbreviation":"PK"},{"name":"Palau","abbreviation":"PW"},{"name":"State of Palestine","abbreviation":"PS"},{"name":"Panama","abbreviation":"PA"},{"name":"Papua New Guinea","abbreviation":"PG"},{"name":"Paraguay","abbreviation":"PY"},{"name":"Peru","abbreviation":"PE"},{"name":"Philippines","abbreviation":"PH"},{"name":"Pitcairn","abbreviation":"PN"},{"name":"Poland","abbreviation":"PL"},{"name":"Portugal","abbreviation":"PT"},{"name":"Puerto Rico","abbreviation":"PR"},{"name":"Qatar","abbreviation":"QA"},{"name":"Réunion","abbreviation":"RE"},{"name":"Romania","abbreviation":"RO"},{"name":"Russian Federation","abbreviation":"RU"},{"name":"Rwanda","abbreviation":"RW"},{"name":"Saint Barthélemy","abbreviation":"BL"},{"name":"Saint Helena, Ascension and Tristan da Cunha","abbreviation":"SH"},{"name":"Saint Kitts and Nevis","abbreviation":"KN"},{"name":"Saint Lucia","abbreviation":"LC"},{"name":"Saint Martin (French part)","abbreviation":"MF"},{"name":"Saint Pierre and Miquelon","abbreviation":"PM"},{"name":"Saint Vincent and the Grenadines","abbreviation":"VC"},{"name":"Samoa","abbreviation":"WS"},{"name":"San Marino","abbreviation":"SM"},{"name":"Sao Tome and Principe","abbreviation":"ST"},{"name":"Saudi Arabia","abbreviation":"SA"},{"name":"Senegal","abbreviation":"SN"},{"name":"Serbia","abbreviation":"RS"},{"name":"Seychelles","abbreviation":"SC"},{"name":"Sierra Leone","abbreviation":"SL"},{"name":"Singapore","abbreviation":"SG"},{"name":"Sint Maarten (Dutch part)","abbreviation":"SX"},{"name":"Slovakia","abbreviation":"SK"},{"name":"Slovenia","abbreviation":"SI"},{"name":"Solomon Islands","abbreviation":"SB"},{"name":"Somalia","abbreviation":"SO"},{"name":"South Africa","abbreviation":"ZA"},{"name":"South Georgia and the South Sandwich Islands","abbreviation":"GS"},{"name":"South Sudan","abbreviation":"SS"},{"name":"Spain","abbreviation":"ES"},{"name":"Sri Lanka","abbreviation":"LK"},{"name":"Sudan","abbreviation":"SD"},{"name":"Suriname","abbreviation":"SR"},{"name":"Svalbard and Jan Mayen","abbreviation":"SJ"},{"name":"Sweden","abbreviation":"SE"},{"name":"Switzerland","abbreviation":"CH"},{"name":"Syrian Arab Republic","abbreviation":"SY"},{"name":"Taiwan, Province of China","abbreviation":"TW"},{"name":"Tajikistan","abbreviation":"TJ"},{"name":"United Republic of Tanzania","abbreviation":"TZ"},{"name":"Thailand","abbreviation":"TH"},{"name":"Timor-Leste","abbreviation":"TL"},{"name":"Togo","abbreviation":"TG"},{"name":"Tokelau","abbreviation":"TK"},{"name":"Tonga","abbreviation":"TO"},{"name":"Trinidad and Tobago","abbreviation":"TT"},{"name":"Tunisia","abbreviation":"TN"},{"name":"Türkiye","abbreviation":"TR"},{"name":"Turkmenistan","abbreviation":"TM"},{"name":"Turks and Caicos Islands","abbreviation":"TC"},{"name":"Tuvalu","abbreviation":"TV"},{"name":"Uganda","abbreviation":"UG"},{"name":"Ukraine","abbreviation":"UA"},{"name":"United Arab Emirates","abbreviation":"AE"},{"name":"United Kingdom of Great Britain and Northern Ireland","abbreviation":"GB"},{"name":"United States Minor Outlying Islands","abbreviation":"UM"},{"name":"United States of America","abbreviation":"US"},{"name":"Uruguay","abbreviation":"UY"},{"name":"Uzbekistan","abbreviation":"UZ"},{"name":"Vanuatu","abbreviation":"VU"},{"name":"Bolivarian Republic of Venezuela","abbreviation":"VE"},{"name":"Viet Nam","abbreviation":"VN"},{"name":"Virgin Islands (British)","abbreviation":"VG"},{"name":"Virgin Islands (U.S.)","abbreviation":"VI"},{"name":"Wallis and Futuna","abbreviation":"WF"},{"name":"Western Sahara","abbreviation":"EH"},{"name":"Yemen","abbreviation":"YE"},{"name":"Zambia","abbreviation":"ZM"},{"name":"Zimbabwe","abbreviation":"ZW"}],

		                counties: {
		            // Data taken from http://www.downloadexcelfiles.com/gb_en/download-excel-file-list-counties-uk
		            "uk": [
		                {name: 'Bath and North East Somerset'},
		                {name: 'Aberdeenshire'},
		                {name: 'Anglesey'},
		                {name: 'Angus'},
		                {name: 'Bedford'},
		                {name: 'Blackburn with Darwen'},
		                {name: 'Blackpool'},
		                {name: 'Bournemouth'},
		                {name: 'Bracknell Forest'},
		                {name: 'Brighton & Hove'},
		                {name: 'Bristol'},
		                {name: 'Buckinghamshire'},
		                {name: 'Cambridgeshire'},
		                {name: 'Carmarthenshire'},
		                {name: 'Central Bedfordshire'},
		                {name: 'Ceredigion'},
		                {name: 'Cheshire East'},
		                {name: 'Cheshire West and Chester'},
		                {name: 'Clackmannanshire'},
		                {name: 'Conwy'},
		                {name: 'Cornwall'},
		                {name: 'County Antrim'},
		                {name: 'County Armagh'},
		                {name: 'County Down'},
		                {name: 'County Durham'},
		                {name: 'County Fermanagh'},
		                {name: 'County Londonderry'},
		                {name: 'County Tyrone'},
		                {name: 'Cumbria'},
		                {name: 'Darlington'},
		                {name: 'Denbighshire'},
		                {name: 'Derby'},
		                {name: 'Derbyshire'},
		                {name: 'Devon'},
		                {name: 'Dorset'},
		                {name: 'Dumfries and Galloway'},
		                {name: 'Dundee'},
		                {name: 'East Lothian'},
		                {name: 'East Riding of Yorkshire'},
		                {name: 'East Sussex'},
		                {name: 'Edinburgh?'},
		                {name: 'Essex'},
		                {name: 'Falkirk'},
		                {name: 'Fife'},
		                {name: 'Flintshire'},
		                {name: 'Gloucestershire'},
		                {name: 'Greater London'},
		                {name: 'Greater Manchester'},
		                {name: 'Gwent'},
		                {name: 'Gwynedd'},
		                {name: 'Halton'},
		                {name: 'Hampshire'},
		                {name: 'Hartlepool'},
		                {name: 'Herefordshire'},
		                {name: 'Hertfordshire'},
		                {name: 'Highlands'},
		                {name: 'Hull'},
		                {name: 'Isle of Wight'},
		                {name: 'Isles of Scilly'},
		                {name: 'Kent'},
		                {name: 'Lancashire'},
		                {name: 'Leicester'},
		                {name: 'Leicestershire'},
		                {name: 'Lincolnshire'},
		                {name: 'Lothian'},
		                {name: 'Luton'},
		                {name: 'Medway'},
		                {name: 'Merseyside'},
		                {name: 'Mid Glamorgan'},
		                {name: 'Middlesbrough'},
		                {name: 'Milton Keynes'},
		                {name: 'Monmouthshire'},
		                {name: 'Moray'},
		                {name: 'Norfolk'},
		                {name: 'North East Lincolnshire'},
		                {name: 'North Lincolnshire'},
		                {name: 'North Somerset'},
		                {name: 'North Yorkshire'},
		                {name: 'Northamptonshire'},
		                {name: 'Northumberland'},
		                {name: 'Nottingham'},
		                {name: 'Nottinghamshire'},
		                {name: 'Oxfordshire'},
		                {name: 'Pembrokeshire'},
		                {name: 'Perth and Kinross'},
		                {name: 'Peterborough'},
		                {name: 'Plymouth'},
		                {name: 'Poole'},
		                {name: 'Portsmouth'},
		                {name: 'Powys'},
		                {name: 'Reading'},
		                {name: 'Redcar and Cleveland'},
		                {name: 'Rutland'},
		                {name: 'Scottish Borders'},
		                {name: 'Shropshire'},
		                {name: 'Slough'},
		                {name: 'Somerset'},
		                {name: 'South Glamorgan'},
		                {name: 'South Gloucestershire'},
		                {name: 'South Yorkshire'},
		                {name: 'Southampton'},
		                {name: 'Southend-on-Sea'},
		                {name: 'Staffordshire'},
		                {name: 'Stirlingshire'},
		                {name: 'Stockton-on-Tees'},
		                {name: 'Stoke-on-Trent'},
		                {name: 'Strathclyde'},
		                {name: 'Suffolk'},
		                {name: 'Surrey'},
		                {name: 'Swindon'},
		                {name: 'Telford and Wrekin'},
		                {name: 'Thurrock'},
		                {name: 'Torbay'},
		                {name: 'Tyne and Wear'},
		                {name: 'Warrington'},
		                {name: 'Warwickshire'},
		                {name: 'West Berkshire'},
		                {name: 'West Glamorgan'},
		                {name: 'West Lothian'},
		                {name: 'West Midlands'},
		                {name: 'West Sussex'},
		                {name: 'West Yorkshire'},
		                {name: 'Western Isles'},
		                {name: 'Wiltshire'},
		                {name: 'Windsor and Maidenhead'},
		                {name: 'Wokingham'},
		                {name: 'Worcestershire'},
		                {name: 'Wrexham'},
		                {name: 'York'}]
		                                },
		        provinces: {
		            "ca": [
		                {name: 'Alberta', abbreviation: 'AB'},
		                {name: 'British Columbia', abbreviation: 'BC'},
		                {name: 'Manitoba', abbreviation: 'MB'},
		                {name: 'New Brunswick', abbreviation: 'NB'},
		                {name: 'Newfoundland and Labrador', abbreviation: 'NL'},
		                {name: 'Nova Scotia', abbreviation: 'NS'},
		                {name: 'Ontario', abbreviation: 'ON'},
		                {name: 'Prince Edward Island', abbreviation: 'PE'},
		                {name: 'Quebec', abbreviation: 'QC'},
		                {name: 'Saskatchewan', abbreviation: 'SK'},

		                // The case could be made that the following are not actually provinces
		                // since they are technically considered "territories" however they all
		                // look the same on an envelope!
		                {name: 'Northwest Territories', abbreviation: 'NT'},
		                {name: 'Nunavut', abbreviation: 'NU'},
		                {name: 'Yukon', abbreviation: 'YT'}
		            ],
		            "it": [
		                { name: "Agrigento", abbreviation: "AG", code: 84 },
		                { name: "Alessandria", abbreviation: "AL", code: 6 },
		                { name: "Ancona", abbreviation: "AN", code: 42 },
		                { name: "Aosta", abbreviation: "AO", code: 7 },
		                { name: "L'Aquila", abbreviation: "AQ", code: 66 },
		                { name: "Arezzo", abbreviation: "AR", code: 51 },
		                { name: "Ascoli-Piceno", abbreviation: "AP", code: 44 },
		                { name: "Asti", abbreviation: "AT", code: 5 },
		                { name: "Avellino", abbreviation: "AV", code: 64 },
		                { name: "Bari", abbreviation: "BA", code: 72 },
		                { name: "Barletta-Andria-Trani", abbreviation: "BT", code: 72 },
		                { name: "Belluno", abbreviation: "BL", code: 25 },
		                { name: "Benevento", abbreviation: "BN", code: 62 },
		                { name: "Bergamo", abbreviation: "BG", code: 16 },
		                { name: "Biella", abbreviation: "BI", code: 96 },
		                { name: "Bologna", abbreviation: "BO", code: 37 },
		                { name: "Bolzano", abbreviation: "BZ", code: 21 },
		                { name: "Brescia", abbreviation: "BS", code: 17 },
		                { name: "Brindisi", abbreviation: "BR", code: 74 },
		                { name: "Cagliari", abbreviation: "CA", code: 92 },
		                { name: "Caltanissetta", abbreviation: "CL", code: 85 },
		                { name: "Campobasso", abbreviation: "CB", code: 70 },
		                { name: "Carbonia Iglesias", abbreviation: "CI", code: 70 },
		                { name: "Caserta", abbreviation: "CE", code: 61 },
		                { name: "Catania", abbreviation: "CT", code: 87 },
		                { name: "Catanzaro", abbreviation: "CZ", code: 79 },
		                { name: "Chieti", abbreviation: "CH", code: 69 },
		                { name: "Como", abbreviation: "CO", code: 13 },
		                { name: "Cosenza", abbreviation: "CS", code: 78 },
		                { name: "Cremona", abbreviation: "CR", code: 19 },
		                { name: "Crotone", abbreviation: "KR", code: 101 },
		                { name: "Cuneo", abbreviation: "CN", code: 4 },
		                { name: "Enna", abbreviation: "EN", code: 86 },
		                { name: "Fermo", abbreviation: "FM", code: 86 },
		                { name: "Ferrara", abbreviation: "FE", code: 38 },
		                { name: "Firenze", abbreviation: "FI", code: 48 },
		                { name: "Foggia", abbreviation: "FG", code: 71 },
		                { name: "Forli-Cesena", abbreviation: "FC", code: 71 },
		                { name: "Frosinone", abbreviation: "FR", code: 60 },
		                { name: "Genova", abbreviation: "GE", code: 10 },
		                { name: "Gorizia", abbreviation: "GO", code: 31 },
		                { name: "Grosseto", abbreviation: "GR", code: 53 },
		                { name: "Imperia", abbreviation: "IM", code: 8 },
		                { name: "Isernia", abbreviation: "IS", code: 94 },
		                { name: "La-Spezia", abbreviation: "SP", code: 66 },
		                { name: "Latina", abbreviation: "LT", code: 59 },
		                { name: "Lecce", abbreviation: "LE", code: 75 },
		                { name: "Lecco", abbreviation: "LC", code: 97 },
		                { name: "Livorno", abbreviation: "LI", code: 49 },
		                { name: "Lodi", abbreviation: "LO", code: 98 },
		                { name: "Lucca", abbreviation: "LU", code: 46 },
		                { name: "Macerata", abbreviation: "MC", code: 43 },
		                { name: "Mantova", abbreviation: "MN", code: 20 },
		                { name: "Massa-Carrara", abbreviation: "MS", code: 45 },
		                { name: "Matera", abbreviation: "MT", code: 77 },
		                { name: "Medio Campidano", abbreviation: "VS", code: 77 },
		                { name: "Messina", abbreviation: "ME", code: 83 },
		                { name: "Milano", abbreviation: "MI", code: 15 },
		                { name: "Modena", abbreviation: "MO", code: 36 },
		                { name: "Monza-Brianza", abbreviation: "MB", code: 36 },
		                { name: "Napoli", abbreviation: "NA", code: 63 },
		                { name: "Novara", abbreviation: "NO", code: 3 },
		                { name: "Nuoro", abbreviation: "NU", code: 91 },
		                { name: "Ogliastra", abbreviation: "OG", code: 91 },
		                { name: "Olbia Tempio", abbreviation: "OT", code: 91 },
		                { name: "Oristano", abbreviation: "OR", code: 95 },
		                { name: "Padova", abbreviation: "PD", code: 28 },
		                { name: "Palermo", abbreviation: "PA", code: 82 },
		                { name: "Parma", abbreviation: "PR", code: 34 },
		                { name: "Pavia", abbreviation: "PV", code: 18 },
		                { name: "Perugia", abbreviation: "PG", code: 54 },
		                { name: "Pesaro-Urbino", abbreviation: "PU", code: 41 },
		                { name: "Pescara", abbreviation: "PE", code: 68 },
		                { name: "Piacenza", abbreviation: "PC", code: 33 },
		                { name: "Pisa", abbreviation: "PI", code: 50 },
		                { name: "Pistoia", abbreviation: "PT", code: 47 },
		                { name: "Pordenone", abbreviation: "PN", code: 93 },
		                { name: "Potenza", abbreviation: "PZ", code: 76 },
		                { name: "Prato", abbreviation: "PO", code: 100 },
		                { name: "Ragusa", abbreviation: "RG", code: 88 },
		                { name: "Ravenna", abbreviation: "RA", code: 39 },
		                { name: "Reggio-Calabria", abbreviation: "RC", code: 35 },
		                { name: "Reggio-Emilia", abbreviation: "RE", code: 35 },
		                { name: "Rieti", abbreviation: "RI", code: 57 },
		                { name: "Rimini", abbreviation: "RN", code: 99 },
		                { name: "Roma", abbreviation: "Roma", code: 58 },
		                { name: "Rovigo", abbreviation: "RO", code: 29 },
		                { name: "Salerno", abbreviation: "SA", code: 65 },
		                { name: "Sassari", abbreviation: "SS", code: 90 },
		                { name: "Savona", abbreviation: "SV", code: 9 },
		                { name: "Siena", abbreviation: "SI", code: 52 },
		                { name: "Siracusa", abbreviation: "SR", code: 89 },
		                { name: "Sondrio", abbreviation: "SO", code: 14 },
		                { name: "Taranto", abbreviation: "TA", code: 73 },
		                { name: "Teramo", abbreviation: "TE", code: 67 },
		                { name: "Terni", abbreviation: "TR", code: 55 },
		                { name: "Torino", abbreviation: "TO", code: 1 },
		                { name: "Trapani", abbreviation: "TP", code: 81 },
		                { name: "Trento", abbreviation: "TN", code: 22 },
		                { name: "Treviso", abbreviation: "TV", code: 26 },
		                { name: "Trieste", abbreviation: "TS", code: 32 },
		                { name: "Udine", abbreviation: "UD", code: 30 },
		                { name: "Varese", abbreviation: "VA", code: 12 },
		                { name: "Venezia", abbreviation: "VE", code: 27 },
		                { name: "Verbania", abbreviation: "VB", code: 27 },
		                { name: "Vercelli", abbreviation: "VC", code: 2 },
		                { name: "Verona", abbreviation: "VR", code: 23 },
		                { name: "Vibo-Valentia", abbreviation: "VV", code: 102 },
		                { name: "Vicenza", abbreviation: "VI", code: 24 },
		                { name: "Viterbo", abbreviation: "VT", code: 56 }
		            ]
		        },

		            // from: https://github.com/samsargent/Useful-Autocomplete-Data/blob/master/data/nationalities.json
		        nationalities: [
		           {name: 'Afghan'},
		           {name: 'Albanian'},
		           {name: 'Algerian'},
		           {name: 'American'},
		           {name: 'Andorran'},
		           {name: 'Angolan'},
		           {name: 'Antiguans'},
		           {name: 'Argentinean'},
		           {name: 'Armenian'},
		           {name: 'Australian'},
		           {name: 'Austrian'},
		           {name: 'Azerbaijani'},
		           {name: 'Bahami'},
		           {name: 'Bahraini'},
		           {name: 'Bangladeshi'},
		           {name: 'Barbadian'},
		           {name: 'Barbudans'},
		           {name: 'Batswana'},
		           {name: 'Belarusian'},
		           {name: 'Belgian'},
		           {name: 'Belizean'},
		           {name: 'Beninese'},
		           {name: 'Bhutanese'},
		           {name: 'Bolivian'},
		           {name: 'Bosnian'},
		           {name: 'Brazilian'},
		           {name: 'British'},
		           {name: 'Bruneian'},
		           {name: 'Bulgarian'},
		           {name: 'Burkinabe'},
		           {name: 'Burmese'},
		           {name: 'Burundian'},
		           {name: 'Cambodian'},
		           {name: 'Cameroonian'},
		           {name: 'Canadian'},
		           {name: 'Cape Verdean'},
		           {name: 'Central African'},
		           {name: 'Chadian'},
		           {name: 'Chilean'},
		           {name: 'Chinese'},
		           {name: 'Colombian'},
		           {name: 'Comoran'},
		           {name: 'Congolese'},
		           {name: 'Costa Rican'},
		           {name: 'Croatian'},
		           {name: 'Cuban'},
		           {name: 'Cypriot'},
		           {name: 'Czech'},
		           {name: 'Danish'},
		           {name: 'Djibouti'},
		           {name: 'Dominican'},
		           {name: 'Dutch'},
		           {name: 'East Timorese'},
		           {name: 'Ecuadorean'},
		           {name: 'Egyptian'},
		           {name: 'Emirian'},
		           {name: 'Equatorial Guinean'},
		           {name: 'Eritrean'},
		           {name: 'Estonian'},
		           {name: 'Ethiopian'},
		           {name: 'Fijian'},
		           {name: 'Filipino'},
		           {name: 'Finnish'},
		           {name: 'French'},
		           {name: 'Gabonese'},
		           {name: 'Gambian'},
		           {name: 'Georgian'},
		           {name: 'German'},
		           {name: 'Ghanaian'},
		           {name: 'Greek'},
		           {name: 'Grenadian'},
		           {name: 'Guatemalan'},
		           {name: 'Guinea-Bissauan'},
		           {name: 'Guinean'},
		           {name: 'Guyanese'},
		           {name: 'Haitian'},
		           {name: 'Herzegovinian'},
		           {name: 'Honduran'},
		           {name: 'Hungarian'},
		           {name: 'I-Kiribati'},
		           {name: 'Icelander'},
		           {name: 'Indian'},
		           {name: 'Indonesian'},
		           {name: 'Iranian'},
		           {name: 'Iraqi'},
		           {name: 'Irish'},
		           {name: 'Israeli'},
		           {name: 'Italian'},
		           {name: 'Ivorian'},
		           {name: 'Jamaican'},
		           {name: 'Japanese'},
		           {name: 'Jordanian'},
		           {name: 'Kazakhstani'},
		           {name: 'Kenyan'},
		           {name: 'Kittian and Nevisian'},
		           {name: 'Kuwaiti'},
		           {name: 'Kyrgyz'},
		           {name: 'Laotian'},
		           {name: 'Latvian'},
		           {name: 'Lebanese'},
		           {name: 'Liberian'},
		           {name: 'Libyan'},
		           {name: 'Liechtensteiner'},
		           {name: 'Lithuanian'},
		           {name: 'Luxembourger'},
		           {name: 'Macedonian'},
		           {name: 'Malagasy'},
		           {name: 'Malawian'},
		           {name: 'Malaysian'},
		           {name: 'Maldivan'},
		           {name: 'Malian'},
		           {name: 'Maltese'},
		           {name: 'Marshallese'},
		           {name: 'Mauritanian'},
		           {name: 'Mauritian'},
		           {name: 'Mexican'},
		           {name: 'Micronesian'},
		           {name: 'Moldovan'},
		           {name: 'Monacan'},
		           {name: 'Mongolian'},
		           {name: 'Moroccan'},
		           {name: 'Mosotho'},
		           {name: 'Motswana'},
		           {name: 'Mozambican'},
		           {name: 'Namibian'},
		           {name: 'Nauruan'},
		           {name: 'Nepalese'},
		           {name: 'New Zealander'},
		           {name: 'Nicaraguan'},
		           {name: 'Nigerian'},
		           {name: 'Nigerien'},
		           {name: 'North Korean'},
		           {name: 'Northern Irish'},
		           {name: 'Norwegian'},
		           {name: 'Omani'},
		           {name: 'Pakistani'},
		           {name: 'Palauan'},
		           {name: 'Panamanian'},
		           {name: 'Papua New Guinean'},
		           {name: 'Paraguayan'},
		           {name: 'Peruvian'},
		           {name: 'Polish'},
		           {name: 'Portuguese'},
		           {name: 'Qatari'},
		           {name: 'Romani'},
		           {name: 'Russian'},
		           {name: 'Rwandan'},
		           {name: 'Saint Lucian'},
		           {name: 'Salvadoran'},
		           {name: 'Samoan'},
		           {name: 'San Marinese'},
		           {name: 'Sao Tomean'},
		           {name: 'Saudi'},
		           {name: 'Scottish'},
		           {name: 'Senegalese'},
		           {name: 'Serbian'},
		           {name: 'Seychellois'},
		           {name: 'Sierra Leonean'},
		           {name: 'Singaporean'},
		           {name: 'Slovakian'},
		           {name: 'Slovenian'},
		           {name: 'Solomon Islander'},
		           {name: 'Somali'},
		           {name: 'South African'},
		           {name: 'South Korean'},
		           {name: 'Spanish'},
		           {name: 'Sri Lankan'},
		           {name: 'Sudanese'},
		           {name: 'Surinamer'},
		           {name: 'Swazi'},
		           {name: 'Swedish'},
		           {name: 'Swiss'},
		           {name: 'Syrian'},
		           {name: 'Taiwanese'},
		           {name: 'Tajik'},
		           {name: 'Tanzanian'},
		           {name: 'Thai'},
		           {name: 'Togolese'},
		           {name: 'Tongan'},
		           {name: 'Trinidadian or Tobagonian'},
		           {name: 'Tunisian'},
		           {name: 'Turkish'},
		           {name: 'Tuvaluan'},
		           {name: 'Ugandan'},
		           {name: 'Ukrainian'},
		           {name: 'Uruguaya'},
		           {name: 'Uzbekistani'},
		           {name: 'Venezuela'},
		           {name: 'Vietnamese'},
		           {name: 'Wels'},
		           {name: 'Yemenit'},
		           {name: 'Zambia'},
		           {name: 'Zimbabwe'},
		        ],
		          // http://www.loc.gov/standards/iso639-2/php/code_list.php (ISO-639-1 codes)
		        locale_languages: [
		          "aa",
		          "ab",
		          "ae",
		          "af",
		          "ak",
		          "am",
		          "an",
		          "ar",
		          "as",
		          "av",
		          "ay",
		          "az",
		          "ba",
		          "be",
		          "bg",
		          "bh",
		          "bi",
		          "bm",
		          "bn",
		          "bo",
		          "br",
		          "bs",
		          "ca",
		          "ce",
		          "ch",
		          "co",
		          "cr",
		          "cs",
		          "cu",
		          "cv",
		          "cy",
		          "da",
		          "de",
		          "dv",
		          "dz",
		          "ee",
		          "el",
		          "en",
		          "eo",
		          "es",
		          "et",
		          "eu",
		          "fa",
		          "ff",
		          "fi",
		          "fj",
		          "fo",
		          "fr",
		          "fy",
		          "ga",
		          "gd",
		          "gl",
		          "gn",
		          "gu",
		          "gv",
		          "ha",
		          "he",
		          "hi",
		          "ho",
		          "hr",
		          "ht",
		          "hu",
		          "hy",
		          "hz",
		          "ia",
		          "id",
		          "ie",
		          "ig",
		          "ii",
		          "ik",
		          "io",
		          "is",
		          "it",
		          "iu",
		          "ja",
		          "jv",
		          "ka",
		          "kg",
		          "ki",
		          "kj",
		          "kk",
		          "kl",
		          "km",
		          "kn",
		          "ko",
		          "kr",
		          "ks",
		          "ku",
		          "kv",
		          "kw",
		          "ky",
		          "la",
		          "lb",
		          "lg",
		          "li",
		          "ln",
		          "lo",
		          "lt",
		          "lu",
		          "lv",
		          "mg",
		          "mh",
		          "mi",
		          "mk",
		          "ml",
		          "mn",
		          "mr",
		          "ms",
		          "mt",
		          "my",
		          "na",
		          "nb",
		          "nd",
		          "ne",
		          "ng",
		          "nl",
		          "nn",
		          "no",
		          "nr",
		          "nv",
		          "ny",
		          "oc",
		          "oj",
		          "om",
		          "or",
		          "os",
		          "pa",
		          "pi",
		          "pl",
		          "ps",
		          "pt",
		          "qu",
		          "rm",
		          "rn",
		          "ro",
		          "ru",
		          "rw",
		          "sa",
		          "sc",
		          "sd",
		          "se",
		          "sg",
		          "si",
		          "sk",
		          "sl",
		          "sm",
		          "sn",
		          "so",
		          "sq",
		          "sr",
		          "ss",
		          "st",
		          "su",
		          "sv",
		          "sw",
		          "ta",
		          "te",
		          "tg",
		          "th",
		          "ti",
		          "tk",
		          "tl",
		          "tn",
		          "to",
		          "tr",
		          "ts",
		          "tt",
		          "tw",
		          "ty",
		          "ug",
		          "uk",
		          "ur",
		          "uz",
		          "ve",
		          "vi",
		          "vo",
		          "wa",
		          "wo",
		          "xh",
		          "yi",
		          "yo",
		          "za",
		          "zh",
		          "zu"
		        ],

		        // From http://data.okfn.org/data/core/language-codes#resource-language-codes-full (IETF language tags)
		        locale_regions: [
		          "agq-CM",
		          "asa-TZ",
		          "ast-ES",
		          "bas-CM",
		          "bem-ZM",
		          "bez-TZ",
		          "brx-IN",
		          "cgg-UG",
		          "chr-US",
		          "dav-KE",
		          "dje-NE",
		          "dsb-DE",
		          "dua-CM",
		          "dyo-SN",
		          "ebu-KE",
		          "ewo-CM",
		          "fil-PH",
		          "fur-IT",
		          "gsw-CH",
		          "gsw-FR",
		          "gsw-LI",
		          "guz-KE",
		          "haw-US",
		          "hsb-DE",
		          "jgo-CM",
		          "jmc-TZ",
		          "kab-DZ",
		          "kam-KE",
		          "kde-TZ",
		          "kea-CV",
		          "khq-ML",
		          "kkj-CM",
		          "kln-KE",
		          "kok-IN",
		          "ksb-TZ",
		          "ksf-CM",
		          "ksh-DE",
		          "lag-TZ",
		          "lkt-US",
		          "luo-KE",
		          "luy-KE",
		          "mas-KE",
		          "mas-TZ",
		          "mer-KE",
		          "mfe-MU",
		          "mgh-MZ",
		          "mgo-CM",
		          "mua-CM",
		          "naq-NA",
		          "nmg-CM",
		          "nnh-CM",
		          "nus-SD",
		          "nyn-UG",
		          "rof-TZ",
		          "rwk-TZ",
		          "sah-RU",
		          "saq-KE",
		          "sbp-TZ",
		          "seh-MZ",
		          "ses-ML",
		          "shi-Latn",
		          "shi-Latn-MA",
		          "shi-Tfng",
		          "shi-Tfng-MA",
		          "smn-FI",
		          "teo-KE",
		          "teo-UG",
		          "twq-NE",
		          "tzm-Latn",
		          "tzm-Latn-MA",
		          "vai-Latn",
		          "vai-Latn-LR",
		          "vai-Vaii",
		          "vai-Vaii-LR",
		          "vun-TZ",
		          "wae-CH",
		          "xog-UG",
		          "yav-CM",
		          "zgh-MA",
		          "af-NA",
		          "af-ZA",
		          "ak-GH",
		          "am-ET",
		          "ar-001",
		          "ar-AE",
		          "ar-BH",
		          "ar-DJ",
		          "ar-DZ",
		          "ar-EG",
		          "ar-EH",
		          "ar-ER",
		          "ar-IL",
		          "ar-IQ",
		          "ar-JO",
		          "ar-KM",
		          "ar-KW",
		          "ar-LB",
		          "ar-LY",
		          "ar-MA",
		          "ar-MR",
		          "ar-OM",
		          "ar-PS",
		          "ar-QA",
		          "ar-SA",
		          "ar-SD",
		          "ar-SO",
		          "ar-SS",
		          "ar-SY",
		          "ar-TD",
		          "ar-TN",
		          "ar-YE",
		          "as-IN",
		          "az-Cyrl",
		          "az-Cyrl-AZ",
		          "az-Latn",
		          "az-Latn-AZ",
		          "be-BY",
		          "bg-BG",
		          "bm-Latn",
		          "bm-Latn-ML",
		          "bn-BD",
		          "bn-IN",
		          "bo-CN",
		          "bo-IN",
		          "br-FR",
		          "bs-Cyrl",
		          "bs-Cyrl-BA",
		          "bs-Latn",
		          "bs-Latn-BA",
		          "ca-AD",
		          "ca-ES",
		          "ca-ES-VALENCIA",
		          "ca-FR",
		          "ca-IT",
		          "cs-CZ",
		          "cy-GB",
		          "da-DK",
		          "da-GL",
		          "de-AT",
		          "de-BE",
		          "de-CH",
		          "de-DE",
		          "de-LI",
		          "de-LU",
		          "dz-BT",
		          "ee-GH",
		          "ee-TG",
		          "el-CY",
		          "el-GR",
		          "en-001",
		          "en-150",
		          "en-AG",
		          "en-AI",
		          "en-AS",
		          "en-AU",
		          "en-BB",
		          "en-BE",
		          "en-BM",
		          "en-BS",
		          "en-BW",
		          "en-BZ",
		          "en-CA",
		          "en-CC",
		          "en-CK",
		          "en-CM",
		          "en-CX",
		          "en-DG",
		          "en-DM",
		          "en-ER",
		          "en-FJ",
		          "en-FK",
		          "en-FM",
		          "en-GB",
		          "en-GD",
		          "en-GG",
		          "en-GH",
		          "en-GI",
		          "en-GM",
		          "en-GU",
		          "en-GY",
		          "en-HK",
		          "en-IE",
		          "en-IM",
		          "en-IN",
		          "en-IO",
		          "en-JE",
		          "en-JM",
		          "en-KE",
		          "en-KI",
		          "en-KN",
		          "en-KY",
		          "en-LC",
		          "en-LR",
		          "en-LS",
		          "en-MG",
		          "en-MH",
		          "en-MO",
		          "en-MP",
		          "en-MS",
		          "en-MT",
		          "en-MU",
		          "en-MW",
		          "en-MY",
		          "en-NA",
		          "en-NF",
		          "en-NG",
		          "en-NR",
		          "en-NU",
		          "en-NZ",
		          "en-PG",
		          "en-PH",
		          "en-PK",
		          "en-PN",
		          "en-PR",
		          "en-PW",
		          "en-RW",
		          "en-SB",
		          "en-SC",
		          "en-SD",
		          "en-SG",
		          "en-SH",
		          "en-SL",
		          "en-SS",
		          "en-SX",
		          "en-SZ",
		          "en-TC",
		          "en-TK",
		          "en-TO",
		          "en-TT",
		          "en-TV",
		          "en-TZ",
		          "en-UG",
		          "en-UM",
		          "en-US",
		          "en-US-POSIX",
		          "en-VC",
		          "en-VG",
		          "en-VI",
		          "en-VU",
		          "en-WS",
		          "en-ZA",
		          "en-ZM",
		          "en-ZW",
		          "eo-001",
		          "es-419",
		          "es-AR",
		          "es-BO",
		          "es-CL",
		          "es-CO",
		          "es-CR",
		          "es-CU",
		          "es-DO",
		          "es-EA",
		          "es-EC",
		          "es-ES",
		          "es-GQ",
		          "es-GT",
		          "es-HN",
		          "es-IC",
		          "es-MX",
		          "es-NI",
		          "es-PA",
		          "es-PE",
		          "es-PH",
		          "es-PR",
		          "es-PY",
		          "es-SV",
		          "es-US",
		          "es-UY",
		          "es-VE",
		          "et-EE",
		          "eu-ES",
		          "fa-AF",
		          "fa-IR",
		          "ff-CM",
		          "ff-GN",
		          "ff-MR",
		          "ff-SN",
		          "fi-FI",
		          "fo-FO",
		          "fr-BE",
		          "fr-BF",
		          "fr-BI",
		          "fr-BJ",
		          "fr-BL",
		          "fr-CA",
		          "fr-CD",
		          "fr-CF",
		          "fr-CG",
		          "fr-CH",
		          "fr-CI",
		          "fr-CM",
		          "fr-DJ",
		          "fr-DZ",
		          "fr-FR",
		          "fr-GA",
		          "fr-GF",
		          "fr-GN",
		          "fr-GP",
		          "fr-GQ",
		          "fr-HT",
		          "fr-KM",
		          "fr-LU",
		          "fr-MA",
		          "fr-MC",
		          "fr-MF",
		          "fr-MG",
		          "fr-ML",
		          "fr-MQ",
		          "fr-MR",
		          "fr-MU",
		          "fr-NC",
		          "fr-NE",
		          "fr-PF",
		          "fr-PM",
		          "fr-RE",
		          "fr-RW",
		          "fr-SC",
		          "fr-SN",
		          "fr-SY",
		          "fr-TD",
		          "fr-TG",
		          "fr-TN",
		          "fr-VU",
		          "fr-WF",
		          "fr-YT",
		          "fy-NL",
		          "ga-IE",
		          "gd-GB",
		          "gl-ES",
		          "gu-IN",
		          "gv-IM",
		          "ha-Latn",
		          "ha-Latn-GH",
		          "ha-Latn-NE",
		          "ha-Latn-NG",
		          "he-IL",
		          "hi-IN",
		          "hr-BA",
		          "hr-HR",
		          "hu-HU",
		          "hy-AM",
		          "id-ID",
		          "ig-NG",
		          "ii-CN",
		          "is-IS",
		          "it-CH",
		          "it-IT",
		          "it-SM",
		          "ja-JP",
		          "ka-GE",
		          "ki-KE",
		          "kk-Cyrl",
		          "kk-Cyrl-KZ",
		          "kl-GL",
		          "km-KH",
		          "kn-IN",
		          "ko-KP",
		          "ko-KR",
		          "ks-Arab",
		          "ks-Arab-IN",
		          "kw-GB",
		          "ky-Cyrl",
		          "ky-Cyrl-KG",
		          "lb-LU",
		          "lg-UG",
		          "ln-AO",
		          "ln-CD",
		          "ln-CF",
		          "ln-CG",
		          "lo-LA",
		          "lt-LT",
		          "lu-CD",
		          "lv-LV",
		          "mg-MG",
		          "mk-MK",
		          "ml-IN",
		          "mn-Cyrl",
		          "mn-Cyrl-MN",
		          "mr-IN",
		          "ms-Latn",
		          "ms-Latn-BN",
		          "ms-Latn-MY",
		          "ms-Latn-SG",
		          "mt-MT",
		          "my-MM",
		          "nb-NO",
		          "nb-SJ",
		          "nd-ZW",
		          "ne-IN",
		          "ne-NP",
		          "nl-AW",
		          "nl-BE",
		          "nl-BQ",
		          "nl-CW",
		          "nl-NL",
		          "nl-SR",
		          "nl-SX",
		          "nn-NO",
		          "om-ET",
		          "om-KE",
		          "or-IN",
		          "os-GE",
		          "os-RU",
		          "pa-Arab",
		          "pa-Arab-PK",
		          "pa-Guru",
		          "pa-Guru-IN",
		          "pl-PL",
		          "ps-AF",
		          "pt-AO",
		          "pt-BR",
		          "pt-CV",
		          "pt-GW",
		          "pt-MO",
		          "pt-MZ",
		          "pt-PT",
		          "pt-ST",
		          "pt-TL",
		          "qu-BO",
		          "qu-EC",
		          "qu-PE",
		          "rm-CH",
		          "rn-BI",
		          "ro-MD",
		          "ro-RO",
		          "ru-BY",
		          "ru-KG",
		          "ru-KZ",
		          "ru-MD",
		          "ru-RU",
		          "ru-UA",
		          "rw-RW",
		          "se-FI",
		          "se-NO",
		          "se-SE",
		          "sg-CF",
		          "si-LK",
		          "sk-SK",
		          "sl-SI",
		          "sn-ZW",
		          "so-DJ",
		          "so-ET",
		          "so-KE",
		          "so-SO",
		          "sq-AL",
		          "sq-MK",
		          "sq-XK",
		          "sr-Cyrl",
		          "sr-Cyrl-BA",
		          "sr-Cyrl-ME",
		          "sr-Cyrl-RS",
		          "sr-Cyrl-XK",
		          "sr-Latn",
		          "sr-Latn-BA",
		          "sr-Latn-ME",
		          "sr-Latn-RS",
		          "sr-Latn-XK",
		          "sv-AX",
		          "sv-FI",
		          "sv-SE",
		          "sw-CD",
		          "sw-KE",
		          "sw-TZ",
		          "sw-UG",
		          "ta-IN",
		          "ta-LK",
		          "ta-MY",
		          "ta-SG",
		          "te-IN",
		          "th-TH",
		          "ti-ER",
		          "ti-ET",
		          "to-TO",
		          "tr-CY",
		          "tr-TR",
		          "ug-Arab",
		          "ug-Arab-CN",
		          "uk-UA",
		          "ur-IN",
		          "ur-PK",
		          "uz-Arab",
		          "uz-Arab-AF",
		          "uz-Cyrl",
		          "uz-Cyrl-UZ",
		          "uz-Latn",
		          "uz-Latn-UZ",
		          "vi-VN",
		          "yi-001",
		          "yo-BJ",
		          "yo-NG",
		          "zh-Hans",
		          "zh-Hans-CN",
		          "zh-Hans-HK",
		          "zh-Hans-MO",
		          "zh-Hans-SG",
		          "zh-Hant",
		          "zh-Hant-HK",
		          "zh-Hant-MO",
		          "zh-Hant-TW",
		          "zu-ZA"
		        ],

		        us_states_and_dc: [
		            {name: 'Alabama', abbreviation: 'AL'},
		            {name: 'Alaska', abbreviation: 'AK'},
		            {name: 'Arizona', abbreviation: 'AZ'},
		            {name: 'Arkansas', abbreviation: 'AR'},
		            {name: 'California', abbreviation: 'CA'},
		            {name: 'Colorado', abbreviation: 'CO'},
		            {name: 'Connecticut', abbreviation: 'CT'},
		            {name: 'Delaware', abbreviation: 'DE'},
		            {name: 'District of Columbia', abbreviation: 'DC'},
		            {name: 'Florida', abbreviation: 'FL'},
		            {name: 'Georgia', abbreviation: 'GA'},
		            {name: 'Hawaii', abbreviation: 'HI'},
		            {name: 'Idaho', abbreviation: 'ID'},
		            {name: 'Illinois', abbreviation: 'IL'},
		            {name: 'Indiana', abbreviation: 'IN'},
		            {name: 'Iowa', abbreviation: 'IA'},
		            {name: 'Kansas', abbreviation: 'KS'},
		            {name: 'Kentucky', abbreviation: 'KY'},
		            {name: 'Louisiana', abbreviation: 'LA'},
		            {name: 'Maine', abbreviation: 'ME'},
		            {name: 'Maryland', abbreviation: 'MD'},
		            {name: 'Massachusetts', abbreviation: 'MA'},
		            {name: 'Michigan', abbreviation: 'MI'},
		            {name: 'Minnesota', abbreviation: 'MN'},
		            {name: 'Mississippi', abbreviation: 'MS'},
		            {name: 'Missouri', abbreviation: 'MO'},
		            {name: 'Montana', abbreviation: 'MT'},
		            {name: 'Nebraska', abbreviation: 'NE'},
		            {name: 'Nevada', abbreviation: 'NV'},
		            {name: 'New Hampshire', abbreviation: 'NH'},
		            {name: 'New Jersey', abbreviation: 'NJ'},
		            {name: 'New Mexico', abbreviation: 'NM'},
		            {name: 'New York', abbreviation: 'NY'},
		            {name: 'North Carolina', abbreviation: 'NC'},
		            {name: 'North Dakota', abbreviation: 'ND'},
		            {name: 'Ohio', abbreviation: 'OH'},
		            {name: 'Oklahoma', abbreviation: 'OK'},
		            {name: 'Oregon', abbreviation: 'OR'},
		            {name: 'Pennsylvania', abbreviation: 'PA'},
		            {name: 'Rhode Island', abbreviation: 'RI'},
		            {name: 'South Carolina', abbreviation: 'SC'},
		            {name: 'South Dakota', abbreviation: 'SD'},
		            {name: 'Tennessee', abbreviation: 'TN'},
		            {name: 'Texas', abbreviation: 'TX'},
		            {name: 'Utah', abbreviation: 'UT'},
		            {name: 'Vermont', abbreviation: 'VT'},
		            {name: 'Virginia', abbreviation: 'VA'},
		            {name: 'Washington', abbreviation: 'WA'},
		            {name: 'West Virginia', abbreviation: 'WV'},
		            {name: 'Wisconsin', abbreviation: 'WI'},
		            {name: 'Wyoming', abbreviation: 'WY'}
		        ],

		        territories: [
		            {name: 'American Samoa', abbreviation: 'AS'},
		            {name: 'Federated States of Micronesia', abbreviation: 'FM'},
		            {name: 'Guam', abbreviation: 'GU'},
		            {name: 'Marshall Islands', abbreviation: 'MH'},
		            {name: 'Northern Mariana Islands', abbreviation: 'MP'},
		            {name: 'Puerto Rico', abbreviation: 'PR'},
		            {name: 'Virgin Islands, U.S.', abbreviation: 'VI'}
		        ],

		        armed_forces: [
		            {name: 'Armed Forces Europe', abbreviation: 'AE'},
		            {name: 'Armed Forces Pacific', abbreviation: 'AP'},
		            {name: 'Armed Forces the Americas', abbreviation: 'AA'}
		        ],

		        country_regions: {
		            it: [
		                { name: "Valle d'Aosta", abbreviation: "VDA" },
		                { name: "Piemonte", abbreviation: "PIE" },
		                { name: "Lombardia", abbreviation: "LOM" },
		                { name: "Veneto", abbreviation: "VEN" },
		                { name: "Trentino Alto Adige", abbreviation: "TAA" },
		                { name: "Friuli Venezia Giulia", abbreviation: "FVG" },
		                { name: "Liguria", abbreviation: "LIG" },
		                { name: "Emilia Romagna", abbreviation: "EMR" },
		                { name: "Toscana", abbreviation: "TOS" },
		                { name: "Umbria", abbreviation: "UMB" },
		                { name: "Marche", abbreviation: "MAR" },
		                { name: "Abruzzo", abbreviation: "ABR" },
		                { name: "Lazio", abbreviation: "LAZ" },
		                { name: "Campania", abbreviation: "CAM" },
		                { name: "Puglia", abbreviation: "PUG" },
		                { name: "Basilicata", abbreviation: "BAS" },
		                { name: "Molise", abbreviation: "MOL" },
		                { name: "Calabria", abbreviation: "CAL" },
		                { name: "Sicilia", abbreviation: "SIC" },
		                { name: "Sardegna", abbreviation: "SAR" }
		            ],
		            mx: [
		                { name: 'Aguascalientes', abbreviation: 'AGU' },
		                { name: 'Baja California', abbreviation: 'BCN' },
		                { name: 'Baja California Sur', abbreviation: 'BCS' },
		                { name: 'Campeche', abbreviation: 'CAM' },
		                { name: 'Chiapas', abbreviation: 'CHP' },
		                { name: 'Chihuahua', abbreviation: 'CHH' },
		                { name: 'Ciudad de México', abbreviation: 'DIF' },
		                { name: 'Coahuila', abbreviation: 'COA' },
		                { name: 'Colima', abbreviation: 'COL' },
		                { name: 'Durango', abbreviation: 'DUR' },
		                { name: 'Guanajuato', abbreviation: 'GUA' },
		                { name: 'Guerrero', abbreviation: 'GRO' },
		                { name: 'Hidalgo', abbreviation: 'HID' },
		                { name: 'Jalisco', abbreviation: 'JAL' },
		                { name: 'México', abbreviation: 'MEX' },
		                { name: 'Michoacán', abbreviation: 'MIC' },
		                { name: 'Morelos', abbreviation: 'MOR' },
		                { name: 'Nayarit', abbreviation: 'NAY' },
		                { name: 'Nuevo León', abbreviation: 'NLE' },
		                { name: 'Oaxaca', abbreviation: 'OAX' },
		                { name: 'Puebla', abbreviation: 'PUE' },
		                { name: 'Querétaro', abbreviation: 'QUE' },
		                { name: 'Quintana Roo', abbreviation: 'ROO' },
		                { name: 'San Luis Potosí', abbreviation: 'SLP' },
		                { name: 'Sinaloa', abbreviation: 'SIN' },
		                { name: 'Sonora', abbreviation: 'SON' },
		                { name: 'Tabasco', abbreviation: 'TAB' },
		                { name: 'Tamaulipas', abbreviation: 'TAM' },
		                { name: 'Tlaxcala', abbreviation: 'TLA' },
		                { name: 'Veracruz', abbreviation: 'VER' },
		                { name: 'Yucatán', abbreviation: 'YUC' },
		                { name: 'Zacatecas', abbreviation: 'ZAC' }
		            ]
		        },

		        street_suffixes: {
		            'us': [
		                {name: 'Avenue', abbreviation: 'Ave'},
		                {name: 'Boulevard', abbreviation: 'Blvd'},
		                {name: 'Center', abbreviation: 'Ctr'},
		                {name: 'Circle', abbreviation: 'Cir'},
		                {name: 'Court', abbreviation: 'Ct'},
		                {name: 'Drive', abbreviation: 'Dr'},
		                {name: 'Extension', abbreviation: 'Ext'},
		                {name: 'Glen', abbreviation: 'Gln'},
		                {name: 'Grove', abbreviation: 'Grv'},
		                {name: 'Heights', abbreviation: 'Hts'},
		                {name: 'Highway', abbreviation: 'Hwy'},
		                {name: 'Junction', abbreviation: 'Jct'},
		                {name: 'Key', abbreviation: 'Key'},
		                {name: 'Lane', abbreviation: 'Ln'},
		                {name: 'Loop', abbreviation: 'Loop'},
		                {name: 'Manor', abbreviation: 'Mnr'},
		                {name: 'Mill', abbreviation: 'Mill'},
		                {name: 'Park', abbreviation: 'Park'},
		                {name: 'Parkway', abbreviation: 'Pkwy'},
		                {name: 'Pass', abbreviation: 'Pass'},
		                {name: 'Path', abbreviation: 'Path'},
		                {name: 'Pike', abbreviation: 'Pike'},
		                {name: 'Place', abbreviation: 'Pl'},
		                {name: 'Plaza', abbreviation: 'Plz'},
		                {name: 'Point', abbreviation: 'Pt'},
		                {name: 'Ridge', abbreviation: 'Rdg'},
		                {name: 'River', abbreviation: 'Riv'},
		                {name: 'Road', abbreviation: 'Rd'},
		                {name: 'Square', abbreviation: 'Sq'},
		                {name: 'Street', abbreviation: 'St'},
		                {name: 'Terrace', abbreviation: 'Ter'},
		                {name: 'Trail', abbreviation: 'Trl'},
		                {name: 'Turnpike', abbreviation: 'Tpke'},
		                {name: 'View', abbreviation: 'Vw'},
		                {name: 'Way', abbreviation: 'Way'}
		            ],
		            'it': [
		                { name: 'Accesso', abbreviation: 'Acc.' },
		                { name: 'Alzaia', abbreviation: 'Alz.' },
		                { name: 'Arco', abbreviation: 'Arco' },
		                { name: 'Archivolto', abbreviation: 'Acv.' },
		                { name: 'Arena', abbreviation: 'Arena' },
		                { name: 'Argine', abbreviation: 'Argine' },
		                { name: 'Bacino', abbreviation: 'Bacino' },
		                { name: 'Banchi', abbreviation: 'Banchi' },
		                { name: 'Banchina', abbreviation: 'Ban.' },
		                { name: 'Bastioni', abbreviation: 'Bas.' },
		                { name: 'Belvedere', abbreviation: 'Belv.' },
		                { name: 'Borgata', abbreviation: 'B.ta' },
		                { name: 'Borgo', abbreviation: 'B.go' },
		                { name: 'Calata', abbreviation: 'Cal.' },
		                { name: 'Calle', abbreviation: 'Calle' },
		                { name: 'Campiello', abbreviation: 'Cam.' },
		                { name: 'Campo', abbreviation: 'Cam.' },
		                { name: 'Canale', abbreviation: 'Can.' },
		                { name: 'Carraia', abbreviation: 'Carr.' },
		                { name: 'Cascina', abbreviation: 'Cascina' },
		                { name: 'Case sparse', abbreviation: 'c.s.' },
		                { name: 'Cavalcavia', abbreviation: 'Cv.' },
		                { name: 'Circonvallazione', abbreviation: 'Cv.' },
		                { name: 'Complanare', abbreviation: 'C.re' },
		                { name: 'Contrada', abbreviation: 'C.da' },
		                { name: 'Corso', abbreviation: 'C.so' },
		                { name: 'Corte', abbreviation: 'C.te' },
		                { name: 'Cortile', abbreviation: 'C.le' },
		                { name: 'Diramazione', abbreviation: 'Dir.' },
		                { name: 'Fondaco', abbreviation: 'F.co' },
		                { name: 'Fondamenta', abbreviation: 'F.ta' },
		                { name: 'Fondo', abbreviation: 'F.do' },
		                { name: 'Frazione', abbreviation: 'Fr.' },
		                { name: 'Isola', abbreviation: 'Is.' },
		                { name: 'Largo', abbreviation: 'L.go' },
		                { name: 'Litoranea', abbreviation: 'Lit.' },
		                { name: 'Lungolago', abbreviation: 'L.go lago' },
		                { name: 'Lungo Po', abbreviation: 'l.go Po' },
		                { name: 'Molo', abbreviation: 'Molo' },
		                { name: 'Mura', abbreviation: 'Mura' },
		                { name: 'Passaggio privato', abbreviation: 'pass. priv.' },
		                { name: 'Passeggiata', abbreviation: 'Pass.' },
		                { name: 'Piazza', abbreviation: 'P.zza' },
		                { name: 'Piazzale', abbreviation: 'P.le' },
		                { name: 'Ponte', abbreviation: 'P.te' },
		                { name: 'Portico', abbreviation: 'P.co' },
		                { name: 'Rampa', abbreviation: 'Rampa' },
		                { name: 'Regione', abbreviation: 'Reg.' },
		                { name: 'Rione', abbreviation: 'R.ne' },
		                { name: 'Rio', abbreviation: 'Rio' },
		                { name: 'Ripa', abbreviation: 'Ripa' },
		                { name: 'Riva', abbreviation: 'Riva' },
		                { name: 'Rondò', abbreviation: 'Rondò' },
		                { name: 'Rotonda', abbreviation: 'Rot.' },
		                { name: 'Sagrato', abbreviation: 'Sagr.' },
		                { name: 'Salita', abbreviation: 'Sal.' },
		                { name: 'Scalinata', abbreviation: 'Scal.' },
		                { name: 'Scalone', abbreviation: 'Scal.' },
		                { name: 'Slargo', abbreviation: 'Sl.' },
		                { name: 'Sottoportico', abbreviation: 'Sott.' },
		                { name: 'Strada', abbreviation: 'Str.' },
		                { name: 'Stradale', abbreviation: 'Str.le' },
		                { name: 'Strettoia', abbreviation: 'Strett.' },
		                { name: 'Traversa', abbreviation: 'Trav.' },
		                { name: 'Via', abbreviation: 'V.' },
		                { name: 'Viale', abbreviation: 'V.le' },
		                { name: 'Vicinale', abbreviation: 'Vic.le' },
		                { name: 'Vicolo', abbreviation: 'Vic.' }
		            ],
		            'uk' : [
		                {name: 'Avenue', abbreviation: 'Ave'},
		                {name: 'Close', abbreviation: 'Cl'},
		                {name: 'Court', abbreviation: 'Ct'},
		                {name: 'Crescent', abbreviation: 'Cr'},
		                {name: 'Drive', abbreviation: 'Dr'},
		                {name: 'Garden', abbreviation: 'Gdn'},
		                {name: 'Gardens', abbreviation: 'Gdns'},
		                {name: 'Green', abbreviation: 'Gn'},
		                {name: 'Grove', abbreviation: 'Gr'},
		                {name: 'Lane', abbreviation: 'Ln'},
		                {name: 'Mount', abbreviation: 'Mt'},
		                {name: 'Place', abbreviation: 'Pl'},
		                {name: 'Park', abbreviation: 'Pk'},
		                {name: 'Ridge', abbreviation: 'Rdg'},
		                {name: 'Road', abbreviation: 'Rd'},
		                {name: 'Square', abbreviation: 'Sq'},
		                {name: 'Street', abbreviation: 'St'},
		                {name: 'Terrace', abbreviation: 'Ter'},
		                {name: 'Valley', abbreviation: 'Val'}
		            ]
		        },

		        months: [
		            {name: 'January', short_name: 'Jan', numeric: '01', days: 31},
		            // Not messing with leap years...
		            {name: 'February', short_name: 'Feb', numeric: '02', days: 28},
		            {name: 'March', short_name: 'Mar', numeric: '03', days: 31},
		            {name: 'April', short_name: 'Apr', numeric: '04', days: 30},
		            {name: 'May', short_name: 'May', numeric: '05', days: 31},
		            {name: 'June', short_name: 'Jun', numeric: '06', days: 30},
		            {name: 'July', short_name: 'Jul', numeric: '07', days: 31},
		            {name: 'August', short_name: 'Aug', numeric: '08', days: 31},
		            {name: 'September', short_name: 'Sep', numeric: '09', days: 30},
		            {name: 'October', short_name: 'Oct', numeric: '10', days: 31},
		            {name: 'November', short_name: 'Nov', numeric: '11', days: 30},
		            {name: 'December', short_name: 'Dec', numeric: '12', days: 31}
		        ],

		        // http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29
		        cc_types: [
		            {name: "American Express", short_name: 'amex', prefix: '34', length: 15},
		            {name: "Bankcard", short_name: 'bankcard', prefix: '5610', length: 16},
		            {name: "China UnionPay", short_name: 'chinaunion', prefix: '62', length: 16},
		            {name: "Diners Club Carte Blanche", short_name: 'dccarte', prefix: '300', length: 14},
		            {name: "Diners Club enRoute", short_name: 'dcenroute', prefix: '2014', length: 15},
		            {name: "Diners Club International", short_name: 'dcintl', prefix: '36', length: 14},
		            {name: "Diners Club United States & Canada", short_name: 'dcusc', prefix: '54', length: 16},
		            {name: "Discover Card", short_name: 'discover', prefix: '6011', length: 16},
		            {name: "InstaPayment", short_name: 'instapay', prefix: '637', length: 16},
		            {name: "JCB", short_name: 'jcb', prefix: '3528', length: 16},
		            {name: "Laser", short_name: 'laser', prefix: '6304', length: 16},
		            {name: "Maestro", short_name: 'maestro', prefix: '5018', length: 16},
		            {name: "Mastercard", short_name: 'mc', prefix: '51', length: 16},
		            {name: "Solo", short_name: 'solo', prefix: '6334', length: 16},
		            {name: "Switch", short_name: 'switch', prefix: '4903', length: 16},
		            {name: "Visa", short_name: 'visa', prefix: '4', length: 16},
		            {name: "Visa Electron", short_name: 'electron', prefix: '4026', length: 16}
		        ],

		        //return all world currency by ISO 4217
		        currency_types: [
		            {'code' : 'AED', 'name' : 'United Arab Emirates Dirham'},
		            {'code' : 'AFN', 'name' : 'Afghanistan Afghani'},
		            {'code' : 'ALL', 'name' : 'Albania Lek'},
		            {'code' : 'AMD', 'name' : 'Armenia Dram'},
		            {'code' : 'ANG', 'name' : 'Netherlands Antilles Guilder'},
		            {'code' : 'AOA', 'name' : 'Angola Kwanza'},
		            {'code' : 'ARS', 'name' : 'Argentina Peso'},
		            {'code' : 'AUD', 'name' : 'Australia Dollar'},
		            {'code' : 'AWG', 'name' : 'Aruba Guilder'},
		            {'code' : 'AZN', 'name' : 'Azerbaijan New Manat'},
		            {'code' : 'BAM', 'name' : 'Bosnia and Herzegovina Convertible Marka'},
		            {'code' : 'BBD', 'name' : 'Barbados Dollar'},
		            {'code' : 'BDT', 'name' : 'Bangladesh Taka'},
		            {'code' : 'BGN', 'name' : 'Bulgaria Lev'},
		            {'code' : 'BHD', 'name' : 'Bahrain Dinar'},
		            {'code' : 'BIF', 'name' : 'Burundi Franc'},
		            {'code' : 'BMD', 'name' : 'Bermuda Dollar'},
		            {'code' : 'BND', 'name' : 'Brunei Darussalam Dollar'},
		            {'code' : 'BOB', 'name' : 'Bolivia Boliviano'},
		            {'code' : 'BRL', 'name' : 'Brazil Real'},
		            {'code' : 'BSD', 'name' : 'Bahamas Dollar'},
		            {'code' : 'BTN', 'name' : 'Bhutan Ngultrum'},
		            {'code' : 'BWP', 'name' : 'Botswana Pula'},
		            {'code' : 'BYR', 'name' : 'Belarus Ruble'},
		            {'code' : 'BZD', 'name' : 'Belize Dollar'},
		            {'code' : 'CAD', 'name' : 'Canada Dollar'},
		            {'code' : 'CDF', 'name' : 'Congo/Kinshasa Franc'},
		            {'code' : 'CHF', 'name' : 'Switzerland Franc'},
		            {'code' : 'CLP', 'name' : 'Chile Peso'},
		            {'code' : 'CNY', 'name' : 'China Yuan Renminbi'},
		            {'code' : 'COP', 'name' : 'Colombia Peso'},
		            {'code' : 'CRC', 'name' : 'Costa Rica Colon'},
		            {'code' : 'CUC', 'name' : 'Cuba Convertible Peso'},
		            {'code' : 'CUP', 'name' : 'Cuba Peso'},
		            {'code' : 'CVE', 'name' : 'Cape Verde Escudo'},
		            {'code' : 'CZK', 'name' : 'Czech Republic Koruna'},
		            {'code' : 'DJF', 'name' : 'Djibouti Franc'},
		            {'code' : 'DKK', 'name' : 'Denmark Krone'},
		            {'code' : 'DOP', 'name' : 'Dominican Republic Peso'},
		            {'code' : 'DZD', 'name' : 'Algeria Dinar'},
		            {'code' : 'EGP', 'name' : 'Egypt Pound'},
		            {'code' : 'ERN', 'name' : 'Eritrea Nakfa'},
		            {'code' : 'ETB', 'name' : 'Ethiopia Birr'},
		            {'code' : 'EUR', 'name' : 'Euro Member Countries'},
		            {'code' : 'FJD', 'name' : 'Fiji Dollar'},
		            {'code' : 'FKP', 'name' : 'Falkland Islands (Malvinas) Pound'},
		            {'code' : 'GBP', 'name' : 'United Kingdom Pound'},
		            {'code' : 'GEL', 'name' : 'Georgia Lari'},
		            {'code' : 'GGP', 'name' : 'Guernsey Pound'},
		            {'code' : 'GHS', 'name' : 'Ghana Cedi'},
		            {'code' : 'GIP', 'name' : 'Gibraltar Pound'},
		            {'code' : 'GMD', 'name' : 'Gambia Dalasi'},
		            {'code' : 'GNF', 'name' : 'Guinea Franc'},
		            {'code' : 'GTQ', 'name' : 'Guatemala Quetzal'},
		            {'code' : 'GYD', 'name' : 'Guyana Dollar'},
		            {'code' : 'HKD', 'name' : 'Hong Kong Dollar'},
		            {'code' : 'HNL', 'name' : 'Honduras Lempira'},
		            {'code' : 'HRK', 'name' : 'Croatia Kuna'},
		            {'code' : 'HTG', 'name' : 'Haiti Gourde'},
		            {'code' : 'HUF', 'name' : 'Hungary Forint'},
		            {'code' : 'IDR', 'name' : 'Indonesia Rupiah'},
		            {'code' : 'ILS', 'name' : 'Israel Shekel'},
		            {'code' : 'IMP', 'name' : 'Isle of Man Pound'},
		            {'code' : 'INR', 'name' : 'India Rupee'},
		            {'code' : 'IQD', 'name' : 'Iraq Dinar'},
		            {'code' : 'IRR', 'name' : 'Iran Rial'},
		            {'code' : 'ISK', 'name' : 'Iceland Krona'},
		            {'code' : 'JEP', 'name' : 'Jersey Pound'},
		            {'code' : 'JMD', 'name' : 'Jamaica Dollar'},
		            {'code' : 'JOD', 'name' : 'Jordan Dinar'},
		            {'code' : 'JPY', 'name' : 'Japan Yen'},
		            {'code' : 'KES', 'name' : 'Kenya Shilling'},
		            {'code' : 'KGS', 'name' : 'Kyrgyzstan Som'},
		            {'code' : 'KHR', 'name' : 'Cambodia Riel'},
		            {'code' : 'KMF', 'name' : 'Comoros Franc'},
		            {'code' : 'KPW', 'name' : 'Korea (North) Won'},
		            {'code' : 'KRW', 'name' : 'Korea (South) Won'},
		            {'code' : 'KWD', 'name' : 'Kuwait Dinar'},
		            {'code' : 'KYD', 'name' : 'Cayman Islands Dollar'},
		            {'code' : 'KZT', 'name' : 'Kazakhstan Tenge'},
		            {'code' : 'LAK', 'name' : 'Laos Kip'},
		            {'code' : 'LBP', 'name' : 'Lebanon Pound'},
		            {'code' : 'LKR', 'name' : 'Sri Lanka Rupee'},
		            {'code' : 'LRD', 'name' : 'Liberia Dollar'},
		            {'code' : 'LSL', 'name' : 'Lesotho Loti'},
		            {'code' : 'LTL', 'name' : 'Lithuania Litas'},
		            {'code' : 'LYD', 'name' : 'Libya Dinar'},
		            {'code' : 'MAD', 'name' : 'Morocco Dirham'},
		            {'code' : 'MDL', 'name' : 'Moldova Leu'},
		            {'code' : 'MGA', 'name' : 'Madagascar Ariary'},
		            {'code' : 'MKD', 'name' : 'Macedonia Denar'},
		            {'code' : 'MMK', 'name' : 'Myanmar (Burma) Kyat'},
		            {'code' : 'MNT', 'name' : 'Mongolia Tughrik'},
		            {'code' : 'MOP', 'name' : 'Macau Pataca'},
		            {'code' : 'MRO', 'name' : 'Mauritania Ouguiya'},
		            {'code' : 'MUR', 'name' : 'Mauritius Rupee'},
		            {'code' : 'MVR', 'name' : 'Maldives (Maldive Islands) Rufiyaa'},
		            {'code' : 'MWK', 'name' : 'Malawi Kwacha'},
		            {'code' : 'MXN', 'name' : 'Mexico Peso'},
		            {'code' : 'MYR', 'name' : 'Malaysia Ringgit'},
		            {'code' : 'MZN', 'name' : 'Mozambique Metical'},
		            {'code' : 'NAD', 'name' : 'Namibia Dollar'},
		            {'code' : 'NGN', 'name' : 'Nigeria Naira'},
		            {'code' : 'NIO', 'name' : 'Nicaragua Cordoba'},
		            {'code' : 'NOK', 'name' : 'Norway Krone'},
		            {'code' : 'NPR', 'name' : 'Nepal Rupee'},
		            {'code' : 'NZD', 'name' : 'New Zealand Dollar'},
		            {'code' : 'OMR', 'name' : 'Oman Rial'},
		            {'code' : 'PAB', 'name' : 'Panama Balboa'},
		            {'code' : 'PEN', 'name' : 'Peru Nuevo Sol'},
		            {'code' : 'PGK', 'name' : 'Papua New Guinea Kina'},
		            {'code' : 'PHP', 'name' : 'Philippines Peso'},
		            {'code' : 'PKR', 'name' : 'Pakistan Rupee'},
		            {'code' : 'PLN', 'name' : 'Poland Zloty'},
		            {'code' : 'PYG', 'name' : 'Paraguay Guarani'},
		            {'code' : 'QAR', 'name' : 'Qatar Riyal'},
		            {'code' : 'RON', 'name' : 'Romania New Leu'},
		            {'code' : 'RSD', 'name' : 'Serbia Dinar'},
		            {'code' : 'RUB', 'name' : 'Russia Ruble'},
		            {'code' : 'RWF', 'name' : 'Rwanda Franc'},
		            {'code' : 'SAR', 'name' : 'Saudi Arabia Riyal'},
		            {'code' : 'SBD', 'name' : 'Solomon Islands Dollar'},
		            {'code' : 'SCR', 'name' : 'Seychelles Rupee'},
		            {'code' : 'SDG', 'name' : 'Sudan Pound'},
		            {'code' : 'SEK', 'name' : 'Sweden Krona'},
		            {'code' : 'SGD', 'name' : 'Singapore Dollar'},
		            {'code' : 'SHP', 'name' : 'Saint Helena Pound'},
		            {'code' : 'SLL', 'name' : 'Sierra Leone Leone'},
		            {'code' : 'SOS', 'name' : 'Somalia Shilling'},
		            {'code' : 'SPL', 'name' : 'Seborga Luigino'},
		            {'code' : 'SRD', 'name' : 'Suriname Dollar'},
		            {'code' : 'STD', 'name' : 'São Tomé and Príncipe Dobra'},
		            {'code' : 'SVC', 'name' : 'El Salvador Colon'},
		            {'code' : 'SYP', 'name' : 'Syria Pound'},
		            {'code' : 'SZL', 'name' : 'Swaziland Lilangeni'},
		            {'code' : 'THB', 'name' : 'Thailand Baht'},
		            {'code' : 'TJS', 'name' : 'Tajikistan Somoni'},
		            {'code' : 'TMT', 'name' : 'Turkmenistan Manat'},
		            {'code' : 'TND', 'name' : 'Tunisia Dinar'},
		            {'code' : 'TOP', 'name' : 'Tonga Pa\'anga'},
		            {'code' : 'TRY', 'name' : 'Turkey Lira'},
		            {'code' : 'TTD', 'name' : 'Trinidad and Tobago Dollar'},
		            {'code' : 'TVD', 'name' : 'Tuvalu Dollar'},
		            {'code' : 'TWD', 'name' : 'Taiwan New Dollar'},
		            {'code' : 'TZS', 'name' : 'Tanzania Shilling'},
		            {'code' : 'UAH', 'name' : 'Ukraine Hryvnia'},
		            {'code' : 'UGX', 'name' : 'Uganda Shilling'},
		            {'code' : 'USD', 'name' : 'United States Dollar'},
		            {'code' : 'UYU', 'name' : 'Uruguay Peso'},
		            {'code' : 'UZS', 'name' : 'Uzbekistan Som'},
		            {'code' : 'VEF', 'name' : 'Venezuela Bolivar'},
		            {'code' : 'VND', 'name' : 'Viet Nam Dong'},
		            {'code' : 'VUV', 'name' : 'Vanuatu Vatu'},
		            {'code' : 'WST', 'name' : 'Samoa Tala'},
		            {'code' : 'XAF', 'name' : 'Communauté Financière Africaine (BEAC) CFA Franc BEAC'},
		            {'code' : 'XCD', 'name' : 'East Caribbean Dollar'},
		            {'code' : 'XDR', 'name' : 'International Monetary Fund (IMF) Special Drawing Rights'},
		            {'code' : 'XOF', 'name' : 'Communauté Financière Africaine (BCEAO) Franc'},
		            {'code' : 'XPF', 'name' : 'Comptoirs Français du Pacifique (CFP) Franc'},
		            {'code' : 'YER', 'name' : 'Yemen Rial'},
		            {'code' : 'ZAR', 'name' : 'South Africa Rand'},
		            {'code' : 'ZMW', 'name' : 'Zambia Kwacha'},
		            {'code' : 'ZWD', 'name' : 'Zimbabwe Dollar'}
		        ],

		        // return the names of all valide colors
		        colorNames : [  "AliceBlue", "Black", "Navy", "DarkBlue", "MediumBlue", "Blue", "DarkGreen", "Green", "Teal", "DarkCyan", "DeepSkyBlue", "DarkTurquoise", "MediumSpringGreen", "Lime", "SpringGreen",
		            "Aqua", "Cyan", "MidnightBlue", "DodgerBlue", "LightSeaGreen", "ForestGreen", "SeaGreen", "DarkSlateGray", "LimeGreen", "MediumSeaGreen", "Turquoise", "RoyalBlue", "SteelBlue", "DarkSlateBlue", "MediumTurquoise",
		            "Indigo", "DarkOliveGreen", "CadetBlue", "CornflowerBlue", "RebeccaPurple", "MediumAquaMarine", "DimGray", "SlateBlue", "OliveDrab", "SlateGray", "LightSlateGray", "MediumSlateBlue", "LawnGreen", "Chartreuse",
		            "Aquamarine", "Maroon", "Purple", "Olive", "Gray", "SkyBlue", "LightSkyBlue", "BlueViolet", "DarkRed", "DarkMagenta", "SaddleBrown", "Ivory", "White",
		            "DarkSeaGreen", "LightGreen", "MediumPurple", "DarkViolet", "PaleGreen", "DarkOrchid", "YellowGreen", "Sienna", "Brown", "DarkGray", "LightBlue", "GreenYellow", "PaleTurquoise", "LightSteelBlue", "PowderBlue",
		            "FireBrick", "DarkGoldenRod", "MediumOrchid", "RosyBrown", "DarkKhaki", "Silver", "MediumVioletRed", "IndianRed", "Peru", "Chocolate", "Tan", "LightGray", "Thistle", "Orchid", "GoldenRod", "PaleVioletRed",
		            "Crimson", "Gainsboro", "Plum", "BurlyWood", "LightCyan", "Lavender", "DarkSalmon", "Violet", "PaleGoldenRod", "LightCoral", "Khaki", "AliceBlue", "HoneyDew", "Azure", "SandyBrown", "Wheat", "Beige", "WhiteSmoke",
		            "MintCream", "GhostWhite", "Salmon", "AntiqueWhite", "Linen", "LightGoldenRodYellow", "OldLace", "Red", "Fuchsia", "Magenta", "DeepPink", "OrangeRed", "Tomato", "HotPink", "Coral", "DarkOrange", "LightSalmon", "Orange",
		            "LightPink", "Pink", "Gold", "PeachPuff", "NavajoWhite", "Moccasin", "Bisque", "MistyRose", "BlanchedAlmond", "PapayaWhip", "LavenderBlush", "SeaShell", "Cornsilk", "LemonChiffon", "FloralWhite", "Snow", "Yellow", "LightYellow"
		        ],

		        // Data taken from https://www.sec.gov/rules/other/4-460list.htm
		        company: [ "3Com Corp",
		        "3M Company",
		        "A.G. Edwards Inc.",
		        "Abbott Laboratories",
		        "Abercrombie & Fitch Co.",
		        "ABM Industries Incorporated",
		        "Ace Hardware Corporation",
		        "ACT Manufacturing Inc.",
		        "Acterna Corp.",
		        "Adams Resources & Energy, Inc.",
		        "ADC Telecommunications, Inc.",
		        "Adelphia Communications Corporation",
		        "Administaff, Inc.",
		        "Adobe Systems Incorporated",
		        "Adolph Coors Company",
		        "Advance Auto Parts, Inc.",
		        "Advanced Micro Devices, Inc.",
		        "AdvancePCS, Inc.",
		        "Advantica Restaurant Group, Inc.",
		        "The AES Corporation",
		        "Aetna Inc.",
		        "Affiliated Computer Services, Inc.",
		        "AFLAC Incorporated",
		        "AGCO Corporation",
		        "Agilent Technologies, Inc.",
		        "Agway Inc.",
		        "Apartment Investment and Management Company",
		        "Air Products and Chemicals, Inc.",
		        "Airborne, Inc.",
		        "Airgas, Inc.",
		        "AK Steel Holding Corporation",
		        "Alaska Air Group, Inc.",
		        "Alberto-Culver Company",
		        "Albertson's, Inc.",
		        "Alcoa Inc.",
		        "Alleghany Corporation",
		        "Allegheny Energy, Inc.",
		        "Allegheny Technologies Incorporated",
		        "Allergan, Inc.",
		        "ALLETE, Inc.",
		        "Alliant Energy Corporation",
		        "Allied Waste Industries, Inc.",
		        "Allmerica Financial Corporation",
		        "The Allstate Corporation",
		        "ALLTEL Corporation",
		        "The Alpine Group, Inc.",
		        "Amazon.com, Inc.",
		        "AMC Entertainment Inc.",
		        "American Power Conversion Corporation",
		        "Amerada Hess Corporation",
		        "AMERCO",
		        "Ameren Corporation",
		        "America West Holdings Corporation",
		        "American Axle & Manufacturing Holdings, Inc.",
		        "American Eagle Outfitters, Inc.",
		        "American Electric Power Company, Inc.",
		        "American Express Company",
		        "American Financial Group, Inc.",
		        "American Greetings Corporation",
		        "American International Group, Inc.",
		        "American Standard Companies Inc.",
		        "American Water Works Company, Inc.",
		        "AmerisourceBergen Corporation",
		        "Ames Department Stores, Inc.",
		        "Amgen Inc.",
		        "Amkor Technology, Inc.",
		        "AMR Corporation",
		        "AmSouth Bancorp.",
		        "Amtran, Inc.",
		        "Anadarko Petroleum Corporation",
		        "Analog Devices, Inc.",
		        "Anheuser-Busch Companies, Inc.",
		        "Anixter International Inc.",
		        "AnnTaylor Inc.",
		        "Anthem, Inc.",
		        "AOL Time Warner Inc.",
		        "Aon Corporation",
		        "Apache Corporation",
		        "Apple Computer, Inc.",
		        "Applera Corporation",
		        "Applied Industrial Technologies, Inc.",
		        "Applied Materials, Inc.",
		        "Aquila, Inc.",
		        "ARAMARK Corporation",
		        "Arch Coal, Inc.",
		        "Archer Daniels Midland Company",
		        "Arkansas Best Corporation",
		        "Armstrong Holdings, Inc.",
		        "Arrow Electronics, Inc.",
		        "ArvinMeritor, Inc.",
		        "Ashland Inc.",
		        "Astoria Financial Corporation",
		        "AT&T Corp.",
		        "Atmel Corporation",
		        "Atmos Energy Corporation",
		        "Audiovox Corporation",
		        "Autoliv, Inc.",
		        "Automatic Data Processing, Inc.",
		        "AutoNation, Inc.",
		        "AutoZone, Inc.",
		        "Avaya Inc.",
		        "Avery Dennison Corporation",
		        "Avista Corporation",
		        "Avnet, Inc.",
		        "Avon Products, Inc.",
		        "Baker Hughes Incorporated",
		        "Ball Corporation",
		        "Bank of America Corporation",
		        "The Bank of New York Company, Inc.",
		        "Bank One Corporation",
		        "Banknorth Group, Inc.",
		        "Banta Corporation",
		        "Barnes & Noble, Inc.",
		        "Bausch & Lomb Incorporated",
		        "Baxter International Inc.",
		        "BB&T Corporation",
		        "The Bear Stearns Companies Inc.",
		        "Beazer Homes USA, Inc.",
		        "Beckman Coulter, Inc.",
		        "Becton, Dickinson and Company",
		        "Bed Bath & Beyond Inc.",
		        "Belk, Inc.",
		        "Bell Microproducts Inc.",
		        "BellSouth Corporation",
		        "Belo Corp.",
		        "Bemis Company, Inc.",
		        "Benchmark Electronics, Inc.",
		        "Berkshire Hathaway Inc.",
		        "Best Buy Co., Inc.",
		        "Bethlehem Steel Corporation",
		        "Beverly Enterprises, Inc.",
		        "Big Lots, Inc.",
		        "BJ Services Company",
		        "BJ's Wholesale Club, Inc.",
		        "The Black & Decker Corporation",
		        "Black Hills Corporation",
		        "BMC Software, Inc.",
		        "The Boeing Company",
		        "Boise Cascade Corporation",
		        "Borders Group, Inc.",
		        "BorgWarner Inc.",
		        "Boston Scientific Corporation",
		        "Bowater Incorporated",
		        "Briggs & Stratton Corporation",
		        "Brightpoint, Inc.",
		        "Brinker International, Inc.",
		        "Bristol-Myers Squibb Company",
		        "Broadwing, Inc.",
		        "Brown Shoe Company, Inc.",
		        "Brown-Forman Corporation",
		        "Brunswick Corporation",
		        "Budget Group, Inc.",
		        "Burlington Coat Factory Warehouse Corporation",
		        "Burlington Industries, Inc.",
		        "Burlington Northern Santa Fe Corporation",
		        "Burlington Resources Inc.",
		        "C. H. Robinson Worldwide Inc.",
		        "Cablevision Systems Corp",
		        "Cabot Corp",
		        "Cadence Design Systems, Inc.",
		        "Calpine Corp.",
		        "Campbell Soup Co.",
		        "Capital One Financial Corp.",
		        "Cardinal Health Inc.",
		        "Caremark Rx Inc.",
		        "Carlisle Cos. Inc.",
		        "Carpenter Technology Corp.",
		        "Casey's General Stores Inc.",
		        "Caterpillar Inc.",
		        "CBRL Group Inc.",
		        "CDI Corp.",
		        "CDW Computer Centers Inc.",
		        "CellStar Corp.",
		        "Cendant Corp",
		        "Cenex Harvest States Cooperatives",
		        "Centex Corp.",
		        "CenturyTel Inc.",
		        "Ceridian Corp.",
		        "CH2M Hill Cos. Ltd.",
		        "Champion Enterprises Inc.",
		        "Charles Schwab Corp.",
		        "Charming Shoppes Inc.",
		        "Charter Communications Inc.",
		        "Charter One Financial Inc.",
		        "ChevronTexaco Corp.",
		        "Chiquita Brands International Inc.",
		        "Chubb Corp",
		        "Ciena Corp.",
		        "Cigna Corp",
		        "Cincinnati Financial Corp.",
		        "Cinergy Corp.",
		        "Cintas Corp.",
		        "Circuit City Stores Inc.",
		        "Cisco Systems Inc.",
		        "Citigroup, Inc",
		        "Citizens Communications Co.",
		        "CKE Restaurants Inc.",
		        "Clear Channel Communications Inc.",
		        "The Clorox Co.",
		        "CMGI Inc.",
		        "CMS Energy Corp.",
		        "CNF Inc.",
		        "Coca-Cola Co.",
		        "Coca-Cola Enterprises Inc.",
		        "Colgate-Palmolive Co.",
		        "Collins & Aikman Corp.",
		        "Comcast Corp.",
		        "Comdisco Inc.",
		        "Comerica Inc.",
		        "Comfort Systems USA Inc.",
		        "Commercial Metals Co.",
		        "Community Health Systems Inc.",
		        "Compass Bancshares Inc",
		        "Computer Associates International Inc.",
		        "Computer Sciences Corp.",
		        "Compuware Corp.",
		        "Comverse Technology Inc.",
		        "ConAgra Foods Inc.",
		        "Concord EFS Inc.",
		        "Conectiv, Inc",
		        "Conoco Inc",
		        "Conseco Inc.",
		        "Consolidated Freightways Corp.",
		        "Consolidated Edison Inc.",
		        "Constellation Brands Inc.",
		        "Constellation Emergy Group Inc.",
		        "Continental Airlines Inc.",
		        "Convergys Corp.",
		        "Cooper Cameron Corp.",
		        "Cooper Industries Ltd.",
		        "Cooper Tire & Rubber Co.",
		        "Corn Products International Inc.",
		        "Corning Inc.",
		        "Costco Wholesale Corp.",
		        "Countrywide Credit Industries Inc.",
		        "Coventry Health Care Inc.",
		        "Cox Communications Inc.",
		        "Crane Co.",
		        "Crompton Corp.",
		        "Crown Cork & Seal Co. Inc.",
		        "CSK Auto Corp.",
		        "CSX Corp.",
		        "Cummins Inc.",
		        "CVS Corp.",
		        "Cytec Industries Inc.",
		        "D&K Healthcare Resources, Inc.",
		        "D.R. Horton Inc.",
		        "Dana Corporation",
		        "Danaher Corporation",
		        "Darden Restaurants Inc.",
		        "DaVita Inc.",
		        "Dean Foods Company",
		        "Deere & Company",
		        "Del Monte Foods Co",
		        "Dell Computer Corporation",
		        "Delphi Corp.",
		        "Delta Air Lines Inc.",
		        "Deluxe Corporation",
		        "Devon Energy Corporation",
		        "Di Giorgio Corporation",
		        "Dial Corporation",
		        "Diebold Incorporated",
		        "Dillard's Inc.",
		        "DIMON Incorporated",
		        "Dole Food Company, Inc.",
		        "Dollar General Corporation",
		        "Dollar Tree Stores, Inc.",
		        "Dominion Resources, Inc.",
		        "Domino's Pizza LLC",
		        "Dover Corporation, Inc.",
		        "Dow Chemical Company",
		        "Dow Jones & Company, Inc.",
		        "DPL Inc.",
		        "DQE Inc.",
		        "Dreyer's Grand Ice Cream, Inc.",
		        "DST Systems, Inc.",
		        "DTE Energy Co.",
		        "E.I. Du Pont de Nemours and Company",
		        "Duke Energy Corp",
		        "Dun & Bradstreet Inc.",
		        "DURA Automotive Systems Inc.",
		        "DynCorp",
		        "Dynegy Inc.",
		        "E*Trade Group, Inc.",
		        "E.W. Scripps Company",
		        "Earthlink, Inc.",
		        "Eastman Chemical Company",
		        "Eastman Kodak Company",
		        "Eaton Corporation",
		        "Echostar Communications Corporation",
		        "Ecolab Inc.",
		        "Edison International",
		        "EGL Inc.",
		        "El Paso Corporation",
		        "Electronic Arts Inc.",
		        "Electronic Data Systems Corp.",
		        "Eli Lilly and Company",
		        "EMC Corporation",
		        "Emcor Group Inc.",
		        "Emerson Electric Co.",
		        "Encompass Services Corporation",
		        "Energizer Holdings Inc.",
		        "Energy East Corporation",
		        "Engelhard Corporation",
		        "Enron Corp.",
		        "Entergy Corporation",
		        "Enterprise Products Partners L.P.",
		        "EOG Resources, Inc.",
		        "Equifax Inc.",
		        "Equitable Resources Inc.",
		        "Equity Office Properties Trust",
		        "Equity Residential Properties Trust",
		        "Estee Lauder Companies Inc.",
		        "Exelon Corporation",
		        "Exide Technologies",
		        "Expeditors International of Washington Inc.",
		        "Express Scripts Inc.",
		        "ExxonMobil Corporation",
		        "Fairchild Semiconductor International Inc.",
		        "Family Dollar Stores Inc.",
		        "Farmland Industries Inc.",
		        "Federal Mogul Corp.",
		        "Federated Department Stores Inc.",
		        "Federal Express Corp.",
		        "Felcor Lodging Trust Inc.",
		        "Ferro Corp.",
		        "Fidelity National Financial Inc.",
		        "Fifth Third Bancorp",
		        "First American Financial Corp.",
		        "First Data Corp.",
		        "First National of Nebraska Inc.",
		        "First Tennessee National Corp.",
		        "FirstEnergy Corp.",
		        "Fiserv Inc.",
		        "Fisher Scientific International Inc.",
		        "FleetBoston Financial Co.",
		        "Fleetwood Enterprises Inc.",
		        "Fleming Companies Inc.",
		        "Flowers Foods Inc.",
		        "Flowserv Corp",
		        "Fluor Corp",
		        "FMC Corp",
		        "Foamex International Inc",
		        "Foot Locker Inc",
		        "Footstar Inc.",
		        "Ford Motor Co",
		        "Forest Laboratories Inc.",
		        "Fortune Brands Inc.",
		        "Foster Wheeler Ltd.",
		        "FPL Group Inc.",
		        "Franklin Resources Inc.",
		        "Freeport McMoran Copper & Gold Inc.",
		        "Frontier Oil Corp",
		        "Furniture Brands International Inc.",
		        "Gannett Co., Inc.",
		        "Gap Inc.",
		        "Gateway Inc.",
		        "GATX Corporation",
		        "Gemstar-TV Guide International Inc.",
		        "GenCorp Inc.",
		        "General Cable Corporation",
		        "General Dynamics Corporation",
		        "General Electric Company",
		        "General Mills Inc",
		        "General Motors Corporation",
		        "Genesis Health Ventures Inc.",
		        "Gentek Inc.",
		        "Gentiva Health Services Inc.",
		        "Genuine Parts Company",
		        "Genuity Inc.",
		        "Genzyme Corporation",
		        "Georgia Gulf Corporation",
		        "Georgia-Pacific Corporation",
		        "Gillette Company",
		        "Gold Kist Inc.",
		        "Golden State Bancorp Inc.",
		        "Golden West Financial Corporation",
		        "Goldman Sachs Group Inc.",
		        "Goodrich Corporation",
		        "The Goodyear Tire & Rubber Company",
		        "Granite Construction Incorporated",
		        "Graybar Electric Company Inc.",
		        "Great Lakes Chemical Corporation",
		        "Great Plains Energy Inc.",
		        "GreenPoint Financial Corp.",
		        "Greif Bros. Corporation",
		        "Grey Global Group Inc.",
		        "Group 1 Automotive Inc.",
		        "Guidant Corporation",
		        "H&R Block Inc.",
		        "H.B. Fuller Company",
		        "H.J. Heinz Company",
		        "Halliburton Co.",
		        "Harley-Davidson Inc.",
		        "Harman International Industries Inc.",
		        "Harrah's Entertainment Inc.",
		        "Harris Corp.",
		        "Harsco Corp.",
		        "Hartford Financial Services Group Inc.",
		        "Hasbro Inc.",
		        "Hawaiian Electric Industries Inc.",
		        "HCA Inc.",
		        "Health Management Associates Inc.",
		        "Health Net Inc.",
		        "Healthsouth Corp",
		        "Henry Schein Inc.",
		        "Hercules Inc.",
		        "Herman Miller Inc.",
		        "Hershey Foods Corp.",
		        "Hewlett-Packard Company",
		        "Hibernia Corp.",
		        "Hillenbrand Industries Inc.",
		        "Hilton Hotels Corp.",
		        "Hollywood Entertainment Corp.",
		        "Home Depot Inc.",
		        "Hon Industries Inc.",
		        "Honeywell International Inc.",
		        "Hormel Foods Corp.",
		        "Host Marriott Corp.",
		        "Household International Corp.",
		        "Hovnanian Enterprises Inc.",
		        "Hub Group Inc.",
		        "Hubbell Inc.",
		        "Hughes Supply Inc.",
		        "Humana Inc.",
		        "Huntington Bancshares Inc.",
		        "Idacorp Inc.",
		        "IDT Corporation",
		        "IKON Office Solutions Inc.",
		        "Illinois Tool Works Inc.",
		        "IMC Global Inc.",
		        "Imperial Sugar Company",
		        "IMS Health Inc.",
		        "Ingles Market Inc",
		        "Ingram Micro Inc.",
		        "Insight Enterprises Inc.",
		        "Integrated Electrical Services Inc.",
		        "Intel Corporation",
		        "International Paper Co.",
		        "Interpublic Group of Companies Inc.",
		        "Interstate Bakeries Corporation",
		        "International Business Machines Corp.",
		        "International Flavors & Fragrances Inc.",
		        "International Multifoods Corporation",
		        "Intuit Inc.",
		        "IT Group Inc.",
		        "ITT Industries Inc.",
		        "Ivax Corp.",
		        "J.B. Hunt Transport Services Inc.",
		        "J.C. Penny Co.",
		        "J.P. Morgan Chase & Co.",
		        "Jabil Circuit Inc.",
		        "Jack In The Box Inc.",
		        "Jacobs Engineering Group Inc.",
		        "JDS Uniphase Corp.",
		        "Jefferson-Pilot Co.",
		        "John Hancock Financial Services Inc.",
		        "Johnson & Johnson",
		        "Johnson Controls Inc.",
		        "Jones Apparel Group Inc.",
		        "KB Home",
		        "Kellogg Company",
		        "Kellwood Company",
		        "Kelly Services Inc.",
		        "Kemet Corp.",
		        "Kennametal Inc.",
		        "Kerr-McGee Corporation",
		        "KeyCorp",
		        "KeySpan Corp.",
		        "Kimball International Inc.",
		        "Kimberly-Clark Corporation",
		        "Kindred Healthcare Inc.",
		        "KLA-Tencor Corporation",
		        "K-Mart Corp.",
		        "Knight-Ridder Inc.",
		        "Kohl's Corp.",
		        "KPMG Consulting Inc.",
		        "Kroger Co.",
		        "L-3 Communications Holdings Inc.",
		        "Laboratory Corporation of America Holdings",
		        "Lam Research Corporation",
		        "LandAmerica Financial Group Inc.",
		        "Lands' End Inc.",
		        "Landstar System Inc.",
		        "La-Z-Boy Inc.",
		        "Lear Corporation",
		        "Legg Mason Inc.",
		        "Leggett & Platt Inc.",
		        "Lehman Brothers Holdings Inc.",
		        "Lennar Corporation",
		        "Lennox International Inc.",
		        "Level 3 Communications Inc.",
		        "Levi Strauss & Co.",
		        "Lexmark International Inc.",
		        "Limited Inc.",
		        "Lincoln National Corporation",
		        "Linens 'n Things Inc.",
		        "Lithia Motors Inc.",
		        "Liz Claiborne Inc.",
		        "Lockheed Martin Corporation",
		        "Loews Corporation",
		        "Longs Drug Stores Corporation",
		        "Louisiana-Pacific Corporation",
		        "Lowe's Companies Inc.",
		        "LSI Logic Corporation",
		        "The LTV Corporation",
		        "The Lubrizol Corporation",
		        "Lucent Technologies Inc.",
		        "Lyondell Chemical Company",
		        "M & T Bank Corporation",
		        "Magellan Health Services Inc.",
		        "Mail-Well Inc.",
		        "Mandalay Resort Group",
		        "Manor Care Inc.",
		        "Manpower Inc.",
		        "Marathon Oil Corporation",
		        "Mariner Health Care Inc.",
		        "Markel Corporation",
		        "Marriott International Inc.",
		        "Marsh & McLennan Companies Inc.",
		        "Marsh Supermarkets Inc.",
		        "Marshall & Ilsley Corporation",
		        "Martin Marietta Materials Inc.",
		        "Masco Corporation",
		        "Massey Energy Company",
		        "MasTec Inc.",
		        "Mattel Inc.",
		        "Maxim Integrated Products Inc.",
		        "Maxtor Corporation",
		        "Maxxam Inc.",
		        "The May Department Stores Company",
		        "Maytag Corporation",
		        "MBNA Corporation",
		        "McCormick & Company Incorporated",
		        "McDonald's Corporation",
		        "The McGraw-Hill Companies Inc.",
		        "McKesson Corporation",
		        "McLeodUSA Incorporated",
		        "M.D.C. Holdings Inc.",
		        "MDU Resources Group Inc.",
		        "MeadWestvaco Corporation",
		        "Medtronic Inc.",
		        "Mellon Financial Corporation",
		        "The Men's Wearhouse Inc.",
		        "Merck & Co., Inc.",
		        "Mercury General Corporation",
		        "Merrill Lynch & Co. Inc.",
		        "Metaldyne Corporation",
		        "Metals USA Inc.",
		        "MetLife Inc.",
		        "Metris Companies Inc",
		        "MGIC Investment Corporation",
		        "MGM Mirage",
		        "Michaels Stores Inc.",
		        "Micron Technology Inc.",
		        "Microsoft Corporation",
		        "Milacron Inc.",
		        "Millennium Chemicals Inc.",
		        "Mirant Corporation",
		        "Mohawk Industries Inc.",
		        "Molex Incorporated",
		        "The MONY Group Inc.",
		        "Morgan Stanley Dean Witter & Co.",
		        "Motorola Inc.",
		        "MPS Group Inc.",
		        "Murphy Oil Corporation",
		        "Nabors Industries Inc",
		        "Nacco Industries Inc",
		        "Nash Finch Company",
		        "National City Corp.",
		        "National Commerce Financial Corporation",
		        "National Fuel Gas Company",
		        "National Oilwell Inc",
		        "National Rural Utilities Cooperative Finance Corporation",
		        "National Semiconductor Corporation",
		        "National Service Industries Inc",
		        "Navistar International Corporation",
		        "NCR Corporation",
		        "The Neiman Marcus Group Inc.",
		        "New Jersey Resources Corporation",
		        "New York Times Company",
		        "Newell Rubbermaid Inc",
		        "Newmont Mining Corporation",
		        "Nextel Communications Inc",
		        "Nicor Inc",
		        "Nike Inc",
		        "NiSource Inc",
		        "Noble Energy Inc",
		        "Nordstrom Inc",
		        "Norfolk Southern Corporation",
		        "Nortek Inc",
		        "North Fork Bancorporation Inc",
		        "Northeast Utilities System",
		        "Northern Trust Corporation",
		        "Northrop Grumman Corporation",
		        "NorthWestern Corporation",
		        "Novellus Systems Inc",
		        "NSTAR",
		        "NTL Incorporated",
		        "Nucor Corp",
		        "Nvidia Corp",
		        "NVR Inc",
		        "Northwest Airlines Corp",
		        "Occidental Petroleum Corp",
		        "Ocean Energy Inc",
		        "Office Depot Inc.",
		        "OfficeMax Inc",
		        "OGE Energy Corp",
		        "Oglethorpe Power Corp.",
		        "Ohio Casualty Corp.",
		        "Old Republic International Corp.",
		        "Olin Corp.",
		        "OM Group Inc",
		        "Omnicare Inc",
		        "Omnicom Group",
		        "On Semiconductor Corp",
		        "ONEOK Inc",
		        "Oracle Corp",
		        "Oshkosh Truck Corp",
		        "Outback Steakhouse Inc.",
		        "Owens & Minor Inc.",
		        "Owens Corning",
		        "Owens-Illinois Inc",
		        "Oxford Health Plans Inc",
		        "Paccar Inc",
		        "PacifiCare Health Systems Inc",
		        "Packaging Corp. of America",
		        "Pactiv Corp",
		        "Pall Corp",
		        "Pantry Inc",
		        "Park Place Entertainment Corp",
		        "Parker Hannifin Corp.",
		        "Pathmark Stores Inc.",
		        "Paychex Inc",
		        "Payless Shoesource Inc",
		        "Penn Traffic Co.",
		        "Pennzoil-Quaker State Company",
		        "Pentair Inc",
		        "Peoples Energy Corp.",
		        "PeopleSoft Inc",
		        "Pep Boys Manny, Moe & Jack",
		        "Potomac Electric Power Co.",
		        "Pepsi Bottling Group Inc.",
		        "PepsiAmericas Inc.",
		        "PepsiCo Inc.",
		        "Performance Food Group Co.",
		        "Perini Corp",
		        "PerkinElmer Inc",
		        "Perot Systems Corp",
		        "Petco Animal Supplies Inc.",
		        "Peter Kiewit Sons', Inc.",
		        "PETsMART Inc",
		        "Pfizer Inc",
		        "Pacific Gas & Electric Corp.",
		        "Pharmacia Corp",
		        "Phar Mor Inc.",
		        "Phelps Dodge Corp.",
		        "Philip Morris Companies Inc.",
		        "Phillips Petroleum Co",
		        "Phillips Van Heusen Corp.",
		        "Phoenix Companies Inc",
		        "Pier 1 Imports Inc.",
		        "Pilgrim's Pride Corporation",
		        "Pinnacle West Capital Corp",
		        "Pioneer-Standard Electronics Inc.",
		        "Pitney Bowes Inc.",
		        "Pittston Brinks Group",
		        "Plains All American Pipeline LP",
		        "PNC Financial Services Group Inc.",
		        "PNM Resources Inc",
		        "Polaris Industries Inc.",
		        "Polo Ralph Lauren Corp",
		        "PolyOne Corp",
		        "Popular Inc",
		        "Potlatch Corp",
		        "PPG Industries Inc",
		        "PPL Corp",
		        "Praxair Inc",
		        "Precision Castparts Corp",
		        "Premcor Inc.",
		        "Pride International Inc",
		        "Primedia Inc",
		        "Principal Financial Group Inc.",
		        "Procter & Gamble Co.",
		        "Pro-Fac Cooperative Inc.",
		        "Progress Energy Inc",
		        "Progressive Corporation",
		        "Protective Life Corp",
		        "Provident Financial Group",
		        "Providian Financial Corp.",
		        "Prudential Financial Inc.",
		        "PSS World Medical Inc",
		        "Public Service Enterprise Group Inc.",
		        "Publix Super Markets Inc.",
		        "Puget Energy Inc.",
		        "Pulte Homes Inc",
		        "Qualcomm Inc",
		        "Quanta Services Inc.",
		        "Quantum Corp",
		        "Quest Diagnostics Inc.",
		        "Questar Corp",
		        "Quintiles Transnational",
		        "Qwest Communications Intl Inc",
		        "R.J. Reynolds Tobacco Company",
		        "R.R. Donnelley & Sons Company",
		        "Radio Shack Corporation",
		        "Raymond James Financial Inc.",
		        "Raytheon Company",
		        "Reader's Digest Association Inc.",
		        "Reebok International Ltd.",
		        "Regions Financial Corp.",
		        "Regis Corporation",
		        "Reliance Steel & Aluminum Co.",
		        "Reliant Energy Inc.",
		        "Rent A Center Inc",
		        "Republic Services Inc",
		        "Revlon Inc",
		        "RGS Energy Group Inc",
		        "Rite Aid Corp",
		        "Riverwood Holding Inc.",
		        "RoadwayCorp",
		        "Robert Half International Inc.",
		        "Rock-Tenn Co",
		        "Rockwell Automation Inc",
		        "Rockwell Collins Inc",
		        "Rohm & Haas Co.",
		        "Ross Stores Inc",
		        "RPM Inc.",
		        "Ruddick Corp",
		        "Ryder System Inc",
		        "Ryerson Tull Inc",
		        "Ryland Group Inc.",
		        "Sabre Holdings Corp",
		        "Safeco Corp",
		        "Safeguard Scientifics Inc.",
		        "Safeway Inc",
		        "Saks Inc",
		        "Sanmina-SCI Inc",
		        "Sara Lee Corp",
		        "SBC Communications Inc",
		        "Scana Corp.",
		        "Schering-Plough Corp",
		        "Scholastic Corp",
		        "SCI Systems Onc.",
		        "Science Applications Intl. Inc.",
		        "Scientific-Atlanta Inc",
		        "Scotts Company",
		        "Seaboard Corp",
		        "Sealed Air Corp",
		        "Sears Roebuck & Co",
		        "Sempra Energy",
		        "Sequa Corp",
		        "Service Corp. International",
		        "ServiceMaster Co",
		        "Shaw Group Inc",
		        "Sherwin-Williams Company",
		        "Shopko Stores Inc",
		        "Siebel Systems Inc",
		        "Sierra Health Services Inc",
		        "Sierra Pacific Resources",
		        "Silgan Holdings Inc.",
		        "Silicon Graphics Inc",
		        "Simon Property Group Inc",
		        "SLM Corporation",
		        "Smith International Inc",
		        "Smithfield Foods Inc",
		        "Smurfit-Stone Container Corp",
		        "Snap-On Inc",
		        "Solectron Corp",
		        "Solutia Inc",
		        "Sonic Automotive Inc.",
		        "Sonoco Products Co.",
		        "Southern Company",
		        "Southern Union Company",
		        "SouthTrust Corp.",
		        "Southwest Airlines Co",
		        "Southwest Gas Corp",
		        "Sovereign Bancorp Inc.",
		        "Spartan Stores Inc",
		        "Spherion Corp",
		        "Sports Authority Inc",
		        "Sprint Corp.",
		        "SPX Corp",
		        "St. Jude Medical Inc",
		        "St. Paul Cos.",
		        "Staff Leasing Inc.",
		        "StanCorp Financial Group Inc",
		        "Standard Pacific Corp.",
		        "Stanley Works",
		        "Staples Inc",
		        "Starbucks Corp",
		        "Starwood Hotels & Resorts Worldwide Inc",
		        "State Street Corp.",
		        "Stater Bros. Holdings Inc.",
		        "Steelcase Inc",
		        "Stein Mart Inc",
		        "Stewart & Stevenson Services Inc",
		        "Stewart Information Services Corp",
		        "Stilwell Financial Inc",
		        "Storage Technology Corporation",
		        "Stryker Corp",
		        "Sun Healthcare Group Inc.",
		        "Sun Microsystems Inc.",
		        "SunGard Data Systems Inc.",
		        "Sunoco Inc.",
		        "SunTrust Banks Inc",
		        "Supervalu Inc",
		        "Swift Transportation, Co., Inc",
		        "Symbol Technologies Inc",
		        "Synovus Financial Corp.",
		        "Sysco Corp",
		        "Systemax Inc.",
		        "Target Corp.",
		        "Tech Data Corporation",
		        "TECO Energy Inc",
		        "Tecumseh Products Company",
		        "Tektronix Inc",
		        "Teleflex Incorporated",
		        "Telephone & Data Systems Inc",
		        "Tellabs Inc.",
		        "Temple-Inland Inc",
		        "Tenet Healthcare Corporation",
		        "Tenneco Automotive Inc.",
		        "Teradyne Inc",
		        "Terex Corp",
		        "Tesoro Petroleum Corp.",
		        "Texas Industries Inc.",
		        "Texas Instruments Incorporated",
		        "Textron Inc",
		        "Thermo Electron Corporation",
		        "Thomas & Betts Corporation",
		        "Tiffany & Co",
		        "Timken Company",
		        "TJX Companies Inc",
		        "TMP Worldwide Inc",
		        "Toll Brothers Inc",
		        "Torchmark Corporation",
		        "Toro Company",
		        "Tower Automotive Inc.",
		        "Toys 'R' Us Inc",
		        "Trans World Entertainment Corp.",
		        "TransMontaigne Inc",
		        "Transocean Inc",
		        "TravelCenters of America Inc.",
		        "Triad Hospitals Inc",
		        "Tribune Company",
		        "Trigon Healthcare Inc.",
		        "Trinity Industries Inc",
		        "Trump Hotels & Casino Resorts Inc.",
		        "TruServ Corporation",
		        "TRW Inc",
		        "TXU Corp",
		        "Tyson Foods Inc",
		        "U.S. Bancorp",
		        "U.S. Industries Inc.",
		        "UAL Corporation",
		        "UGI Corporation",
		        "Unified Western Grocers Inc",
		        "Union Pacific Corporation",
		        "Union Planters Corp",
		        "Unisource Energy Corp",
		        "Unisys Corporation",
		        "United Auto Group Inc",
		        "United Defense Industries Inc.",
		        "United Parcel Service Inc",
		        "United Rentals Inc",
		        "United Stationers Inc",
		        "United Technologies Corporation",
		        "UnitedHealth Group Incorporated",
		        "Unitrin Inc",
		        "Universal Corporation",
		        "Universal Forest Products Inc",
		        "Universal Health Services Inc",
		        "Unocal Corporation",
		        "Unova Inc",
		        "UnumProvident Corporation",
		        "URS Corporation",
		        "US Airways Group Inc",
		        "US Oncology Inc",
		        "USA Interactive",
		        "USFreighways Corporation",
		        "USG Corporation",
		        "UST Inc",
		        "Valero Energy Corporation",
		        "Valspar Corporation",
		        "Value City Department Stores Inc",
		        "Varco International Inc",
		        "Vectren Corporation",
		        "Veritas Software Corporation",
		        "Verizon Communications Inc",
		        "VF Corporation",
		        "Viacom Inc",
		        "Viad Corp",
		        "Viasystems Group Inc",
		        "Vishay Intertechnology Inc",
		        "Visteon Corporation",
		        "Volt Information Sciences Inc",
		        "Vulcan Materials Company",
		        "W.R. Berkley Corporation",
		        "W.R. Grace & Co",
		        "W.W. Grainger Inc",
		        "Wachovia Corporation",
		        "Wakenhut Corporation",
		        "Walgreen Co",
		        "Wallace Computer Services Inc",
		        "Wal-Mart Stores Inc",
		        "Walt Disney Co",
		        "Walter Industries Inc",
		        "Washington Mutual Inc",
		        "Washington Post Co.",
		        "Waste Management Inc",
		        "Watsco Inc",
		        "Weatherford International Inc",
		        "Weis Markets Inc.",
		        "Wellpoint Health Networks Inc",
		        "Wells Fargo & Company",
		        "Wendy's International Inc",
		        "Werner Enterprises Inc",
		        "WESCO International Inc",
		        "Western Digital Inc",
		        "Western Gas Resources Inc",
		        "WestPoint Stevens Inc",
		        "Weyerhauser Company",
		        "WGL Holdings Inc",
		        "Whirlpool Corporation",
		        "Whole Foods Market Inc",
		        "Willamette Industries Inc.",
		        "Williams Companies Inc",
		        "Williams Sonoma Inc",
		        "Winn Dixie Stores Inc",
		        "Wisconsin Energy Corporation",
		        "Wm Wrigley Jr Company",
		        "World Fuel Services Corporation",
		        "WorldCom Inc",
		        "Worthington Industries Inc",
		        "WPS Resources Corporation",
		        "Wyeth",
		        "Wyndham International Inc",
		        "Xcel Energy Inc",
		        "Xerox Corp",
		        "Xilinx Inc",
		        "XO Communications Inc",
		        "Yellow Corporation",
		        "York International Corp",
		        "Yum Brands Inc.",
		        "Zale Corporation",
		        "Zions Bancorporation"
		      ],

		        fileExtension : {
		            "raster"    : ["bmp", "gif", "gpl", "ico", "jpeg", "psd", "png", "psp", "raw", "tiff"],
		            "vector"    : ["3dv", "amf", "awg", "ai", "cgm", "cdr", "cmx", "dxf", "e2d", "egt", "eps", "fs", "odg", "svg", "xar"],
		            "3d"        : ["3dmf", "3dm", "3mf", "3ds", "an8", "aoi", "blend", "cal3d", "cob", "ctm", "iob", "jas", "max", "mb", "mdx", "obj", "x", "x3d"],
		            "document"  : ["doc", "docx", "dot", "html", "xml", "odt", "odm", "ott", "csv", "rtf", "tex", "xhtml", "xps"]
		        },

		        // Data taken from https://github.com/dmfilipenko/timezones.json/blob/master/timezones.json
		        timezones: [
		                  {
		                    "name": "Dateline Standard Time",
		                    "abbr": "DST",
		                    "offset": -12,
		                    "isdst": false,
		                    "text": "(UTC-12:00) International Date Line West",
		                    "utc": [
		                      "Etc/GMT+12"
		                    ]
		                  },
		                  {
		                    "name": "UTC-11",
		                    "abbr": "U",
		                    "offset": -11,
		                    "isdst": false,
		                    "text": "(UTC-11:00) Coordinated Universal Time-11",
		                    "utc": [
		                      "Etc/GMT+11",
		                      "Pacific/Midway",
		                      "Pacific/Niue",
		                      "Pacific/Pago_Pago"
		                    ]
		                  },
		                  {
		                    "name": "Hawaiian Standard Time",
		                    "abbr": "HST",
		                    "offset": -10,
		                    "isdst": false,
		                    "text": "(UTC-10:00) Hawaii",
		                    "utc": [
		                      "Etc/GMT+10",
		                      "Pacific/Honolulu",
		                      "Pacific/Johnston",
		                      "Pacific/Rarotonga",
		                      "Pacific/Tahiti"
		                    ]
		                  },
		                  {
		                    "name": "Alaskan Standard Time",
		                    "abbr": "AKDT",
		                    "offset": -8,
		                    "isdst": true,
		                    "text": "(UTC-09:00) Alaska",
		                    "utc": [
		                      "America/Anchorage",
		                      "America/Juneau",
		                      "America/Nome",
		                      "America/Sitka",
		                      "America/Yakutat"
		                    ]
		                  },
		                  {
		                    "name": "Pacific Standard Time (Mexico)",
		                    "abbr": "PDT",
		                    "offset": -7,
		                    "isdst": true,
		                    "text": "(UTC-08:00) Baja California",
		                    "utc": [
		                      "America/Santa_Isabel"
		                    ]
		                  },
		                  {
		                    "name": "Pacific Daylight Time",
		                    "abbr": "PDT",
		                    "offset": -7,
		                    "isdst": true,
		                    "text": "(UTC-07:00) Pacific Time (US & Canada)",
		                    "utc": [
		                      "America/Dawson",
		                      "America/Los_Angeles",
		                      "America/Tijuana",
		                      "America/Vancouver",
		                      "America/Whitehorse"
		                    ]
		                  },
		                  {
		                    "name": "Pacific Standard Time",
		                    "abbr": "PST",
		                    "offset": -8,
		                    "isdst": false,
		                    "text": "(UTC-08:00) Pacific Time (US & Canada)",
		                    "utc": [
		                      "America/Dawson",
		                      "America/Los_Angeles",
		                      "America/Tijuana",
		                      "America/Vancouver",
		                      "America/Whitehorse",
		                      "PST8PDT"
		                    ]
		                  },
		                  {
		                    "name": "US Mountain Standard Time",
		                    "abbr": "UMST",
		                    "offset": -7,
		                    "isdst": false,
		                    "text": "(UTC-07:00) Arizona",
		                    "utc": [
		                      "America/Creston",
		                      "America/Dawson_Creek",
		                      "America/Hermosillo",
		                      "America/Phoenix",
		                      "Etc/GMT+7"
		                    ]
		                  },
		                  {
		                    "name": "Mountain Standard Time (Mexico)",
		                    "abbr": "MDT",
		                    "offset": -6,
		                    "isdst": true,
		                    "text": "(UTC-07:00) Chihuahua, La Paz, Mazatlan",
		                    "utc": [
		                      "America/Chihuahua",
		                      "America/Mazatlan"
		                    ]
		                  },
		                  {
		                    "name": "Mountain Standard Time",
		                    "abbr": "MDT",
		                    "offset": -6,
		                    "isdst": true,
		                    "text": "(UTC-07:00) Mountain Time (US & Canada)",
		                    "utc": [
		                      "America/Boise",
		                      "America/Cambridge_Bay",
		                      "America/Denver",
		                      "America/Edmonton",
		                      "America/Inuvik",
		                      "America/Ojinaga",
		                      "America/Yellowknife",
		                      "MST7MDT"
		                    ]
		                  },
		                  {
		                    "name": "Central America Standard Time",
		                    "abbr": "CAST",
		                    "offset": -6,
		                    "isdst": false,
		                    "text": "(UTC-06:00) Central America",
		                    "utc": [
		                      "America/Belize",
		                      "America/Costa_Rica",
		                      "America/El_Salvador",
		                      "America/Guatemala",
		                      "America/Managua",
		                      "America/Tegucigalpa",
		                      "Etc/GMT+6",
		                      "Pacific/Galapagos"
		                    ]
		                  },
		                  {
		                    "name": "Central Standard Time",
		                    "abbr": "CDT",
		                    "offset": -5,
		                    "isdst": true,
		                    "text": "(UTC-06:00) Central Time (US & Canada)",
		                    "utc": [
		                      "America/Chicago",
		                      "America/Indiana/Knox",
		                      "America/Indiana/Tell_City",
		                      "America/Matamoros",
		                      "America/Menominee",
		                      "America/North_Dakota/Beulah",
		                      "America/North_Dakota/Center",
		                      "America/North_Dakota/New_Salem",
		                      "America/Rainy_River",
		                      "America/Rankin_Inlet",
		                      "America/Resolute",
		                      "America/Winnipeg",
		                      "CST6CDT"
		                    ]
		                  },
		                  {
		                    "name": "Central Standard Time (Mexico)",
		                    "abbr": "CDT",
		                    "offset": -5,
		                    "isdst": true,
		                    "text": "(UTC-06:00) Guadalajara, Mexico City, Monterrey",
		                    "utc": [
		                      "America/Bahia_Banderas",
		                      "America/Cancun",
		                      "America/Merida",
		                      "America/Mexico_City",
		                      "America/Monterrey"
		                    ]
		                  },
		                  {
		                    "name": "Canada Central Standard Time",
		                    "abbr": "CCST",
		                    "offset": -6,
		                    "isdst": false,
		                    "text": "(UTC-06:00) Saskatchewan",
		                    "utc": [
		                      "America/Regina",
		                      "America/Swift_Current"
		                    ]
		                  },
		                  {
		                    "name": "SA Pacific Standard Time",
		                    "abbr": "SPST",
		                    "offset": -5,
		                    "isdst": false,
		                    "text": "(UTC-05:00) Bogota, Lima, Quito",
		                    "utc": [
		                      "America/Bogota",
		                      "America/Cayman",
		                      "America/Coral_Harbour",
		                      "America/Eirunepe",
		                      "America/Guayaquil",
		                      "America/Jamaica",
		                      "America/Lima",
		                      "America/Panama",
		                      "America/Rio_Branco",
		                      "Etc/GMT+5"
		                    ]
		                  },
		                  {
		                    "name": "Eastern Standard Time",
		                    "abbr": "EDT",
		                    "offset": -4,
		                    "isdst": true,
		                    "text": "(UTC-05:00) Eastern Time (US & Canada)",
		                    "utc": [
		                      "America/Detroit",
		                      "America/Havana",
		                      "America/Indiana/Petersburg",
		                      "America/Indiana/Vincennes",
		                      "America/Indiana/Winamac",
		                      "America/Iqaluit",
		                      "America/Kentucky/Monticello",
		                      "America/Louisville",
		                      "America/Montreal",
		                      "America/Nassau",
		                      "America/New_York",
		                      "America/Nipigon",
		                      "America/Pangnirtung",
		                      "America/Port-au-Prince",
		                      "America/Thunder_Bay",
		                      "America/Toronto",
		                      "EST5EDT"
		                    ]
		                  },
		                  {
		                    "name": "US Eastern Standard Time",
		                    "abbr": "UEDT",
		                    "offset": -4,
		                    "isdst": true,
		                    "text": "(UTC-05:00) Indiana (East)",
		                    "utc": [
		                      "America/Indiana/Marengo",
		                      "America/Indiana/Vevay",
		                      "America/Indianapolis"
		                    ]
		                  },
		                  {
		                    "name": "Venezuela Standard Time",
		                    "abbr": "VST",
		                    "offset": -4.5,
		                    "isdst": false,
		                    "text": "(UTC-04:30) Caracas",
		                    "utc": [
		                      "America/Caracas"
		                    ]
		                  },
		                  {
		                    "name": "Paraguay Standard Time",
		                    "abbr": "PYT",
		                    "offset": -4,
		                    "isdst": false,
		                    "text": "(UTC-04:00) Asuncion",
		                    "utc": [
		                      "America/Asuncion"
		                    ]
		                  },
		                  {
		                    "name": "Atlantic Standard Time",
		                    "abbr": "ADT",
		                    "offset": -3,
		                    "isdst": true,
		                    "text": "(UTC-04:00) Atlantic Time (Canada)",
		                    "utc": [
		                      "America/Glace_Bay",
		                      "America/Goose_Bay",
		                      "America/Halifax",
		                      "America/Moncton",
		                      "America/Thule",
		                      "Atlantic/Bermuda"
		                    ]
		                  },
		                  {
		                    "name": "Central Brazilian Standard Time",
		                    "abbr": "CBST",
		                    "offset": -4,
		                    "isdst": false,
		                    "text": "(UTC-04:00) Cuiaba",
		                    "utc": [
		                      "America/Campo_Grande",
		                      "America/Cuiaba"
		                    ]
		                  },
		                  {
		                    "name": "SA Western Standard Time",
		                    "abbr": "SWST",
		                    "offset": -4,
		                    "isdst": false,
		                    "text": "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan",
		                    "utc": [
		                      "America/Anguilla",
		                      "America/Antigua",
		                      "America/Aruba",
		                      "America/Barbados",
		                      "America/Blanc-Sablon",
		                      "America/Boa_Vista",
		                      "America/Curacao",
		                      "America/Dominica",
		                      "America/Grand_Turk",
		                      "America/Grenada",
		                      "America/Guadeloupe",
		                      "America/Guyana",
		                      "America/Kralendijk",
		                      "America/La_Paz",
		                      "America/Lower_Princes",
		                      "America/Manaus",
		                      "America/Marigot",
		                      "America/Martinique",
		                      "America/Montserrat",
		                      "America/Port_of_Spain",
		                      "America/Porto_Velho",
		                      "America/Puerto_Rico",
		                      "America/Santo_Domingo",
		                      "America/St_Barthelemy",
		                      "America/St_Kitts",
		                      "America/St_Lucia",
		                      "America/St_Thomas",
		                      "America/St_Vincent",
		                      "America/Tortola",
		                      "Etc/GMT+4"
		                    ]
		                  },
		                  {
		                    "name": "Pacific SA Standard Time",
		                    "abbr": "PSST",
		                    "offset": -4,
		                    "isdst": false,
		                    "text": "(UTC-04:00) Santiago",
		                    "utc": [
		                      "America/Santiago",
		                      "Antarctica/Palmer"
		                    ]
		                  },
		                  {
		                    "name": "Newfoundland Standard Time",
		                    "abbr": "NDT",
		                    "offset": -2.5,
		                    "isdst": true,
		                    "text": "(UTC-03:30) Newfoundland",
		                    "utc": [
		                      "America/St_Johns"
		                    ]
		                  },
		                  {
		                    "name": "E. South America Standard Time",
		                    "abbr": "ESAST",
		                    "offset": -3,
		                    "isdst": false,
		                    "text": "(UTC-03:00) Brasilia",
		                    "utc": [
		                      "America/Sao_Paulo"
		                    ]
		                  },
		                  {
		                    "name": "Argentina Standard Time",
		                    "abbr": "AST",
		                    "offset": -3,
		                    "isdst": false,
		                    "text": "(UTC-03:00) Buenos Aires",
		                    "utc": [
		                      "America/Argentina/La_Rioja",
		                      "America/Argentina/Rio_Gallegos",
		                      "America/Argentina/Salta",
		                      "America/Argentina/San_Juan",
		                      "America/Argentina/San_Luis",
		                      "America/Argentina/Tucuman",
		                      "America/Argentina/Ushuaia",
		                      "America/Buenos_Aires",
		                      "America/Catamarca",
		                      "America/Cordoba",
		                      "America/Jujuy",
		                      "America/Mendoza"
		                    ]
		                  },
		                  {
		                    "name": "SA Eastern Standard Time",
		                    "abbr": "SEST",
		                    "offset": -3,
		                    "isdst": false,
		                    "text": "(UTC-03:00) Cayenne, Fortaleza",
		                    "utc": [
		                      "America/Araguaina",
		                      "America/Belem",
		                      "America/Cayenne",
		                      "America/Fortaleza",
		                      "America/Maceio",
		                      "America/Paramaribo",
		                      "America/Recife",
		                      "America/Santarem",
		                      "Antarctica/Rothera",
		                      "Atlantic/Stanley",
		                      "Etc/GMT+3"
		                    ]
		                  },
		                  {
		                    "name": "Greenland Standard Time",
		                    "abbr": "GDT",
		                    "offset": -3,
		                    "isdst": true,
		                    "text": "(UTC-03:00) Greenland",
		                    "utc": [
		                      "America/Godthab"
		                    ]
		                  },
		                  {
		                    "name": "Montevideo Standard Time",
		                    "abbr": "MST",
		                    "offset": -3,
		                    "isdst": false,
		                    "text": "(UTC-03:00) Montevideo",
		                    "utc": [
		                      "America/Montevideo"
		                    ]
		                  },
		                  {
		                    "name": "Bahia Standard Time",
		                    "abbr": "BST",
		                    "offset": -3,
		                    "isdst": false,
		                    "text": "(UTC-03:00) Salvador",
		                    "utc": [
		                      "America/Bahia"
		                    ]
		                  },
		                  {
		                    "name": "UTC-02",
		                    "abbr": "U",
		                    "offset": -2,
		                    "isdst": false,
		                    "text": "(UTC-02:00) Coordinated Universal Time-02",
		                    "utc": [
		                      "America/Noronha",
		                      "Atlantic/South_Georgia",
		                      "Etc/GMT+2"
		                    ]
		                  },
		                  {
		                    "name": "Mid-Atlantic Standard Time",
		                    "abbr": "MDT",
		                    "offset": -1,
		                    "isdst": true,
		                    "text": "(UTC-02:00) Mid-Atlantic - Old",
		                    "utc": []
		                  },
		                  {
		                    "name": "Azores Standard Time",
		                    "abbr": "ADT",
		                    "offset": 0,
		                    "isdst": true,
		                    "text": "(UTC-01:00) Azores",
		                    "utc": [
		                      "America/Scoresbysund",
		                      "Atlantic/Azores"
		                    ]
		                  },
		                  {
		                    "name": "Cape Verde Standard Time",
		                    "abbr": "CVST",
		                    "offset": -1,
		                    "isdst": false,
		                    "text": "(UTC-01:00) Cape Verde Is.",
		                    "utc": [
		                      "Atlantic/Cape_Verde",
		                      "Etc/GMT+1"
		                    ]
		                  },
		                  {
		                    "name": "Morocco Standard Time",
		                    "abbr": "MDT",
		                    "offset": 1,
		                    "isdst": true,
		                    "text": "(UTC) Casablanca",
		                    "utc": [
		                      "Africa/Casablanca",
		                      "Africa/El_Aaiun"
		                    ]
		                  },
		                  {
		                    "name": "UTC",
		                    "abbr": "UTC",
		                    "offset": 0,
		                    "isdst": false,
		                    "text": "(UTC) Coordinated Universal Time",
		                    "utc": [
		                      "America/Danmarkshavn",
		                      "Etc/GMT"
		                    ]
		                  },
		                  {
		                    "name": "GMT Standard Time",
		                    "abbr": "GMT",
		                    "offset": 0,
		                    "isdst": false,
		                    "text": "(UTC) Edinburgh, London",
		                    "utc": [
		                      "Europe/Isle_of_Man",
		                      "Europe/Guernsey",
		                      "Europe/Jersey",
		                      "Europe/London"
		                    ]
		                  },
		                  {
		                    "name": "British Summer Time",
		                    "abbr": "BST",
		                    "offset": 1,
		                    "isdst": true,
		                    "text": "(UTC+01:00) Edinburgh, London",
		                    "utc": [
		                      "Europe/Isle_of_Man",
		                      "Europe/Guernsey",
		                      "Europe/Jersey",
		                      "Europe/London"
		                    ]
		                  },
		                  {
		                    "name": "GMT Standard Time",
		                    "abbr": "GDT",
		                    "offset": 1,
		                    "isdst": true,
		                    "text": "(UTC) Dublin, Lisbon",
		                    "utc": [
		                      "Atlantic/Canary",
		                      "Atlantic/Faeroe",
		                      "Atlantic/Madeira",
		                      "Europe/Dublin",
		                      "Europe/Lisbon"
		                    ]
		                  },
		                  {
		                    "name": "Greenwich Standard Time",
		                    "abbr": "GST",
		                    "offset": 0,
		                    "isdst": false,
		                    "text": "(UTC) Monrovia, Reykjavik",
		                    "utc": [
		                      "Africa/Abidjan",
		                      "Africa/Accra",
		                      "Africa/Bamako",
		                      "Africa/Banjul",
		                      "Africa/Bissau",
		                      "Africa/Conakry",
		                      "Africa/Dakar",
		                      "Africa/Freetown",
		                      "Africa/Lome",
		                      "Africa/Monrovia",
		                      "Africa/Nouakchott",
		                      "Africa/Ouagadougou",
		                      "Africa/Sao_Tome",
		                      "Atlantic/Reykjavik",
		                      "Atlantic/St_Helena"
		                    ]
		                  },
		                  {
		                    "name": "W. Europe Standard Time",
		                    "abbr": "WEDT",
		                    "offset": 2,
		                    "isdst": true,
		                    "text": "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna",
		                    "utc": [
		                      "Arctic/Longyearbyen",
		                      "Europe/Amsterdam",
		                      "Europe/Andorra",
		                      "Europe/Berlin",
		                      "Europe/Busingen",
		                      "Europe/Gibraltar",
		                      "Europe/Luxembourg",
		                      "Europe/Malta",
		                      "Europe/Monaco",
		                      "Europe/Oslo",
		                      "Europe/Rome",
		                      "Europe/San_Marino",
		                      "Europe/Stockholm",
		                      "Europe/Vaduz",
		                      "Europe/Vatican",
		                      "Europe/Vienna",
		                      "Europe/Zurich"
		                    ]
		                  },
		                  {
		                    "name": "Central Europe Standard Time",
		                    "abbr": "CEDT",
		                    "offset": 2,
		                    "isdst": true,
		                    "text": "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague",
		                    "utc": [
		                      "Europe/Belgrade",
		                      "Europe/Bratislava",
		                      "Europe/Budapest",
		                      "Europe/Ljubljana",
		                      "Europe/Podgorica",
		                      "Europe/Prague",
		                      "Europe/Tirane"
		                    ]
		                  },
		                  {
		                    "name": "Romance Standard Time",
		                    "abbr": "RDT",
		                    "offset": 2,
		                    "isdst": true,
		                    "text": "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris",
		                    "utc": [
		                      "Africa/Ceuta",
		                      "Europe/Brussels",
		                      "Europe/Copenhagen",
		                      "Europe/Madrid",
		                      "Europe/Paris"
		                    ]
		                  },
		                  {
		                    "name": "Central European Standard Time",
		                    "abbr": "CEDT",
		                    "offset": 2,
		                    "isdst": true,
		                    "text": "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb",
		                    "utc": [
		                      "Europe/Sarajevo",
		                      "Europe/Skopje",
		                      "Europe/Warsaw",
		                      "Europe/Zagreb"
		                    ]
		                  },
		                  {
		                    "name": "W. Central Africa Standard Time",
		                    "abbr": "WCAST",
		                    "offset": 1,
		                    "isdst": false,
		                    "text": "(UTC+01:00) West Central Africa",
		                    "utc": [
		                      "Africa/Algiers",
		                      "Africa/Bangui",
		                      "Africa/Brazzaville",
		                      "Africa/Douala",
		                      "Africa/Kinshasa",
		                      "Africa/Lagos",
		                      "Africa/Libreville",
		                      "Africa/Luanda",
		                      "Africa/Malabo",
		                      "Africa/Ndjamena",
		                      "Africa/Niamey",
		                      "Africa/Porto-Novo",
		                      "Africa/Tunis",
		                      "Etc/GMT-1"
		                    ]
		                  },
		                  {
		                    "name": "Namibia Standard Time",
		                    "abbr": "NST",
		                    "offset": 1,
		                    "isdst": false,
		                    "text": "(UTC+01:00) Windhoek",
		                    "utc": [
		                      "Africa/Windhoek"
		                    ]
		                  },
		                  {
		                    "name": "GTB Standard Time",
		                    "abbr": "GDT",
		                    "offset": 3,
		                    "isdst": true,
		                    "text": "(UTC+02:00) Athens, Bucharest",
		                    "utc": [
		                      "Asia/Nicosia",
		                      "Europe/Athens",
		                      "Europe/Bucharest",
		                      "Europe/Chisinau"
		                    ]
		                  },
		                  {
		                    "name": "Middle East Standard Time",
		                    "abbr": "MEDT",
		                    "offset": 3,
		                    "isdst": true,
		                    "text": "(UTC+02:00) Beirut",
		                    "utc": [
		                      "Asia/Beirut"
		                    ]
		                  },
		                  {
		                    "name": "Egypt Standard Time",
		                    "abbr": "EST",
		                    "offset": 2,
		                    "isdst": false,
		                    "text": "(UTC+02:00) Cairo",
		                    "utc": [
		                      "Africa/Cairo"
		                    ]
		                  },
		                  {
		                    "name": "Syria Standard Time",
		                    "abbr": "SDT",
		                    "offset": 3,
		                    "isdst": true,
		                    "text": "(UTC+02:00) Damascus",
		                    "utc": [
		                      "Asia/Damascus"
		                    ]
		                  },
		                  {
		                    "name": "E. Europe Standard Time",
		                    "abbr": "EEDT",
		                    "offset": 3,
		                    "isdst": true,
		                    "text": "(UTC+02:00) E. Europe",
		                    "utc": [
		                      "Asia/Nicosia",
		                      "Europe/Athens",
		                      "Europe/Bucharest",
		                      "Europe/Chisinau",
		                      "Europe/Helsinki",
		                      "Europe/Kiev",
		                      "Europe/Mariehamn",
		                      "Europe/Nicosia",
		                      "Europe/Riga",
		                      "Europe/Sofia",
		                      "Europe/Tallinn",
		                      "Europe/Uzhgorod",
		                      "Europe/Vilnius",
		                      "Europe/Zaporozhye"
		                    ]
		                  },
		                  {
		                    "name": "South Africa Standard Time",
		                    "abbr": "SAST",
		                    "offset": 2,
		                    "isdst": false,
		                    "text": "(UTC+02:00) Harare, Pretoria",
		                    "utc": [
		                      "Africa/Blantyre",
		                      "Africa/Bujumbura",
		                      "Africa/Gaborone",
		                      "Africa/Harare",
		                      "Africa/Johannesburg",
		                      "Africa/Kigali",
		                      "Africa/Lubumbashi",
		                      "Africa/Lusaka",
		                      "Africa/Maputo",
		                      "Africa/Maseru",
		                      "Africa/Mbabane",
		                      "Etc/GMT-2"
		                    ]
		                  },
		                  {
		                    "name": "FLE Standard Time",
		                    "abbr": "FDT",
		                    "offset": 3,
		                    "isdst": true,
		                    "text": "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius",
		                    "utc": [
		                      "Europe/Helsinki",
		                      "Europe/Kiev",
		                      "Europe/Mariehamn",
		                      "Europe/Riga",
		                      "Europe/Sofia",
		                      "Europe/Tallinn",
		                      "Europe/Uzhgorod",
		                      "Europe/Vilnius",
		                      "Europe/Zaporozhye"
		                    ]
		                  },
		                  {
		                    "name": "Turkey Standard Time",
		                    "abbr": "TDT",
		                    "offset": 3,
		                    "isdst": false,
		                    "text": "(UTC+03:00) Istanbul",
		                    "utc": [
		                      "Europe/Istanbul"
		                    ]
		                  },
		                  {
		                    "name": "Israel Standard Time",
		                    "abbr": "JDT",
		                    "offset": 3,
		                    "isdst": true,
		                    "text": "(UTC+02:00) Jerusalem",
		                    "utc": [
		                      "Asia/Jerusalem"
		                    ]
		                  },
		                  {
		                    "name": "Libya Standard Time",
		                    "abbr": "LST",
		                    "offset": 2,
		                    "isdst": false,
		                    "text": "(UTC+02:00) Tripoli",
		                    "utc": [
		                      "Africa/Tripoli"
		                    ]
		                  },
		                  {
		                    "name": "Jordan Standard Time",
		                    "abbr": "JST",
		                    "offset": 3,
		                    "isdst": false,
		                    "text": "(UTC+03:00) Amman",
		                    "utc": [
		                      "Asia/Amman"
		                    ]
		                  },
		                  {
		                    "name": "Arabic Standard Time",
		                    "abbr": "AST",
		                    "offset": 3,
		                    "isdst": false,
		                    "text": "(UTC+03:00) Baghdad",
		                    "utc": [
		                      "Asia/Baghdad"
		                    ]
		                  },
		                  {
		                    "name": "Kaliningrad Standard Time",
		                    "abbr": "KST",
		                    "offset": 3,
		                    "isdst": false,
		                    "text": "(UTC+02:00) Kaliningrad",
		                    "utc": [
		                      "Europe/Kaliningrad"
		                    ]
		                  },
		                  {
		                    "name": "Arab Standard Time",
		                    "abbr": "AST",
		                    "offset": 3,
		                    "isdst": false,
		                    "text": "(UTC+03:00) Kuwait, Riyadh",
		                    "utc": [
		                      "Asia/Aden",
		                      "Asia/Bahrain",
		                      "Asia/Kuwait",
		                      "Asia/Qatar",
		                      "Asia/Riyadh"
		                    ]
		                  },
		                  {
		                    "name": "E. Africa Standard Time",
		                    "abbr": "EAST",
		                    "offset": 3,
		                    "isdst": false,
		                    "text": "(UTC+03:00) Nairobi",
		                    "utc": [
		                      "Africa/Addis_Ababa",
		                      "Africa/Asmera",
		                      "Africa/Dar_es_Salaam",
		                      "Africa/Djibouti",
		                      "Africa/Juba",
		                      "Africa/Kampala",
		                      "Africa/Khartoum",
		                      "Africa/Mogadishu",
		                      "Africa/Nairobi",
		                      "Antarctica/Syowa",
		                      "Etc/GMT-3",
		                      "Indian/Antananarivo",
		                      "Indian/Comoro",
		                      "Indian/Mayotte"
		                    ]
		                  },
		                  {
		                    "name": "Moscow Standard Time",
		                    "abbr": "MSK",
		                    "offset": 3,
		                    "isdst": false,
		                    "text": "(UTC+03:00) Moscow, St. Petersburg, Volgograd, Minsk",
		                    "utc": [
		                        "Europe/Kirov",
		                      "Europe/Moscow",
		                      "Europe/Simferopol",
		                      "Europe/Volgograd",
		                      "Europe/Minsk"
		                    ]
		                  },
		                  {
		                    "name": "Samara Time",
		                    "abbr": "SAMT",
		                    "offset": 4,
		                    "isdst": false,
		                    "text": "(UTC+04:00) Samara, Ulyanovsk, Saratov",
		                    "utc": [
		                        "Europe/Astrakhan",
		                      "Europe/Samara",
		                        "Europe/Ulyanovsk"
		                    ]
		                  },
		                  {
		                    "name": "Iran Standard Time",
		                    "abbr": "IDT",
		                    "offset": 4.5,
		                    "isdst": true,
		                    "text": "(UTC+03:30) Tehran",
		                    "utc": [
		                      "Asia/Tehran"
		                    ]
		                  },
		                  {
		                    "name": "Arabian Standard Time",
		                    "abbr": "AST",
		                    "offset": 4,
		                    "isdst": false,
		                    "text": "(UTC+04:00) Abu Dhabi, Muscat",
		                    "utc": [
		                      "Asia/Dubai",
		                      "Asia/Muscat",
		                      "Etc/GMT-4"
		                    ]
		                  },
		                  {
		                    "name": "Azerbaijan Standard Time",
		                    "abbr": "ADT",
		                    "offset": 5,
		                    "isdst": true,
		                    "text": "(UTC+04:00) Baku",
		                    "utc": [
		                      "Asia/Baku"
		                    ]
		                  },
		                  {
		                    "name": "Mauritius Standard Time",
		                    "abbr": "MST",
		                    "offset": 4,
		                    "isdst": false,
		                    "text": "(UTC+04:00) Port Louis",
		                    "utc": [
		                      "Indian/Mahe",
		                      "Indian/Mauritius",
		                      "Indian/Reunion"
		                    ]
		                  },
		                  {
		                    "name": "Georgian Standard Time",
		                    "abbr": "GET",
		                    "offset": 4,
		                    "isdst": false,
		                    "text": "(UTC+04:00) Tbilisi",
		                    "utc": [
		                      "Asia/Tbilisi"
		                    ]
		                  },
		                  {
		                    "name": "Caucasus Standard Time",
		                    "abbr": "CST",
		                    "offset": 4,
		                    "isdst": false,
		                    "text": "(UTC+04:00) Yerevan",
		                    "utc": [
		                      "Asia/Yerevan"
		                    ]
		                  },
		                  {
		                    "name": "Afghanistan Standard Time",
		                    "abbr": "AST",
		                    "offset": 4.5,
		                    "isdst": false,
		                    "text": "(UTC+04:30) Kabul",
		                    "utc": [
		                      "Asia/Kabul"
		                    ]
		                  },
		                  {
		                    "name": "West Asia Standard Time",
		                    "abbr": "WAST",
		                    "offset": 5,
		                    "isdst": false,
		                    "text": "(UTC+05:00) Ashgabat, Tashkent",
		                    "utc": [
		                      "Antarctica/Mawson",
		                      "Asia/Aqtau",
		                      "Asia/Aqtobe",
		                      "Asia/Ashgabat",
		                      "Asia/Dushanbe",
		                      "Asia/Oral",
		                      "Asia/Samarkand",
		                      "Asia/Tashkent",
		                      "Etc/GMT-5",
		                      "Indian/Kerguelen",
		                      "Indian/Maldives"
		                    ]
		                  },
		                  {
		                    "name": "Yekaterinburg Time",
		                    "abbr": "YEKT",
		                    "offset": 5,
		                    "isdst": false,
		                    "text": "(UTC+05:00) Yekaterinburg",
		                    "utc": [
		                      "Asia/Yekaterinburg"
		                    ]
		                  },
		                  {
		                    "name": "Pakistan Standard Time",
		                    "abbr": "PKT",
		                    "offset": 5,
		                    "isdst": false,
		                    "text": "(UTC+05:00) Islamabad, Karachi",
		                    "utc": [
		                      "Asia/Karachi"
		                    ]
		                  },
		                  {
		                    "name": "India Standard Time",
		                    "abbr": "IST",
		                    "offset": 5.5,
		                    "isdst": false,
		                    "text": "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi",
		                    "utc": [
		                      "Asia/Kolkata"
		                    ]
		                  },
		                  {
		                    "name": "Sri Lanka Standard Time",
		                    "abbr": "SLST",
		                    "offset": 5.5,
		                    "isdst": false,
		                    "text": "(UTC+05:30) Sri Jayawardenepura",
		                    "utc": [
		                      "Asia/Colombo"
		                    ]
		                  },
		                  {
		                    "name": "Nepal Standard Time",
		                    "abbr": "NST",
		                    "offset": 5.75,
		                    "isdst": false,
		                    "text": "(UTC+05:45) Kathmandu",
		                    "utc": [
		                      "Asia/Kathmandu"
		                    ]
		                  },
		                  {
		                    "name": "Central Asia Standard Time",
		                    "abbr": "CAST",
		                    "offset": 6,
		                    "isdst": false,
		                    "text": "(UTC+06:00) Nur-Sultan (Astana)",
		                    "utc": [
		                      "Antarctica/Vostok",
		                      "Asia/Almaty",
		                      "Asia/Bishkek",
		                      "Asia/Qyzylorda",
		                      "Asia/Urumqi",
		                      "Etc/GMT-6",
		                      "Indian/Chagos"
		                    ]
		                  },
		                  {
		                    "name": "Bangladesh Standard Time",
		                    "abbr": "BST",
		                    "offset": 6,
		                    "isdst": false,
		                    "text": "(UTC+06:00) Dhaka",
		                    "utc": [
		                      "Asia/Dhaka",
		                      "Asia/Thimphu"
		                    ]
		                  },
		                  {
		                    "name": "Myanmar Standard Time",
		                    "abbr": "MST",
		                    "offset": 6.5,
		                    "isdst": false,
		                    "text": "(UTC+06:30) Yangon (Rangoon)",
		                    "utc": [
		                      "Asia/Rangoon",
		                      "Indian/Cocos"
		                    ]
		                  },
		                  {
		                    "name": "SE Asia Standard Time",
		                    "abbr": "SAST",
		                    "offset": 7,
		                    "isdst": false,
		                    "text": "(UTC+07:00) Bangkok, Hanoi, Jakarta",
		                    "utc": [
		                      "Antarctica/Davis",
		                      "Asia/Bangkok",
		                      "Asia/Hovd",
		                      "Asia/Jakarta",
		                      "Asia/Phnom_Penh",
		                      "Asia/Pontianak",
		                      "Asia/Saigon",
		                      "Asia/Vientiane",
		                      "Etc/GMT-7",
		                      "Indian/Christmas"
		                    ]
		                  },
		                  {
		                    "name": "N. Central Asia Standard Time",
		                    "abbr": "NCAST",
		                    "offset": 7,
		                    "isdst": false,
		                    "text": "(UTC+07:00) Novosibirsk",
		                    "utc": [
		                      "Asia/Novokuznetsk",
		                      "Asia/Novosibirsk",
		                      "Asia/Omsk"
		                    ]
		                  },
		                  {
		                    "name": "China Standard Time",
		                    "abbr": "CST",
		                    "offset": 8,
		                    "isdst": false,
		                    "text": "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi",
		                    "utc": [
		                      "Asia/Hong_Kong",
		                      "Asia/Macau",
		                      "Asia/Shanghai"
		                    ]
		                  },
		                  {
		                    "name": "North Asia Standard Time",
		                    "abbr": "NAST",
		                    "offset": 8,
		                    "isdst": false,
		                    "text": "(UTC+08:00) Krasnoyarsk",
		                    "utc": [
		                      "Asia/Krasnoyarsk"
		                    ]
		                  },
		                  {
		                    "name": "Singapore Standard Time",
		                    "abbr": "MPST",
		                    "offset": 8,
		                    "isdst": false,
		                    "text": "(UTC+08:00) Kuala Lumpur, Singapore",
		                    "utc": [
		                      "Asia/Brunei",
		                      "Asia/Kuala_Lumpur",
		                      "Asia/Kuching",
		                      "Asia/Makassar",
		                      "Asia/Manila",
		                      "Asia/Singapore",
		                      "Etc/GMT-8"
		                    ]
		                  },
		                  {
		                    "name": "W. Australia Standard Time",
		                    "abbr": "WAST",
		                    "offset": 8,
		                    "isdst": false,
		                    "text": "(UTC+08:00) Perth",
		                    "utc": [
		                      "Antarctica/Casey",
		                      "Australia/Perth"
		                    ]
		                  },
		                  {
		                    "name": "Taipei Standard Time",
		                    "abbr": "TST",
		                    "offset": 8,
		                    "isdst": false,
		                    "text": "(UTC+08:00) Taipei",
		                    "utc": [
		                      "Asia/Taipei"
		                    ]
		                  },
		                  {
		                    "name": "Ulaanbaatar Standard Time",
		                    "abbr": "UST",
		                    "offset": 8,
		                    "isdst": false,
		                    "text": "(UTC+08:00) Ulaanbaatar",
		                    "utc": [
		                      "Asia/Choibalsan",
		                      "Asia/Ulaanbaatar"
		                    ]
		                  },
		                  {
		                    "name": "North Asia East Standard Time",
		                    "abbr": "NAEST",
		                    "offset": 8,
		                    "isdst": false,
		                    "text": "(UTC+08:00) Irkutsk",
		                    "utc": [
		                      "Asia/Irkutsk"
		                    ]
		                  },
		                  {
		                    "name": "Japan Standard Time",
		                    "abbr": "JST",
		                    "offset": 9,
		                    "isdst": false,
		                    "text": "(UTC+09:00) Osaka, Sapporo, Tokyo",
		                    "utc": [
		                      "Asia/Dili",
		                      "Asia/Jayapura",
		                      "Asia/Tokyo",
		                      "Etc/GMT-9",
		                      "Pacific/Palau"
		                    ]
		                  },
		                  {
		                    "name": "Korea Standard Time",
		                    "abbr": "KST",
		                    "offset": 9,
		                    "isdst": false,
		                    "text": "(UTC+09:00) Seoul",
		                    "utc": [
		                      "Asia/Pyongyang",
		                      "Asia/Seoul"
		                    ]
		                  },
		                  {
		                    "name": "Cen. Australia Standard Time",
		                    "abbr": "CAST",
		                    "offset": 9.5,
		                    "isdst": false,
		                    "text": "(UTC+09:30) Adelaide",
		                    "utc": [
		                      "Australia/Adelaide",
		                      "Australia/Broken_Hill"
		                    ]
		                  },
		                  {
		                    "name": "AUS Central Standard Time",
		                    "abbr": "ACST",
		                    "offset": 9.5,
		                    "isdst": false,
		                    "text": "(UTC+09:30) Darwin",
		                    "utc": [
		                      "Australia/Darwin"
		                    ]
		                  },
		                  {
		                    "name": "E. Australia Standard Time",
		                    "abbr": "EAST",
		                    "offset": 10,
		                    "isdst": false,
		                    "text": "(UTC+10:00) Brisbane",
		                    "utc": [
		                      "Australia/Brisbane",
		                      "Australia/Lindeman"
		                    ]
		                  },
		                  {
		                    "name": "AUS Eastern Standard Time",
		                    "abbr": "AEST",
		                    "offset": 10,
		                    "isdst": false,
		                    "text": "(UTC+10:00) Canberra, Melbourne, Sydney",
		                    "utc": [
		                      "Australia/Melbourne",
		                      "Australia/Sydney"
		                    ]
		                  },
		                  {
		                    "name": "West Pacific Standard Time",
		                    "abbr": "WPST",
		                    "offset": 10,
		                    "isdst": false,
		                    "text": "(UTC+10:00) Guam, Port Moresby",
		                    "utc": [
		                      "Antarctica/DumontDUrville",
		                      "Etc/GMT-10",
		                      "Pacific/Guam",
		                      "Pacific/Port_Moresby",
		                      "Pacific/Saipan",
		                      "Pacific/Truk"
		                    ]
		                  },
		                  {
		                    "name": "Tasmania Standard Time",
		                    "abbr": "TST",
		                    "offset": 10,
		                    "isdst": false,
		                    "text": "(UTC+10:00) Hobart",
		                    "utc": [
		                      "Australia/Currie",
		                      "Australia/Hobart"
		                    ]
		                  },
		                  {
		                    "name": "Yakutsk Standard Time",
		                    "abbr": "YST",
		                    "offset": 9,
		                    "isdst": false,
		                    "text": "(UTC+09:00) Yakutsk",
		                    "utc": [
		                      "Asia/Chita",
		                      "Asia/Khandyga",
		                      "Asia/Yakutsk"
		                    ]
		                  },
		                  {
		                    "name": "Central Pacific Standard Time",
		                    "abbr": "CPST",
		                    "offset": 11,
		                    "isdst": false,
		                    "text": "(UTC+11:00) Solomon Is., New Caledonia",
		                    "utc": [
		                      "Antarctica/Macquarie",
		                      "Etc/GMT-11",
		                      "Pacific/Efate",
		                      "Pacific/Guadalcanal",
		                      "Pacific/Kosrae",
		                      "Pacific/Noumea",
		                      "Pacific/Ponape"
		                    ]
		                  },
		                  {
		                    "name": "Vladivostok Standard Time",
		                    "abbr": "VST",
		                    "offset": 11,
		                    "isdst": false,
		                    "text": "(UTC+11:00) Vladivostok",
		                    "utc": [
		                      "Asia/Sakhalin",
		                      "Asia/Ust-Nera",
		                      "Asia/Vladivostok"
		                    ]
		                  },
		                  {
		                    "name": "New Zealand Standard Time",
		                    "abbr": "NZST",
		                    "offset": 12,
		                    "isdst": false,
		                    "text": "(UTC+12:00) Auckland, Wellington",
		                    "utc": [
		                      "Antarctica/McMurdo",
		                      "Pacific/Auckland"
		                    ]
		                  },
		                  {
		                    "name": "UTC+12",
		                    "abbr": "U",
		                    "offset": 12,
		                    "isdst": false,
		                    "text": "(UTC+12:00) Coordinated Universal Time+12",
		                    "utc": [
		                      "Etc/GMT-12",
		                      "Pacific/Funafuti",
		                      "Pacific/Kwajalein",
		                      "Pacific/Majuro",
		                      "Pacific/Nauru",
		                      "Pacific/Tarawa",
		                      "Pacific/Wake",
		                      "Pacific/Wallis"
		                    ]
		                  },
		                  {
		                    "name": "Fiji Standard Time",
		                    "abbr": "FST",
		                    "offset": 12,
		                    "isdst": false,
		                    "text": "(UTC+12:00) Fiji",
		                    "utc": [
		                      "Pacific/Fiji"
		                    ]
		                  },
		                  {
		                    "name": "Magadan Standard Time",
		                    "abbr": "MST",
		                    "offset": 12,
		                    "isdst": false,
		                    "text": "(UTC+12:00) Magadan",
		                    "utc": [
		                      "Asia/Anadyr",
		                      "Asia/Kamchatka",
		                      "Asia/Magadan",
		                      "Asia/Srednekolymsk"
		                    ]
		                  },
		                  {
		                    "name": "Kamchatka Standard Time",
		                    "abbr": "KDT",
		                    "offset": 13,
		                    "isdst": true,
		                    "text": "(UTC+12:00) Petropavlovsk-Kamchatsky - Old",
		                    "utc": [
		                      "Asia/Kamchatka"
		                    ]
		                  },
		                  {
		                    "name": "Tonga Standard Time",
		                    "abbr": "TST",
		                    "offset": 13,
		                    "isdst": false,
		                    "text": "(UTC+13:00) Nuku'alofa",
		                    "utc": [
		                      "Etc/GMT-13",
		                      "Pacific/Enderbury",
		                      "Pacific/Fakaofo",
		                      "Pacific/Tongatapu"
		                    ]
		                  },
		                  {
		                    "name": "Samoa Standard Time",
		                    "abbr": "SST",
		                    "offset": 13,
		                    "isdst": false,
		                    "text": "(UTC+13:00) Samoa",
		                    "utc": [
		                      "Pacific/Apia"
		                    ]
		                  }
		                ],
		        //List source: http://answers.google.com/answers/threadview/id/589312.html
		        profession: [
		            "Airline Pilot",
		            "Academic Team",
		            "Accountant",
		            "Account Executive",
		            "Actor",
		            "Actuary",
		            "Acquisition Analyst",
		            "Administrative Asst.",
		            "Administrative Analyst",
		            "Administrator",
		            "Advertising Director",
		            "Aerospace Engineer",
		            "Agent",
		            "Agricultural Inspector",
		            "Agricultural Scientist",
		            "Air Traffic Controller",
		            "Animal Trainer",
		            "Anthropologist",
		            "Appraiser",
		            "Architect",
		            "Art Director",
		            "Artist",
		            "Astronomer",
		            "Athletic Coach",
		            "Auditor",
		            "Author",
		            "Baker",
		            "Banker",
		            "Bankruptcy Attorney",
		            "Benefits Manager",
		            "Biologist",
		            "Bio-feedback Specialist",
		            "Biomedical Engineer",
		            "Biotechnical Researcher",
		            "Broadcaster",
		            "Broker",
		            "Building Manager",
		            "Building Contractor",
		            "Building Inspector",
		            "Business Analyst",
		            "Business Planner",
		            "Business Manager",
		            "Buyer",
		            "Call Center Manager",
		            "Career Counselor",
		            "Cash Manager",
		            "Ceramic Engineer",
		            "Chief Executive Officer",
		            "Chief Operation Officer",
		            "Chef",
		            "Chemical Engineer",
		            "Chemist",
		            "Child Care Manager",
		            "Chief Medical Officer",
		            "Chiropractor",
		            "Cinematographer",
		            "City Housing Manager",
		            "City Manager",
		            "Civil Engineer",
		            "Claims Manager",
		            "Clinical Research Assistant",
		            "Collections Manager",
		            "Compliance Manager",
		            "Comptroller",
		            "Computer Manager",
		            "Commercial Artist",
		            "Communications Affairs Director",
		            "Communications Director",
		            "Communications Engineer",
		            "Compensation Analyst",
		            "Computer Programmer",
		            "Computer Ops. Manager",
		            "Computer Engineer",
		            "Computer Operator",
		            "Computer Graphics Specialist",
		            "Construction Engineer",
		            "Construction Manager",
		            "Consultant",
		            "Consumer Relations Manager",
		            "Contract Administrator",
		            "Copyright Attorney",
		            "Copywriter",
		            "Corporate Planner",
		            "Corrections Officer",
		            "Cosmetologist",
		            "Credit Analyst",
		            "Cruise Director",
		            "Chief Information Officer",
		            "Chief Technology Officer",
		            "Customer Service Manager",
		            "Cryptologist",
		            "Dancer",
		            "Data Security Manager",
		            "Database Manager",
		            "Day Care Instructor",
		            "Dentist",
		            "Designer",
		            "Design Engineer",
		            "Desktop Publisher",
		            "Developer",
		            "Development Officer",
		            "Diamond Merchant",
		            "Dietitian",
		            "Direct Marketer",
		            "Director",
		            "Distribution Manager",
		            "Diversity Manager",
		            "Economist",
		            "EEO Compliance Manager",
		            "Editor",
		            "Education Adminator",
		            "Electrical Engineer",
		            "Electro Optical Engineer",
		            "Electronics Engineer",
		            "Embassy Management",
		            "Employment Agent",
		            "Engineer Technician",
		            "Entrepreneur",
		            "Environmental Analyst",
		            "Environmental Attorney",
		            "Environmental Engineer",
		            "Environmental Specialist",
		            "Escrow Officer",
		            "Estimator",
		            "Executive Assistant",
		            "Executive Director",
		            "Executive Recruiter",
		            "Facilities Manager",
		            "Family Counselor",
		            "Fashion Events Manager",
		            "Fashion Merchandiser",
		            "Fast Food Manager",
		            "Film Producer",
		            "Film Production Assistant",
		            "Financial Analyst",
		            "Financial Planner",
		            "Financier",
		            "Fine Artist",
		            "Wildlife Specialist",
		            "Fitness Consultant",
		            "Flight Attendant",
		            "Flight Engineer",
		            "Floral Designer",
		            "Food & Beverage Director",
		            "Food Service Manager",
		            "Forestry Technician",
		            "Franchise Management",
		            "Franchise Sales",
		            "Fraud Investigator",
		            "Freelance Writer",
		            "Fund Raiser",
		            "General Manager",
		            "Geologist",
		            "General Counsel",
		            "Geriatric Specialist",
		            "Gerontologist",
		            "Glamour Photographer",
		            "Golf Club Manager",
		            "Gourmet Chef",
		            "Graphic Designer",
		            "Grounds Keeper",
		            "Hazardous Waste Manager",
		            "Health Care Manager",
		            "Health Therapist",
		            "Health Service Administrator",
		            "Hearing Officer",
		            "Home Economist",
		            "Horticulturist",
		            "Hospital Administrator",
		            "Hotel Manager",
		            "Human Resources Manager",
		            "Importer",
		            "Industrial Designer",
		            "Industrial Engineer",
		            "Information Director",
		            "Inside Sales",
		            "Insurance Adjuster",
		            "Interior Decorator",
		            "Internal Controls Director",
		            "International Acct.",
		            "International Courier",
		            "International Lawyer",
		            "Interpreter",
		            "Investigator",
		            "Investment Banker",
		            "Investment Manager",
		            "IT Architect",
		            "IT Project Manager",
		            "IT Systems Analyst",
		            "Jeweler",
		            "Joint Venture Manager",
		            "Journalist",
		            "Labor Negotiator",
		            "Labor Organizer",
		            "Labor Relations Manager",
		            "Lab Services Director",
		            "Lab Technician",
		            "Land Developer",
		            "Landscape Architect",
		            "Law Enforcement Officer",
		            "Lawyer",
		            "Lead Software Engineer",
		            "Lead Software Test Engineer",
		            "Leasing Manager",
		            "Legal Secretary",
		            "Library Manager",
		            "Litigation Attorney",
		            "Loan Officer",
		            "Lobbyist",
		            "Logistics Manager",
		            "Maintenance Manager",
		            "Management Consultant",
		            "Managed Care Director",
		            "Managing Partner",
		            "Manufacturing Director",
		            "Manpower Planner",
		            "Marine Biologist",
		            "Market Res. Analyst",
		            "Marketing Director",
		            "Materials Manager",
		            "Mathematician",
		            "Membership Chairman",
		            "Mechanic",
		            "Mechanical Engineer",
		            "Media Buyer",
		            "Medical Investor",
		            "Medical Secretary",
		            "Medical Technician",
		            "Mental Health Counselor",
		            "Merchandiser",
		            "Metallurgical Engineering",
		            "Meteorologist",
		            "Microbiologist",
		            "MIS Manager",
		            "Motion Picture Director",
		            "Multimedia Director",
		            "Musician",
		            "Network Administrator",
		            "Network Specialist",
		            "Network Operator",
		            "New Product Manager",
		            "Novelist",
		            "Nuclear Engineer",
		            "Nuclear Specialist",
		            "Nutritionist",
		            "Nursing Administrator",
		            "Occupational Therapist",
		            "Oceanographer",
		            "Office Manager",
		            "Operations Manager",
		            "Operations Research Director",
		            "Optical Technician",
		            "Optometrist",
		            "Organizational Development Manager",
		            "Outplacement Specialist",
		            "Paralegal",
		            "Park Ranger",
		            "Patent Attorney",
		            "Payroll Specialist",
		            "Personnel Specialist",
		            "Petroleum Engineer",
		            "Pharmacist",
		            "Photographer",
		            "Physical Therapist",
		            "Physician",
		            "Physician Assistant",
		            "Physicist",
		            "Planning Director",
		            "Podiatrist",
		            "Political Analyst",
		            "Political Scientist",
		            "Politician",
		            "Portfolio Manager",
		            "Preschool Management",
		            "Preschool Teacher",
		            "Principal",
		            "Private Banker",
		            "Private Investigator",
		            "Probation Officer",
		            "Process Engineer",
		            "Producer",
		            "Product Manager",
		            "Product Engineer",
		            "Production Engineer",
		            "Production Planner",
		            "Professional Athlete",
		            "Professional Coach",
		            "Professor",
		            "Project Engineer",
		            "Project Manager",
		            "Program Manager",
		            "Property Manager",
		            "Public Administrator",
		            "Public Safety Director",
		            "PR Specialist",
		            "Publisher",
		            "Purchasing Agent",
		            "Publishing Director",
		            "Quality Assurance Specialist",
		            "Quality Control Engineer",
		            "Quality Control Inspector",
		            "Radiology Manager",
		            "Railroad Engineer",
		            "Real Estate Broker",
		            "Recreational Director",
		            "Recruiter",
		            "Redevelopment Specialist",
		            "Regulatory Affairs Manager",
		            "Registered Nurse",
		            "Rehabilitation Counselor",
		            "Relocation Manager",
		            "Reporter",
		            "Research Specialist",
		            "Restaurant Manager",
		            "Retail Store Manager",
		            "Risk Analyst",
		            "Safety Engineer",
		            "Sales Engineer",
		            "Sales Trainer",
		            "Sales Promotion Manager",
		            "Sales Representative",
		            "Sales Manager",
		            "Service Manager",
		            "Sanitation Engineer",
		            "Scientific Programmer",
		            "Scientific Writer",
		            "Securities Analyst",
		            "Security Consultant",
		            "Security Director",
		            "Seminar Presenter",
		            "Ship's Officer",
		            "Singer",
		            "Social Director",
		            "Social Program Planner",
		            "Social Research",
		            "Social Scientist",
		            "Social Worker",
		            "Sociologist",
		            "Software Developer",
		            "Software Engineer",
		            "Software Test Engineer",
		            "Soil Scientist",
		            "Special Events Manager",
		            "Special Education Teacher",
		            "Special Projects Director",
		            "Speech Pathologist",
		            "Speech Writer",
		            "Sports Event Manager",
		            "Statistician",
		            "Store Manager",
		            "Strategic Alliance Director",
		            "Strategic Planning Director",
		            "Stress Reduction Specialist",
		            "Stockbroker",
		            "Surveyor",
		            "Structural Engineer",
		            "Superintendent",
		            "Supply Chain Director",
		            "System Engineer",
		            "Systems Analyst",
		            "Systems Programmer",
		            "System Administrator",
		            "Tax Specialist",
		            "Teacher",
		            "Technical Support Specialist",
		            "Technical Illustrator",
		            "Technical Writer",
		            "Technology Director",
		            "Telecom Analyst",
		            "Telemarketer",
		            "Theatrical Director",
		            "Title Examiner",
		            "Tour Escort",
		            "Tour Guide Director",
		            "Traffic Manager",
		            "Trainer Translator",
		            "Transportation Manager",
		            "Travel Agent",
		            "Treasurer",
		            "TV Programmer",
		            "Underwriter",
		            "Union Representative",
		            "University Administrator",
		            "University Dean",
		            "Urban Planner",
		            "Veterinarian",
		            "Vendor Relations Director",
		            "Viticulturist",
		            "Warehouse Manager"
		        ],
		        animals : {
		          //list of ocean animals comes from https://owlcation.com/stem/list-of-ocean-animals
		          "ocean" : ["Acantharea","Anemone","Angelfish King","Ahi Tuna","Albacore","American Oyster","Anchovy","Armored Snail","Arctic Char","Atlantic Bluefin Tuna","Atlantic Cod","Atlantic Goliath Grouper","Atlantic Trumpetfish","Atlantic Wolffish","Baleen Whale","Banded Butterflyfish","Banded Coral Shrimp","Banded Sea Krait","Barnacle","Barndoor Skate","Barracuda","Basking Shark","Bass","Beluga Whale","Bluebanded Goby","Bluehead Wrasse","Bluefish","Bluestreak Cleaner-Wrasse","Blue Marlin","Blue Shark","Blue Spiny Lobster","Blue Tang","Blue Whale","Broadclub Cuttlefish","Bull Shark","Chambered Nautilus","Chilean Basket Star","Chilean Jack Mackerel","Chinook Salmon","Christmas Tree Worm","Clam","Clown Anemonefish","Clown Triggerfish","Cod","Coelacanth","Cockscomb Cup Coral","Common Fangtooth","Conch","Cookiecutter Shark","Copepod","Coral","Corydoras","Cownose Ray","Crab","Crown-of-Thorns Starfish","Cushion Star","Cuttlefish","California Sea Otters","Dolphin","Dolphinfish","Dory","Devil Fish","Dugong","Dumbo Octopus","Dungeness Crab","Eccentric Sand Dollar","Edible Sea Cucumber","Eel","Elephant Seal","Elkhorn Coral","Emperor Shrimp","Estuarine Crocodile","Fathead Sculpin","Fiddler Crab","Fin Whale","Flameback","Flamingo Tongue Snail","Flashlight Fish","Flatback Turtle","Flatfish","Flying Fish","Flounder","Fluke","French Angelfish","Frilled Shark","Fugu (also called Pufferfish)","Gar","Geoduck","Giant Barrel Sponge","Giant Caribbean Sea Anemone","Giant Clam","Giant Isopod","Giant Kingfish","Giant Oarfish","Giant Pacific Octopus","Giant Pyrosome","Giant Sea Star","Giant Squid","Glowing Sucker Octopus","Giant Tube Worm","Goblin Shark","Goosefish","Great White Shark","Greenland Shark","Grey Atlantic Seal","Grouper","Grunion","Guineafowl Puffer","Haddock","Hake","Halibut","Hammerhead Shark","Hapuka","Harbor Porpoise","Harbor Seal","Hatchetfish","Hawaiian Monk Seal","Hawksbill Turtle","Hector's Dolphin","Hermit Crab","Herring","Hoki","Horn Shark","Horseshoe Crab","Humpback Anglerfish","Humpback Whale","Icefish","Imperator Angelfish","Irukandji Jellyfish","Isopod","Ivory Bush Coral","Japanese Spider Crab","Jellyfish","John Dory","Juan Fernandez Fur Seal","Killer Whale","Kiwa Hirsuta","Krill","Lagoon Triggerfish","Lamprey","Leafy Seadragon","Leopard Seal","Limpet","Ling","Lionfish","Lions Mane Jellyfish","Lobe Coral","Lobster","Loggerhead Turtle","Longnose Sawshark","Longsnout Seahorse","Lophelia Coral","Marrus Orthocanna","Manatee","Manta Ray","Marlin","Megamouth Shark","Mexican Lookdown","Mimic Octopus","Moon Jelly","Mollusk","Monkfish","Moray Eel","Mullet","Mussel","Megaladon","Napoleon Wrasse","Nassau Grouper","Narwhal","Nautilus","Needlefish","Northern Seahorse","North Atlantic Right Whale","Northern Red Snapper","Norway Lobster","Nudibranch","Nurse Shark","Oarfish","Ocean Sunfish","Oceanic Whitetip Shark","Octopus","Olive Sea Snake","Orange Roughy","Ostracod","Otter","Oyster","Pacific Angelshark","Pacific Blackdragon","Pacific Halibut","Pacific Sardine","Pacific Sea Nettle Jellyfish","Pacific White Sided Dolphin","Pantropical Spotted Dolphin","Patagonian Toothfish","Peacock Mantis Shrimp","Pelagic Thresher Shark","Penguin","Peruvian Anchoveta","Pilchard","Pink Salmon","Pinniped","Plankton","Porpoise","Polar Bear","Portuguese Man o' War","Pycnogonid Sea Spider","Quahog","Queen Angelfish","Queen Conch","Queen Parrotfish","Queensland Grouper","Ragfish","Ratfish","Rattail Fish","Ray","Red Drum","Red King Crab","Ringed Seal","Risso's Dolphin","Ross Seals","Sablefish","Salmon","Sand Dollar","Sandbar Shark","Sawfish","Sarcastic Fringehead","Scalloped Hammerhead Shark","Seahorse","Sea Cucumber","Sea Lion","Sea Urchin","Seal","Shark","Shortfin Mako Shark","Shovelnose Guitarfish","Shrimp","Silverside Fish","Skipjack Tuna","Slender Snipe Eel","Smalltooth Sawfish","Smelts","Sockeye Salmon","Southern Stingray","Sponge","Spotted Porcupinefish","Spotted Dolphin","Spotted Eagle Ray","Spotted Moray","Squid","Squidworm","Starfish","Stickleback","Stonefish","Stoplight Loosejaw","Sturgeon","Swordfish","Tan Bristlemouth","Tasseled Wobbegong","Terrible Claw Lobster","Threespot Damselfish","Tiger Prawn","Tiger Shark","Tilefish","Toadfish","Tropical Two-Wing Flyfish","Tuna","Umbrella Squid","Velvet Crab","Venus Flytrap Sea Anemone","Vigtorniella Worm","Viperfish","Vampire Squid","Vaquita","Wahoo","Walrus","West Indian Manatee","Whale","Whale Shark","Whiptail Gulper","White-Beaked Dolphin","White-Ring Garden Eel","White Shrimp","Wobbegong","Wrasse","Wreckfish","Xiphosura","Yellowtail Damselfish","Yelloweye Rockfish","Yellow Cup Black Coral","Yellow Tube Sponge","Yellowfin Tuna","Zebrashark","Zooplankton"],
		          //list of desert, grassland, and forest animals comes from http://www.skyenimals.com/
		          "desert" : ["Aardwolf","Addax","African Wild Ass","Ant","Antelope","Armadillo","Baboon","Badger","Bat","Bearded Dragon","Beetle","Bird","Black-footed Cat","Boa","Brown Bear","Bustard","Butterfly","Camel","Caracal","Caracara","Caterpillar","Centipede","Cheetah","Chipmunk","Chuckwalla","Climbing Mouse","Coati","Cobra","Cotton Rat","Cougar","Courser","Crane Fly","Crow","Dassie Rat","Dove","Dunnart","Eagle","Echidna","Elephant","Emu","Falcon","Fly","Fox","Frogmouth","Gecko","Geoffroy's Cat","Gerbil","Grasshopper","Guanaco","Gundi","Hamster","Hawk","Hedgehog","Hyena","Hyrax","Jackal","Kangaroo","Kangaroo Rat","Kestrel","Kowari","Kultarr","Leopard","Lion","Macaw","Meerkat","Mouse","Oryx","Ostrich","Owl","Pronghorn","Python","Rabbit","Raccoon","Rattlesnake","Rhinoceros","Sand Cat","Spectacled Bear","Spiny Mouse","Starling","Stick Bug","Tarantula","Tit","Toad","Tortoise","Tyrant Flycatcher","Viper","Vulture","Waxwing","Xerus","Zebra"],
		          "grassland" : ["Aardvark","Aardwolf","Accentor","African Buffalo","African Wild Dog","Alpaca","Anaconda","Ant","Anteater","Antelope","Armadillo","Baboon","Badger","Bandicoot","Barbet","Bat","Bee","Bee-eater","Beetle","Bird","Bison","Black-footed Cat","Black-footed Ferret","Bluebird","Boa","Bowerbird","Brown Bear","Bush Dog","Bushshrike","Bustard","Butterfly","Buzzard","Caracal","Caracara","Cardinal","Caterpillar","Cheetah","Chipmunk","Civet","Climbing Mouse","Clouded Leopard","Coati","Cobra","Cockatoo","Cockroach","Common Genet","Cotton Rat","Cougar","Courser","Coyote","Crane","Crane Fly","Cricket","Crow","Culpeo","Death Adder","Deer","Deer Mouse","Dingo","Dinosaur","Dove","Drongo","Duck","Duiker","Dunnart","Eagle","Echidna","Elephant","Elk","Emu","Falcon","Finch","Flea","Fly","Flying Frog","Fox","Frog","Frogmouth","Garter Snake","Gazelle","Gecko","Geoffroy's Cat","Gerbil","Giant Tortoise","Giraffe","Grasshopper","Grison","Groundhog","Grouse","Guanaco","Guinea Pig","Hamster","Harrier","Hartebeest","Hawk","Hedgehog","Helmetshrike","Hippopotamus","Hornbill","Hyena","Hyrax","Impala","Jackal","Jaguar","Jaguarundi","Kangaroo","Kangaroo Rat","Kestrel","Kultarr","Ladybug","Leopard","Lion","Macaw","Meerkat","Mouse","Newt","Oryx","Ostrich","Owl","Pangolin","Pheasant","Prairie Dog","Pronghorn","Przewalski's Horse","Python","Quoll","Rabbit","Raven","Rhinoceros","Shelduck","Sloth Bear","Spectacled Bear","Squirrel","Starling","Stick Bug","Tamandua","Tasmanian Devil","Thornbill","Thrush","Toad","Tortoise"],
		          "forest" : ["Agouti","Anaconda","Anoa","Ant","Anteater","Antelope","Armadillo","Asian Black Bear","Aye-aye","Babirusa","Baboon","Badger","Bandicoot","Banteng","Barbet","Basilisk","Bat","Bearded Dragon","Bee","Bee-eater","Beetle","Bettong","Binturong","Bird-of-paradise","Bongo","Bowerbird","Bulbul","Bush Dog","Bushbaby","Bushshrike","Butterfly","Buzzard","Caecilian","Cardinal","Cassowary","Caterpillar","Centipede","Chameleon","Chimpanzee","Cicada","Civet","Clouded Leopard","Coati","Cobra","Cockatoo","Cockroach","Colugo","Cotinga","Cotton Rat","Cougar","Crane Fly","Cricket","Crocodile","Crow","Cuckoo","Cuscus","Death Adder","Deer","Dhole","Dingo","Dinosaur","Drongo","Duck","Duiker","Eagle","Echidna","Elephant","Finch","Flat-headed Cat","Flea","Flowerpecker","Fly","Flying Frog","Fossa","Frog","Frogmouth","Gaur","Gecko","Gorilla","Grison","Hawaiian Honeycreeper","Hawk","Hedgehog","Helmetshrike","Hornbill","Hyrax","Iguana","Jackal","Jaguar","Jaguarundi","Kestrel","Ladybug","Lemur","Leopard","Lion","Macaw","Mandrill","Margay","Monkey","Mouse","Mouse Deer","Newt","Okapi","Old World Flycatcher","Orangutan","Owl","Pangolin","Peafowl","Pheasant","Possum","Python","Quokka","Rabbit","Raccoon","Red Panda","Red River Hog","Rhinoceros","Sloth Bear","Spectacled Bear","Squirrel","Starling","Stick Bug","Sun Bear","Tamandua","Tamarin","Tapir","Tarantula","Thrush","Tiger","Tit","Toad","Tortoise","Toucan","Trogon","Trumpeter","Turaco","Turtle","Tyrant Flycatcher","Viper","Vulture","Wallaby","Warbler","Wasp","Waxwing","Weaver","Weaver-finch","Whistler","White-eye","Whydah","Woodswallow","Worm","Wren","Xenops","Yellowjacket","Accentor","African Buffalo","American Black Bear","Anole","Bird","Bison","Boa","Brown Bear","Chipmunk","Common Genet","Copperhead","Coyote","Deer Mouse","Dormouse","Elk","Emu","Fisher","Fox","Garter Snake","Giant Panda","Giant Tortoise","Groundhog","Grouse","Guanaco","Himalayan Tahr","Kangaroo","Koala","Numbat","Quoll","Raccoon dog","Tasmanian Devil","Thornbill","Turkey","Vole","Weasel","Wildcat","Wolf","Wombat","Woodchuck","Woodpecker"],
		          //list of farm animals comes from https://www.buzzle.com/articles/farm-animals-list.html
		          "farm" : ["Alpaca","Buffalo","Banteng","Cow","Cat","Chicken","Carp","Camel","Donkey","Dog","Duck","Emu","Goat","Gayal","Guinea","Goose","Horse","Honey","Llama","Pig","Pigeon","Rhea","Rabbit","Sheep","Silkworm","Turkey","Yak","Zebu"],
		          //list of pet animals comes from https://www.dogbreedinfo.com/pets/pet.htm
		          "pet" : ["Bearded Dragon","Birds","Burro","Cats","Chameleons","Chickens","Chinchillas","Chinese Water Dragon","Cows","Dogs","Donkey","Ducks","Ferrets","Fish","Geckos","Geese","Gerbils","Goats","Guinea Fowl","Guinea Pigs","Hamsters","Hedgehogs","Horses","Iguanas","Llamas","Lizards","Mice","Mule","Peafowl","Pigs and Hogs","Pigeons","Ponies","Pot Bellied Pig","Rabbits","Rats","Sheep","Skinks","Snakes","Stick Insects","Sugar Gliders","Tarantula","Turkeys","Turtles"],
		          //list of zoo animals comes from https://bronxzoo.com/animals
		          "zoo" : ["Aardvark","African Wild Dog","Aldabra Tortoise","American Alligator","American Bison","Amur Tiger","Anaconda","Andean Condor","Asian Elephant","Baby Doll Sheep","Bald Eagle","Barred Owl","Blue Iguana","Boer Goat","California Sea Lion","Caribbean Flamingo","Chinchilla","Collared Lemur","Coquerel's Sifaka","Cuban Amazon Parrot","Ebony Langur","Fennec Fox","Fossa","Gelada","Giant Anteater","Giraffe","Gorilla","Grizzly Bear","Henkel's Leaf-tailed Gecko","Indian Gharial","Indian Rhinoceros","King Cobra","King Vulture","Komodo Dragon","Linne's Two-toed Sloth","Lion","Little Penguin","Madagascar Tree Boa","Magellanic Penguin","Malayan Tapir","Malayan Tiger","Matschies Tree Kangaroo","Mini Donkey","Monarch Butterfly","Nile crocodile","North American Porcupine","Nubian Ibex","Okapi","Poison Dart Frog","Polar Bear","Pygmy Marmoset","Radiated Tortoise","Red Panda","Red Ruffed Lemur","Ring-tailed Lemur","Ring-tailed Mongoose","Rock Hyrax","Small Clawed Asian Otter","Snow Leopard","Snowy Owl","Southern White-faced Owl","Southern White Rhinocerous","Squirrel Monkey","Tufted Puffin","White Cheeked Gibbon","White-throated Bee Eater","Zebra"]
		        },
		        primes: [
		            // 1230 first primes, i.e. all primes up to the first one greater than 10000, inclusive.
		            2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999,3001,3011,3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,3167,3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,3299,3301,3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,3371,3373,3389,3391,3407,3413,3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529,3533,3539,3541,3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,3643,3659,3671,3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,3761,3767,3769,3779,3793,3797,3803,3821,3823,3833,3847,3851,3853,3863,3877,3881,3889,3907,3911,3917,3919,3923,3929,3931,3943,3947,3967,3989,4001,4003,4007,4013,4019,4021,4027,4049,4051,4057,4073,4079,4091,4093,4099,4111,4127,4129,4133,4139,4153,4157,4159,4177,4201,4211,4217,4219,4229,4231,4241,4243,4253,4259,4261,4271,4273,4283,4289,4297,4327,4337,4339,4349,4357,4363,4373,4391,4397,4409,4421,4423,4441,4447,4451,4457,4463,4481,4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,4621,4637,4639,4643,4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,4733,4751,4759,4783,4787,4789,4793,4799,4801,4813,4817,4831,4861,4871,4877,4889,4903,4909,4919,4931,4933,4937,4943,4951,4957,4967,4969,4973,4987,4993,4999,5003,5009,5011,5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,5167,5171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,5303,5309,5323,5333,5347,5351,5381,5387,5393,5399,5407,5413,5417,5419,5431,5437,5441,5443,5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,5531,5557,5563,5569,5573,5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,5683,5689,5693,5701,5711,5717,5737,5741,5743,5749,5779,5783,5791,5801,5807,5813,5821,5827,5839,5843,5849,5851,5857,5861,5867,5869,5879,5881,5897,5903,5923,5927,5939,5953,5981,5987,6007,6011,6029,6037,6043,6047,6053,6067,6073,6079,6089,6091,6101,6113,6121,6131,6133,6143,6151,6163,6173,6197,6199,6203,6211,6217,6221,6229,6247,6257,6263,6269,6271,6277,6287,6299,6301,6311,6317,6323,6329,6337,6343,6353,6359,6361,6367,6373,6379,6389,6397,6421,6427,6449,6451,6469,6473,6481,6491,6521,6529,6547,6551,6553,6563,6569,6571,6577,6581,6599,6607,6619,6637,6653,6659,6661,6673,6679,6689,6691,6701,6703,6709,6719,6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833,6841,6857,6863,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971,6977,6983,6991,6997,7001,7013,7019,7027,7039,7043,7057,7069,7079,7103,7109,7121,7127,7129,7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243,7247,7253,7283,7297,7307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,7451,7457,7459,7477,7481,7487,7489,7499,7507,7517,7523,7529,7537,7541,7547,7549,7559,7561,7573,7577,7583,7589,7591,7603,7607,7621,7639,7643,7649,7669,7673,7681,7687,7691,7699,7703,7717,7723,7727,7741,7753,7757,7759,7789,7793,7817,7823,7829,7841,7853,7867,7873,7877,7879,7883,7901,7907,7919,7927,7933,7937,7949,7951,7963,7993,8009,8011,8017,8039,8053,8059,8069,8081,8087,8089,8093,8101,8111,8117,8123,8147,8161,8167,8171,8179,8191,8209,8219,8221,8231,8233,8237,8243,8263,8269,8273,8287,8291,8293,8297,8311,8317,8329,8353,8363,8369,8377,8387,8389,8419,8423,8429,8431,8443,8447,8461,8467,8501,8513,8521,8527,8537,8539,8543,8563,8573,8581,8597,8599,8609,8623,8627,8629,8641,8647,8663,8669,8677,8681,8689,8693,8699,8707,8713,8719,8731,8737,8741,8747,8753,8761,8779,8783,8803,8807,8819,8821,8831,8837,8839,8849,8861,8863,8867,8887,8893,8923,8929,8933,8941,8951,8963,8969,8971,8999,9001,9007,9011,9013,9029,9041,9043,9049,9059,9067,9091,9103,9109,9127,9133,9137,9151,9157,9161,9173,9181,9187,9199,9203,9209,9221,9227,9239,9241,9257,9277,9281,9283,9293,9311,9319,9323,9337,9341,9343,9349,9371,9377,9391,9397,9403,9413,9419,9421,9431,9433,9437,9439,9461,9463,9467,9473,9479,9491,9497,9511,9521,9533,9539,9547,9551,9587,9601,9613,9619,9623,9629,9631,9643,9649,9661,9677,9679,9689,9697,9719,9721,9733,9739,9743,9749,9767,9769,9781,9787,9791,9803,9811,9817,9829,9833,9839,9851,9857,9859,9871,9883,9887,9901,9907,9923,9929,9931,9941,9949,9967,9973,10007
		        ],
		        emotions: [
		            "love",
		            "joy",
		            "surprise",
		            "anger",
		            "sadness",
		            "fear"
		        ],
		        music_genres: {
		            'general': [
		                'Rock', 
		                'Pop', 
		                'Hip-Hop', 
		                'Jazz', 
		                'Classical', 
		                'Electronic', 
		                'Country', 
		                'R&B', 
		                'Reggae', 
		                'Blues', 
		                'Metal', 
		                'Folk', 
		                'Alternative', 
		                'Punk',
		                'Disco', 
		                'Funk', 
		                'Techno',
		                'Indie',
		                'Gospel', 
		                'Dance', 
		                'Children\'s', 
		                'World'
		            ],
		            'alternative': [
		                'Art Punk',
		                'Alternative Rock',
		                'Britpunk',
		                'College Rock',
		                'Crossover Thrash',
		                'Crust Punk',
		                'Emo / Emocore',
		                'Experimental Rock',
		                'Folk Punk',
		                'Goth / Gothic Rock',
		                'Grunge',
		                'Hardcore Punk',
		                'Hard Rock',
		                'Indie Rock',
		                'Lo-fi',
		                'Musique Concrète',
		                'New Wave',
		                'Progressive Rock',
		                'Punk',
		                'Shoegaze',
		                'Steampunk',
		            ], 'blues': [
		                'Acoustic Blues',
		                'African Blues',
		                'Blues Rock',
		                'Blues Shouter',
		                'British Blues',
		                'Canadian Blues',
		                'Chicago Blues',
		                'Classic Blues',
		                'Classic Female Blues',
		                'Contemporary Blues',
		                'Country Blues',
		                'Dark Blues',
		                'Delta Blues',
		                'Detroit Blues',
		                'Doom Blues',
		                'Electric Blues',
		                'Folk Blues',
		                'Gospel Blues',
		                'Harmonica Blues',
		                'Hill Country Blues',
		                'Hokum Blues',
		                'Jazz Blues',
		                'Jump Blues',
		                'Kansas City Blues',
		                'Louisiana Blues',
		                'Memphis Blues',
		                'Modern Blues',
		                'New Orlean Blues',
		                'NY Blues',
		                'Piano Blues',
		                'Piedmont Blues',
		                'Punk Blues',
		                'Ragtime Blues',
		                'Rhythm Blues',
		                'Soul Blues',
		                'St.Louis Blues',
		                'Soul Blues',
		                'Swamp Blues',
		                'Texas Blues',
		                'Urban Blues',
		                'Vandeville',
		                'West Coast Blues',
		            ], 'children\'s': [
		                'Lullabies',
		                'Sing - Along',
		                'Stories'
		            ], 'classical': [
		                'Avant-Garde',
		                'Ballet',
		                'Baroque',
		                'Cantata',
		                'Chamber Music',
		                'String Quartet',
		                'Chant',
		                'Choral',
		                'Classical Crossover',
		                'Concerto',
		                'Concerto Grosso',
		                'Contemporary Classical',
		                'Early Music',
		                'Expressionist',
		                'High Classical',
		                'Impressionist',
		                'Mass Requiem',
		                'Medieval',
		                'Minimalism',
		                'Modern Composition',
		                'Modern Classical',
		                'Opera',
		                'Oratorio',
		                'Orchestral',
		                'Organum',
		                'Renaissance',
		                'Romantic (early period)',
		                'Romantic (later period)',
		                'Sonata',
		                'Symphonic',
		                'Symphony',
		                'Twelve-tone',
		                'Wedding Music'
		            ], 'country': [
		                'Alternative Country',
		                'Americana',
		                'Australian Country',
		                'Bakersfield Sound',
		                'Bluegrass',
		                'Blues Country',
		                'Cajun Fiddle Tunes',
		                'Christian Country',
		                'Classic Country',
		                'Close Harmony',
		                'Contemporary Bluegrass',
		                'Contemporary Country',
		                'Country Gospel',
		                'Country Pop',
		                'Country Rap',
		                'Country Rock',
		                'Country Soul',
		                'Cowboy / Western',
		                'Cowpunk',
		                'Dansband',
		                'Honky Tonk',
		                'Franco-Country',
		                'Gulf and Western',
		                'Hellbilly Music',
		                'Honky Tonk',
		                'Instrumental Country',
		                'Lubbock Sound',
		                'Nashville Sound',
		                'Neotraditional Country',
		                'Outlaw Country',
		                'Progressive',
		                'Psychobilly / Punkabilly',
		                'Red Dirt',
		                'Sertanejo',
		                'Texas County',
		                'Traditional Bluegrass',
		                'Traditional Country',
		                'Truck-Driving Country',
		                'Urban Cowboy',
		                'Western Swing'
		            ], 'dance': [
		                'Club / Club Dance',
		                'Breakcore',
		                'Breakbeat / Breakstep',
		                'Chillstep',
		                'Deep House',
		                'Dubstep',
		                'Dancehall',
		                'Electro House',
		                'Electroswing',
		                'Exercise',
		                'Future Garage',
		                'Garage',
		                'Glitch Hop',
		                'Glitch Pop',
		                'Grime',
		                'Hardcore',
		                'Hard Dance',
		                'Hi-NRG / Eurodance',
		                'Horrorcore',
		                'House',
		                'Jackin House',
		                'Jungle / Drum n bass',
		                'Liquid Dub',
		                'Regstep',
		                'Speedcore',
		                'Techno',
		                'Trance',
		                'Trap'
		            ], electronic: [
		                '2-Step',
		                '8bit',
		                'Ambient',
		                'Asian Underground',
		                'Bassline',
		                'Chillwave',
		                'Chiptune',
		                'Crunk',
		                'Downtempo',
		                'Drum & Bass',
		                'Hard Step',
		                'Electro',
		                'Electro-swing',
		                'Electroacoustic',
		                'Electronica',
		                'Electronic Rock',
		                'Eurodance',
		                'Hardstyle',
		                'Hi-Nrg',
		                'IDM/Experimental',
		                'Industrial',
		                'Trip Hop',
		                'Vaporwave',
		                'UK Garage',
		                'House',
		                'Dubstep',
		                'Deep House',
		                'EDM',
		                'Future Bass',
		                'Psychedelic trance'
		            ], 'jazz' : [
		                'Acid Jazz',
		                'Afro-Cuban Jazz',
		                'Avant-Garde Jazz',
		                'Bebop',
		                'Big Band',
		                'Blue Note',
		                'British Dance Band (Jazz)',
		                'Cape Jazz',
		                'Chamber Jazz',
		                'Contemporary Jazz',
		                'Continental Jazz',
		                'Cool Jazz',
		                'Crossover Jazz',
		                'Dark Jazz',
		                'Dixieland',
		                'Early Jazz',
		                'Electro Swing (Jazz)',
		                'Ethio-jazz',
		                'Ethno-Jazz',
		                'European Free Jazz',
		                'Free Funk (Avant-Garde / Funk Jazz)',
		                'Free Jazz',
		                'Fusion',
		                'Gypsy Jazz',
		                'Hard Bop',
		                'Indo Jazz',
		                'Jazz Blues',
		                'Jazz-Funk (see Free Funk)',
		                'Jazz-Fusion',
		                'Jazz Rap',
		                'Jazz Rock',
		                'Kansas City Jazz',
		                'Latin Jazz',
		                'M-Base Jazz',
		                'Mainstream Jazz',
		                'Modal Jazz',
		                'Neo-Bop',
		                'Neo-Swing',
		                'Nu Jazz',
		                'Orchestral Jazz',
		                'Post-Bop',
		                'Punk Jazz',
		                'Ragtime',
		                'Ska Jazz',
		                'Skiffle (also Folk)',
		                'Smooth Jazz',
		                'Soul Jazz',
		                'Swing Jazz',
		                'Straight-Ahead Jazz',
		                'Trad Jazz',
		                'Third Stream',
		                'Jazz-Funk',
		                'Free Jazz',
		                'West Coast Jazz'
		            ], 'metal': [
		                'Heavy Metal',
		                'Speed Metal',
		                'Thrash Metal',
		                'Power Metal',
		                'Death Metal',
		                'Black Metal',
		                'Pagan Metal',
		                'Viking Metal',
		                'Folk Metal',
		                'Symphonic Metal',
		                'Gothic Metal',
		                'Glam Metal',
		                'Hair Metal',
		                'Doom Metal',
		                'Groove Metal',
		                'Industrial Metal',
		                'Modern Metal',
		                'Neoclassical Metal',
		                'New Wave Of British Heavy Metal',
		                'Post Metal',
		                'Progressive Metal',
		                'Avantgarde Metal',
		                'Sludge',
		                'Djent',
		                'Drone',
		                'Kawaii Metal',
		                'Pirate Metal',
		                'Nu Metal',
		                'Neue Deutsche Härte',
		                'Math Metal',
		                'Crossover',
		                'Grindcore',
		                'Hardcore',
		                'Metalcore',
		                'Deathcore',
		                'Post Hardcore',
		                'Mathcore'
		            ], 'folk': [
		                'American Folk Revival',
		                'Anti - Folk',
		                'British Folk Revival',
		                'Contemporary Folk',
		                'Filk Music',
		                'Freak Folk',
		                'Indie Folk',
		                'Industrial Folk',
		                'Neofolk',
		                'Progressive Folk',
		                'Psychedelic Folk',
		                'Sung Poetry',
		                'Techno - Folk',
		                'Folk Rock',
		                'Old-time Music',
		                'Bluegrass',
		                'Appalachian',
		                'Roots Revival',
		                'Celtic',
		                'Indie Folk'
		            ], 'pop': [
		                'Adult Contemporary',
		                'Arab Pop',
		                'Baroque',
		                'Britpop',
		                'Bubblegum Pop',
		                'Chamber Pop',
		                'Chanson',
		                'Christian Pop',
		                'Classical Crossover',
		                'Europop',
		                'Austropop',
		                'Balkan Pop',
		                'French Pop',
		                'Korean Pop',
		                'Japanese Pop',
		                'Chinese Pop',
		                'Latin Pop',
		                'Laïkó',
		                'Nederpop',
		                'Russian Pop',
		                'Dance Pop',
		                'Dream Pop',
		                'Electro Pop',
		                'Iranian Pop',
		                'Jangle Pop',
		                'Latin Ballad',
		                'Levenslied',
		                'Louisiana Swamp Pop',
		                'Mexican Pop',
		                'Motorpop',
		                'New Romanticism',
		                'Orchestral Pop',
		                'Pop Rap',
		                'Popera',
		                'Pop / Rock',
		                'Pop Punk',
		                'Power Pop',
		                'Psychedelic Pop',
		                'Russian Pop',
		                'Schlager',
		                'Soft Rock',
		                'Sophisti - Pop',
		                'Space Age Pop',
		                'Sunshine Pop',
		                'Surf Pop',
		                'Synthpop',
		                'Teen Pop',
		                'Traditional Pop Music',
		                'Turkish Pop',
		                'Vispop',
		                'Wonky Pop'
		            ], 'r&b': [
		                '(Carolina) Beach Music',
		                'Contemporary R & B',
		                'Disco',
		                'Doo Wop',
		                'Funk',
		                'Modern Soul',
		                'Motown',
		                'Neo - Soul',
		                'Northern Soul',
		                'Psychedelic Soul',
		                'Quiet Storm',
		                'Soul',
		                'Soul Blues',
		                'Southern Soul'
		            ], 'reggae': [
		                '2 - Tone',
		                'Dub',
		                'Roots Reggae',
		                'Reggae Fusion',
		                'Reggae en Español',
		                'Spanish Reggae',
		                'Reggae 110',
		                'Reggae Bultrón',
		                'Romantic Flow',
		                'Lovers Rock',
		                'Raggamuffin',
		                'Ragga',
		                'Dancehall',
		                'Ska',
		            ], 'rock': [
		                'Acid Rock',
		                'Adult - Oriented Rock',
		                'Afro Punk',
		                'Adult Alternative',
		                'Alternative Rock',
		                'American Traditional Rock',
		                'Anatolian Rock',
		                'Arena Rock',
		                'Art Rock',
		                'Blues - Rock',
		                'British Invasion',
		                'Cock Rock',
		                'Death Metal / Black Metal',
		                'Doom Metal',
		                'Glam Rock',
		                'Gothic Metal',
		                'Grind Core',
		                'Hair Metal',
		                'Hard Rock',
		                'Math Metal',
		                'Math Rock',
		                'Metal',
		                'Metal Core',
		                'Noise Rock',
		                'Jam Bands',
		                'Post Punk',
		                'Post Rock',
		                'Prog - Rock / Art Rock',
		                'Progressive Metal',
		                'Psychedelic',
		                'Rock & Roll',
		                'Rockabilly',
		                'Roots Rock',
		                'Singer / Songwriter',
		                'Southern Rock',
		                'Spazzcore',
		                'Stoner Metal',
		                'Surf',
		                'Technical Death Metal',
		                'Tex - Mex',
		                'Thrash Metal',
		                'Time Lord Rock(Trock)',
		                'Trip - hop',
		                'Yacht Rock',
		                'School House Rock'
		            ], 'hip-hop': [
		                'Alternative Rap',
		                'Avant - Garde',
		                'Bounce',
		                'Chap Hop',
		                'Christian Hip Hop',
		                'Conscious Hip Hop',
		                'Country - Rap',
		                'Grunk',
		                'Crunkcore',
		                'Cumbia Rap',
		                'Dirty South',
		                'East Coast',
		                'Brick City Club',
		                'Hardcore Hip Hop',
		                'Mafioso Rap',
		                'New Jersey Hip Hop',
		                'Freestyle Rap',
		                'G - Funk',
		                'Gangsta Rap',
		                'Golden Age',
		                'Grime',
		                'Hardcore Rap',
		                'Hip - Hop',
		                'Hip Pop',
		                'Horrorcore',
		                'Hyphy',
		                'Industrial Hip Hop',
		                'Instrumental Hip Hop',
		                'Jazz Rap',
		                'Latin Rap',
		                'Low Bap',
		                'Lyrical Hip Hop',
		                'Merenrap',
		                'Midwest Hip Hop',
		                'Chicago Hip Hop',
		                'Detroit Hip Hop',
		                'Horrorcore',
		                'St.Louis Hip Hop',
		                'Twin Cities Hip Hop',
		                'Motswako',
		                'Nerdcore',
		                'New Jack Swing',
		                'New School Hip Hop',
		                'Old School Rap',
		                'Rap',
		                'Trap',
		                'Turntablism',
		                'Underground Rap',
		                'West Coast Rap',
		                'East Coast Rap',
		                'Trap',
		                'UK Grime',
		                'Hyphy',
		                'Emo-rap',
		                'Cloud rap',
		                'G-funk',
		                'Boom Bap',
		                'Mumble',
		                'Drill',
		                'UK Drill',
		                'Soundcloud Rap',
		                'Lo-fi'
		            ], 'punk': [
		                'Afro-punk',
		                'Anarcho punk',
		                'Art punk',
		                'Christian punk',
		                'Crust punk',
		                'Deathrock',
		                'Egg punk',
		                'Garage punk',
		                'Glam punk',
		                'Hardcore punk',
		                'Horror punk',
		                'Incelcore/e-punk',
		                'Oi!',
		                'Peace punk',
		                'Punk pathetique',
		                'Queercore',
		                'Riot Grrrl',
		                'Skate punk',
		                'Street punk',
		                'Taqwacore',
		                'Trallpunk'
		            ], 'disco': [
		                'Nu-disco',
		                'Disco-funk',
		                'Hi-NRG',
		                'Italo Disco',
		                'Eurodisco',
		                'Boogie',
		                'Space Disco',
		                'Post-disco',
		                'Electro Disco',
		                'Disco House',
		                'Disco Pop',
		                'Soulful House'
		            ], 'funk': [
		                'Funk Rock',
		                'P-Funk (Parliament-Funkadelic)',
		                'Psychedelic Funk',
		                'Funk Metal',
		                'Electro-Funk',
		                'Go-go',
		                'Boogie-Funk',
		                'Jazz-Funk',
		                'Soul-Funk',
		                'Funky Disco',
		                'Nu-Funk',
		                'Afrobeat',
		                'Latin Funk',
		                'G-Funk',
		                'Acid Jazz',
		                'Funktronica',
		                'Folk-Funk',
		                'Space Funk',
		                'Ambient Funk',
		                'Hard Funk',
		                'Fusion Funk'
		            ], 'techno': [
		                'Acid Techno',
		                'Ambient Techno',
		                'Detroit Techno',
		                'Dub Techno',
		                'Minimal Techno',
		                'Industrial Techno',
		                'Hard Techno',
		                'Trance',
		                'Progressive Techno',
		                'Tech House',
		                'Electronica',
		                'Breakbeat Techno',
		                'Electro Techno',
		                'Melodic Techno',
		                'Experimental Techno',
		                'Dark Techno',
		                'Ebm',
		                'Hypnotic Techno',
		                'Psychedelic Techno',
		                'Rave Techno',
		                'Techno-Pop'
		            ], 'indie': [
		                'Indie Rock',
		                'Indie Pop',
		                'Indie Folk',
		                'Indie Electronic',
		                'Indie Punk',
		                'Indie Hip-Hop',
		                'Dream Pop',
		                'Shoegaze',
		                'Lo-fi',
		                'Chillwave',
		                'Freak Folk',
		                'Noise Pop',
		                'Math Rock',
		                'Post-Punk',
		                'Garage Rock',
		                'Experimental Indie',
		                'Surf Rock',
		                'Alternative Country',
		                'Indie Soul',
		                'Art Rock',
		                'Indie R&B',
		                'Indietronica',
		                'Emo',
		                'Post-Rock',
		                'Indie Pop-Rock',
		                'Indie Synthpop',
		                'Noise Rock',
		                'Psych Folk',
		                'Indie Blues'
		            ], 'gospel': [
		                'Traditional Gospel',
		                'Contemporary Gospel',
		                'Southern Gospel',
		                'Black Gospel',
		                'Urban Contemporary Gospel',
		                'Gospel Blues',
		                'Bluegrass Gospel',
		                'Country Gospel',
		                'Praise and Worship',
		                'Christian Hip-Hop',
		                'Gospel Jazz',
		                'Reggae Gospel',
		                'African Gospel',
		                'Latin Gospel',
		                'R&B Gospel',
		                'Gospel Choir',
		                'Acappella Gospel',
		                'Instrumental Gospel',
		                'Gospel Rap'
		            ], 'world': [
		                'African',
		                'Arabic',
		                'Asian',
		                'Caribbean',
		                'Celtic',
		                'European',
		                'Latin American',
		                'Middle Eastern',
		                'Native American',
		                'Polynesian',
		                'Reggae',
		                'Ska',
		                'Salsa',
		                'Flamenco',
		                'Bossa Nova',
		                'Tango',
		                'Fado',
		                'Klezmer',
		                'Balkan',
		                'Afrobeat',
		                'Mongolian Throat Singing',
		                'Indian Classical',
		                'Gamelan',
		                'Sufi Music',
		                'Zydeco',
		                'Kora Music',
		                'Andean Music',
		                'Irish Traditional',
		                'Gypsy Jazz',
		                'Bollywood',
		                'Bhangra',
		                'Jawaiian',
		                'Hawaiian Slack Key Guitar',
		                'Calypso',
		                'Cuban Son',
		                'Taiko Drumming',
		                'African Highlife',
		                'Merengue',
		                'Tuvan Throat Singing'
		            ]
		        },

		        // Data sourced from https://unicode.org/emoji/charts/full-emoji-list.html
		        emojis: {
		            "smileys_and_emotion": [
		                "0x1f600",
		                "0x1f603",
		                "0x1f604",
		                "0x1f601",
		                "0x1f606",
		                "0x1f605",
		                "0x1f923",
		                "0x1f602",
		                "0x1f642",
		                "0x1f643",
		                "0x1fae0",
		                "0x1f609",
		                "0x1f60a",
		                "0x1f607",
		                "0x1f970",
		                "0x1f60d",
		                "0x1f929",
		                "0x1f618",
		                "0x1f617",
		                "0x263a",
		                "0x1f61a",
		                "0x1f619",
		                "0x1f972",
		                "0x1f60b",
		                "0x1f61b",
		                "0x1f61c",
		                "0x1f92a",
		                "0x1f61d",
		                "0x1f911",
		                "0x1f917",
		                "0x1f92d",
		                "0x1fae2",
		                "0x1fae3",
		                "0x1f92b",
		                "0x1f914",
		                "0x1fae1",
		                "0x1f910",
		                "0x1f928",
		                "0x1f610",
		                "0x1f611",
		                "0x1f636",
		                "0x1fae5",
		                "0x1f636",
		                "0x200d",
		                "0x1f32b",
		                "0xfe0f",
		                "0x1f60f",
		                "0x1f612",
		                "0x1f644",
		                "0x1f62c",
		                "0x1f62e",
		                "0x200d",
		                "0x1f4a8",
		                "0x1f925",
		                "0x1fae8",
		                "0x1f642",
		                "0x200d",
		                "0x2194",
		                "0xfe0f",
		                "0x1f642",
		                "0x200d",
		                "0x2195",
		                "0xfe0f",
		                "0x1f60c",
		                "0x1f614",
		                "0x1f62a",
		                "0x1f924",
		                "0x1f634",
		                "0x1f637",
		                "0x1f912",
		                "0x1f915",
		                "0x1f922",
		                "0x1f92e",
		                "0x1f927",
		                "0x1f975",
		                "0x1f976",
		                "0x1f974",
		                "0x1f635",
		                "0x1f635",
		                "0x200d",
		                "0x1f4ab",
		                "0x1f92f",
		                "0x1f920",
		                "0x1f973",
		                "0x1f978",
		                "0x1f60e",
		                "0x1f913",
		                "0x1f9d0",
		                "0x1f615",
		                "0x1fae4",
		                "0x1f61f",
		                "0x1f641",
		                "0x2639",
		                "0x1f62e",
		                "0x1f62f",
		                "0x1f632",
		                "0x1f633",
		                "0x1f97a",
		                "0x1f979",
		                "0x1f626",
		                "0x1f627",
		                "0x1f628",
		                "0x1f630",
		                "0x1f625",
		                "0x1f622",
		                "0x1f62d",
		                "0x1f631",
		                "0x1f616",
		                "0x1f623",
		                "0x1f61e",
		                "0x1f613",
		                "0x1f629",
		                "0x1f62b",
		                "0x1f971",
		                "0x1f624",
		                "0x1f621",
		                "0x1f620",
		                "0x1f92c",
		                "0x1f608",
		                "0x1f47f",
		                "0x1f480",
		                "0x2620",
		                "0x1f4a9",
		                "0x1f921",
		                "0x1f479",
		                "0x1f47a",
		                "0x1f47b",
		                "0x1f47d",
		                "0x1f47e",
		                "0x1f916",
		                "0x1f63a",
		                "0x1f638",
		                "0x1f639",
		                "0x1f63b",
		                "0x1f63c",
		                "0x1f63d",
		                "0x1f640",
		                "0x1f63f",
		                "0x1f63e",
		                "0x1f648",
		                "0x1f649",
		                "0x1f64a",
		                "0x1f48c",
		                "0x1f498",
		                "0x1f49d",
		                "0x1f496",
		                "0x1f497",
		                "0x1f493",
		                "0x1f49e",
		                "0x1f495",
		                "0x1f49f",
		                "0x2763",
		                "0x1f494",
		                "0x2764",
		                "0xfe0f",
		                "0x200d",
		                "0x1f525",
		                "0x2764",
		                "0xfe0f",
		                "0x200d",
		                "0x1fa79",
		                "0x2764",
		                "0x1fa77",
		                "0x1f9e1",
		                "0x1f49b",
		                "0x1f49a",
		                "0x1f499",
		                "0x1fa75",
		                "0x1f49c",
		                "0x1f90e",
		                "0x1f5a4",
		                "0x1fa76",
		                "0x1f90d",
		                "0x1f48b",
		                "0x1f4af",
		                "0x1f4a2",
		                "0x1f4a5",
		                "0x1f4ab",
		                "0x1f4a6",
		                "0x1f4a8",
		                "0x1f573",
		                "0x1f4ac",
		                "0x1f441",
		                "0xfe0f",
		                "0x200d",
		                "0x1f5e8",
		                "0xfe0f",
		                "0x1f5e8",
		                "0x1f5ef",
		                "0x1f4ad",
		                "0x1f4a4"
		            ],
		            "people_and_body": [
		                "0x1f44b",
		                "0x1f91a",
		                "0x1f590",
		                "0x270b",
		                "0x1f596",
		                "0x1faf1",
		                "0x1faf2",
		                "0x1faf3",
		                "0x1faf4",
		                "0x1faf7",
		                "0x1faf8",
		                "0x1f44c",
		                "0x1f90c",
		                "0x1f90f",
		                "0x270c",
		                "0x1f91e",
		                "0x1faf0",
		                "0x1f91f",
		                "0x1f918",
		                "0x1f919",
		                "0x1f448",
		                "0x1f449",
		                "0x1f446",
		                "0x1f595",
		                "0x1f447",
		                "0x261d",
		                "0x1faf5",
		                "0x1f44d",
		                "0x1f44e",
		                "0x270a",
		                "0x1f44a",
		                "0x1f91b",
		                "0x1f91c",
		                "0x1f44f",
		                "0x1f64c",
		                "0x1faf6",
		                "0x1f450",
		                "0x1f932",
		                "0x1f91d",
		                "0x1f64f",
		                "0x270d",
		                "0x1f485",
		                "0x1f933",
		                "0x1f4aa",
		                "0x1f9be",
		                "0x1f9bf",
		                "0x1f9b5",
		                "0x1f9b6",
		                "0x1f442",
		                "0x1f9bb",
		                "0x1f443",
		                "0x1f9e0",
		                "0x1fac0",
		                "0x1fac1",
		                "0x1f9b7",
		                "0x1f9b4",
		                "0x1f440",
		                "0x1f441",
		                "0x1f445",
		                "0x1f444",
		                "0x1fae6",
		                "0x1f476",
		                "0x1f9d2",
		                "0x1f466",
		                "0x1f467",
		                "0x1f9d1",
		                "0x1f471",
		                "0x1f468",
		                "0x1f9d4",
		                "0x1f9d4",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9d4",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f468",
		                "0x200d",
		                "0x1f9b0",
		                "0x1f468",
		                "0x200d",
		                "0x1f9b1",
		                "0x1f468",
		                "0x200d",
		                "0x1f9b3",
		                "0x1f468",
		                "0x200d",
		                "0x1f9b2",
		                "0x1f469",
		                "0x1f469",
		                "0x200d",
		                "0x1f9b0",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9b0",
		                "0x1f469",
		                "0x200d",
		                "0x1f9b1",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9b1",
		                "0x1f469",
		                "0x200d",
		                "0x1f9b3",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9b3",
		                "0x1f469",
		                "0x200d",
		                "0x1f9b2",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9b2",
		                "0x1f471",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f471",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9d3",
		                "0x1f474",
		                "0x1f475",
		                "0x1f64d",
		                "0x1f64d",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f64d",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f64e",
		                "0x1f64e",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f64e",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f645",
		                "0x1f645",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f645",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f646",
		                "0x1f646",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f646",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f481",
		                "0x1f481",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f481",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f64b",
		                "0x1f64b",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f64b",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9cf",
		                "0x1f9cf",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9cf",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f647",
		                "0x1f647",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f647",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f926",
		                "0x1f926",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f926",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f937",
		                "0x1f937",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f937",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9d1",
		                "0x200d",
		                "0x2695",
		                "0xfe0f",
		                "0x1f468",
		                "0x200d",
		                "0x2695",
		                "0xfe0f",
		                "0x1f469",
		                "0x200d",
		                "0x2695",
		                "0xfe0f",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f393",
		                "0x1f468",
		                "0x200d",
		                "0x1f393",
		                "0x1f469",
		                "0x200d",
		                "0x1f393",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f3eb",
		                "0x1f468",
		                "0x200d",
		                "0x1f3eb",
		                "0x1f469",
		                "0x200d",
		                "0x1f3eb",
		                "0x1f9d1",
		                "0x200d",
		                "0x2696",
		                "0xfe0f",
		                "0x1f468",
		                "0x200d",
		                "0x2696",
		                "0xfe0f",
		                "0x1f469",
		                "0x200d",
		                "0x2696",
		                "0xfe0f",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f33e",
		                "0x1f468",
		                "0x200d",
		                "0x1f33e",
		                "0x1f469",
		                "0x200d",
		                "0x1f33e",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f373",
		                "0x1f468",
		                "0x200d",
		                "0x1f373",
		                "0x1f469",
		                "0x200d",
		                "0x1f373",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f527",
		                "0x1f468",
		                "0x200d",
		                "0x1f527",
		                "0x1f469",
		                "0x200d",
		                "0x1f527",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f3ed",
		                "0x1f468",
		                "0x200d",
		                "0x1f3ed",
		                "0x1f469",
		                "0x200d",
		                "0x1f3ed",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f4bc",
		                "0x1f468",
		                "0x200d",
		                "0x1f4bc",
		                "0x1f469",
		                "0x200d",
		                "0x1f4bc",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f52c",
		                "0x1f468",
		                "0x200d",
		                "0x1f52c",
		                "0x1f469",
		                "0x200d",
		                "0x1f52c",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f4bb",
		                "0x1f468",
		                "0x200d",
		                "0x1f4bb",
		                "0x1f469",
		                "0x200d",
		                "0x1f4bb",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f3a4",
		                "0x1f468",
		                "0x200d",
		                "0x1f3a4",
		                "0x1f469",
		                "0x200d",
		                "0x1f3a4",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f3a8",
		                "0x1f468",
		                "0x200d",
		                "0x1f3a8",
		                "0x1f469",
		                "0x200d",
		                "0x1f3a8",
		                "0x1f9d1",
		                "0x200d",
		                "0x2708",
		                "0xfe0f",
		                "0x1f468",
		                "0x200d",
		                "0x2708",
		                "0xfe0f",
		                "0x1f469",
		                "0x200d",
		                "0x2708",
		                "0xfe0f",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f680",
		                "0x1f468",
		                "0x200d",
		                "0x1f680",
		                "0x1f469",
		                "0x200d",
		                "0x1f680",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f692",
		                "0x1f468",
		                "0x200d",
		                "0x1f692",
		                "0x1f469",
		                "0x200d",
		                "0x1f692",
		                "0x1f46e",
		                "0x1f46e",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f46e",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f575",
		                "0x1f575",
		                "0xfe0f",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f575",
		                "0xfe0f",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f482",
		                "0x1f482",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f482",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f977",
		                "0x1f477",
		                "0x1f477",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f477",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1fac5",
		                "0x1f934",
		                "0x1f478",
		                "0x1f473",
		                "0x1f473",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f473",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f472",
		                "0x1f9d5",
		                "0x1f935",
		                "0x1f935",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f935",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f470",
		                "0x1f470",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f470",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f930",
		                "0x1fac3",
		                "0x1fac4",
		                "0x1f931",
		                "0x1f469",
		                "0x200d",
		                "0x1f37c",
		                "0x1f468",
		                "0x200d",
		                "0x1f37c",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f37c",
		                "0x1f47c",
		                "0x1f385",
		                "0x1f936",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f384",
		                "0x1f9b8",
		                "0x1f9b8",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9b8",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9b9",
		                "0x1f9b9",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9b9",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9d9",
		                "0x1f9d9",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9d9",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9da",
		                "0x1f9da",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9da",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9db",
		                "0x1f9db",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9db",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9dc",
		                "0x1f9dc",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9dc",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9dd",
		                "0x1f9dd",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9dd",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9de",
		                "0x1f9de",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9de",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9df",
		                "0x1f9df",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9df",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9cc",
		                "0x1f486",
		                "0x1f486",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f486",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f487",
		                "0x1f487",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f487",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f6b6",
		                "0x1f6b6",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f6b6",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f6b6",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f6b6",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f6b6",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f9cd",
		                "0x1f9cd",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9cd",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9ce",
		                "0x1f9ce",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9ce",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9ce",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f9ce",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f9ce",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9af",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9af",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f468",
		                "0x200d",
		                "0x1f9af",
		                "0x1f468",
		                "0x200d",
		                "0x1f9af",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f469",
		                "0x200d",
		                "0x1f9af",
		                "0x1f469",
		                "0x200d",
		                "0x1f9af",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9bc",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9bc",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f468",
		                "0x200d",
		                "0x1f9bc",
		                "0x1f468",
		                "0x200d",
		                "0x1f9bc",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f469",
		                "0x200d",
		                "0x1f9bc",
		                "0x1f469",
		                "0x200d",
		                "0x1f9bc",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9bd",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9bd",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f468",
		                "0x200d",
		                "0x1f9bd",
		                "0x1f468",
		                "0x200d",
		                "0x1f9bd",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f469",
		                "0x200d",
		                "0x1f9bd",
		                "0x1f469",
		                "0x200d",
		                "0x1f9bd",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f3c3",
		                "0x1f3c3",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f3c3",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f3c3",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f3c3",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f3c3",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x200d",
		                "0x27a1",
		                "0xfe0f",
		                "0x1f483",
		                "0x1f57a",
		                "0x1f574",
		                "0x1f46f",
		                "0x1f46f",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f46f",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9d6",
		                "0x1f9d6",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9d6",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9d7",
		                "0x1f9d7",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9d7",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f93a",
		                "0x1f3c7",
		                "0x26f7",
		                "0x1f3c2",
		                "0x1f3cc",
		                "0x1f3cc",
		                "0xfe0f",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f3cc",
		                "0xfe0f",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f3c4",
		                "0x1f3c4",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f3c4",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f6a3",
		                "0x1f6a3",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f6a3",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f3ca",
		                "0x1f3ca",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f3ca",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x26f9",
		                "0x26f9",
		                "0xfe0f",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x26f9",
		                "0xfe0f",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f3cb",
		                "0x1f3cb",
		                "0xfe0f",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f3cb",
		                "0xfe0f",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f6b4",
		                "0x1f6b4",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f6b4",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f6b5",
		                "0x1f6b5",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f6b5",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f938",
		                "0x1f938",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f938",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f93c",
		                "0x1f93c",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f93c",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f93d",
		                "0x1f93d",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f93d",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f93e",
		                "0x1f93e",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f93e",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f939",
		                "0x1f939",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f939",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f9d8",
		                "0x1f9d8",
		                "0x200d",
		                "0x2642",
		                "0xfe0f",
		                "0x1f9d8",
		                "0x200d",
		                "0x2640",
		                "0xfe0f",
		                "0x1f6c0",
		                "0x1f6cc",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f91d",
		                "0x200d",
		                "0x1f9d1",
		                "0x1f46d",
		                "0x1f46b",
		                "0x1f46c",
		                "0x1f48f",
		                "0x1f469",
		                "0x200d",
		                "0x2764",
		                "0xfe0f",
		                "0x200d",
		                "0x1f48b",
		                "0x200d",
		                "0x1f468",
		                "0x1f468",
		                "0x200d",
		                "0x2764",
		                "0xfe0f",
		                "0x200d",
		                "0x1f48b",
		                "0x200d",
		                "0x1f468",
		                "0x1f469",
		                "0x200d",
		                "0x2764",
		                "0xfe0f",
		                "0x200d",
		                "0x1f48b",
		                "0x200d",
		                "0x1f469",
		                "0x1f491",
		                "0x1f469",
		                "0x200d",
		                "0x2764",
		                "0xfe0f",
		                "0x200d",
		                "0x1f468",
		                "0x1f468",
		                "0x200d",
		                "0x2764",
		                "0xfe0f",
		                "0x200d",
		                "0x1f468",
		                "0x1f469",
		                "0x200d",
		                "0x2764",
		                "0xfe0f",
		                "0x200d",
		                "0x1f469",
		                "0x1f468",
		                "0x200d",
		                "0x1f469",
		                "0x200d",
		                "0x1f466",
		                "0x1f468",
		                "0x200d",
		                "0x1f469",
		                "0x200d",
		                "0x1f467",
		                "0x1f468",
		                "0x200d",
		                "0x1f469",
		                "0x200d",
		                "0x1f467",
		                "0x200d",
		                "0x1f466",
		                "0x1f468",
		                "0x200d",
		                "0x1f469",
		                "0x200d",
		                "0x1f466",
		                "0x200d",
		                "0x1f466",
		                "0x1f468",
		                "0x200d",
		                "0x1f469",
		                "0x200d",
		                "0x1f467",
		                "0x200d",
		                "0x1f467",
		                "0x1f468",
		                "0x200d",
		                "0x1f468",
		                "0x200d",
		                "0x1f466",
		                "0x1f468",
		                "0x200d",
		                "0x1f468",
		                "0x200d",
		                "0x1f467",
		                "0x1f468",
		                "0x200d",
		                "0x1f468",
		                "0x200d",
		                "0x1f467",
		                "0x200d",
		                "0x1f466",
		                "0x1f468",
		                "0x200d",
		                "0x1f468",
		                "0x200d",
		                "0x1f466",
		                "0x200d",
		                "0x1f466",
		                "0x1f468",
		                "0x200d",
		                "0x1f468",
		                "0x200d",
		                "0x1f467",
		                "0x200d",
		                "0x1f467",
		                "0x1f469",
		                "0x200d",
		                "0x1f469",
		                "0x200d",
		                "0x1f466",
		                "0x1f469",
		                "0x200d",
		                "0x1f469",
		                "0x200d",
		                "0x1f467",
		                "0x1f469",
		                "0x200d",
		                "0x1f469",
		                "0x200d",
		                "0x1f467",
		                "0x200d",
		                "0x1f466",
		                "0x1f469",
		                "0x200d",
		                "0x1f469",
		                "0x200d",
		                "0x1f466",
		                "0x200d",
		                "0x1f466",
		                "0x1f469",
		                "0x200d",
		                "0x1f469",
		                "0x200d",
		                "0x1f467",
		                "0x200d",
		                "0x1f467",
		                "0x1f468",
		                "0x200d",
		                "0x1f466",
		                "0x1f468",
		                "0x200d",
		                "0x1f466",
		                "0x200d",
		                "0x1f466",
		                "0x1f468",
		                "0x200d",
		                "0x1f467",
		                "0x1f468",
		                "0x200d",
		                "0x1f467",
		                "0x200d",
		                "0x1f466",
		                "0x1f468",
		                "0x200d",
		                "0x1f467",
		                "0x200d",
		                "0x1f467",
		                "0x1f469",
		                "0x200d",
		                "0x1f466",
		                "0x1f469",
		                "0x200d",
		                "0x1f466",
		                "0x200d",
		                "0x1f466",
		                "0x1f469",
		                "0x200d",
		                "0x1f467",
		                "0x1f469",
		                "0x200d",
		                "0x1f467",
		                "0x200d",
		                "0x1f466",
		                "0x1f469",
		                "0x200d",
		                "0x1f467",
		                "0x200d",
		                "0x1f467",
		                "0x1f5e3",
		                "0x1f464",
		                "0x1f465",
		                "0x1fac2",
		                "0x1f46a",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9d2",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9d2",
		                "0x200d",
		                "0x1f9d2",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9d2",
		                "0x1f9d1",
		                "0x200d",
		                "0x1f9d2",
		                "0x200d",
		                "0x1f9d2",
		                "0x1f463"
		            ],
		            "animals_and_nature": [
		                "0x1f435",
		                "0x1f412",
		                "0x1f98d",
		                "0x1f9a7",
		                "0x1f436",
		                "0x1f415",
		                "0x1f9ae",
		                "0x1f415",
		                "0x200d",
		                "0x1f9ba",
		                "0x1f429",
		                "0x1f43a",
		                "0x1f98a",
		                "0x1f99d",
		                "0x1f431",
		                "0x1f408",
		                "0x1f408",
		                "0x200d",
		                "0x2b1b",
		                "0x1f981",
		                "0x1f42f",
		                "0x1f405",
		                "0x1f406",
		                "0x1f434",
		                "0x1face",
		                "0x1facf",
		                "0x1f40e",
		                "0x1f984",
		                "0x1f993",
		                "0x1f98c",
		                "0x1f9ac",
		                "0x1f42e",
		                "0x1f402",
		                "0x1f403",
		                "0x1f404",
		                "0x1f437",
		                "0x1f416",
		                "0x1f417",
		                "0x1f43d",
		                "0x1f40f",
		                "0x1f411",
		                "0x1f410",
		                "0x1f42a",
		                "0x1f42b",
		                "0x1f999",
		                "0x1f992",
		                "0x1f418",
		                "0x1f9a3",
		                "0x1f98f",
		                "0x1f99b",
		                "0x1f42d",
		                "0x1f401",
		                "0x1f400",
		                "0x1f439",
		                "0x1f430",
		                "0x1f407",
		                "0x1f43f",
		                "0x1f9ab",
		                "0x1f994",
		                "0x1f987",
		                "0x1f43b",
		                "0x1f43b",
		                "0x200d",
		                "0x2744",
		                "0xfe0f",
		                "0x1f428",
		                "0x1f43c",
		                "0x1f9a5",
		                "0x1f9a6",
		                "0x1f9a8",
		                "0x1f998",
		                "0x1f9a1",
		                "0x1f43e",
		                "0x1f983",
		                "0x1f414",
		                "0x1f413",
		                "0x1f423",
		                "0x1f424",
		                "0x1f425",
		                "0x1f426",
		                "0x1f427",
		                "0x1f54a",
		                "0x1f985",
		                "0x1f986",
		                "0x1f9a2",
		                "0x1f989",
		                "0x1f9a4",
		                "0x1fab6",
		                "0x1f9a9",
		                "0x1f99a",
		                "0x1f99c",
		                "0x1fabd",
		                "0x1f426",
		                "0x200d",
		                "0x2b1b",
		                "0x1fabf",
		                "0x1f426",
		                "0x200d",
		                "0x1f525",
		                "0x1f438",
		                "0x1f40a",
		                "0x1f422",
		                "0x1f98e",
		                "0x1f40d",
		                "0x1f432",
		                "0x1f409",
		                "0x1f995",
		                "0x1f996",
		                "0x1f433",
		                "0x1f40b",
		                "0x1f42c",
		                "0x1f9ad",
		                "0x1f41f",
		                "0x1f420",
		                "0x1f421",
		                "0x1f988",
		                "0x1f419",
		                "0x1f41a",
		                "0x1fab8",
		                "0x1fabc",
		                "0x1f40c",
		                "0x1f98b",
		                "0x1f41b",
		                "0x1f41c",
		                "0x1f41d",
		                "0x1fab2",
		                "0x1f41e",
		                "0x1f997",
		                "0x1fab3",
		                "0x1f577",
		                "0x1f578",
		                "0x1f982",
		                "0x1f99f",
		                "0x1fab0",
		                "0x1fab1",
		                "0x1f9a0",
		                "0x1f490",
		                "0x1f338",
		                "0x1f4ae",
		                "0x1fab7",
		                "0x1f3f5",
		                "0x1f339",
		                "0x1f940",
		                "0x1f33a",
		                "0x1f33b",
		                "0x1f33c",
		                "0x1f337",
		                "0x1fabb",
		                "0x1f331",
		                "0x1fab4",
		                "0x1f332",
		                "0x1f333",
		                "0x1f334",
		                "0x1f335",
		                "0x1f33e",
		                "0x1f33f",
		                "0x2618",
		                "0x1f340",
		                "0x1f341",
		                "0x1f342",
		                "0x1f343",
		                "0x1fab9",
		                "0x1faba",
		                "0x1f344"
		            ],
		            "food_and_drink": [
		                "0x1f347",
		                "0x1f348",
		                "0x1f349",
		                "0x1f34a",
		                "0x1f34b",
		                "0x1f34b",
		                "0x200d",
		                "0x1f7e9",
		                "0x1f34c",
		                "0x1f34d",
		                "0x1f96d",
		                "0x1f34e",
		                "0x1f34f",
		                "0x1f350",
		                "0x1f351",
		                "0x1f352",
		                "0x1f353",
		                "0x1fad0",
		                "0x1f95d",
		                "0x1f345",
		                "0x1fad2",
		                "0x1f965",
		                "0x1f951",
		                "0x1f346",
		                "0x1f954",
		                "0x1f955",
		                "0x1f33d",
		                "0x1f336",
		                "0x1fad1",
		                "0x1f952",
		                "0x1f96c",
		                "0x1f966",
		                "0x1f9c4",
		                "0x1f9c5",
		                "0x1f95c",
		                "0x1fad8",
		                "0x1f330",
		                "0x1fada",
		                "0x1fadb",
		                "0x1f344",
		                "0x200d",
		                "0x1f7eb",
		                "0x1f35e",
		                "0x1f950",
		                "0x1f956",
		                "0x1fad3",
		                "0x1f968",
		                "0x1f96f",
		                "0x1f95e",
		                "0x1f9c7",
		                "0x1f9c0",
		                "0x1f356",
		                "0x1f357",
		                "0x1f969",
		                "0x1f953",
		                "0x1f354",
		                "0x1f35f",
		                "0x1f355",
		                "0x1f32d",
		                "0x1f96a",
		                "0x1f32e",
		                "0x1f32f",
		                "0x1fad4",
		                "0x1f959",
		                "0x1f9c6",
		                "0x1f95a",
		                "0x1f373",
		                "0x1f958",
		                "0x1f372",
		                "0x1fad5",
		                "0x1f963",
		                "0x1f957",
		                "0x1f37f",
		                "0x1f9c8",
		                "0x1f9c2",
		                "0x1f96b",
		                "0x1f371",
		                "0x1f358",
		                "0x1f359",
		                "0x1f35a",
		                "0x1f35b",
		                "0x1f35c",
		                "0x1f35d",
		                "0x1f360",
		                "0x1f362",
		                "0x1f363",
		                "0x1f364",
		                "0x1f365",
		                "0x1f96e",
		                "0x1f361",
		                "0x1f95f",
		                "0x1f960",
		                "0x1f961",
		                "0x1f980",
		                "0x1f99e",
		                "0x1f990",
		                "0x1f991",
		                "0x1f9aa",
		                "0x1f366",
		                "0x1f367",
		                "0x1f368",
		                "0x1f369",
		                "0x1f36a",
		                "0x1f382",
		                "0x1f370",
		                "0x1f9c1",
		                "0x1f967",
		                "0x1f36b",
		                "0x1f36c",
		                "0x1f36d",
		                "0x1f36e",
		                "0x1f36f",
		                "0x1f37c",
		                "0x1f95b",
		                "0x2615",
		                "0x1fad6",
		                "0x1f375",
		                "0x1f376",
		                "0x1f37e",
		                "0x1f377",
		                "0x1f378",
		                "0x1f379",
		                "0x1f37a",
		                "0x1f37b",
		                "0x1f942",
		                "0x1f943",
		                "0x1fad7",
		                "0x1f964",
		                "0x1f9cb",
		                "0x1f9c3",
		                "0x1f9c9",
		                "0x1f9ca",
		                "0x1f962",
		                "0x1f37d",
		                "0x1f374",
		                "0x1f944",
		                "0x1f52a",
		                "0x1fad9",
		                "0x1f3fa"
		            ],
		            "travel_and_places": [
		                "0x1f30d",
		                "0x1f30e",
		                "0x1f30f",
		                "0x1f310",
		                "0x1f5fa",
		                "0x1f5fe",
		                "0x1f9ed",
		                "0x1f3d4",
		                "0x26f0",
		                "0x1f30b",
		                "0x1f5fb",
		                "0x1f3d5",
		                "0x1f3d6",
		                "0x1f3dc",
		                "0x1f3dd",
		                "0x1f3de",
		                "0x1f3df",
		                "0x1f3db",
		                "0x1f3d7",
		                "0x1f9f1",
		                "0x1faa8",
		                "0x1fab5",
		                "0x1f6d6",
		                "0x1f3d8",
		                "0x1f3da",
		                "0x1f3e0",
		                "0x1f3e1",
		                "0x1f3e2",
		                "0x1f3e3",
		                "0x1f3e4",
		                "0x1f3e5",
		                "0x1f3e6",
		                "0x1f3e8",
		                "0x1f3e9",
		                "0x1f3ea",
		                "0x1f3eb",
		                "0x1f3ec",
		                "0x1f3ed",
		                "0x1f3ef",
		                "0x1f3f0",
		                "0x1f492",
		                "0x1f5fc",
		                "0x1f5fd",
		                "0x26ea",
		                "0x1f54c",
		                "0x1f6d5",
		                "0x1f54d",
		                "0x26e9",
		                "0x1f54b",
		                "0x26f2",
		                "0x26fa",
		                "0x1f301",
		                "0x1f303",
		                "0x1f3d9",
		                "0x1f304",
		                "0x1f305",
		                "0x1f306",
		                "0x1f307",
		                "0x1f309",
		                "0x2668",
		                "0x1f3a0",
		                "0x1f6dd",
		                "0x1f3a1",
		                "0x1f3a2",
		                "0x1f488",
		                "0x1f3aa",
		                "0x1f682",
		                "0x1f683",
		                "0x1f684",
		                "0x1f685",
		                "0x1f686",
		                "0x1f687",
		                "0x1f688",
		                "0x1f689",
		                "0x1f68a",
		                "0x1f69d",
		                "0x1f69e",
		                "0x1f68b",
		                "0x1f68c",
		                "0x1f68d",
		                "0x1f68e",
		                "0x1f690",
		                "0x1f691",
		                "0x1f692",
		                "0x1f693",
		                "0x1f694",
		                "0x1f695",
		                "0x1f696",
		                "0x1f697",
		                "0x1f698",
		                "0x1f699",
		                "0x1f6fb",
		                "0x1f69a",
		                "0x1f69b",
		                "0x1f69c",
		                "0x1f3ce",
		                "0x1f3cd",
		                "0x1f6f5",
		                "0x1f9bd",
		                "0x1f9bc",
		                "0x1f6fa",
		                "0x1f6b2",
		                "0x1f6f4",
		                "0x1f6f9",
		                "0x1f6fc",
		                "0x1f68f",
		                "0x1f6e3",
		                "0x1f6e4",
		                "0x1f6e2",
		                "0x26fd",
		                "0x1f6de",
		                "0x1f6a8",
		                "0x1f6a5",
		                "0x1f6a6",
		                "0x1f6d1",
		                "0x1f6a7",
		                "0x2693",
		                "0x1f6df",
		                "0x26f5",
		                "0x1f6f6",
		                "0x1f6a4",
		                "0x1f6f3",
		                "0x26f4",
		                "0x1f6e5",
		                "0x1f6a2",
		                "0x2708",
		                "0x1f6e9",
		                "0x1f6eb",
		                "0x1f6ec",
		                "0x1fa82",
		                "0x1f4ba",
		                "0x1f681",
		                "0x1f69f",
		                "0x1f6a0",
		                "0x1f6a1",
		                "0x1f6f0",
		                "0x1f680",
		                "0x1f6f8",
		                "0x1f6ce",
		                "0x1f9f3",
		                "0x231b",
		                "0x23f3",
		                "0x231a",
		                "0x23f0",
		                "0x23f1",
		                "0x23f2",
		                "0x1f570",
		                "0x1f55b",
		                "0x1f567",
		                "0x1f550",
		                "0x1f55c",
		                "0x1f551",
		                "0x1f55d",
		                "0x1f552",
		                "0x1f55e",
		                "0x1f553",
		                "0x1f55f",
		                "0x1f554",
		                "0x1f560",
		                "0x1f555",
		                "0x1f561",
		                "0x1f556",
		                "0x1f562",
		                "0x1f557",
		                "0x1f563",
		                "0x1f558",
		                "0x1f564",
		                "0x1f559",
		                "0x1f565",
		                "0x1f55a",
		                "0x1f566",
		                "0x1f311",
		                "0x1f312",
		                "0x1f313",
		                "0x1f314",
		                "0x1f315",
		                "0x1f316",
		                "0x1f317",
		                "0x1f318",
		                "0x1f319",
		                "0x1f31a",
		                "0x1f31b",
		                "0x1f31c",
		                "0x1f321",
		                "0x2600",
		                "0x1f31d",
		                "0x1f31e",
		                "0x1fa90",
		                "0x2b50",
		                "0x1f31f",
		                "0x1f320",
		                "0x1f30c",
		                "0x2601",
		                "0x26c5",
		                "0x26c8",
		                "0x1f324",
		                "0x1f325",
		                "0x1f326",
		                "0x1f327",
		                "0x1f328",
		                "0x1f329",
		                "0x1f32a",
		                "0x1f32b",
		                "0x1f32c",
		                "0x1f300",
		                "0x1f308",
		                "0x1f302",
		                "0x2602",
		                "0x2614",
		                "0x26f1",
		                "0x26a1",
		                "0x2744",
		                "0x2603",
		                "0x26c4",
		                "0x2604",
		                "0x1f525",
		                "0x1f4a7",
		                "0x1f30a"
		            ],
		            "activities": [
		                "0x1f383",
		                "0x1f384",
		                "0x1f386",
		                "0x1f387",
		                "0x1f9e8",
		                "0x2728",
		                "0x1f388",
		                "0x1f389",
		                "0x1f38a",
		                "0x1f38b",
		                "0x1f38d",
		                "0x1f38e",
		                "0x1f38f",
		                "0x1f390",
		                "0x1f391",
		                "0x1f9e7",
		                "0x1f380",
		                "0x1f381",
		                "0x1f397",
		                "0x1f39f",
		                "0x1f3ab",
		                "0x1f396",
		                "0x1f3c6",
		                "0x1f3c5",
		                "0x1f947",
		                "0x1f948",
		                "0x1f949",
		                "0x26bd",
		                "0x26be",
		                "0x1f94e",
		                "0x1f3c0",
		                "0x1f3d0",
		                "0x1f3c8",
		                "0x1f3c9",
		                "0x1f3be",
		                "0x1f94f",
		                "0x1f3b3",
		                "0x1f3cf",
		                "0x1f3d1",
		                "0x1f3d2",
		                "0x1f94d",
		                "0x1f3d3",
		                "0x1f3f8",
		                "0x1f94a",
		                "0x1f94b",
		                "0x1f945",
		                "0x26f3",
		                "0x26f8",
		                "0x1f3a3",
		                "0x1f93f",
		                "0x1f3bd",
		                "0x1f3bf",
		                "0x1f6f7",
		                "0x1f94c",
		                "0x1f3af",
		                "0x1fa80",
		                "0x1fa81",
		                "0x1f52b",
		                "0x1f3b1",
		                "0x1f52e",
		                "0x1fa84",
		                "0x1f3ae",
		                "0x1f579",
		                "0x1f3b0",
		                "0x1f3b2",
		                "0x1f9e9",
		                "0x1f9f8",
		                "0x1fa85",
		                "0x1faa9",
		                "0x1fa86",
		                "0x2660",
		                "0x2665",
		                "0x2666",
		                "0x2663",
		                "0x265f",
		                "0x1f0cf",
		                "0x1f004",
		                "0x1f3b4",
		                "0x1f3ad",
		                "0x1f5bc",
		                "0x1f3a8",
		                "0x1f9f5",
		                "0x1faa1",
		                "0x1f9f6",
		                "0x1faa2"
		            ],
		            "objects": [
		                "0x1f453",
		                "0x1f576",
		                "0x1f97d",
		                "0x1f97c",
		                "0x1f9ba",
		                "0x1f454",
		                "0x1f455",
		                "0x1f456",
		                "0x1f9e3",
		                "0x1f9e4",
		                "0x1f9e5",
		                "0x1f9e6",
		                "0x1f457",
		                "0x1f458",
		                "0x1f97b",
		                "0x1fa71",
		                "0x1fa72",
		                "0x1fa73",
		                "0x1f459",
		                "0x1f45a",
		                "0x1faad",
		                "0x1f45b",
		                "0x1f45c",
		                "0x1f45d",
		                "0x1f6cd",
		                "0x1f392",
		                "0x1fa74",
		                "0x1f45e",
		                "0x1f45f",
		                "0x1f97e",
		                "0x1f97f",
		                "0x1f460",
		                "0x1f461",
		                "0x1fa70",
		                "0x1f462",
		                "0x1faae",
		                "0x1f451",
		                "0x1f452",
		                "0x1f3a9",
		                "0x1f393",
		                "0x1f9e2",
		                "0x1fa96",
		                "0x26d1",
		                "0x1f4ff",
		                "0x1f484",
		                "0x1f48d",
		                "0x1f48e",
		                "0x1f507",
		                "0x1f508",
		                "0x1f509",
		                "0x1f50a",
		                "0x1f4e2",
		                "0x1f4e3",
		                "0x1f4ef",
		                "0x1f514",
		                "0x1f515",
		                "0x1f3bc",
		                "0x1f3b5",
		                "0x1f3b6",
		                "0x1f399",
		                "0x1f39a",
		                "0x1f39b",
		                "0x1f3a4",
		                "0x1f3a7",
		                "0x1f4fb",
		                "0x1f3b7",
		                "0x1fa97",
		                "0x1f3b8",
		                "0x1f3b9",
		                "0x1f3ba",
		                "0x1f3bb",
		                "0x1fa95",
		                "0x1f941",
		                "0x1fa98",
		                "0x1fa87",
		                "0x1fa88",
		                "0x1f4f1",
		                "0x1f4f2",
		                "0x260e",
		                "0x1f4de",
		                "0x1f4df",
		                "0x1f4e0",
		                "0x1f50b",
		                "0x1faab",
		                "0x1f50c",
		                "0x1f4bb",
		                "0x1f5a5",
		                "0x1f5a8",
		                "0x2328",
		                "0x1f5b1",
		                "0x1f5b2",
		                "0x1f4bd",
		                "0x1f4be",
		                "0x1f4bf",
		                "0x1f4c0",
		                "0x1f9ee",
		                "0x1f3a5",
		                "0x1f39e",
		                "0x1f4fd",
		                "0x1f3ac",
		                "0x1f4fa",
		                "0x1f4f7",
		                "0x1f4f8",
		                "0x1f4f9",
		                "0x1f4fc",
		                "0x1f50d",
		                "0x1f50e",
		                "0x1f56f",
		                "0x1f4a1",
		                "0x1f526",
		                "0x1f3ee",
		                "0x1fa94",
		                "0x1f4d4",
		                "0x1f4d5",
		                "0x1f4d6",
		                "0x1f4d7",
		                "0x1f4d8",
		                "0x1f4d9",
		                "0x1f4da",
		                "0x1f4d3",
		                "0x1f4d2",
		                "0x1f4c3",
		                "0x1f4dc",
		                "0x1f4c4",
		                "0x1f4f0",
		                "0x1f5de",
		                "0x1f4d1",
		                "0x1f516",
		                "0x1f3f7",
		                "0x1f4b0",
		                "0x1fa99",
		                "0x1f4b4",
		                "0x1f4b5",
		                "0x1f4b6",
		                "0x1f4b7",
		                "0x1f4b8",
		                "0x1f4b3",
		                "0x1f9fe",
		                "0x1f4b9",
		                "0x2709",
		                "0x1f4e7",
		                "0x1f4e8",
		                "0x1f4e9",
		                "0x1f4e4",
		                "0x1f4e5",
		                "0x1f4e6",
		                "0x1f4eb",
		                "0x1f4ea",
		                "0x1f4ec",
		                "0x1f4ed",
		                "0x1f4ee",
		                "0x1f5f3",
		                "0x270f",
		                "0x2712",
		                "0x1f58b",
		                "0x1f58a",
		                "0x1f58c",
		                "0x1f58d",
		                "0x1f4dd",
		                "0x1f4bc",
		                "0x1f4c1",
		                "0x1f4c2",
		                "0x1f5c2",
		                "0x1f4c5",
		                "0x1f4c6",
		                "0x1f5d2",
		                "0x1f5d3",
		                "0x1f4c7",
		                "0x1f4c8",
		                "0x1f4c9",
		                "0x1f4ca",
		                "0x1f4cb",
		                "0x1f4cc",
		                "0x1f4cd",
		                "0x1f4ce",
		                "0x1f587",
		                "0x1f4cf",
		                "0x1f4d0",
		                "0x2702",
		                "0x1f5c3",
		                "0x1f5c4",
		                "0x1f5d1",
		                "0x1f512",
		                "0x1f513",
		                "0x1f50f",
		                "0x1f510",
		                "0x1f511",
		                "0x1f5dd",
		                "0x1f528",
		                "0x1fa93",
		                "0x26cf",
		                "0x2692",
		                "0x1f6e0",
		                "0x1f5e1",
		                "0x2694",
		                "0x1f4a3",
		                "0x1fa83",
		                "0x1f3f9",
		                "0x1f6e1",
		                "0x1fa9a",
		                "0x1f527",
		                "0x1fa9b",
		                "0x1f529",
		                "0x2699",
		                "0x1f5dc",
		                "0x2696",
		                "0x1f9af",
		                "0x1f517",
		                "0x26d3",
		                "0xfe0f",
		                "0x200d",
		                "0x1f4a5",
		                "0x26d3",
		                "0x1fa9d",
		                "0x1f9f0",
		                "0x1f9f2",
		                "0x1fa9c",
		                "0x2697",
		                "0x1f9ea",
		                "0x1f9eb",
		                "0x1f9ec",
		                "0x1f52c",
		                "0x1f52d",
		                "0x1f4e1",
		                "0x1f489",
		                "0x1fa78",
		                "0x1f48a",
		                "0x1fa79",
		                "0x1fa7c",
		                "0x1fa7a",
		                "0x1fa7b",
		                "0x1f6aa",
		                "0x1f6d7",
		                "0x1fa9e",
		                "0x1fa9f",
		                "0x1f6cf",
		                "0x1f6cb",
		                "0x1fa91",
		                "0x1f6bd",
		                "0x1faa0",
		                "0x1f6bf",
		                "0x1f6c1",
		                "0x1faa4",
		                "0x1fa92",
		                "0x1f9f4",
		                "0x1f9f7",
		                "0x1f9f9",
		                "0x1f9fa",
		                "0x1f9fb",
		                "0x1faa3",
		                "0x1f9fc",
		                "0x1fae7",
		                "0x1faa5",
		                "0x1f9fd",
		                "0x1f9ef",
		                "0x1f6d2",
		                "0x1f6ac",
		                "0x26b0",
		                "0x1faa6",
		                "0x26b1",
		                "0x1f9ff",
		                "0x1faac",
		                "0x1f5ff",
		                "0x1faa7",
		                "0x1faaa"
		            ],
		            "symbols": [
		                "0x1f3e7",
		                "0x1f6ae",
		                "0x1f6b0",
		                "0x267f",
		                "0x1f6b9",
		                "0x1f6ba",
		                "0x1f6bb",
		                "0x1f6bc",
		                "0x1f6be",
		                "0x1f6c2",
		                "0x1f6c3",
		                "0x1f6c4",
		                "0x1f6c5",
		                "0x26a0",
		                "0x1f6b8",
		                "0x26d4",
		                "0x1f6ab",
		                "0x1f6b3",
		                "0x1f6ad",
		                "0x1f6af",
		                "0x1f6b1",
		                "0x1f6b7",
		                "0x1f4f5",
		                "0x1f51e",
		                "0x2622",
		                "0x2623",
		                "0x2b06",
		                "0x2197",
		                "0x27a1",
		                "0x2198",
		                "0x2b07",
		                "0x2199",
		                "0x2b05",
		                "0x2196",
		                "0x2195",
		                "0x2194",
		                "0x21a9",
		                "0x21aa",
		                "0x2934",
		                "0x2935",
		                "0x1f503",
		                "0x1f504",
		                "0x1f519",
		                "0x1f51a",
		                "0x1f51b",
		                "0x1f51c",
		                "0x1f51d",
		                "0x1f6d0",
		                "0x269b",
		                "0x1f549",
		                "0x2721",
		                "0x2638",
		                "0x262f",
		                "0x271d",
		                "0x2626",
		                "0x262a",
		                "0x262e",
		                "0x1f54e",
		                "0x1f52f",
		                "0x1faaf",
		                "0x2648",
		                "0x2649",
		                "0x264a",
		                "0x264b",
		                "0x264c",
		                "0x264d",
		                "0x264e",
		                "0x264f",
		                "0x2650",
		                "0x2651",
		                "0x2652",
		                "0x2653",
		                "0x26ce",
		                "0x1f500",
		                "0x1f501",
		                "0x1f502",
		                "0x25b6",
		                "0x23e9",
		                "0x23ed",
		                "0x23ef",
		                "0x25c0",
		                "0x23ea",
		                "0x23ee",
		                "0x1f53c",
		                "0x23eb",
		                "0x1f53d",
		                "0x23ec",
		                "0x23f8",
		                "0x23f9",
		                "0x23fa",
		                "0x23cf",
		                "0x1f3a6",
		                "0x1f505",
		                "0x1f506",
		                "0x1f4f6",
		                "0x1f6dc",
		                "0x1f4f3",
		                "0x1f4f4",
		                "0x2640",
		                "0x2642",
		                "0x26a7",
		                "0x2716",
		                "0x2795",
		                "0x2796",
		                "0x2797",
		                "0x1f7f0",
		                "0x267e",
		                "0x203c",
		                "0x2049",
		                "0x2753",
		                "0x2754",
		                "0x2755",
		                "0x2757",
		                "0x3030",
		                "0x1f4b1",
		                "0x1f4b2",
		                "0x2695",
		                "0x267b",
		                "0x269c",
		                "0x1f531",
		                "0x1f4db",
		                "0x1f530",
		                "0x2b55",
		                "0x2705",
		                "0x2611",
		                "0x2714",
		                "0x274c",
		                "0x274e",
		                "0x27b0",
		                "0x27bf",
		                "0x303d",
		                "0x2733",
		                "0x2734",
		                "0x2747",
		                "0x00a9",
		                "0x00ae",
		                "0x2122",
		                "0x0023",
		                "0xfe0f",
		                "0x20e3",
		                "0x002a",
		                "0xfe0f",
		                "0x20e3",
		                "0x0030",
		                "0xfe0f",
		                "0x20e3",
		                "0x0031",
		                "0xfe0f",
		                "0x20e3",
		                "0x0032",
		                "0xfe0f",
		                "0x20e3",
		                "0x0033",
		                "0xfe0f",
		                "0x20e3",
		                "0x0034",
		                "0xfe0f",
		                "0x20e3",
		                "0x0035",
		                "0xfe0f",
		                "0x20e3",
		                "0x0036",
		                "0xfe0f",
		                "0x20e3",
		                "0x0037",
		                "0xfe0f",
		                "0x20e3",
		                "0x0038",
		                "0xfe0f",
		                "0x20e3",
		                "0x0039",
		                "0xfe0f",
		                "0x20e3",
		                "0x1f51f",
		                "0x1f520",
		                "0x1f521",
		                "0x1f522",
		                "0x1f523",
		                "0x1f524",
		                "0x1f170",
		                "0x1f18e",
		                "0x1f171",
		                "0x1f191",
		                "0x1f192",
		                "0x1f193",
		                "0x2139",
		                "0x1f194",
		                "0x24c2",
		                "0x1f195",
		                "0x1f196",
		                "0x1f17e",
		                "0x1f197",
		                "0x1f17f",
		                "0x1f198",
		                "0x1f199",
		                "0x1f19a",
		                "0x1f201",
		                "0x1f202",
		                "0x1f237",
		                "0x1f236",
		                "0x1f22f",
		                "0x1f250",
		                "0x1f239",
		                "0x1f21a",
		                "0x1f232",
		                "0x1f251",
		                "0x1f238",
		                "0x1f234",
		                "0x1f233",
		                "0x3297",
		                "0x3299",
		                "0x1f23a",
		                "0x1f235",
		                "0x1f534",
		                "0x1f7e0",
		                "0x1f7e1",
		                "0x1f7e2",
		                "0x1f535",
		                "0x1f7e3",
		                "0x1f7e4",
		                "0x26ab",
		                "0x26aa",
		                "0x1f7e5",
		                "0x1f7e7",
		                "0x1f7e8",
		                "0x1f7e9",
		                "0x1f7e6",
		                "0x1f7ea",
		                "0x1f7eb",
		                "0x2b1b",
		                "0x2b1c",
		                "0x25fc",
		                "0x25fb",
		                "0x25fe",
		                "0x25fd",
		                "0x25aa",
		                "0x25ab",
		                "0x1f536",
		                "0x1f537",
		                "0x1f538",
		                "0x1f539",
		                "0x1f53a",
		                "0x1f53b",
		                "0x1f4a0",
		                "0x1f518",
		                "0x1f533",
		                "0x1f532"
		            ],
		            "flags": [
		                "0x1f3c1",
		                "0x1f6a9",
		                "0x1f38c",
		                "0x1f3f4",
		                "0x1f3f3",
		                "0x1f3f3",
		                "0xfe0f",
		                "0x200d",
		                "0x1f308",
		                "0x1f3f3",
		                "0xfe0f",
		                "0x200d",
		                "0x26a7",
		                "0xfe0f",
		                "0x1f3f4",
		                "0x200d",
		                "0x2620",
		                "0xfe0f",
		                "0x1f1e6",
		                "0x1f1e8",
		                "0x1f1e6",
		                "0x1f1e9",
		                "0x1f1e6",
		                "0x1f1ea",
		                "0x1f1e6",
		                "0x1f1eb",
		                "0x1f1e6",
		                "0x1f1ec",
		                "0x1f1e6",
		                "0x1f1ee",
		                "0x1f1e6",
		                "0x1f1f1",
		                "0x1f1e6",
		                "0x1f1f2",
		                "0x1f1e6",
		                "0x1f1f4",
		                "0x1f1e6",
		                "0x1f1f6",
		                "0x1f1e6",
		                "0x1f1f7",
		                "0x1f1e6",
		                "0x1f1f8",
		                "0x1f1e6",
		                "0x1f1f9",
		                "0x1f1e6",
		                "0x1f1fa",
		                "0x1f1e6",
		                "0x1f1fc",
		                "0x1f1e6",
		                "0x1f1fd",
		                "0x1f1e6",
		                "0x1f1ff",
		                "0x1f1e7",
		                "0x1f1e6",
		                "0x1f1e7",
		                "0x1f1e7",
		                "0x1f1e7",
		                "0x1f1e9",
		                "0x1f1e7",
		                "0x1f1ea",
		                "0x1f1e7",
		                "0x1f1eb",
		                "0x1f1e7",
		                "0x1f1ec",
		                "0x1f1e7",
		                "0x1f1ed",
		                "0x1f1e7",
		                "0x1f1ee",
		                "0x1f1e7",
		                "0x1f1ef",
		                "0x1f1e7",
		                "0x1f1f1",
		                "0x1f1e7",
		                "0x1f1f2",
		                "0x1f1e7",
		                "0x1f1f3",
		                "0x1f1e7",
		                "0x1f1f4",
		                "0x1f1e7",
		                "0x1f1f6",
		                "0x1f1e7",
		                "0x1f1f7",
		                "0x1f1e7",
		                "0x1f1f8",
		                "0x1f1e7",
		                "0x1f1f9",
		                "0x1f1e7",
		                "0x1f1fb",
		                "0x1f1e7",
		                "0x1f1fc",
		                "0x1f1e7",
		                "0x1f1fe",
		                "0x1f1e7",
		                "0x1f1ff",
		                "0x1f1e8",
		                "0x1f1e6",
		                "0x1f1e8",
		                "0x1f1e8",
		                "0x1f1e8",
		                "0x1f1e9",
		                "0x1f1e8",
		                "0x1f1eb",
		                "0x1f1e8",
		                "0x1f1ec",
		                "0x1f1e8",
		                "0x1f1ed",
		                "0x1f1e8",
		                "0x1f1ee",
		                "0x1f1e8",
		                "0x1f1f0",
		                "0x1f1e8",
		                "0x1f1f1",
		                "0x1f1e8",
		                "0x1f1f2",
		                "0x1f1e8",
		                "0x1f1f3",
		                "0x1f1e8",
		                "0x1f1f4",
		                "0x1f1e8",
		                "0x1f1f5",
		                "0x1f1e8",
		                "0x1f1f7",
		                "0x1f1e8",
		                "0x1f1fa",
		                "0x1f1e8",
		                "0x1f1fb",
		                "0x1f1e8",
		                "0x1f1fc",
		                "0x1f1e8",
		                "0x1f1fd",
		                "0x1f1e8",
		                "0x1f1fe",
		                "0x1f1e8",
		                "0x1f1ff",
		                "0x1f1e9",
		                "0x1f1ea",
		                "0x1f1e9",
		                "0x1f1ec",
		                "0x1f1e9",
		                "0x1f1ef",
		                "0x1f1e9",
		                "0x1f1f0",
		                "0x1f1e9",
		                "0x1f1f2",
		                "0x1f1e9",
		                "0x1f1f4",
		                "0x1f1e9",
		                "0x1f1ff",
		                "0x1f1ea",
		                "0x1f1e6",
		                "0x1f1ea",
		                "0x1f1e8",
		                "0x1f1ea",
		                "0x1f1ea",
		                "0x1f1ea",
		                "0x1f1ec",
		                "0x1f1ea",
		                "0x1f1ed",
		                "0x1f1ea",
		                "0x1f1f7",
		                "0x1f1ea",
		                "0x1f1f8",
		                "0x1f1ea",
		                "0x1f1f9",
		                "0x1f1ea",
		                "0x1f1fa",
		                "0x1f1eb",
		                "0x1f1ee",
		                "0x1f1eb",
		                "0x1f1ef",
		                "0x1f1eb",
		                "0x1f1f0",
		                "0x1f1eb",
		                "0x1f1f2",
		                "0x1f1eb",
		                "0x1f1f4",
		                "0x1f1eb",
		                "0x1f1f7",
		                "0x1f1ec",
		                "0x1f1e6",
		                "0x1f1ec",
		                "0x1f1e7",
		                "0x1f1ec",
		                "0x1f1e9",
		                "0x1f1ec",
		                "0x1f1ea",
		                "0x1f1ec",
		                "0x1f1eb",
		                "0x1f1ec",
		                "0x1f1ec",
		                "0x1f1ec",
		                "0x1f1ed",
		                "0x1f1ec",
		                "0x1f1ee",
		                "0x1f1ec",
		                "0x1f1f1",
		                "0x1f1ec",
		                "0x1f1f2",
		                "0x1f1ec",
		                "0x1f1f3",
		                "0x1f1ec",
		                "0x1f1f5",
		                "0x1f1ec",
		                "0x1f1f6",
		                "0x1f1ec",
		                "0x1f1f7",
		                "0x1f1ec",
		                "0x1f1f8",
		                "0x1f1ec",
		                "0x1f1f9",
		                "0x1f1ec",
		                "0x1f1fa",
		                "0x1f1ec",
		                "0x1f1fc",
		                "0x1f1ec",
		                "0x1f1fe",
		                "0x1f1ed",
		                "0x1f1f0",
		                "0x1f1ed",
		                "0x1f1f2",
		                "0x1f1ed",
		                "0x1f1f3",
		                "0x1f1ed",
		                "0x1f1f7",
		                "0x1f1ed",
		                "0x1f1f9",
		                "0x1f1ed",
		                "0x1f1fa",
		                "0x1f1ee",
		                "0x1f1e8",
		                "0x1f1ee",
		                "0x1f1e9",
		                "0x1f1ee",
		                "0x1f1ea",
		                "0x1f1ee",
		                "0x1f1f1",
		                "0x1f1ee",
		                "0x1f1f2",
		                "0x1f1ee",
		                "0x1f1f3",
		                "0x1f1ee",
		                "0x1f1f4",
		                "0x1f1ee",
		                "0x1f1f6",
		                "0x1f1ee",
		                "0x1f1f7",
		                "0x1f1ee",
		                "0x1f1f8",
		                "0x1f1ee",
		                "0x1f1f9",
		                "0x1f1ef",
		                "0x1f1ea",
		                "0x1f1ef",
		                "0x1f1f2",
		                "0x1f1ef",
		                "0x1f1f4",
		                "0x1f1ef",
		                "0x1f1f5",
		                "0x1f1f0",
		                "0x1f1ea",
		                "0x1f1f0",
		                "0x1f1ec",
		                "0x1f1f0",
		                "0x1f1ed",
		                "0x1f1f0",
		                "0x1f1ee",
		                "0x1f1f0",
		                "0x1f1f2",
		                "0x1f1f0",
		                "0x1f1f3",
		                "0x1f1f0",
		                "0x1f1f5",
		                "0x1f1f0",
		                "0x1f1f7",
		                "0x1f1f0",
		                "0x1f1fc",
		                "0x1f1f0",
		                "0x1f1fe",
		                "0x1f1f0",
		                "0x1f1ff",
		                "0x1f1f1",
		                "0x1f1e6",
		                "0x1f1f1",
		                "0x1f1e7",
		                "0x1f1f1",
		                "0x1f1e8",
		                "0x1f1f1",
		                "0x1f1ee",
		                "0x1f1f1",
		                "0x1f1f0",
		                "0x1f1f1",
		                "0x1f1f7",
		                "0x1f1f1",
		                "0x1f1f8",
		                "0x1f1f1",
		                "0x1f1f9",
		                "0x1f1f1",
		                "0x1f1fa",
		                "0x1f1f1",
		                "0x1f1fb",
		                "0x1f1f1",
		                "0x1f1fe",
		                "0x1f1f2",
		                "0x1f1e6",
		                "0x1f1f2",
		                "0x1f1e8",
		                "0x1f1f2",
		                "0x1f1e9",
		                "0x1f1f2",
		                "0x1f1ea",
		                "0x1f1f2",
		                "0x1f1eb",
		                "0x1f1f2",
		                "0x1f1ec",
		                "0x1f1f2",
		                "0x1f1ed",
		                "0x1f1f2",
		                "0x1f1f0",
		                "0x1f1f2",
		                "0x1f1f1",
		                "0x1f1f2",
		                "0x1f1f2",
		                "0x1f1f2",
		                "0x1f1f3",
		                "0x1f1f2",
		                "0x1f1f4",
		                "0x1f1f2",
		                "0x1f1f5",
		                "0x1f1f2",
		                "0x1f1f6",
		                "0x1f1f2",
		                "0x1f1f7",
		                "0x1f1f2",
		                "0x1f1f8",
		                "0x1f1f2",
		                "0x1f1f9",
		                "0x1f1f2",
		                "0x1f1fa",
		                "0x1f1f2",
		                "0x1f1fb",
		                "0x1f1f2",
		                "0x1f1fc",
		                "0x1f1f2",
		                "0x1f1fd",
		                "0x1f1f2",
		                "0x1f1fe",
		                "0x1f1f2",
		                "0x1f1ff",
		                "0x1f1f3",
		                "0x1f1e6",
		                "0x1f1f3",
		                "0x1f1e8",
		                "0x1f1f3",
		                "0x1f1ea",
		                "0x1f1f3",
		                "0x1f1eb",
		                "0x1f1f3",
		                "0x1f1ec",
		                "0x1f1f3",
		                "0x1f1ee",
		                "0x1f1f3",
		                "0x1f1f1",
		                "0x1f1f3",
		                "0x1f1f4",
		                "0x1f1f3",
		                "0x1f1f5",
		                "0x1f1f3",
		                "0x1f1f7",
		                "0x1f1f3",
		                "0x1f1fa",
		                "0x1f1f3",
		                "0x1f1ff",
		                "0x1f1f4",
		                "0x1f1f2",
		                "0x1f1f5",
		                "0x1f1e6",
		                "0x1f1f5",
		                "0x1f1ea",
		                "0x1f1f5",
		                "0x1f1eb",
		                "0x1f1f5",
		                "0x1f1ec",
		                "0x1f1f5",
		                "0x1f1ed",
		                "0x1f1f5",
		                "0x1f1f0",
		                "0x1f1f5",
		                "0x1f1f1",
		                "0x1f1f5",
		                "0x1f1f2",
		                "0x1f1f5",
		                "0x1f1f3",
		                "0x1f1f5",
		                "0x1f1f7",
		                "0x1f1f5",
		                "0x1f1f8",
		                "0x1f1f5",
		                "0x1f1f9",
		                "0x1f1f5",
		                "0x1f1fc",
		                "0x1f1f5",
		                "0x1f1fe",
		                "0x1f1f6",
		                "0x1f1e6",
		                "0x1f1f7",
		                "0x1f1ea",
		                "0x1f1f7",
		                "0x1f1f4",
		                "0x1f1f7",
		                "0x1f1f8",
		                "0x1f1f7",
		                "0x1f1fa",
		                "0x1f1f7",
		                "0x1f1fc",
		                "0x1f1f8",
		                "0x1f1e6",
		                "0x1f1f8",
		                "0x1f1e7",
		                "0x1f1f8",
		                "0x1f1e8",
		                "0x1f1f8",
		                "0x1f1e9",
		                "0x1f1f8",
		                "0x1f1ea",
		                "0x1f1f8",
		                "0x1f1ec",
		                "0x1f1f8",
		                "0x1f1ed",
		                "0x1f1f8",
		                "0x1f1ee",
		                "0x1f1f8",
		                "0x1f1ef",
		                "0x1f1f8",
		                "0x1f1f0",
		                "0x1f1f8",
		                "0x1f1f1",
		                "0x1f1f8",
		                "0x1f1f2",
		                "0x1f1f8",
		                "0x1f1f3",
		                "0x1f1f8",
		                "0x1f1f4",
		                "0x1f1f8",
		                "0x1f1f7",
		                "0x1f1f8",
		                "0x1f1f8",
		                "0x1f1f8",
		                "0x1f1f9",
		                "0x1f1f8",
		                "0x1f1fb",
		                "0x1f1f8",
		                "0x1f1fd",
		                "0x1f1f8",
		                "0x1f1fe",
		                "0x1f1f8",
		                "0x1f1ff",
		                "0x1f1f9",
		                "0x1f1e6",
		                "0x1f1f9",
		                "0x1f1e8",
		                "0x1f1f9",
		                "0x1f1e9",
		                "0x1f1f9",
		                "0x1f1eb",
		                "0x1f1f9",
		                "0x1f1ec",
		                "0x1f1f9",
		                "0x1f1ed",
		                "0x1f1f9",
		                "0x1f1ef",
		                "0x1f1f9",
		                "0x1f1f0",
		                "0x1f1f9",
		                "0x1f1f1",
		                "0x1f1f9",
		                "0x1f1f2",
		                "0x1f1f9",
		                "0x1f1f3",
		                "0x1f1f9",
		                "0x1f1f4",
		                "0x1f1f9",
		                "0x1f1f7",
		                "0x1f1f9",
		                "0x1f1f9",
		                "0x1f1f9",
		                "0x1f1fb",
		                "0x1f1f9",
		                "0x1f1fc",
		                "0x1f1f9",
		                "0x1f1ff",
		                "0x1f1fa",
		                "0x1f1e6",
		                "0x1f1fa",
		                "0x1f1ec",
		                "0x1f1fa",
		                "0x1f1f2",
		                "0x1f1fa",
		                "0x1f1f3",
		                "0x1f1fa",
		                "0x1f1f8",
		                "0x1f1fa",
		                "0x1f1fe",
		                "0x1f1fa",
		                "0x1f1ff",
		                "0x1f1fb",
		                "0x1f1e6",
		                "0x1f1fb",
		                "0x1f1e8",
		                "0x1f1fb",
		                "0x1f1ea",
		                "0x1f1fb",
		                "0x1f1ec",
		                "0x1f1fb",
		                "0x1f1ee",
		                "0x1f1fb",
		                "0x1f1f3",
		                "0x1f1fb",
		                "0x1f1fa",
		                "0x1f1fc",
		                "0x1f1eb",
		                "0x1f1fc",
		                "0x1f1f8",
		                "0x1f1fd",
		                "0x1f1f0",
		                "0x1f1fe",
		                "0x1f1ea",
		                "0x1f1fe",
		                "0x1f1f9",
		                "0x1f1ff",
		                "0x1f1e6",
		                "0x1f1ff",
		                "0x1f1f2",
		                "0x1f1ff",
		                "0x1f1fc",
		                "0x1f3f4",
		                "0xe0067",
		                "0xe0062",
		                "0xe0065",
		                "0xe006e",
		                "0xe0067",
		                "0xe007f",
		                "0x1f3f4",
		                "0xe0067",
		                "0xe0062",
		                "0xe0073",
		                "0xe0063",
		                "0xe0074",
		                "0xe007f",
		                "0x1f3f4",
		                "0xe0067",
		                "0xe0062",
		                "0xe0077",
		                "0xe006c",
		                "0xe0073",
		                "0xe007f"
		            ]
		        }
		    };

		    var o_hasOwnProperty = Object.prototype.hasOwnProperty;
		    var o_keys = (Object.keys || function(obj) {
		      var result = [];
		      for (var key in obj) {
		        if (o_hasOwnProperty.call(obj, key)) {
		          result.push(key);
		        }
		      }

		      return result;
		    });


		    function _copyObject(source, target) {
		      var keys = o_keys(source);
		      var key;

		      for (var i = 0, l = keys.length; i < l; i++) {
		        key = keys[i];
		        target[key] = source[key] || target[key];
		      }
		    }

		    function _copyArray(source, target) {
		      for (var i = 0, l = source.length; i < l; i++) {
		        target[i] = source[i];
		      }
		    }

		    function copyObject(source, _target) {
		        var isArray = Array.isArray(source);
		        var target = _target || (isArray ? new Array(source.length) : {});

		        if (isArray) {
		          _copyArray(source, target);
		        } else {
		          _copyObject(source, target);
		        }

		        return target;
		    }

		    /** Get the data based on key**/
		    Chance.prototype.get = function (name) {
		        return copyObject(data[name]);
		    };

		    // Mac Address
		    Chance.prototype.mac_address = function(options){
		        // typically mac addresses are separated by ":"
		        // however they can also be separated by "-"
		        // the network variant uses a dot every fourth byte

		        options = initOptions(options);
		        if(!options.separator) {
		            options.separator =  options.networkVersion ? "." : ":";
		        }

		        var mac_pool="ABCDEF1234567890",
		            mac = "";
		        if(!options.networkVersion) {
		            mac = this.n(this.string, 6, { pool: mac_pool, length:2 }).join(options.separator);
		        } else {
		            mac = this.n(this.string, 3, { pool: mac_pool, length:4 }).join(options.separator);
		        }

		        return mac;
		    };

		    Chance.prototype.normal = function (options) {
		        options = initOptions(options, {mean : 0, dev : 1, pool : []});

		        testRange(
		            options.pool.constructor !== Array,
		            "Chance: The pool option must be a valid array."
		        );
		        testRange(
		            typeof options.mean !== 'number',
		            "Chance: Mean (mean) must be a number"
		        );
		        testRange(
		            typeof options.dev !== 'number',
		            "Chance: Standard deviation (dev) must be a number"
		        );

		        // If a pool has been passed, then we are returning an item from that pool,
		        // using the normal distribution settings that were passed in
		        if (options.pool.length > 0) {
		            return this.normal_pool(options);
		        }

		        // The Marsaglia Polar method
		        var s, u, v, norm,
		            mean = options.mean,
		            dev = options.dev;

		        do {
		            // U and V are from the uniform distribution on (-1, 1)
		            u = this.random() * 2 - 1;
		            v = this.random() * 2 - 1;

		            s = u * u + v * v;
		        } while (s >= 1);

		        // Compute the standard normal variate
		        norm = u * Math.sqrt(-2 * Math.log(s) / s);

		        // Shape and scale
		        return dev * norm + mean;
		    };

		    Chance.prototype.normal_pool = function(options) {
		        var performanceCounter = 0;
		        do {
		            var idx = Math.round(this.normal({ mean: options.mean, dev: options.dev }));
		            if (idx < options.pool.length && idx >= 0) {
		                return options.pool[idx];
		            } else {
		                performanceCounter++;
		            }
		        } while(performanceCounter < 100);

		        throw new RangeError("Chance: Your pool is too small for the given mean and standard deviation. Please adjust.");
		    };

		    Chance.prototype.radio = function (options) {
		        // Initial Letter (Typically Designated by Side of Mississippi River)
		        options = initOptions(options, {side : "?"});
		        var fl = "";
		        switch (options.side.toLowerCase()) {
		        case "east":
		        case "e":
		            fl = "W";
		            break;
		        case "west":
		        case "w":
		            fl = "K";
		            break;
		        default:
		            fl = this.character({pool: "KW"});
		            break;
		        }

		        return fl + this.character({alpha: true, casing: "upper"}) +
		                this.character({alpha: true, casing: "upper"}) +
		                this.character({alpha: true, casing: "upper"});
		    };

		    // Set the data as key and data or the data map
		    Chance.prototype.set = function (name, values) {
		        if (typeof name === "string") {
		            data[name] = values;
		        } else {
		            data = copyObject(name, data);
		        }
		    };

		    Chance.prototype.tv = function (options) {
		        return this.radio(options);
		    };

		    // ID number for Brazil companies
		    Chance.prototype.cnpj = function () {
		        var n = this.n(this.natural, 8, { max: 9 });
		        var d1 = 2+n[7]*6+n[6]*7+n[5]*8+n[4]*9+n[3]*2+n[2]*3+n[1]*4+n[0]*5;
		        d1 = 11 - (d1 % 11);
		        if (d1>=10){
		            d1 = 0;
		        }
		        var d2 = d1*2+3+n[7]*7+n[6]*8+n[5]*9+n[4]*2+n[3]*3+n[2]*4+n[1]*5+n[0]*6;
		        d2 = 11 - (d2 % 11);
		        if (d2>=10){
		            d2 = 0;
		        }
		        return ''+n[0]+n[1]+'.'+n[2]+n[3]+n[4]+'.'+n[5]+n[6]+n[7]+'/0001-'+d1+d2;
		    };

		    Chance.prototype.emotion = function () {
		        return this.pick(this.get("emotions"));
		    };

		    // -- End Miscellaneous --

		    Chance.prototype.mersenne_twister = function (seed) {
		        return new MersenneTwister(seed);
		    };

		    Chance.prototype.blueimp_md5 = function () {
		        return new BlueImpMD5();
		    };

		    // Mersenne Twister from https://gist.github.com/banksean/300494
		    /*
		       A C-program for MT19937, with initialization improved 2002/1/26.
		       Coded by Takuji Nishimura and Makoto Matsumoto.

		       Before using, initialize the state by using init_genrand(seed)
		       or init_by_array(init_key, key_length).

		       Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
		       All rights reserved.

		       Redistribution and use in source and binary forms, with or without
		       modification, are permitted provided that the following conditions
		       are met:

		       1. Redistributions of source code must retain the above copyright
		       notice, this list of conditions and the following disclaimer.

		       2. Redistributions in binary form must reproduce the above copyright
		       notice, this list of conditions and the following disclaimer in the
		       documentation and/or other materials provided with the distribution.

		       3. The names of its contributors may not be used to endorse or promote
		       products derived from this software without specific prior written
		       permission.

		       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
		       "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
		       LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
		       A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
		       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
		       EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
		       PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
		       PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
		       LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
		       NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
		       SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


		       Any feedback is very welcome.
		       http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
		       email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
		     */
		    var MersenneTwister = function (seed) {
		        if (seed === undefined) {
		            // kept random number same size as time used previously to ensure no unexpected results downstream
		            seed = Math.floor(Math.random()*Math.pow(10,13));
		        }
		        /* Period parameters */
		        this.N = 624;
		        this.M = 397;
		        this.MATRIX_A = 0x9908b0df;   /* constant vector a */
		        this.UPPER_MASK = 0x80000000; /* most significant w-r bits */
		        this.LOWER_MASK = 0x7fffffff; /* least significant r bits */

		        this.mt = new Array(this.N); /* the array for the state vector */
		        this.mti = this.N + 1; /* mti==N + 1 means mt[N] is not initialized */

		        this.init_genrand(seed);
		    };

		    /* initializes mt[N] with a seed */
		    MersenneTwister.prototype.init_genrand = function (s) {
		        this.mt[0] = s >>> 0;
		        for (this.mti = 1; this.mti < this.N; this.mti++) {
		            s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30);
		            this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253) + this.mti;
		            /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
		            /* In the previous versions, MSBs of the seed affect   */
		            /* only MSBs of the array mt[].                        */
		            /* 2002/01/09 modified by Makoto Matsumoto             */
		            this.mt[this.mti] >>>= 0;
		            /* for >32 bit machines */
		        }
		    };

		    /* initialize by an array with array-length */
		    /* init_key is the array for initializing keys */
		    /* key_length is its length */
		    /* slight change for C++, 2004/2/26 */
		    MersenneTwister.prototype.init_by_array = function (init_key, key_length) {
		        var i = 1, j = 0, k, s;
		        this.init_genrand(19650218);
		        k = (this.N > key_length ? this.N : key_length);
		        for (; k; k--) {
		            s = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30);
		            this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1664525) << 16) + ((s & 0x0000ffff) * 1664525))) + init_key[j] + j; /* non linear */
		            this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */
		            i++;
		            j++;
		            if (i >= this.N) { this.mt[0] = this.mt[this.N - 1]; i = 1; }
		            if (j >= key_length) { j = 0; }
		        }
		        for (k = this.N - 1; k; k--) {
		            s = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30);
		            this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1566083941) << 16) + (s & 0x0000ffff) * 1566083941)) - i; /* non linear */
		            this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */
		            i++;
		            if (i >= this.N) { this.mt[0] = this.mt[this.N - 1]; i = 1; }
		        }

		        this.mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */
		    };

		    /* generates a random number on [0,0xffffffff]-interval */
		    MersenneTwister.prototype.genrand_int32 = function () {
		        var y;
		        var mag01 = new Array(0x0, this.MATRIX_A);
		        /* mag01[x] = x * MATRIX_A  for x=0,1 */

		        if (this.mti >= this.N) { /* generate N words at one time */
		            var kk;

		            if (this.mti === this.N + 1) {   /* if init_genrand() has not been called, */
		                this.init_genrand(5489); /* a default initial seed is used */
		            }
		            for (kk = 0; kk < this.N - this.M; kk++) {
		                y = (this.mt[kk]&this.UPPER_MASK)|(this.mt[kk + 1]&this.LOWER_MASK);
		                this.mt[kk] = this.mt[kk + this.M] ^ (y >>> 1) ^ mag01[y & 0x1];
		            }
		            for (;kk < this.N - 1; kk++) {
		                y = (this.mt[kk]&this.UPPER_MASK)|(this.mt[kk + 1]&this.LOWER_MASK);
		                this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ (y >>> 1) ^ mag01[y & 0x1];
		            }
		            y = (this.mt[this.N - 1]&this.UPPER_MASK)|(this.mt[0]&this.LOWER_MASK);
		            this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1];

		            this.mti = 0;
		        }

		        y = this.mt[this.mti++];

		        /* Tempering */
		        y ^= (y >>> 11);
		        y ^= (y << 7) & 0x9d2c5680;
		        y ^= (y << 15) & 0xefc60000;
		        y ^= (y >>> 18);

		        return y >>> 0;
		    };

		    /* generates a random number on [0,0x7fffffff]-interval */
		    MersenneTwister.prototype.genrand_int31 = function () {
		        return (this.genrand_int32() >>> 1);
		    };

		    /* generates a random number on [0,1]-real-interval */
		    MersenneTwister.prototype.genrand_real1 = function () {
		        return this.genrand_int32() * (1.0 / 4294967295.0);
		        /* divided by 2^32-1 */
		    };

		    /* generates a random number on [0,1)-real-interval */
		    MersenneTwister.prototype.random = function () {
		        return this.genrand_int32() * (1.0 / 4294967296.0);
		        /* divided by 2^32 */
		    };

		    /* generates a random number on (0,1)-real-interval */
		    MersenneTwister.prototype.genrand_real3 = function () {
		        return (this.genrand_int32() + 0.5) * (1.0 / 4294967296.0);
		        /* divided by 2^32 */
		    };

		    /* generates a random number on [0,1) with 53-bit resolution*/
		    MersenneTwister.prototype.genrand_res53 = function () {
		        var a = this.genrand_int32()>>>5, b = this.genrand_int32()>>>6;
		        return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
		    };

		    // BlueImp MD5 hashing algorithm from https://github.com/blueimp/JavaScript-MD5
		    var BlueImpMD5 = function () {};

		    BlueImpMD5.prototype.VERSION = '1.0.1';

		    /*
		    * Add integers, wrapping at 2^32. This uses 16-bit operations internally
		    * to work around bugs in some JS interpreters.
		    */
		    BlueImpMD5.prototype.safe_add = function safe_add(x, y) {
		        var lsw = (x & 0xFFFF) + (y & 0xFFFF),
		            msw = (x >> 16) + (y >> 16) + (lsw >> 16);
		        return (msw << 16) | (lsw & 0xFFFF);
		    };

		    /*
		    * Bitwise rotate a 32-bit number to the left.
		    */
		    BlueImpMD5.prototype.bit_roll = function (num, cnt) {
		        return (num << cnt) | (num >>> (32 - cnt));
		    };

		    /*
		    * These functions implement the five basic operations the algorithm uses.
		    */
		    BlueImpMD5.prototype.md5_cmn = function (q, a, b, x, s, t) {
		        return this.safe_add(this.bit_roll(this.safe_add(this.safe_add(a, q), this.safe_add(x, t)), s), b);
		    };
		    BlueImpMD5.prototype.md5_ff = function (a, b, c, d, x, s, t) {
		        return this.md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
		    };
		    BlueImpMD5.prototype.md5_gg = function (a, b, c, d, x, s, t) {
		        return this.md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
		    };
		    BlueImpMD5.prototype.md5_hh = function (a, b, c, d, x, s, t) {
		        return this.md5_cmn(b ^ c ^ d, a, b, x, s, t);
		    };
		    BlueImpMD5.prototype.md5_ii = function (a, b, c, d, x, s, t) {
		        return this.md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
		    };

		    /*
		    * Calculate the MD5 of an array of little-endian words, and a bit length.
		    */
		    BlueImpMD5.prototype.binl_md5 = function (x, len) {
		        /* append padding */
		        x[len >> 5] |= 0x80 << (len % 32);
		        x[(((len + 64) >>> 9) << 4) + 14] = len;

		        var i, olda, oldb, oldc, oldd,
		            a =  1732584193,
		            b = -271733879,
		            c = -1732584194,
		            d =  271733878;

		        for (i = 0; i < x.length; i += 16) {
		            olda = a;
		            oldb = b;
		            oldc = c;
		            oldd = d;

		            a = this.md5_ff(a, b, c, d, x[i],       7, -680876936);
		            d = this.md5_ff(d, a, b, c, x[i +  1], 12, -389564586);
		            c = this.md5_ff(c, d, a, b, x[i +  2], 17,  606105819);
		            b = this.md5_ff(b, c, d, a, x[i +  3], 22, -1044525330);
		            a = this.md5_ff(a, b, c, d, x[i +  4],  7, -176418897);
		            d = this.md5_ff(d, a, b, c, x[i +  5], 12,  1200080426);
		            c = this.md5_ff(c, d, a, b, x[i +  6], 17, -1473231341);
		            b = this.md5_ff(b, c, d, a, x[i +  7], 22, -45705983);
		            a = this.md5_ff(a, b, c, d, x[i +  8],  7,  1770035416);
		            d = this.md5_ff(d, a, b, c, x[i +  9], 12, -1958414417);
		            c = this.md5_ff(c, d, a, b, x[i + 10], 17, -42063);
		            b = this.md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
		            a = this.md5_ff(a, b, c, d, x[i + 12],  7,  1804603682);
		            d = this.md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
		            c = this.md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
		            b = this.md5_ff(b, c, d, a, x[i + 15], 22,  1236535329);

		            a = this.md5_gg(a, b, c, d, x[i +  1],  5, -165796510);
		            d = this.md5_gg(d, a, b, c, x[i +  6],  9, -1069501632);
		            c = this.md5_gg(c, d, a, b, x[i + 11], 14,  643717713);
		            b = this.md5_gg(b, c, d, a, x[i],      20, -373897302);
		            a = this.md5_gg(a, b, c, d, x[i +  5],  5, -701558691);
		            d = this.md5_gg(d, a, b, c, x[i + 10],  9,  38016083);
		            c = this.md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
		            b = this.md5_gg(b, c, d, a, x[i +  4], 20, -405537848);
		            a = this.md5_gg(a, b, c, d, x[i +  9],  5,  568446438);
		            d = this.md5_gg(d, a, b, c, x[i + 14],  9, -1019803690);
		            c = this.md5_gg(c, d, a, b, x[i +  3], 14, -187363961);
		            b = this.md5_gg(b, c, d, a, x[i +  8], 20,  1163531501);
		            a = this.md5_gg(a, b, c, d, x[i + 13],  5, -1444681467);
		            d = this.md5_gg(d, a, b, c, x[i +  2],  9, -51403784);
		            c = this.md5_gg(c, d, a, b, x[i +  7], 14,  1735328473);
		            b = this.md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);

		            a = this.md5_hh(a, b, c, d, x[i +  5],  4, -378558);
		            d = this.md5_hh(d, a, b, c, x[i +  8], 11, -2022574463);
		            c = this.md5_hh(c, d, a, b, x[i + 11], 16,  1839030562);
		            b = this.md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
		            a = this.md5_hh(a, b, c, d, x[i +  1],  4, -1530992060);
		            d = this.md5_hh(d, a, b, c, x[i +  4], 11,  1272893353);
		            c = this.md5_hh(c, d, a, b, x[i +  7], 16, -155497632);
		            b = this.md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
		            a = this.md5_hh(a, b, c, d, x[i + 13],  4,  681279174);
		            d = this.md5_hh(d, a, b, c, x[i],      11, -358537222);
		            c = this.md5_hh(c, d, a, b, x[i +  3], 16, -722521979);
		            b = this.md5_hh(b, c, d, a, x[i +  6], 23,  76029189);
		            a = this.md5_hh(a, b, c, d, x[i +  9],  4, -640364487);
		            d = this.md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
		            c = this.md5_hh(c, d, a, b, x[i + 15], 16,  530742520);
		            b = this.md5_hh(b, c, d, a, x[i +  2], 23, -995338651);

		            a = this.md5_ii(a, b, c, d, x[i],       6, -198630844);
		            d = this.md5_ii(d, a, b, c, x[i +  7], 10,  1126891415);
		            c = this.md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
		            b = this.md5_ii(b, c, d, a, x[i +  5], 21, -57434055);
		            a = this.md5_ii(a, b, c, d, x[i + 12],  6,  1700485571);
		            d = this.md5_ii(d, a, b, c, x[i +  3], 10, -1894986606);
		            c = this.md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
		            b = this.md5_ii(b, c, d, a, x[i +  1], 21, -2054922799);
		            a = this.md5_ii(a, b, c, d, x[i +  8],  6,  1873313359);
		            d = this.md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
		            c = this.md5_ii(c, d, a, b, x[i +  6], 15, -1560198380);
		            b = this.md5_ii(b, c, d, a, x[i + 13], 21,  1309151649);
		            a = this.md5_ii(a, b, c, d, x[i +  4],  6, -145523070);
		            d = this.md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
		            c = this.md5_ii(c, d, a, b, x[i +  2], 15,  718787259);
		            b = this.md5_ii(b, c, d, a, x[i +  9], 21, -343485551);

		            a = this.safe_add(a, olda);
		            b = this.safe_add(b, oldb);
		            c = this.safe_add(c, oldc);
		            d = this.safe_add(d, oldd);
		        }
		        return [a, b, c, d];
		    };

		    /*
		    * Convert an array of little-endian words to a string
		    */
		    BlueImpMD5.prototype.binl2rstr = function (input) {
		        var i,
		            output = '';
		        for (i = 0; i < input.length * 32; i += 8) {
		            output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
		        }
		        return output;
		    };

		    /*
		    * Convert a raw string to an array of little-endian words
		    * Characters >255 have their high-byte silently ignored.
		    */
		    BlueImpMD5.prototype.rstr2binl = function (input) {
		        var i,
		            output = [];
		        output[(input.length >> 2) - 1] = undefined;
		        for (i = 0; i < output.length; i += 1) {
		            output[i] = 0;
		        }
		        for (i = 0; i < input.length * 8; i += 8) {
		            output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
		        }
		        return output;
		    };

		    /*
		    * Calculate the MD5 of a raw string
		    */
		    BlueImpMD5.prototype.rstr_md5 = function (s) {
		        return this.binl2rstr(this.binl_md5(this.rstr2binl(s), s.length * 8));
		    };

		    /*
		    * Calculate the HMAC-MD5, of a key and some data (raw strings)
		    */
		    BlueImpMD5.prototype.rstr_hmac_md5 = function (key, data) {
		        var i,
		            bkey = this.rstr2binl(key),
		            ipad = [],
		            opad = [],
		            hash;
		        ipad[15] = opad[15] = undefined;
		        if (bkey.length > 16) {
		            bkey = this.binl_md5(bkey, key.length * 8);
		        }
		        for (i = 0; i < 16; i += 1) {
		            ipad[i] = bkey[i] ^ 0x36363636;
		            opad[i] = bkey[i] ^ 0x5C5C5C5C;
		        }
		        hash = this.binl_md5(ipad.concat(this.rstr2binl(data)), 512 + data.length * 8);
		        return this.binl2rstr(this.binl_md5(opad.concat(hash), 512 + 128));
		    };

		    /*
		    * Convert a raw string to a hex string
		    */
		    BlueImpMD5.prototype.rstr2hex = function (input) {
		        var hex_tab = '0123456789abcdef',
		            output = '',
		            x,
		            i;
		        for (i = 0; i < input.length; i += 1) {
		            x = input.charCodeAt(i);
		            output += hex_tab.charAt((x >>> 4) & 0x0F) +
		                hex_tab.charAt(x & 0x0F);
		        }
		        return output;
		    };

		    /*
		    * Encode a string as utf-8
		    */
		    BlueImpMD5.prototype.str2rstr_utf8 = function (input) {
		        return unescape(encodeURIComponent(input));
		    };

		    /*
		    * Take string arguments and return either raw or hex encoded strings
		    */
		    BlueImpMD5.prototype.raw_md5 = function (s) {
		        return this.rstr_md5(this.str2rstr_utf8(s));
		    };
		    BlueImpMD5.prototype.hex_md5 = function (s) {
		        return this.rstr2hex(this.raw_md5(s));
		    };
		    BlueImpMD5.prototype.raw_hmac_md5 = function (k, d) {
		        return this.rstr_hmac_md5(this.str2rstr_utf8(k), this.str2rstr_utf8(d));
		    };
		    BlueImpMD5.prototype.hex_hmac_md5 = function (k, d) {
		        return this.rstr2hex(this.raw_hmac_md5(k, d));
		    };

		    BlueImpMD5.prototype.md5 = function (string, key, raw) {
		        if (!key) {
		            if (!raw) {
		                return this.hex_md5(string);
		            }

		            return this.raw_md5(string);
		        }

		        if (!raw) {
		            return this.hex_hmac_md5(key, string);
		        }

		        return this.raw_hmac_md5(key, string);
		    };

		    // CommonJS module
		    {
		        if (module.exports) {
		            exports = module.exports = Chance;
		        }
		        exports.Chance = Chance;
		    }

		    // if there is a importsScrips object define chance for worker
		    // allows worker to use full Chance functionality with seed
		    if (typeof importScripts !== 'undefined') {
		        chance = new Chance();
		        self.Chance = Chance;
		    }

		    // If there is a window object, that at least has a document property,
		    // instantiate and define chance on the window
		    if (typeof window === "object" && typeof window.document === "object") {
		        window.Chance = Chance;
		        window.chance = new Chance();
		    }
		})(); 
	} (chance$1, chance$1.exports));
	return chance$1.exports;
}

var chanceExports = requireChance();

var build$1 = {};

var ansiStyles = {exports: {}};

ansiStyles.exports;

var hasRequiredAnsiStyles;

function requireAnsiStyles () {
	if (hasRequiredAnsiStyles) return ansiStyles.exports;
	hasRequiredAnsiStyles = 1;
	(function (module) {

		const ANSI_BACKGROUND_OFFSET = 10;

		const wrapAnsi256 = (offset = 0) => code => `\u001B[${38 + offset};5;${code}m`;

		const wrapAnsi16m = (offset = 0) => (red, green, blue) => `\u001B[${38 + offset};2;${red};${green};${blue}m`;

		function assembleStyles() {
			const codes = new Map();
			const styles = {
				modifier: {
					reset: [0, 0],
					// 21 isn't widely supported and 22 does the same thing
					bold: [1, 22],
					dim: [2, 22],
					italic: [3, 23],
					underline: [4, 24],
					overline: [53, 55],
					inverse: [7, 27],
					hidden: [8, 28],
					strikethrough: [9, 29]
				},
				color: {
					black: [30, 39],
					red: [31, 39],
					green: [32, 39],
					yellow: [33, 39],
					blue: [34, 39],
					magenta: [35, 39],
					cyan: [36, 39],
					white: [37, 39],

					// Bright color
					blackBright: [90, 39],
					redBright: [91, 39],
					greenBright: [92, 39],
					yellowBright: [93, 39],
					blueBright: [94, 39],
					magentaBright: [95, 39],
					cyanBright: [96, 39],
					whiteBright: [97, 39]
				},
				bgColor: {
					bgBlack: [40, 49],
					bgRed: [41, 49],
					bgGreen: [42, 49],
					bgYellow: [43, 49],
					bgBlue: [44, 49],
					bgMagenta: [45, 49],
					bgCyan: [46, 49],
					bgWhite: [47, 49],

					// Bright color
					bgBlackBright: [100, 49],
					bgRedBright: [101, 49],
					bgGreenBright: [102, 49],
					bgYellowBright: [103, 49],
					bgBlueBright: [104, 49],
					bgMagentaBright: [105, 49],
					bgCyanBright: [106, 49],
					bgWhiteBright: [107, 49]
				}
			};

			// Alias bright black as gray (and grey)
			styles.color.gray = styles.color.blackBright;
			styles.bgColor.bgGray = styles.bgColor.bgBlackBright;
			styles.color.grey = styles.color.blackBright;
			styles.bgColor.bgGrey = styles.bgColor.bgBlackBright;

			for (const [groupName, group] of Object.entries(styles)) {
				for (const [styleName, style] of Object.entries(group)) {
					styles[styleName] = {
						open: `\u001B[${style[0]}m`,
						close: `\u001B[${style[1]}m`
					};

					group[styleName] = styles[styleName];

					codes.set(style[0], style[1]);
				}

				Object.defineProperty(styles, groupName, {
					value: group,
					enumerable: false
				});
			}

			Object.defineProperty(styles, 'codes', {
				value: codes,
				enumerable: false
			});

			styles.color.close = '\u001B[39m';
			styles.bgColor.close = '\u001B[49m';

			styles.color.ansi256 = wrapAnsi256();
			styles.color.ansi16m = wrapAnsi16m();
			styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
			styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);

			// From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js
			Object.defineProperties(styles, {
				rgbToAnsi256: {
					value: (red, green, blue) => {
						// We use the extended greyscale palette here, with the exception of
						// black and white. normal palette only has 4 greyscale shades.
						if (red === green && green === blue) {
							if (red < 8) {
								return 16;
							}

							if (red > 248) {
								return 231;
							}

							return Math.round(((red - 8) / 247) * 24) + 232;
						}

						return 16 +
							(36 * Math.round(red / 255 * 5)) +
							(6 * Math.round(green / 255 * 5)) +
							Math.round(blue / 255 * 5);
					},
					enumerable: false
				},
				hexToRgb: {
					value: hex => {
						const matches = /(?<colorString>[a-f\d]{6}|[a-f\d]{3})/i.exec(hex.toString(16));
						if (!matches) {
							return [0, 0, 0];
						}

						let {colorString} = matches.groups;

						if (colorString.length === 3) {
							colorString = colorString.split('').map(character => character + character).join('');
						}

						const integer = Number.parseInt(colorString, 16);

						return [
							(integer >> 16) & 0xFF,
							(integer >> 8) & 0xFF,
							integer & 0xFF
						];
					},
					enumerable: false
				},
				hexToAnsi256: {
					value: hex => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
					enumerable: false
				}
			});

			return styles;
		}

		// Make the export immutable
		Object.defineProperty(module, 'exports', {
			enumerable: true,
			get: assembleStyles
		}); 
	} (ansiStyles));
	return ansiStyles.exports;
}

var collections = {};

var hasRequiredCollections;

function requireCollections () {
	if (hasRequiredCollections) return collections;
	hasRequiredCollections = 1;

	Object.defineProperty(collections, '__esModule', {
	  value: true
	});
	collections.printIteratorEntries = printIteratorEntries;
	collections.printIteratorValues = printIteratorValues;
	collections.printListItems = printListItems;
	collections.printObjectProperties = printObjectProperties;

	/**
	 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 *
	 */
	const getKeysOfEnumerableProperties = (object, compareKeys) => {
	  const keys = Object.keys(object).sort(compareKeys);

	  if (Object.getOwnPropertySymbols) {
	    Object.getOwnPropertySymbols(object).forEach(symbol => {
	      if (Object.getOwnPropertyDescriptor(object, symbol).enumerable) {
	        keys.push(symbol);
	      }
	    });
	  }

	  return keys;
	};
	/**
	 * Return entries (for example, of a map)
	 * with spacing, indentation, and comma
	 * without surrounding punctuation (for example, braces)
	 */

	function printIteratorEntries(
	  iterator,
	  config,
	  indentation,
	  depth,
	  refs,
	  printer, // Too bad, so sad that separator for ECMAScript Map has been ' => '
	  // What a distracting diff if you change a data structure to/from
	  // ECMAScript Object or Immutable.Map/OrderedMap which use the default.
	  separator = ': '
	) {
	  let result = '';
	  let current = iterator.next();

	  if (!current.done) {
	    result += config.spacingOuter;
	    const indentationNext = indentation + config.indent;

	    while (!current.done) {
	      const name = printer(
	        current.value[0],
	        config,
	        indentationNext,
	        depth,
	        refs
	      );
	      const value = printer(
	        current.value[1],
	        config,
	        indentationNext,
	        depth,
	        refs
	      );
	      result += indentationNext + name + separator + value;
	      current = iterator.next();

	      if (!current.done) {
	        result += ',' + config.spacingInner;
	      } else if (!config.min) {
	        result += ',';
	      }
	    }

	    result += config.spacingOuter + indentation;
	  }

	  return result;
	}
	/**
	 * Return values (for example, of a set)
	 * with spacing, indentation, and comma
	 * without surrounding punctuation (braces or brackets)
	 */

	function printIteratorValues(
	  iterator,
	  config,
	  indentation,
	  depth,
	  refs,
	  printer
	) {
	  let result = '';
	  let current = iterator.next();

	  if (!current.done) {
	    result += config.spacingOuter;
	    const indentationNext = indentation + config.indent;

	    while (!current.done) {
	      result +=
	        indentationNext +
	        printer(current.value, config, indentationNext, depth, refs);
	      current = iterator.next();

	      if (!current.done) {
	        result += ',' + config.spacingInner;
	      } else if (!config.min) {
	        result += ',';
	      }
	    }

	    result += config.spacingOuter + indentation;
	  }

	  return result;
	}
	/**
	 * Return items (for example, of an array)
	 * with spacing, indentation, and comma
	 * without surrounding punctuation (for example, brackets)
	 **/

	function printListItems(list, config, indentation, depth, refs, printer) {
	  let result = '';

	  if (list.length) {
	    result += config.spacingOuter;
	    const indentationNext = indentation + config.indent;

	    for (let i = 0; i < list.length; i++) {
	      result += indentationNext;

	      if (i in list) {
	        result += printer(list[i], config, indentationNext, depth, refs);
	      }

	      if (i < list.length - 1) {
	        result += ',' + config.spacingInner;
	      } else if (!config.min) {
	        result += ',';
	      }
	    }

	    result += config.spacingOuter + indentation;
	  }

	  return result;
	}
	/**
	 * Return properties of an object
	 * with spacing, indentation, and comma
	 * without surrounding punctuation (for example, braces)
	 */

	function printObjectProperties(val, config, indentation, depth, refs, printer) {
	  let result = '';
	  const keys = getKeysOfEnumerableProperties(val, config.compareKeys);

	  if (keys.length) {
	    result += config.spacingOuter;
	    const indentationNext = indentation + config.indent;

	    for (let i = 0; i < keys.length; i++) {
	      const key = keys[i];
	      const name = printer(key, config, indentationNext, depth, refs);
	      const value = printer(val[key], config, indentationNext, depth, refs);
	      result += indentationNext + name + ': ' + value;

	      if (i < keys.length - 1) {
	        result += ',' + config.spacingInner;
	      } else if (!config.min) {
	        result += ',';
	      }
	    }

	    result += config.spacingOuter + indentation;
	  }

	  return result;
	}
	return collections;
}

var AsymmetricMatcher = {};

var hasRequiredAsymmetricMatcher;

function requireAsymmetricMatcher () {
	if (hasRequiredAsymmetricMatcher) return AsymmetricMatcher;
	hasRequiredAsymmetricMatcher = 1;

	Object.defineProperty(AsymmetricMatcher, '__esModule', {
	  value: true
	});
	AsymmetricMatcher.test = AsymmetricMatcher.serialize = AsymmetricMatcher.default = undefined;

	var _collections = requireCollections();

	var global = (function () {
	  if (typeof globalThis !== 'undefined') {
	    return globalThis;
	  } else if (typeof global !== 'undefined') {
	    return global;
	  } else if (typeof self !== 'undefined') {
	    return self;
	  } else if (typeof window !== 'undefined') {
	    return window;
	  } else {
	    return Function('return this')();
	  }
	})();

	var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
	const asymmetricMatcher =
	  typeof Symbol === 'function' && Symbol.for
	    ? Symbol.for('jest.asymmetricMatcher')
	    : 0x1357a5;
	const SPACE = ' ';

	const serialize = (val, config, indentation, depth, refs, printer) => {
	  const stringedValue = val.toString();

	  if (
	    stringedValue === 'ArrayContaining' ||
	    stringedValue === 'ArrayNotContaining'
	  ) {
	    if (++depth > config.maxDepth) {
	      return '[' + stringedValue + ']';
	    }

	    return (
	      stringedValue +
	      SPACE +
	      '[' +
	      (0, _collections.printListItems)(
	        val.sample,
	        config,
	        indentation,
	        depth,
	        refs,
	        printer
	      ) +
	      ']'
	    );
	  }

	  if (
	    stringedValue === 'ObjectContaining' ||
	    stringedValue === 'ObjectNotContaining'
	  ) {
	    if (++depth > config.maxDepth) {
	      return '[' + stringedValue + ']';
	    }

	    return (
	      stringedValue +
	      SPACE +
	      '{' +
	      (0, _collections.printObjectProperties)(
	        val.sample,
	        config,
	        indentation,
	        depth,
	        refs,
	        printer
	      ) +
	      '}'
	    );
	  }

	  if (
	    stringedValue === 'StringMatching' ||
	    stringedValue === 'StringNotMatching'
	  ) {
	    return (
	      stringedValue +
	      SPACE +
	      printer(val.sample, config, indentation, depth, refs)
	    );
	  }

	  if (
	    stringedValue === 'StringContaining' ||
	    stringedValue === 'StringNotContaining'
	  ) {
	    return (
	      stringedValue +
	      SPACE +
	      printer(val.sample, config, indentation, depth, refs)
	    );
	  }

	  return val.toAsymmetricMatcher();
	};

	AsymmetricMatcher.serialize = serialize;

	const test = val => val && val.$$typeof === asymmetricMatcher;

	AsymmetricMatcher.test = test;
	const plugin = {
	  serialize,
	  test
	};
	var _default = plugin;
	AsymmetricMatcher.default = _default;
	return AsymmetricMatcher;
}

var ConvertAnsi = {};

var ansiRegex;
var hasRequiredAnsiRegex;

function requireAnsiRegex () {
	if (hasRequiredAnsiRegex) return ansiRegex;
	hasRequiredAnsiRegex = 1;

	ansiRegex = ({onlyFirst = false} = {}) => {
		const pattern = [
			'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
			'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
		].join('|');

		return new RegExp(pattern, onlyFirst ? undefined : 'g');
	};
	return ansiRegex;
}

var hasRequiredConvertAnsi;

function requireConvertAnsi () {
	if (hasRequiredConvertAnsi) return ConvertAnsi;
	hasRequiredConvertAnsi = 1;

	Object.defineProperty(ConvertAnsi, '__esModule', {
	  value: true
	});
	ConvertAnsi.test = ConvertAnsi.serialize = ConvertAnsi.default = undefined;

	var _ansiRegex = _interopRequireDefault(requireAnsiRegex());

	var _ansiStyles = _interopRequireDefault(requireAnsiStyles());

	function _interopRequireDefault(obj) {
	  return obj && obj.__esModule ? obj : {default: obj};
	}

	/**
	 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */
	const toHumanReadableAnsi = text =>
	  text.replace((0, _ansiRegex.default)(), match => {
	    switch (match) {
	      case _ansiStyles.default.red.close:
	      case _ansiStyles.default.green.close:
	      case _ansiStyles.default.cyan.close:
	      case _ansiStyles.default.gray.close:
	      case _ansiStyles.default.white.close:
	      case _ansiStyles.default.yellow.close:
	      case _ansiStyles.default.bgRed.close:
	      case _ansiStyles.default.bgGreen.close:
	      case _ansiStyles.default.bgYellow.close:
	      case _ansiStyles.default.inverse.close:
	      case _ansiStyles.default.dim.close:
	      case _ansiStyles.default.bold.close:
	      case _ansiStyles.default.reset.open:
	      case _ansiStyles.default.reset.close:
	        return '</>';

	      case _ansiStyles.default.red.open:
	        return '<red>';

	      case _ansiStyles.default.green.open:
	        return '<green>';

	      case _ansiStyles.default.cyan.open:
	        return '<cyan>';

	      case _ansiStyles.default.gray.open:
	        return '<gray>';

	      case _ansiStyles.default.white.open:
	        return '<white>';

	      case _ansiStyles.default.yellow.open:
	        return '<yellow>';

	      case _ansiStyles.default.bgRed.open:
	        return '<bgRed>';

	      case _ansiStyles.default.bgGreen.open:
	        return '<bgGreen>';

	      case _ansiStyles.default.bgYellow.open:
	        return '<bgYellow>';

	      case _ansiStyles.default.inverse.open:
	        return '<inverse>';

	      case _ansiStyles.default.dim.open:
	        return '<dim>';

	      case _ansiStyles.default.bold.open:
	        return '<bold>';

	      default:
	        return '';
	    }
	  });

	const test = val =>
	  typeof val === 'string' && !!val.match((0, _ansiRegex.default)());

	ConvertAnsi.test = test;

	const serialize = (val, config, indentation, depth, refs, printer) =>
	  printer(toHumanReadableAnsi(val), config, indentation, depth, refs);

	ConvertAnsi.serialize = serialize;
	const plugin = {
	  serialize,
	  test
	};
	var _default = plugin;
	ConvertAnsi.default = _default;
	return ConvertAnsi;
}

var DOMCollection$1 = {};

var hasRequiredDOMCollection;

function requireDOMCollection () {
	if (hasRequiredDOMCollection) return DOMCollection$1;
	hasRequiredDOMCollection = 1;

	Object.defineProperty(DOMCollection$1, '__esModule', {
	  value: true
	});
	DOMCollection$1.test = DOMCollection$1.serialize = DOMCollection$1.default = undefined;

	var _collections = requireCollections();

	/**
	 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */

	/* eslint-disable local/ban-types-eventually */
	const SPACE = ' ';
	const OBJECT_NAMES = ['DOMStringMap', 'NamedNodeMap'];
	const ARRAY_REGEXP = /^(HTML\w*Collection|NodeList)$/;

	const testName = name =>
	  OBJECT_NAMES.indexOf(name) !== -1 || ARRAY_REGEXP.test(name);

	const test = val =>
	  val &&
	  val.constructor &&
	  !!val.constructor.name &&
	  testName(val.constructor.name);

	DOMCollection$1.test = test;

	const isNamedNodeMap = collection =>
	  collection.constructor.name === 'NamedNodeMap';

	const serialize = (collection, config, indentation, depth, refs, printer) => {
	  const name = collection.constructor.name;

	  if (++depth > config.maxDepth) {
	    return '[' + name + ']';
	  }

	  return (
	    (config.min ? '' : name + SPACE) +
	    (OBJECT_NAMES.indexOf(name) !== -1
	      ? '{' +
	        (0, _collections.printObjectProperties)(
	          isNamedNodeMap(collection)
	            ? Array.from(collection).reduce((props, attribute) => {
	                props[attribute.name] = attribute.value;
	                return props;
	              }, {})
	            : {...collection},
	          config,
	          indentation,
	          depth,
	          refs,
	          printer
	        ) +
	        '}'
	      : '[' +
	        (0, _collections.printListItems)(
	          Array.from(collection),
	          config,
	          indentation,
	          depth,
	          refs,
	          printer
	        ) +
	        ']')
	  );
	};

	DOMCollection$1.serialize = serialize;
	const plugin = {
	  serialize,
	  test
	};
	var _default = plugin;
	DOMCollection$1.default = _default;
	return DOMCollection$1;
}

var DOMElement = {};

var markup = {};

var escapeHTML$1 = {};

var hasRequiredEscapeHTML;

function requireEscapeHTML () {
	if (hasRequiredEscapeHTML) return escapeHTML$1;
	hasRequiredEscapeHTML = 1;

	Object.defineProperty(escapeHTML$1, '__esModule', {
	  value: true
	});
	escapeHTML$1.default = escapeHTML;

	/**
	 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */
	function escapeHTML(str) {
	  return str.replace(/</g, '&lt;').replace(/>/g, '&gt;');
	}
	return escapeHTML$1;
}

var hasRequiredMarkup;

function requireMarkup () {
	if (hasRequiredMarkup) return markup;
	hasRequiredMarkup = 1;

	Object.defineProperty(markup, '__esModule', {
	  value: true
	});
	markup.printText =
	  markup.printProps =
	  markup.printElementAsLeaf =
	  markup.printElement =
	  markup.printComment =
	  markup.printChildren =
	    undefined;

	var _escapeHTML = _interopRequireDefault(requireEscapeHTML());

	function _interopRequireDefault(obj) {
	  return obj && obj.__esModule ? obj : {default: obj};
	}

	/**
	 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */
	// Return empty string if keys is empty.
	const printProps = (keys, props, config, indentation, depth, refs, printer) => {
	  const indentationNext = indentation + config.indent;
	  const colors = config.colors;
	  return keys
	    .map(key => {
	      const value = props[key];
	      let printed = printer(value, config, indentationNext, depth, refs);

	      if (typeof value !== 'string') {
	        if (printed.indexOf('\n') !== -1) {
	          printed =
	            config.spacingOuter +
	            indentationNext +
	            printed +
	            config.spacingOuter +
	            indentation;
	        }

	        printed = '{' + printed + '}';
	      }

	      return (
	        config.spacingInner +
	        indentation +
	        colors.prop.open +
	        key +
	        colors.prop.close +
	        '=' +
	        colors.value.open +
	        printed +
	        colors.value.close
	      );
	    })
	    .join('');
	}; // Return empty string if children is empty.

	markup.printProps = printProps;

	const printChildren = (children, config, indentation, depth, refs, printer) =>
	  children
	    .map(
	      child =>
	        config.spacingOuter +
	        indentation +
	        (typeof child === 'string'
	          ? printText(child, config)
	          : printer(child, config, indentation, depth, refs))
	    )
	    .join('');

	markup.printChildren = printChildren;

	const printText = (text, config) => {
	  const contentColor = config.colors.content;
	  return (
	    contentColor.open + (0, _escapeHTML.default)(text) + contentColor.close
	  );
	};

	markup.printText = printText;

	const printComment = (comment, config) => {
	  const commentColor = config.colors.comment;
	  return (
	    commentColor.open +
	    '<!--' +
	    (0, _escapeHTML.default)(comment) +
	    '-->' +
	    commentColor.close
	  );
	}; // Separate the functions to format props, children, and element,
	// so a plugin could override a particular function, if needed.
	// Too bad, so sad: the traditional (but unnecessary) space
	// in a self-closing tagColor requires a second test of printedProps.

	markup.printComment = printComment;

	const printElement = (
	  type,
	  printedProps,
	  printedChildren,
	  config,
	  indentation
	) => {
	  const tagColor = config.colors.tag;
	  return (
	    tagColor.open +
	    '<' +
	    type +
	    (printedProps &&
	      tagColor.close +
	        printedProps +
	        config.spacingOuter +
	        indentation +
	        tagColor.open) +
	    (printedChildren
	      ? '>' +
	        tagColor.close +
	        printedChildren +
	        config.spacingOuter +
	        indentation +
	        tagColor.open +
	        '</' +
	        type
	      : (printedProps && !config.min ? '' : ' ') + '/') +
	    '>' +
	    tagColor.close
	  );
	};

	markup.printElement = printElement;

	const printElementAsLeaf = (type, config) => {
	  const tagColor = config.colors.tag;
	  return (
	    tagColor.open +
	    '<' +
	    type +
	    tagColor.close +
	    ' …' +
	    tagColor.open +
	    ' />' +
	    tagColor.close
	  );
	};

	markup.printElementAsLeaf = printElementAsLeaf;
	return markup;
}

var hasRequiredDOMElement;

function requireDOMElement () {
	if (hasRequiredDOMElement) return DOMElement;
	hasRequiredDOMElement = 1;

	Object.defineProperty(DOMElement, '__esModule', {
	  value: true
	});
	DOMElement.test = DOMElement.serialize = DOMElement.default = undefined;

	var _markup = requireMarkup();

	/**
	 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */
	const ELEMENT_NODE = 1;
	const TEXT_NODE = 3;
	const COMMENT_NODE = 8;
	const FRAGMENT_NODE = 11;
	const ELEMENT_REGEXP = /^((HTML|SVG)\w*)?Element$/;

	const testHasAttribute = val => {
	  try {
	    return typeof val.hasAttribute === 'function' && val.hasAttribute('is');
	  } catch {
	    return false;
	  }
	};

	const testNode = val => {
	  const constructorName = val.constructor.name;
	  const {nodeType, tagName} = val;
	  const isCustomElement =
	    (typeof tagName === 'string' && tagName.includes('-')) ||
	    testHasAttribute(val);
	  return (
	    (nodeType === ELEMENT_NODE &&
	      (ELEMENT_REGEXP.test(constructorName) || isCustomElement)) ||
	    (nodeType === TEXT_NODE && constructorName === 'Text') ||
	    (nodeType === COMMENT_NODE && constructorName === 'Comment') ||
	    (nodeType === FRAGMENT_NODE && constructorName === 'DocumentFragment')
	  );
	};

	const test = val => {
	  var _val$constructor;

	  return (
	    (val === null || val === undefined
	      ? undefined
	      : (_val$constructor = val.constructor) === null ||
	        _val$constructor === undefined
	      ? undefined
	      : _val$constructor.name) && testNode(val)
	  );
	};

	DOMElement.test = test;

	function nodeIsText(node) {
	  return node.nodeType === TEXT_NODE;
	}

	function nodeIsComment(node) {
	  return node.nodeType === COMMENT_NODE;
	}

	function nodeIsFragment(node) {
	  return node.nodeType === FRAGMENT_NODE;
	}

	const serialize = (node, config, indentation, depth, refs, printer) => {
	  if (nodeIsText(node)) {
	    return (0, _markup.printText)(node.data, config);
	  }

	  if (nodeIsComment(node)) {
	    return (0, _markup.printComment)(node.data, config);
	  }

	  const type = nodeIsFragment(node)
	    ? 'DocumentFragment'
	    : node.tagName.toLowerCase();

	  if (++depth > config.maxDepth) {
	    return (0, _markup.printElementAsLeaf)(type, config);
	  }

	  return (0, _markup.printElement)(
	    type,
	    (0, _markup.printProps)(
	      nodeIsFragment(node)
	        ? []
	        : Array.from(node.attributes)
	            .map(attr => attr.name)
	            .sort(),
	      nodeIsFragment(node)
	        ? {}
	        : Array.from(node.attributes).reduce((props, attribute) => {
	            props[attribute.name] = attribute.value;
	            return props;
	          }, {}),
	      config,
	      indentation + config.indent,
	      depth,
	      refs,
	      printer
	    ),
	    (0, _markup.printChildren)(
	      Array.prototype.slice.call(node.childNodes || node.children),
	      config,
	      indentation + config.indent,
	      depth,
	      refs,
	      printer
	    ),
	    config,
	    indentation
	  );
	};

	DOMElement.serialize = serialize;
	const plugin = {
	  serialize,
	  test
	};
	var _default = plugin;
	DOMElement.default = _default;
	return DOMElement;
}

var Immutable = {};

var hasRequiredImmutable;

function requireImmutable () {
	if (hasRequiredImmutable) return Immutable;
	hasRequiredImmutable = 1;

	Object.defineProperty(Immutable, '__esModule', {
	  value: true
	});
	Immutable.test = Immutable.serialize = Immutable.default = undefined;

	var _collections = requireCollections();

	/**
	 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */
	// SENTINEL constants are from https://github.com/facebook/immutable-js
	const IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@';
	const IS_LIST_SENTINEL = '@@__IMMUTABLE_LIST__@@';
	const IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@';
	const IS_MAP_SENTINEL = '@@__IMMUTABLE_MAP__@@';
	const IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@';
	const IS_RECORD_SENTINEL = '@@__IMMUTABLE_RECORD__@@'; // immutable v4

	const IS_SEQ_SENTINEL = '@@__IMMUTABLE_SEQ__@@';
	const IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@';
	const IS_STACK_SENTINEL = '@@__IMMUTABLE_STACK__@@';

	const getImmutableName = name => 'Immutable.' + name;

	const printAsLeaf = name => '[' + name + ']';

	const SPACE = ' ';
	const LAZY = '…'; // Seq is lazy if it calls a method like filter

	const printImmutableEntries = (
	  val,
	  config,
	  indentation,
	  depth,
	  refs,
	  printer,
	  type
	) =>
	  ++depth > config.maxDepth
	    ? printAsLeaf(getImmutableName(type))
	    : getImmutableName(type) +
	      SPACE +
	      '{' +
	      (0, _collections.printIteratorEntries)(
	        val.entries(),
	        config,
	        indentation,
	        depth,
	        refs,
	        printer
	      ) +
	      '}'; // Record has an entries method because it is a collection in immutable v3.
	// Return an iterator for Immutable Record from version v3 or v4.

	function getRecordEntries(val) {
	  let i = 0;
	  return {
	    next() {
	      if (i < val._keys.length) {
	        const key = val._keys[i++];
	        return {
	          done: false,
	          value: [key, val.get(key)]
	        };
	      }

	      return {
	        done: true,
	        value: undefined
	      };
	    }
	  };
	}

	const printImmutableRecord = (
	  val,
	  config,
	  indentation,
	  depth,
	  refs,
	  printer
	) => {
	  // _name property is defined only for an Immutable Record instance
	  // which was constructed with a second optional descriptive name arg
	  const name = getImmutableName(val._name || 'Record');
	  return ++depth > config.maxDepth
	    ? printAsLeaf(name)
	    : name +
	        SPACE +
	        '{' +
	        (0, _collections.printIteratorEntries)(
	          getRecordEntries(val),
	          config,
	          indentation,
	          depth,
	          refs,
	          printer
	        ) +
	        '}';
	};

	const printImmutableSeq = (val, config, indentation, depth, refs, printer) => {
	  const name = getImmutableName('Seq');

	  if (++depth > config.maxDepth) {
	    return printAsLeaf(name);
	  }

	  if (val[IS_KEYED_SENTINEL]) {
	    return (
	      name +
	      SPACE +
	      '{' + // from Immutable collection of entries or from ECMAScript object
	      (val._iter || val._object
	        ? (0, _collections.printIteratorEntries)(
	            val.entries(),
	            config,
	            indentation,
	            depth,
	            refs,
	            printer
	          )
	        : LAZY) +
	      '}'
	    );
	  }

	  return (
	    name +
	    SPACE +
	    '[' +
	    (val._iter || // from Immutable collection of values
	    val._array || // from ECMAScript array
	    val._collection || // from ECMAScript collection in immutable v4
	    val._iterable // from ECMAScript collection in immutable v3
	      ? (0, _collections.printIteratorValues)(
	          val.values(),
	          config,
	          indentation,
	          depth,
	          refs,
	          printer
	        )
	      : LAZY) +
	    ']'
	  );
	};

	const printImmutableValues = (
	  val,
	  config,
	  indentation,
	  depth,
	  refs,
	  printer,
	  type
	) =>
	  ++depth > config.maxDepth
	    ? printAsLeaf(getImmutableName(type))
	    : getImmutableName(type) +
	      SPACE +
	      '[' +
	      (0, _collections.printIteratorValues)(
	        val.values(),
	        config,
	        indentation,
	        depth,
	        refs,
	        printer
	      ) +
	      ']';

	const serialize = (val, config, indentation, depth, refs, printer) => {
	  if (val[IS_MAP_SENTINEL]) {
	    return printImmutableEntries(
	      val,
	      config,
	      indentation,
	      depth,
	      refs,
	      printer,
	      val[IS_ORDERED_SENTINEL] ? 'OrderedMap' : 'Map'
	    );
	  }

	  if (val[IS_LIST_SENTINEL]) {
	    return printImmutableValues(
	      val,
	      config,
	      indentation,
	      depth,
	      refs,
	      printer,
	      'List'
	    );
	  }

	  if (val[IS_SET_SENTINEL]) {
	    return printImmutableValues(
	      val,
	      config,
	      indentation,
	      depth,
	      refs,
	      printer,
	      val[IS_ORDERED_SENTINEL] ? 'OrderedSet' : 'Set'
	    );
	  }

	  if (val[IS_STACK_SENTINEL]) {
	    return printImmutableValues(
	      val,
	      config,
	      indentation,
	      depth,
	      refs,
	      printer,
	      'Stack'
	    );
	  }

	  if (val[IS_SEQ_SENTINEL]) {
	    return printImmutableSeq(val, config, indentation, depth, refs, printer);
	  } // For compatibility with immutable v3 and v4, let record be the default.

	  return printImmutableRecord(val, config, indentation, depth, refs, printer);
	}; // Explicitly comparing sentinel properties to true avoids false positive
	// when mock identity-obj-proxy returns the key as the value for any key.

	Immutable.serialize = serialize;

	const test = val =>
	  val &&
	  (val[IS_ITERABLE_SENTINEL] === true || val[IS_RECORD_SENTINEL] === true);

	Immutable.test = test;
	const plugin = {
	  serialize,
	  test
	};
	var _default = plugin;
	Immutable.default = _default;
	return Immutable;
}

var ReactElement = {};

var reactIs = {exports: {}};

var reactIs_production_min = {};

/** @license React v17.0.2
 * react-is.production.min.js
 *
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

var hasRequiredReactIs_production_min;

function requireReactIs_production_min () {
	if (hasRequiredReactIs_production_min) return reactIs_production_min;
	hasRequiredReactIs_production_min = 1;
var b=60103,c=60106,d=60107,e=60108,f=60114,g=60109,h=60110,k=60112,l=60113,m=60120,n=60115,p=60116,q=60121,r=60122,u=60117,v=60129,w=60131;
	if("function"===typeof Symbol&&Symbol.for){var x=Symbol.for;b=x("react.element");c=x("react.portal");d=x("react.fragment");e=x("react.strict_mode");f=x("react.profiler");g=x("react.provider");h=x("react.context");k=x("react.forward_ref");l=x("react.suspense");m=x("react.suspense_list");n=x("react.memo");p=x("react.lazy");q=x("react.block");r=x("react.server.block");u=x("react.fundamental");v=x("react.debug_trace_mode");w=x("react.legacy_hidden");}
	function y(a){if("object"===typeof a&&null!==a){var t=a.$$typeof;switch(t){case b:switch(a=a.type,a){case d:case f:case e:case l:case m:return a;default:switch(a=a&&a.$$typeof,a){case h:case k:case p:case n:case g:return a;default:return t}}case c:return t}}}var z=g,A=b,B=k,C=d,D=p,E=n,F=c,G=f,H=e,I=l;reactIs_production_min.ContextConsumer=h;reactIs_production_min.ContextProvider=z;reactIs_production_min.Element=A;reactIs_production_min.ForwardRef=B;reactIs_production_min.Fragment=C;reactIs_production_min.Lazy=D;reactIs_production_min.Memo=E;reactIs_production_min.Portal=F;reactIs_production_min.Profiler=G;reactIs_production_min.StrictMode=H;
	reactIs_production_min.Suspense=I;reactIs_production_min.isAsyncMode=function(){return  false};reactIs_production_min.isConcurrentMode=function(){return  false};reactIs_production_min.isContextConsumer=function(a){return y(a)===h};reactIs_production_min.isContextProvider=function(a){return y(a)===g};reactIs_production_min.isElement=function(a){return "object"===typeof a&&null!==a&&a.$$typeof===b};reactIs_production_min.isForwardRef=function(a){return y(a)===k};reactIs_production_min.isFragment=function(a){return y(a)===d};reactIs_production_min.isLazy=function(a){return y(a)===p};reactIs_production_min.isMemo=function(a){return y(a)===n};
	reactIs_production_min.isPortal=function(a){return y(a)===c};reactIs_production_min.isProfiler=function(a){return y(a)===f};reactIs_production_min.isStrictMode=function(a){return y(a)===e};reactIs_production_min.isSuspense=function(a){return y(a)===l};reactIs_production_min.isValidElementType=function(a){return "string"===typeof a||"function"===typeof a||a===d||a===f||a===v||a===e||a===l||a===m||a===w||"object"===typeof a&&null!==a&&(a.$$typeof===p||a.$$typeof===n||a.$$typeof===g||a.$$typeof===h||a.$$typeof===k||a.$$typeof===u||a.$$typeof===q||a[0]===r)?true:false};
	reactIs_production_min.typeOf=y;
	return reactIs_production_min;
}

var reactIs_development = {};

/** @license React v17.0.2
 * react-is.development.js
 *
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

var hasRequiredReactIs_development;

function requireReactIs_development () {
	if (hasRequiredReactIs_development) return reactIs_development;
	hasRequiredReactIs_development = 1;

	if (process.env.NODE_ENV !== "production") {
	  (function() {

	// ATTENTION
	// When adding new symbols to this file,
	// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
	// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
	// nor polyfill, then a plain number is used for performance.
	var REACT_ELEMENT_TYPE = 0xeac7;
	var REACT_PORTAL_TYPE = 0xeaca;
	var REACT_FRAGMENT_TYPE = 0xeacb;
	var REACT_STRICT_MODE_TYPE = 0xeacc;
	var REACT_PROFILER_TYPE = 0xead2;
	var REACT_PROVIDER_TYPE = 0xeacd;
	var REACT_CONTEXT_TYPE = 0xeace;
	var REACT_FORWARD_REF_TYPE = 0xead0;
	var REACT_SUSPENSE_TYPE = 0xead1;
	var REACT_SUSPENSE_LIST_TYPE = 0xead8;
	var REACT_MEMO_TYPE = 0xead3;
	var REACT_LAZY_TYPE = 0xead4;
	var REACT_BLOCK_TYPE = 0xead9;
	var REACT_SERVER_BLOCK_TYPE = 0xeada;
	var REACT_FUNDAMENTAL_TYPE = 0xead5;
	var REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1;
	var REACT_LEGACY_HIDDEN_TYPE = 0xeae3;

	if (typeof Symbol === 'function' && Symbol.for) {
	  var symbolFor = Symbol.for;
	  REACT_ELEMENT_TYPE = symbolFor('react.element');
	  REACT_PORTAL_TYPE = symbolFor('react.portal');
	  REACT_FRAGMENT_TYPE = symbolFor('react.fragment');
	  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');
	  REACT_PROFILER_TYPE = symbolFor('react.profiler');
	  REACT_PROVIDER_TYPE = symbolFor('react.provider');
	  REACT_CONTEXT_TYPE = symbolFor('react.context');
	  REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref');
	  REACT_SUSPENSE_TYPE = symbolFor('react.suspense');
	  REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list');
	  REACT_MEMO_TYPE = symbolFor('react.memo');
	  REACT_LAZY_TYPE = symbolFor('react.lazy');
	  REACT_BLOCK_TYPE = symbolFor('react.block');
	  REACT_SERVER_BLOCK_TYPE = symbolFor('react.server.block');
	  REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental');
	  symbolFor('react.scope');
	  symbolFor('react.opaque.id');
	  REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode');
	  symbolFor('react.offscreen');
	  REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden');
	}

	// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.

	var enableScopeAPI = false; // Experimental Create Event Handle API.

	function isValidElementType(type) {
	  if (typeof type === 'string' || typeof type === 'function') {
	    return true;
	  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).


	  if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || type === REACT_DEBUG_TRACING_MODE_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || enableScopeAPI ) {
	    return true;
	  }

	  if (typeof type === 'object' && type !== null) {
	    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) {
	      return true;
	    }
	  }

	  return false;
	}

	function typeOf(object) {
	  if (typeof object === 'object' && object !== null) {
	    var $$typeof = object.$$typeof;

	    switch ($$typeof) {
	      case REACT_ELEMENT_TYPE:
	        var type = object.type;

	        switch (type) {
	          case REACT_FRAGMENT_TYPE:
	          case REACT_PROFILER_TYPE:
	          case REACT_STRICT_MODE_TYPE:
	          case REACT_SUSPENSE_TYPE:
	          case REACT_SUSPENSE_LIST_TYPE:
	            return type;

	          default:
	            var $$typeofType = type && type.$$typeof;

	            switch ($$typeofType) {
	              case REACT_CONTEXT_TYPE:
	              case REACT_FORWARD_REF_TYPE:
	              case REACT_LAZY_TYPE:
	              case REACT_MEMO_TYPE:
	              case REACT_PROVIDER_TYPE:
	                return $$typeofType;

	              default:
	                return $$typeof;
	            }

	        }

	      case REACT_PORTAL_TYPE:
	        return $$typeof;
	    }
	  }

	  return undefined;
	}
	var ContextConsumer = REACT_CONTEXT_TYPE;
	var ContextProvider = REACT_PROVIDER_TYPE;
	var Element = REACT_ELEMENT_TYPE;
	var ForwardRef = REACT_FORWARD_REF_TYPE;
	var Fragment = REACT_FRAGMENT_TYPE;
	var Lazy = REACT_LAZY_TYPE;
	var Memo = REACT_MEMO_TYPE;
	var Portal = REACT_PORTAL_TYPE;
	var Profiler = REACT_PROFILER_TYPE;
	var StrictMode = REACT_STRICT_MODE_TYPE;
	var Suspense = REACT_SUSPENSE_TYPE;
	var hasWarnedAboutDeprecatedIsAsyncMode = false;
	var hasWarnedAboutDeprecatedIsConcurrentMode = false; // AsyncMode should be deprecated

	function isAsyncMode(object) {
	  {
	    if (!hasWarnedAboutDeprecatedIsAsyncMode) {
	      hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint

	      console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 18+.');
	    }
	  }

	  return false;
	}
	function isConcurrentMode(object) {
	  {
	    if (!hasWarnedAboutDeprecatedIsConcurrentMode) {
	      hasWarnedAboutDeprecatedIsConcurrentMode = true; // Using console['warn'] to evade Babel and ESLint

	      console['warn']('The ReactIs.isConcurrentMode() alias has been deprecated, ' + 'and will be removed in React 18+.');
	    }
	  }

	  return false;
	}
	function isContextConsumer(object) {
	  return typeOf(object) === REACT_CONTEXT_TYPE;
	}
	function isContextProvider(object) {
	  return typeOf(object) === REACT_PROVIDER_TYPE;
	}
	function isElement(object) {
	  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
	}
	function isForwardRef(object) {
	  return typeOf(object) === REACT_FORWARD_REF_TYPE;
	}
	function isFragment(object) {
	  return typeOf(object) === REACT_FRAGMENT_TYPE;
	}
	function isLazy(object) {
	  return typeOf(object) === REACT_LAZY_TYPE;
	}
	function isMemo(object) {
	  return typeOf(object) === REACT_MEMO_TYPE;
	}
	function isPortal(object) {
	  return typeOf(object) === REACT_PORTAL_TYPE;
	}
	function isProfiler(object) {
	  return typeOf(object) === REACT_PROFILER_TYPE;
	}
	function isStrictMode(object) {
	  return typeOf(object) === REACT_STRICT_MODE_TYPE;
	}
	function isSuspense(object) {
	  return typeOf(object) === REACT_SUSPENSE_TYPE;
	}

	reactIs_development.ContextConsumer = ContextConsumer;
	reactIs_development.ContextProvider = ContextProvider;
	reactIs_development.Element = Element;
	reactIs_development.ForwardRef = ForwardRef;
	reactIs_development.Fragment = Fragment;
	reactIs_development.Lazy = Lazy;
	reactIs_development.Memo = Memo;
	reactIs_development.Portal = Portal;
	reactIs_development.Profiler = Profiler;
	reactIs_development.StrictMode = StrictMode;
	reactIs_development.Suspense = Suspense;
	reactIs_development.isAsyncMode = isAsyncMode;
	reactIs_development.isConcurrentMode = isConcurrentMode;
	reactIs_development.isContextConsumer = isContextConsumer;
	reactIs_development.isContextProvider = isContextProvider;
	reactIs_development.isElement = isElement;
	reactIs_development.isForwardRef = isForwardRef;
	reactIs_development.isFragment = isFragment;
	reactIs_development.isLazy = isLazy;
	reactIs_development.isMemo = isMemo;
	reactIs_development.isPortal = isPortal;
	reactIs_development.isProfiler = isProfiler;
	reactIs_development.isStrictMode = isStrictMode;
	reactIs_development.isSuspense = isSuspense;
	reactIs_development.isValidElementType = isValidElementType;
	reactIs_development.typeOf = typeOf;
	  })();
	}
	return reactIs_development;
}

var hasRequiredReactIs;

function requireReactIs () {
	if (hasRequiredReactIs) return reactIs.exports;
	hasRequiredReactIs = 1;

	if (process.env.NODE_ENV === 'production') {
	  reactIs.exports = requireReactIs_production_min();
	} else {
	  reactIs.exports = requireReactIs_development();
	}
	return reactIs.exports;
}

var hasRequiredReactElement;

function requireReactElement () {
	if (hasRequiredReactElement) return ReactElement;
	hasRequiredReactElement = 1;

	Object.defineProperty(ReactElement, '__esModule', {
	  value: true
	});
	ReactElement.test = ReactElement.serialize = ReactElement.default = undefined;

	var ReactIs = _interopRequireWildcard(requireReactIs());

	var _markup = requireMarkup();

	function _getRequireWildcardCache(nodeInterop) {
	  if (typeof WeakMap !== 'function') return null;
	  var cacheBabelInterop = new WeakMap();
	  var cacheNodeInterop = new WeakMap();
	  return (_getRequireWildcardCache = function (nodeInterop) {
	    return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
	  })(nodeInterop);
	}

	function _interopRequireWildcard(obj, nodeInterop) {
	  if (obj && obj.__esModule) {
	    return obj;
	  }
	  if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
	    return {default: obj};
	  }
	  var cache = _getRequireWildcardCache(nodeInterop);
	  if (cache && cache.has(obj)) {
	    return cache.get(obj);
	  }
	  var newObj = {};
	  var hasPropertyDescriptor =
	    Object.defineProperty && Object.getOwnPropertyDescriptor;
	  for (var key in obj) {
	    if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
	      var desc = hasPropertyDescriptor
	        ? Object.getOwnPropertyDescriptor(obj, key)
	        : null;
	      if (desc && (desc.get || desc.set)) {
	        Object.defineProperty(newObj, key, desc);
	      } else {
	        newObj[key] = obj[key];
	      }
	    }
	  }
	  newObj.default = obj;
	  if (cache) {
	    cache.set(obj, newObj);
	  }
	  return newObj;
	}

	/**
	 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */
	// Given element.props.children, or subtree during recursive traversal,
	// return flattened array of children.
	const getChildren = (arg, children = []) => {
	  if (Array.isArray(arg)) {
	    arg.forEach(item => {
	      getChildren(item, children);
	    });
	  } else if (arg != null && arg !== false) {
	    children.push(arg);
	  }

	  return children;
	};

	const getType = element => {
	  const type = element.type;

	  if (typeof type === 'string') {
	    return type;
	  }

	  if (typeof type === 'function') {
	    return type.displayName || type.name || 'Unknown';
	  }

	  if (ReactIs.isFragment(element)) {
	    return 'React.Fragment';
	  }

	  if (ReactIs.isSuspense(element)) {
	    return 'React.Suspense';
	  }

	  if (typeof type === 'object' && type !== null) {
	    if (ReactIs.isContextProvider(element)) {
	      return 'Context.Provider';
	    }

	    if (ReactIs.isContextConsumer(element)) {
	      return 'Context.Consumer';
	    }

	    if (ReactIs.isForwardRef(element)) {
	      if (type.displayName) {
	        return type.displayName;
	      }

	      const functionName = type.render.displayName || type.render.name || '';
	      return functionName !== ''
	        ? 'ForwardRef(' + functionName + ')'
	        : 'ForwardRef';
	    }

	    if (ReactIs.isMemo(element)) {
	      const functionName =
	        type.displayName || type.type.displayName || type.type.name || '';
	      return functionName !== '' ? 'Memo(' + functionName + ')' : 'Memo';
	    }
	  }

	  return 'UNDEFINED';
	};

	const getPropKeys = element => {
	  const {props} = element;
	  return Object.keys(props)
	    .filter(key => key !== 'children' && props[key] !== undefined)
	    .sort();
	};

	const serialize = (element, config, indentation, depth, refs, printer) =>
	  ++depth > config.maxDepth
	    ? (0, _markup.printElementAsLeaf)(getType(element), config)
	    : (0, _markup.printElement)(
	        getType(element),
	        (0, _markup.printProps)(
	          getPropKeys(element),
	          element.props,
	          config,
	          indentation + config.indent,
	          depth,
	          refs,
	          printer
	        ),
	        (0, _markup.printChildren)(
	          getChildren(element.props.children),
	          config,
	          indentation + config.indent,
	          depth,
	          refs,
	          printer
	        ),
	        config,
	        indentation
	      );

	ReactElement.serialize = serialize;

	const test = val => val != null && ReactIs.isElement(val);

	ReactElement.test = test;
	const plugin = {
	  serialize,
	  test
	};
	var _default = plugin;
	ReactElement.default = _default;
	return ReactElement;
}

var ReactTestComponent = {};

var hasRequiredReactTestComponent;

function requireReactTestComponent () {
	if (hasRequiredReactTestComponent) return ReactTestComponent;
	hasRequiredReactTestComponent = 1;

	Object.defineProperty(ReactTestComponent, '__esModule', {
	  value: true
	});
	ReactTestComponent.test = ReactTestComponent.serialize = ReactTestComponent.default = undefined;

	var _markup = requireMarkup();

	var global = (function () {
	  if (typeof globalThis !== 'undefined') {
	    return globalThis;
	  } else if (typeof global !== 'undefined') {
	    return global;
	  } else if (typeof self !== 'undefined') {
	    return self;
	  } else if (typeof window !== 'undefined') {
	    return window;
	  } else {
	    return Function('return this')();
	  }
	})();

	var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
	const testSymbol =
	  typeof Symbol === 'function' && Symbol.for
	    ? Symbol.for('react.test.json')
	    : 0xea71357;

	const getPropKeys = object => {
	  const {props} = object;
	  return props
	    ? Object.keys(props)
	        .filter(key => props[key] !== undefined)
	        .sort()
	    : [];
	};

	const serialize = (object, config, indentation, depth, refs, printer) =>
	  ++depth > config.maxDepth
	    ? (0, _markup.printElementAsLeaf)(object.type, config)
	    : (0, _markup.printElement)(
	        object.type,
	        object.props
	          ? (0, _markup.printProps)(
	              getPropKeys(object),
	              object.props,
	              config,
	              indentation + config.indent,
	              depth,
	              refs,
	              printer
	            )
	          : '',
	        object.children
	          ? (0, _markup.printChildren)(
	              object.children,
	              config,
	              indentation + config.indent,
	              depth,
	              refs,
	              printer
	            )
	          : '',
	        config,
	        indentation
	      );

	ReactTestComponent.serialize = serialize;

	const test = val => val && val.$$typeof === testSymbol;

	ReactTestComponent.test = test;
	const plugin = {
	  serialize,
	  test
	};
	var _default = plugin;
	ReactTestComponent.default = _default;
	return ReactTestComponent;
}

var hasRequiredBuild;

function requireBuild () {
	if (hasRequiredBuild) return build$1;
	hasRequiredBuild = 1;

	Object.defineProperty(build$1, '__esModule', {
	  value: true
	});
	build$1.default = build$1.DEFAULT_OPTIONS = undefined;
	build$1.format = format;
	build$1.plugins = undefined;

	var _ansiStyles = _interopRequireDefault(requireAnsiStyles());

	var _collections = requireCollections();

	var _AsymmetricMatcher = _interopRequireDefault(
	  requireAsymmetricMatcher()
	);

	var _ConvertAnsi = _interopRequireDefault(requireConvertAnsi());

	var _DOMCollection = _interopRequireDefault(requireDOMCollection());

	var _DOMElement = _interopRequireDefault(requireDOMElement());

	var _Immutable = _interopRequireDefault(requireImmutable());

	var _ReactElement = _interopRequireDefault(requireReactElement());

	var _ReactTestComponent = _interopRequireDefault(
	  requireReactTestComponent()
	);

	function _interopRequireDefault(obj) {
	  return obj && obj.__esModule ? obj : {default: obj};
	}

	/**
	 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */

	/* eslint-disable local/ban-types-eventually */
	const toString = Object.prototype.toString;
	const toISOString = Date.prototype.toISOString;
	const errorToString = Error.prototype.toString;
	const regExpToString = RegExp.prototype.toString;
	/**
	 * Explicitly comparing typeof constructor to function avoids undefined as name
	 * when mock identity-obj-proxy returns the key as the value for any key.
	 */

	const getConstructorName = val =>
	  (typeof val.constructor === 'function' && val.constructor.name) || 'Object';
	/* global window */

	/** Is val is equal to global window object? Works even if it does not exist :) */

	const isWindow = val => typeof window !== 'undefined' && val === window;

	const SYMBOL_REGEXP = /^Symbol\((.*)\)(.*)$/;
	const NEWLINE_REGEXP = /\n/gi;

	class PrettyFormatPluginError extends Error {
	  constructor(message, stack) {
	    super(message);
	    this.stack = stack;
	    this.name = this.constructor.name;
	  }
	}

	function isToStringedArrayType(toStringed) {
	  return (
	    toStringed === '[object Array]' ||
	    toStringed === '[object ArrayBuffer]' ||
	    toStringed === '[object DataView]' ||
	    toStringed === '[object Float32Array]' ||
	    toStringed === '[object Float64Array]' ||
	    toStringed === '[object Int8Array]' ||
	    toStringed === '[object Int16Array]' ||
	    toStringed === '[object Int32Array]' ||
	    toStringed === '[object Uint8Array]' ||
	    toStringed === '[object Uint8ClampedArray]' ||
	    toStringed === '[object Uint16Array]' ||
	    toStringed === '[object Uint32Array]'
	  );
	}

	function printNumber(val) {
	  return Object.is(val, -0) ? '-0' : String(val);
	}

	function printBigInt(val) {
	  return String(`${val}n`);
	}

	function printFunction(val, printFunctionName) {
	  if (!printFunctionName) {
	    return '[Function]';
	  }

	  return '[Function ' + (val.name || 'anonymous') + ']';
	}

	function printSymbol(val) {
	  return String(val).replace(SYMBOL_REGEXP, 'Symbol($1)');
	}

	function printError(val) {
	  return '[' + errorToString.call(val) + ']';
	}
	/**
	 * The first port of call for printing an object, handles most of the
	 * data-types in JS.
	 */

	function printBasicValue(val, printFunctionName, escapeRegex, escapeString) {
	  if (val === true || val === false) {
	    return '' + val;
	  }

	  if (val === undefined) {
	    return 'undefined';
	  }

	  if (val === null) {
	    return 'null';
	  }

	  const typeOf = typeof val;

	  if (typeOf === 'number') {
	    return printNumber(val);
	  }

	  if (typeOf === 'bigint') {
	    return printBigInt(val);
	  }

	  if (typeOf === 'string') {
	    if (escapeString) {
	      return '"' + val.replace(/"|\\/g, '\\$&') + '"';
	    }

	    return '"' + val + '"';
	  }

	  if (typeOf === 'function') {
	    return printFunction(val, printFunctionName);
	  }

	  if (typeOf === 'symbol') {
	    return printSymbol(val);
	  }

	  const toStringed = toString.call(val);

	  if (toStringed === '[object WeakMap]') {
	    return 'WeakMap {}';
	  }

	  if (toStringed === '[object WeakSet]') {
	    return 'WeakSet {}';
	  }

	  if (
	    toStringed === '[object Function]' ||
	    toStringed === '[object GeneratorFunction]'
	  ) {
	    return printFunction(val, printFunctionName);
	  }

	  if (toStringed === '[object Symbol]') {
	    return printSymbol(val);
	  }

	  if (toStringed === '[object Date]') {
	    return isNaN(+val) ? 'Date { NaN }' : toISOString.call(val);
	  }

	  if (toStringed === '[object Error]') {
	    return printError(val);
	  }

	  if (toStringed === '[object RegExp]') {
	    if (escapeRegex) {
	      // https://github.com/benjamingr/RegExp.escape/blob/main/polyfill.js
	      return regExpToString.call(val).replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
	    }

	    return regExpToString.call(val);
	  }

	  if (val instanceof Error) {
	    return printError(val);
	  }

	  return null;
	}
	/**
	 * Handles more complex objects ( such as objects with circular references.
	 * maps and sets etc )
	 */

	function printComplexValue(
	  val,
	  config,
	  indentation,
	  depth,
	  refs,
	  hasCalledToJSON
	) {
	  if (refs.indexOf(val) !== -1) {
	    return '[Circular]';
	  }

	  refs = refs.slice();
	  refs.push(val);
	  const hitMaxDepth = ++depth > config.maxDepth;
	  const min = config.min;

	  if (
	    config.callToJSON &&
	    !hitMaxDepth &&
	    val.toJSON &&
	    typeof val.toJSON === 'function' &&
	    !hasCalledToJSON
	  ) {
	    return printer(val.toJSON(), config, indentation, depth, refs, true);
	  }

	  const toStringed = toString.call(val);

	  if (toStringed === '[object Arguments]') {
	    return hitMaxDepth
	      ? '[Arguments]'
	      : (min ? '' : 'Arguments ') +
	          '[' +
	          (0, _collections.printListItems)(
	            val,
	            config,
	            indentation,
	            depth,
	            refs,
	            printer
	          ) +
	          ']';
	  }

	  if (isToStringedArrayType(toStringed)) {
	    return hitMaxDepth
	      ? '[' + val.constructor.name + ']'
	      : (min
	          ? ''
	          : !config.printBasicPrototype && val.constructor.name === 'Array'
	          ? ''
	          : val.constructor.name + ' ') +
	          '[' +
	          (0, _collections.printListItems)(
	            val,
	            config,
	            indentation,
	            depth,
	            refs,
	            printer
	          ) +
	          ']';
	  }

	  if (toStringed === '[object Map]') {
	    return hitMaxDepth
	      ? '[Map]'
	      : 'Map {' +
	          (0, _collections.printIteratorEntries)(
	            val.entries(),
	            config,
	            indentation,
	            depth,
	            refs,
	            printer,
	            ' => '
	          ) +
	          '}';
	  }

	  if (toStringed === '[object Set]') {
	    return hitMaxDepth
	      ? '[Set]'
	      : 'Set {' +
	          (0, _collections.printIteratorValues)(
	            val.values(),
	            config,
	            indentation,
	            depth,
	            refs,
	            printer
	          ) +
	          '}';
	  } // Avoid failure to serialize global window object in jsdom test environment.
	  // For example, not even relevant if window is prop of React element.

	  return hitMaxDepth || isWindow(val)
	    ? '[' + getConstructorName(val) + ']'
	    : (min
	        ? ''
	        : !config.printBasicPrototype && getConstructorName(val) === 'Object'
	        ? ''
	        : getConstructorName(val) + ' ') +
	        '{' +
	        (0, _collections.printObjectProperties)(
	          val,
	          config,
	          indentation,
	          depth,
	          refs,
	          printer
	        ) +
	        '}';
	}

	function isNewPlugin(plugin) {
	  return plugin.serialize != null;
	}

	function printPlugin(plugin, val, config, indentation, depth, refs) {
	  let printed;

	  try {
	    printed = isNewPlugin(plugin)
	      ? plugin.serialize(val, config, indentation, depth, refs, printer)
	      : plugin.print(
	          val,
	          valChild => printer(valChild, config, indentation, depth, refs),
	          str => {
	            const indentationNext = indentation + config.indent;
	            return (
	              indentationNext +
	              str.replace(NEWLINE_REGEXP, '\n' + indentationNext)
	            );
	          },
	          {
	            edgeSpacing: config.spacingOuter,
	            min: config.min,
	            spacing: config.spacingInner
	          },
	          config.colors
	        );
	  } catch (error) {
	    throw new PrettyFormatPluginError(error.message, error.stack);
	  }

	  if (typeof printed !== 'string') {
	    throw new Error(
	      `pretty-format: Plugin must return type "string" but instead returned "${typeof printed}".`
	    );
	  }

	  return printed;
	}

	function findPlugin(plugins, val) {
	  for (let p = 0; p < plugins.length; p++) {
	    try {
	      if (plugins[p].test(val)) {
	        return plugins[p];
	      }
	    } catch (error) {
	      throw new PrettyFormatPluginError(error.message, error.stack);
	    }
	  }

	  return null;
	}

	function printer(val, config, indentation, depth, refs, hasCalledToJSON) {
	  const plugin = findPlugin(config.plugins, val);

	  if (plugin !== null) {
	    return printPlugin(plugin, val, config, indentation, depth, refs);
	  }

	  const basicResult = printBasicValue(
	    val,
	    config.printFunctionName,
	    config.escapeRegex,
	    config.escapeString
	  );

	  if (basicResult !== null) {
	    return basicResult;
	  }

	  return printComplexValue(
	    val,
	    config,
	    indentation,
	    depth,
	    refs,
	    hasCalledToJSON
	  );
	}

	const DEFAULT_THEME = {
	  comment: 'gray',
	  content: 'reset',
	  prop: 'yellow',
	  tag: 'cyan',
	  value: 'green'
	};
	const DEFAULT_THEME_KEYS = Object.keys(DEFAULT_THEME);
	const DEFAULT_OPTIONS = {
	  callToJSON: true,
	  compareKeys: undefined,
	  escapeRegex: false,
	  escapeString: true,
	  highlight: false,
	  indent: 2,
	  maxDepth: Infinity,
	  min: false,
	  plugins: [],
	  printBasicPrototype: true,
	  printFunctionName: true,
	  theme: DEFAULT_THEME
	};
	build$1.DEFAULT_OPTIONS = DEFAULT_OPTIONS;

	function validateOptions(options) {
	  Object.keys(options).forEach(key => {
	    if (!DEFAULT_OPTIONS.hasOwnProperty(key)) {
	      throw new Error(`pretty-format: Unknown option "${key}".`);
	    }
	  });

	  if (options.min && options.indent !== undefined && options.indent !== 0) {
	    throw new Error(
	      'pretty-format: Options "min" and "indent" cannot be used together.'
	    );
	  }

	  if (options.theme !== undefined) {
	    if (options.theme === null) {
	      throw new Error('pretty-format: Option "theme" must not be null.');
	    }

	    if (typeof options.theme !== 'object') {
	      throw new Error(
	        `pretty-format: Option "theme" must be of type "object" but instead received "${typeof options.theme}".`
	      );
	    }
	  }
	}

	const getColorsHighlight = options =>
	  DEFAULT_THEME_KEYS.reduce((colors, key) => {
	    const value =
	      options.theme && options.theme[key] !== undefined
	        ? options.theme[key]
	        : DEFAULT_THEME[key];
	    const color = value && _ansiStyles.default[value];

	    if (
	      color &&
	      typeof color.close === 'string' &&
	      typeof color.open === 'string'
	    ) {
	      colors[key] = color;
	    } else {
	      throw new Error(
	        `pretty-format: Option "theme" has a key "${key}" whose value "${value}" is undefined in ansi-styles.`
	      );
	    }

	    return colors;
	  }, Object.create(null));

	const getColorsEmpty = () =>
	  DEFAULT_THEME_KEYS.reduce((colors, key) => {
	    colors[key] = {
	      close: '',
	      open: ''
	    };
	    return colors;
	  }, Object.create(null));

	const getPrintFunctionName = options =>
	  options && options.printFunctionName !== undefined
	    ? options.printFunctionName
	    : DEFAULT_OPTIONS.printFunctionName;

	const getEscapeRegex = options =>
	  options && options.escapeRegex !== undefined
	    ? options.escapeRegex
	    : DEFAULT_OPTIONS.escapeRegex;

	const getEscapeString = options =>
	  options && options.escapeString !== undefined
	    ? options.escapeString
	    : DEFAULT_OPTIONS.escapeString;

	const getConfig = options => {
	  var _options$printBasicPr;

	  return {
	    callToJSON:
	      options && options.callToJSON !== undefined
	        ? options.callToJSON
	        : DEFAULT_OPTIONS.callToJSON,
	    colors:
	      options && options.highlight
	        ? getColorsHighlight(options)
	        : getColorsEmpty(),
	    compareKeys:
	      options && typeof options.compareKeys === 'function'
	        ? options.compareKeys
	        : DEFAULT_OPTIONS.compareKeys,
	    escapeRegex: getEscapeRegex(options),
	    escapeString: getEscapeString(options),
	    indent:
	      options && options.min
	        ? ''
	        : createIndent(
	            options && options.indent !== undefined
	              ? options.indent
	              : DEFAULT_OPTIONS.indent
	          ),
	    maxDepth:
	      options && options.maxDepth !== undefined
	        ? options.maxDepth
	        : DEFAULT_OPTIONS.maxDepth,
	    min:
	      options && options.min !== undefined ? options.min : DEFAULT_OPTIONS.min,
	    plugins:
	      options && options.plugins !== undefined
	        ? options.plugins
	        : DEFAULT_OPTIONS.plugins,
	    printBasicPrototype:
	      (_options$printBasicPr =
	        options === null || options === undefined
	          ? undefined
	          : options.printBasicPrototype) !== null &&
	      _options$printBasicPr !== undefined
	        ? _options$printBasicPr
	        : true,
	    printFunctionName: getPrintFunctionName(options),
	    spacingInner: options && options.min ? ' ' : '\n',
	    spacingOuter: options && options.min ? '' : '\n'
	  };
	};

	function createIndent(indent) {
	  return new Array(indent + 1).join(' ');
	}
	/**
	 * Returns a presentation string of your `val` object
	 * @param val any potential JavaScript object
	 * @param options Custom settings
	 */

	function format(val, options) {
	  if (options) {
	    validateOptions(options);

	    if (options.plugins) {
	      const plugin = findPlugin(options.plugins, val);

	      if (plugin !== null) {
	        return printPlugin(plugin, val, getConfig(options), '', 0, []);
	      }
	    }
	  }

	  const basicResult = printBasicValue(
	    val,
	    getPrintFunctionName(options),
	    getEscapeRegex(options),
	    getEscapeString(options)
	  );

	  if (basicResult !== null) {
	    return basicResult;
	  }

	  return printComplexValue(val, getConfig(options), '', 0, []);
	}

	const plugins = {
	  AsymmetricMatcher: _AsymmetricMatcher.default,
	  ConvertAnsi: _ConvertAnsi.default,
	  DOMCollection: _DOMCollection.default,
	  DOMElement: _DOMElement.default,
	  Immutable: _Immutable.default,
	  ReactElement: _ReactElement.default,
	  ReactTestComponent: _ReactTestComponent.default
	};
	build$1.plugins = plugins;
	var _default = format;
	build$1.default = _default;
	return build$1;
}

var buildExports = requireBuild();

/**
 * @source {https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Polyfill}
 * but without thisArg (too hard to type, no need to `this`)
 */
var toStr = Object.prototype.toString;
function isCallable(fn) {
  return typeof fn === "function" || toStr.call(fn) === "[object Function]";
}
function toInteger(value) {
  var number = Number(value);
  if (isNaN(number)) {
    return 0;
  }
  if (number === 0 || !isFinite(number)) {
    return number;
  }
  return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
}
var maxSafeInteger = Math.pow(2, 53) - 1;
function toLength(value) {
  var len = toInteger(value);
  return Math.min(Math.max(len, 0), maxSafeInteger);
}
/**
 * Creates an array from an iterable object.
 * @param iterable An iterable object to convert to an array.
 */

/**
 * Creates an array from an iterable object.
 * @param iterable An iterable object to convert to an array.
 * @param mapfn A mapping function to call on every element of the array.
 * @param thisArg Value of 'this' used to invoke the mapfn.
 */
function arrayFrom(arrayLike, mapFn) {
  // 1. Let C be the this value.
  // edit(@eps1lon): we're not calling it as Array.from
  var C = Array;

  // 2. Let items be ToObject(arrayLike).
  var items = Object(arrayLike);

  // 3. ReturnIfAbrupt(items).
  if (arrayLike == null) {
    throw new TypeError("Array.from requires an array-like object - not null or undefined");
  }

  // 10. Let lenValue be Get(items, "length").
  // 11. Let len be ToLength(lenValue).
  var len = toLength(items.length);

  // 13. If IsConstructor(C) is true, then
  // 13. a. Let A be the result of calling the [[Construct]] internal method
  // of C with an argument list containing the single item len.
  // 14. a. Else, Let A be ArrayCreate(len).
  var A = isCallable(C) ? Object(new C(len)) : new Array(len);

  // 16. Let k be 0.
  var k = 0;
  // 17. Repeat, while k < len… (also steps a - h)
  var kValue;
  while (k < len) {
    kValue = items[k];
    {
      A[k] = kValue;
    }
    k += 1;
  }
  // 18. Let putStatus be Put(A, "length", len, true).
  A.length = len;
  // 20. Return A.
  return A;
}

function _typeof$1(obj) { "@babel/helpers - typeof"; return _typeof$1 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof$1(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey$1(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { _defineProperties(Constructor.prototype, protoProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _defineProperty$1(obj, key, value) { key = _toPropertyKey$1(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey$1(arg) { var key = _toPrimitive$1(arg, "string"); return _typeof$1(key) === "symbol" ? key : String(key); }
function _toPrimitive$1(input, hint) { if (_typeof$1(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof$1(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
// for environments without Set we fallback to arrays with unique members
var SetLike = /*#__PURE__*/function () {
  function SetLike() {
    var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
    _classCallCheck(this, SetLike);
    _defineProperty$1(this, "items", undefined);
    this.items = items;
  }
  _createClass(SetLike, [{
    key: "add",
    value: function add(value) {
      if (this.has(value) === false) {
        this.items.push(value);
      }
      return this;
    }
  }, {
    key: "clear",
    value: function clear() {
      this.items = [];
    }
  }, {
    key: "delete",
    value: function _delete(value) {
      var previousLength = this.items.length;
      this.items = this.items.filter(function (item) {
        return item !== value;
      });
      return previousLength !== this.items.length;
    }
  }, {
    key: "forEach",
    value: function forEach(callbackfn) {
      var _this = this;
      this.items.forEach(function (item) {
        callbackfn(item, item, _this);
      });
    }
  }, {
    key: "has",
    value: function has(value) {
      return this.items.indexOf(value) !== -1;
    }
  }, {
    key: "size",
    get: function get() {
      return this.items.length;
    }
  }]);
  return SetLike;
}();
var SetLike$1 = typeof Set === "undefined" ? Set : SetLike;

// https://w3c.github.io/html-aria/#document-conformance-requirements-for-use-of-aria-attributes-in-html

/**
 * Safe Element.localName for all supported environments
 * @param element
 */
function getLocalName(element) {
  var _element$localName;
  return (// eslint-disable-next-line no-restricted-properties -- actual guard for environments without localName
    (_element$localName = element.localName) !== null && _element$localName !== undefined ? _element$localName :
    // eslint-disable-next-line no-restricted-properties -- required for the fallback
    element.tagName.toLowerCase()
  );
}
var localNameToRoleMappings = {
  article: "article",
  aside: "complementary",
  button: "button",
  datalist: "listbox",
  dd: "definition",
  details: "group",
  dialog: "dialog",
  dt: "term",
  fieldset: "group",
  figure: "figure",
  // WARNING: Only with an accessible name
  form: "form",
  footer: "contentinfo",
  h1: "heading",
  h2: "heading",
  h3: "heading",
  h4: "heading",
  h5: "heading",
  h6: "heading",
  header: "banner",
  hr: "separator",
  html: "document",
  legend: "legend",
  li: "listitem",
  math: "math",
  main: "main",
  menu: "list",
  nav: "navigation",
  ol: "list",
  optgroup: "group",
  // WARNING: Only in certain context
  option: "option",
  output: "status",
  progress: "progressbar",
  // WARNING: Only with an accessible name
  section: "region",
  summary: "button",
  table: "table",
  tbody: "rowgroup",
  textarea: "textbox",
  tfoot: "rowgroup",
  // WARNING: Only in certain context
  td: "cell",
  th: "columnheader",
  thead: "rowgroup",
  tr: "row",
  ul: "list"
};
var prohibitedAttributes = {
  caption: new Set(["aria-label", "aria-labelledby"]),
  code: new Set(["aria-label", "aria-labelledby"]),
  deletion: new Set(["aria-label", "aria-labelledby"]),
  emphasis: new Set(["aria-label", "aria-labelledby"]),
  generic: new Set(["aria-label", "aria-labelledby", "aria-roledescription"]),
  insertion: new Set(["aria-label", "aria-labelledby"]),
  paragraph: new Set(["aria-label", "aria-labelledby"]),
  presentation: new Set(["aria-label", "aria-labelledby"]),
  strong: new Set(["aria-label", "aria-labelledby"]),
  subscript: new Set(["aria-label", "aria-labelledby"]),
  superscript: new Set(["aria-label", "aria-labelledby"])
};

/**
 *
 * @param element
 * @param role The role used for this element. This is specified to control whether you want to use the implicit or explicit role.
 */
function hasGlobalAriaAttributes(element, role) {
  // https://rawgit.com/w3c/aria/stable/#global_states
  // commented attributes are deprecated
  return ["aria-atomic", "aria-busy", "aria-controls", "aria-current", "aria-describedby", "aria-details",
  // "disabled",
  "aria-dropeffect",
  // "errormessage",
  "aria-flowto", "aria-grabbed",
  // "haspopup",
  "aria-hidden",
  // "invalid",
  "aria-keyshortcuts", "aria-label", "aria-labelledby", "aria-live", "aria-owns", "aria-relevant", "aria-roledescription"].some(function (attributeName) {
    var _prohibitedAttributes;
    return element.hasAttribute(attributeName) && !((_prohibitedAttributes = prohibitedAttributes[role]) !== null && _prohibitedAttributes !== undefined && _prohibitedAttributes.has(attributeName));
  });
}
function ignorePresentationalRole(element, implicitRole) {
  // https://rawgit.com/w3c/aria/stable/#conflict_resolution_presentation_none
  return hasGlobalAriaAttributes(element, implicitRole);
}
function getRole(element) {
  var explicitRole = getExplicitRole(element);
  if (explicitRole === null || explicitRole === "presentation") {
    var implicitRole = getImplicitRole(element);
    if (explicitRole !== "presentation" || ignorePresentationalRole(element, implicitRole || "")) {
      return implicitRole;
    }
  }
  return explicitRole;
}
function getImplicitRole(element) {
  var mappedByTag = localNameToRoleMappings[getLocalName(element)];
  if (mappedByTag !== undefined) {
    return mappedByTag;
  }
  switch (getLocalName(element)) {
    case "a":
    case "area":
    case "link":
      if (element.hasAttribute("href")) {
        return "link";
      }
      break;
    case "img":
      if (element.getAttribute("alt") === "" && !ignorePresentationalRole(element, "img")) {
        return "presentation";
      }
      return "img";
    case "input":
      {
        var _ref = element,
          type = _ref.type;
        switch (type) {
          case "button":
          case "image":
          case "reset":
          case "submit":
            return "button";
          case "checkbox":
          case "radio":
            return type;
          case "range":
            return "slider";
          case "email":
          case "tel":
          case "text":
          case "url":
            if (element.hasAttribute("list")) {
              return "combobox";
            }
            return "textbox";
          case "search":
            if (element.hasAttribute("list")) {
              return "combobox";
            }
            return "searchbox";
          case "number":
            return "spinbutton";
          default:
            return null;
        }
      }
    case "select":
      if (element.hasAttribute("multiple") || element.size > 1) {
        return "listbox";
      }
      return "combobox";
  }
  return null;
}
function getExplicitRole(element) {
  var role = element.getAttribute("role");
  if (role !== null) {
    var explicitRole = role.trim().split(" ")[0];
    // String.prototype.split(sep, limit) will always return an array with at least one member
    // as long as limit is either undefined or > 0
    if (explicitRole.length > 0) {
      return explicitRole;
    }
  }
  return null;
}

function isElement$2(node) {
  return node !== null && node.nodeType === node.ELEMENT_NODE;
}
function isHTMLTableCaptionElement(node) {
  return isElement$2(node) && getLocalName(node) === "caption";
}
function isHTMLInputElement(node) {
  return isElement$2(node) && getLocalName(node) === "input";
}
function isHTMLOptGroupElement(node) {
  return isElement$2(node) && getLocalName(node) === "optgroup";
}
function isHTMLSelectElement(node) {
  return isElement$2(node) && getLocalName(node) === "select";
}
function isHTMLTableElement(node) {
  return isElement$2(node) && getLocalName(node) === "table";
}
function isHTMLTextAreaElement(node) {
  return isElement$2(node) && getLocalName(node) === "textarea";
}
function safeWindow(node) {
  var _ref = node.ownerDocument === null ? node : node.ownerDocument,
    defaultView = _ref.defaultView;
  if (defaultView === null) {
    throw new TypeError("no window available");
  }
  return defaultView;
}
function isHTMLFieldSetElement(node) {
  return isElement$2(node) && getLocalName(node) === "fieldset";
}
function isHTMLLegendElement(node) {
  return isElement$2(node) && getLocalName(node) === "legend";
}
function isHTMLSlotElement(node) {
  return isElement$2(node) && getLocalName(node) === "slot";
}
function isSVGElement(node) {
  return isElement$2(node) && node.ownerSVGElement !== undefined;
}
function isSVGSVGElement(node) {
  return isElement$2(node) && getLocalName(node) === "svg";
}
function isSVGTitleElement(node) {
  return isSVGElement(node) && getLocalName(node) === "title";
}

/**
 *
 * @param {Node} node -
 * @param {string} attributeName -
 * @returns {Element[]} -
 */
function queryIdRefs(node, attributeName) {
  if (isElement$2(node) && node.hasAttribute(attributeName)) {
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- safe due to hasAttribute check
    var ids = node.getAttribute(attributeName).split(" ");

    // Browsers that don't support shadow DOM won't have getRootNode
    var root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
    return ids.map(function (id) {
      return root.getElementById(id);
    }).filter(function (element) {
      return element !== null;
    }
    // TODO: why does this not narrow?
    );
  }

  return [];
}
function hasAnyConcreteRoles(node, roles) {
  if (isElement$2(node)) {
    return roles.indexOf(getRole(node)) !== -1;
  }
  return false;
}

/**
 * implements https://w3c.github.io/accname/
 */

/**
 *  A string of characters where all carriage returns, newlines, tabs, and form-feeds are replaced with a single space, and multiple spaces are reduced to a single space. The string contains only character data; it does not contain any markup.
 */

/**
 *
 * @param {string} string -
 * @returns {FlatString} -
 */
function asFlatString(s) {
  return s.trim().replace(/\s\s+/g, " ");
}

/**
 *
 * @param node -
 * @param options - These are not optional to prevent accidentally calling it without options in `computeAccessibleName`
 * @returns {boolean} -
 */
function isHidden(node, getComputedStyleImplementation) {
  if (!isElement$2(node)) {
    return false;
  }
  if (node.hasAttribute("hidden") || node.getAttribute("aria-hidden") === "true") {
    return true;
  }
  var style = getComputedStyleImplementation(node);
  return style.getPropertyValue("display") === "none" || style.getPropertyValue("visibility") === "hidden";
}

/**
 * @param {Node} node -
 * @returns {boolean} - As defined in step 2E of https://w3c.github.io/accname/#mapping_additional_nd_te
 */
function isControl(node) {
  return hasAnyConcreteRoles(node, ["button", "combobox", "listbox", "textbox"]) || hasAbstractRole(node, "range");
}
function hasAbstractRole(node, role) {
  if (!isElement$2(node)) {
    return false;
  }
  switch (role) {
    case "range":
      return hasAnyConcreteRoles(node, ["meter", "progressbar", "scrollbar", "slider", "spinbutton"]);
    default:
      throw new TypeError("No knowledge about abstract role '".concat(role, "'. This is likely a bug :("));
  }
}

/**
 * element.querySelectorAll but also considers owned tree
 * @param element
 * @param selectors
 */
function querySelectorAllSubtree(element, selectors) {
  var elements = arrayFrom(element.querySelectorAll(selectors));
  queryIdRefs(element, "aria-owns").forEach(function (root) {
    // babel transpiles this assuming an iterator
    elements.push.apply(elements, arrayFrom(root.querySelectorAll(selectors)));
  });
  return elements;
}
function querySelectedOptions(listbox) {
  if (isHTMLSelectElement(listbox)) {
    // IE11 polyfill
    return listbox.selectedOptions || querySelectorAllSubtree(listbox, "[selected]");
  }
  return querySelectorAllSubtree(listbox, '[aria-selected="true"]');
}
function isMarkedPresentational(node) {
  return hasAnyConcreteRoles(node, ["none", "presentation"]);
}

/**
 * Elements specifically listed in html-aam
 *
 * We don't need this for `label` or `legend` elements.
 * Their implicit roles already allow "naming from content".
 *
 * sources:
 *
 * - https://w3c.github.io/html-aam/#table-element
 */
function isNativeHostLanguageTextAlternativeElement(node) {
  return isHTMLTableCaptionElement(node);
}

/**
 * https://w3c.github.io/aria/#namefromcontent
 */
function allowsNameFromContent(node) {
  return hasAnyConcreteRoles(node, ["button", "cell", "checkbox", "columnheader", "gridcell", "heading", "label", "legend", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "row", "rowheader", "switch", "tab", "tooltip", "treeitem"]);
}

/**
 * TODO https://github.com/eps1lon/dom-accessibility-api/issues/100
 */
function isDescendantOfNativeHostLanguageTextAlternativeElement(
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- not implemented yet
node) {
  return false;
}
function getValueOfTextbox(element) {
  if (isHTMLInputElement(element) || isHTMLTextAreaElement(element)) {
    return element.value;
  }
  // https://github.com/eps1lon/dom-accessibility-api/issues/4
  return element.textContent || "";
}
function getTextualContent(declaration) {
  var content = declaration.getPropertyValue("content");
  if (/^["'].*["']$/.test(content)) {
    return content.slice(1, -1);
  }
  return "";
}

/**
 * https://html.spec.whatwg.org/multipage/forms.html#category-label
 * TODO: form-associated custom elements
 * @param element
 */
function isLabelableElement(element) {
  var localName = getLocalName(element);
  return localName === "button" || localName === "input" && element.getAttribute("type") !== "hidden" || localName === "meter" || localName === "output" || localName === "progress" || localName === "select" || localName === "textarea";
}

/**
 * > [...], then the first such descendant in tree order is the label element's labeled control.
 * -- https://html.spec.whatwg.org/multipage/forms.html#labeled-control
 * @param element
 */
function findLabelableElement(element) {
  if (isLabelableElement(element)) {
    return element;
  }
  var labelableElement = null;
  element.childNodes.forEach(function (childNode) {
    if (labelableElement === null && isElement$2(childNode)) {
      var descendantLabelableElement = findLabelableElement(childNode);
      if (descendantLabelableElement !== null) {
        labelableElement = descendantLabelableElement;
      }
    }
  });
  return labelableElement;
}

/**
 * Polyfill of HTMLLabelElement.control
 * https://html.spec.whatwg.org/multipage/forms.html#labeled-control
 * @param label
 */
function getControlOfLabel(label) {
  if (label.control !== undefined) {
    return label.control;
  }
  var htmlFor = label.getAttribute("for");
  if (htmlFor !== null) {
    return label.ownerDocument.getElementById(htmlFor);
  }
  return findLabelableElement(label);
}

/**
 * Polyfill of HTMLInputElement.labels
 * https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/labels
 * @param element
 */
function getLabels$1(element) {
  var labelsProperty = element.labels;
  if (labelsProperty === null) {
    return labelsProperty;
  }
  if (labelsProperty !== undefined) {
    return arrayFrom(labelsProperty);
  }

  // polyfill
  if (!isLabelableElement(element)) {
    return null;
  }
  var document = element.ownerDocument;
  return arrayFrom(document.querySelectorAll("label")).filter(function (label) {
    return getControlOfLabel(label) === element;
  });
}

/**
 * Gets the contents of a slot used for computing the accname
 * @param slot
 */
function getSlotContents(slot) {
  // Computing the accessible name for elements containing slots is not
  // currently defined in the spec. This implementation reflects the
  // behavior of NVDA 2020.2/Firefox 81 and iOS VoiceOver/Safari 13.6.
  var assignedNodes = slot.assignedNodes();
  if (assignedNodes.length === 0) {
    // if no nodes are assigned to the slot, it displays the default content
    return arrayFrom(slot.childNodes);
  }
  return assignedNodes;
}

/**
 * implements https://w3c.github.io/accname/#mapping_additional_nd_te
 * @param root
 * @param options
 * @returns
 */
function computeTextAlternative(root) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var consultedNodes = new SetLike$1();
  var window = safeWindow(root);
  var _options$compute = options.compute,
    compute = _options$compute === undefined ? "name" : _options$compute,
    _options$computedStyl = options.computedStyleSupportsPseudoElements,
    computedStyleSupportsPseudoElements = _options$computedStyl === undefined ? options.getComputedStyle !== undefined : _options$computedStyl,
    _options$getComputedS = options.getComputedStyle,
    getComputedStyle = _options$getComputedS === undefined ? window.getComputedStyle.bind(window) : _options$getComputedS,
    _options$hidden = options.hidden,
    hidden = _options$hidden === undefined ? false : _options$hidden;

  // 2F.i
  function computeMiscTextAlternative(node, context) {
    var accumulatedText = "";
    if (isElement$2(node) && computedStyleSupportsPseudoElements) {
      var pseudoBefore = getComputedStyle(node, "::before");
      var beforeContent = getTextualContent(pseudoBefore);
      accumulatedText = "".concat(beforeContent, " ").concat(accumulatedText);
    }

    // FIXME: Including aria-owns is not defined in the spec
    // But it is required in the web-platform-test
    var childNodes = isHTMLSlotElement(node) ? getSlotContents(node) : arrayFrom(node.childNodes).concat(queryIdRefs(node, "aria-owns"));
    childNodes.forEach(function (child) {
      var result = computeTextAlternative(child, {
        isEmbeddedInLabel: context.isEmbeddedInLabel,
        isReferenced: false,
        recursion: true
      });
      // TODO: Unclear why display affects delimiter
      // see https://github.com/w3c/accname/issues/3
      var display = isElement$2(child) ? getComputedStyle(child).getPropertyValue("display") : "inline";
      var separator = display !== "inline" ? " " : "";
      // trailing separator for wpt tests
      accumulatedText += "".concat(separator).concat(result).concat(separator);
    });
    if (isElement$2(node) && computedStyleSupportsPseudoElements) {
      var pseudoAfter = getComputedStyle(node, "::after");
      var afterContent = getTextualContent(pseudoAfter);
      accumulatedText = "".concat(accumulatedText, " ").concat(afterContent);
    }
    return accumulatedText.trim();
  }

  /**
   *
   * @param element
   * @param attributeName
   * @returns A string non-empty string or `null`
   */
  function useAttribute(element, attributeName) {
    var attribute = element.getAttributeNode(attributeName);
    if (attribute !== null && !consultedNodes.has(attribute) && attribute.value.trim() !== "") {
      consultedNodes.add(attribute);
      return attribute.value;
    }
    return null;
  }
  function computeTooltipAttributeValue(node) {
    if (!isElement$2(node)) {
      return null;
    }
    return useAttribute(node, "title");
  }
  function computeElementTextAlternative(node) {
    if (!isElement$2(node)) {
      return null;
    }

    // https://w3c.github.io/html-aam/#fieldset-and-legend-elements
    if (isHTMLFieldSetElement(node)) {
      consultedNodes.add(node);
      var children = arrayFrom(node.childNodes);
      for (var i = 0; i < children.length; i += 1) {
        var child = children[i];
        if (isHTMLLegendElement(child)) {
          return computeTextAlternative(child, {
            isEmbeddedInLabel: false,
            isReferenced: false,
            recursion: false
          });
        }
      }
    } else if (isHTMLTableElement(node)) {
      // https://w3c.github.io/html-aam/#table-element
      consultedNodes.add(node);
      var _children = arrayFrom(node.childNodes);
      for (var _i = 0; _i < _children.length; _i += 1) {
        var _child = _children[_i];
        if (isHTMLTableCaptionElement(_child)) {
          return computeTextAlternative(_child, {
            isEmbeddedInLabel: false,
            isReferenced: false,
            recursion: false
          });
        }
      }
    } else if (isSVGSVGElement(node)) {
      // https://www.w3.org/TR/svg-aam-1.0/
      consultedNodes.add(node);
      var _children2 = arrayFrom(node.childNodes);
      for (var _i2 = 0; _i2 < _children2.length; _i2 += 1) {
        var _child2 = _children2[_i2];
        if (isSVGTitleElement(_child2)) {
          return _child2.textContent;
        }
      }
      return null;
    } else if (getLocalName(node) === "img" || getLocalName(node) === "area") {
      // https://w3c.github.io/html-aam/#area-element
      // https://w3c.github.io/html-aam/#img-element
      var nameFromAlt = useAttribute(node, "alt");
      if (nameFromAlt !== null) {
        return nameFromAlt;
      }
    } else if (isHTMLOptGroupElement(node)) {
      var nameFromLabel = useAttribute(node, "label");
      if (nameFromLabel !== null) {
        return nameFromLabel;
      }
    }
    if (isHTMLInputElement(node) && (node.type === "button" || node.type === "submit" || node.type === "reset")) {
      // https://w3c.github.io/html-aam/#input-type-text-input-type-password-input-type-search-input-type-tel-input-type-email-input-type-url-and-textarea-element-accessible-description-computation
      var nameFromValue = useAttribute(node, "value");
      if (nameFromValue !== null) {
        return nameFromValue;
      }

      // TODO: l10n
      if (node.type === "submit") {
        return "Submit";
      }
      // TODO: l10n
      if (node.type === "reset") {
        return "Reset";
      }
    }
    var labels = getLabels$1(node);
    if (labels !== null && labels.length !== 0) {
      consultedNodes.add(node);
      return arrayFrom(labels).map(function (element) {
        return computeTextAlternative(element, {
          isEmbeddedInLabel: true,
          isReferenced: false,
          recursion: true
        });
      }).filter(function (label) {
        return label.length > 0;
      }).join(" ");
    }

    // https://w3c.github.io/html-aam/#input-type-image-accessible-name-computation
    // TODO: wpt test consider label elements but html-aam does not mention them
    // We follow existing implementations over spec
    if (isHTMLInputElement(node) && node.type === "image") {
      var _nameFromAlt = useAttribute(node, "alt");
      if (_nameFromAlt !== null) {
        return _nameFromAlt;
      }
      var nameFromTitle = useAttribute(node, "title");
      if (nameFromTitle !== null) {
        return nameFromTitle;
      }

      // TODO: l10n
      return "Submit Query";
    }
    if (hasAnyConcreteRoles(node, ["button"])) {
      // https://www.w3.org/TR/html-aam-1.0/#button-element
      var nameFromSubTree = computeMiscTextAlternative(node, {
        isEmbeddedInLabel: false,
        isReferenced: false
      });
      if (nameFromSubTree !== "") {
        return nameFromSubTree;
      }
    }
    return null;
  }
  function computeTextAlternative(current, context) {
    if (consultedNodes.has(current)) {
      return "";
    }

    // 2A
    if (!hidden && isHidden(current, getComputedStyle) && !context.isReferenced) {
      consultedNodes.add(current);
      return "";
    }

    // 2B
    var labelAttributeNode = isElement$2(current) ? current.getAttributeNode("aria-labelledby") : null;
    // TODO: Do we generally need to block query IdRefs of attributes we have already consulted?
    var labelElements = labelAttributeNode !== null && !consultedNodes.has(labelAttributeNode) ? queryIdRefs(current, "aria-labelledby") : [];
    if (compute === "name" && !context.isReferenced && labelElements.length > 0) {
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Can't be null here otherwise labelElements would be empty
      consultedNodes.add(labelAttributeNode);
      return labelElements.map(function (element) {
        // TODO: Chrome will consider repeated values i.e. use a node multiple times while we'll bail out in computeTextAlternative.
        return computeTextAlternative(element, {
          isEmbeddedInLabel: context.isEmbeddedInLabel,
          isReferenced: true,
          // this isn't recursion as specified, otherwise we would skip
          // `aria-label` in
          // <input id="myself" aria-label="foo" aria-labelledby="myself"
          recursion: false
        });
      }).join(" ");
    }

    // 2C
    // Changed from the spec in anticipation of https://github.com/w3c/accname/issues/64
    // spec says we should only consider skipping if we have a non-empty label
    var skipToStep2E = context.recursion && isControl(current) && compute === "name";
    if (!skipToStep2E) {
      var ariaLabel = (isElement$2(current) && current.getAttribute("aria-label") || "").trim();
      if (ariaLabel !== "" && compute === "name") {
        consultedNodes.add(current);
        return ariaLabel;
      }

      // 2D
      if (!isMarkedPresentational(current)) {
        var elementTextAlternative = computeElementTextAlternative(current);
        if (elementTextAlternative !== null) {
          consultedNodes.add(current);
          return elementTextAlternative;
        }
      }
    }

    // special casing, cheating to make tests pass
    // https://github.com/w3c/accname/issues/67
    if (hasAnyConcreteRoles(current, ["menu"])) {
      consultedNodes.add(current);
      return "";
    }

    // 2E
    if (skipToStep2E || context.isEmbeddedInLabel || context.isReferenced) {
      if (hasAnyConcreteRoles(current, ["combobox", "listbox"])) {
        consultedNodes.add(current);
        var selectedOptions = querySelectedOptions(current);
        if (selectedOptions.length === 0) {
          // defined per test `name_heading_combobox`
          return isHTMLInputElement(current) ? current.value : "";
        }
        return arrayFrom(selectedOptions).map(function (selectedOption) {
          return computeTextAlternative(selectedOption, {
            isEmbeddedInLabel: context.isEmbeddedInLabel,
            isReferenced: false,
            recursion: true
          });
        }).join(" ");
      }
      if (hasAbstractRole(current, "range")) {
        consultedNodes.add(current);
        if (current.hasAttribute("aria-valuetext")) {
          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- safe due to hasAttribute guard
          return current.getAttribute("aria-valuetext");
        }
        if (current.hasAttribute("aria-valuenow")) {
          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- safe due to hasAttribute guard
          return current.getAttribute("aria-valuenow");
        }
        // Otherwise, use the value as specified by a host language attribute.
        return current.getAttribute("value") || "";
      }
      if (hasAnyConcreteRoles(current, ["textbox"])) {
        consultedNodes.add(current);
        return getValueOfTextbox(current);
      }
    }

    // 2F: https://w3c.github.io/accname/#step2F
    if (allowsNameFromContent(current) || isElement$2(current) && context.isReferenced || isNativeHostLanguageTextAlternativeElement(current) || isDescendantOfNativeHostLanguageTextAlternativeElement()) {
      var accumulatedText2F = computeMiscTextAlternative(current, {
        isEmbeddedInLabel: context.isEmbeddedInLabel,
        isReferenced: false
      });
      if (accumulatedText2F !== "") {
        consultedNodes.add(current);
        return accumulatedText2F;
      }
    }
    if (current.nodeType === current.TEXT_NODE) {
      consultedNodes.add(current);
      return current.textContent || "";
    }
    if (context.recursion) {
      consultedNodes.add(current);
      return computeMiscTextAlternative(current, {
        isEmbeddedInLabel: context.isEmbeddedInLabel,
        isReferenced: false
      });
    }
    var tooltipAttributeValue = computeTooltipAttributeValue(current);
    if (tooltipAttributeValue !== null) {
      consultedNodes.add(current);
      return tooltipAttributeValue;
    }

    // TODO should this be reachable?
    consultedNodes.add(current);
    return "";
  }
  return asFlatString(computeTextAlternative(root, {
    isEmbeddedInLabel: false,
    // by spec computeAccessibleDescription starts with the referenced elements as roots
    isReferenced: compute === "description",
    recursion: false
  }));
}

function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }

/**
 * @param root
 * @param options
 * @returns
 */
function computeAccessibleDescription(root) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var description = queryIdRefs(root, "aria-describedby").map(function (element) {
    return computeTextAlternative(element, _objectSpread(_objectSpread({}, options), {}, {
      compute: "description"
    }));
  }).join(" ");

  // TODO: Technically we need to make sure that node wasn't used for the accessible name
  //       This causes `description_1.0_combobox-focusable-manual` to fail
  //
  // https://www.w3.org/TR/html-aam-1.0/#accessible-name-and-description-computation
  // says for so many elements to use the `title` that we assume all elements are considered
  if (description === "") {
    var title = root.getAttribute("title");
    description = title === null ? "" : title;
  }
  return description;
}

/**
 * https://w3c.github.io/aria/#namefromprohibited
 */
function prohibitsNaming(node) {
  return hasAnyConcreteRoles(node, ["caption", "code", "deletion", "emphasis", "generic", "insertion", "paragraph", "presentation", "strong", "subscript", "superscript"]);
}

/**
 * implements https://w3c.github.io/accname/#mapping_additional_nd_name
 * @param root
 * @param options
 * @returns
 */
function computeAccessibleName(root) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  if (prohibitsNaming(root)) {
    return "";
  }
  return computeTextAlternative(root, options);
}

var lib = {};

var ariaPropsMap = {};

var iterationDecorator = {};

var iteratorProxy = {};

var hasRequiredIteratorProxy;

function requireIteratorProxy () {
	if (hasRequiredIteratorProxy) return iteratorProxy;
	hasRequiredIteratorProxy = 1;

	Object.defineProperty(iteratorProxy, "__esModule", {
	  value: true
	});
	iteratorProxy.default = undefined;

	// eslint-disable-next-line no-unused-vars
	function iteratorProxy$1() {
	  var values = this;
	  var index = 0;
	  var iter = {
	    '@@iterator': function iterator() {
	      return iter;
	    },
	    next: function next() {
	      if (index < values.length) {
	        var value = values[index];
	        index = index + 1;
	        return {
	          done: false,
	          value: value
	        };
	      } else {
	        return {
	          done: true
	        };
	      }
	    }
	  };
	  return iter;
	}
	var _default = iteratorProxy$1;
	iteratorProxy.default = _default;
	return iteratorProxy;
}

var hasRequiredIterationDecorator;

function requireIterationDecorator () {
	if (hasRequiredIterationDecorator) return iterationDecorator;
	hasRequiredIterationDecorator = 1;

	Object.defineProperty(iterationDecorator, "__esModule", {
	  value: true
	});
	iterationDecorator.default = iterationDecorator$1;
	var _iteratorProxy = _interopRequireDefault(requireIteratorProxy());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
	function iterationDecorator$1(collection, entries) {
	  if (typeof Symbol === 'function' && _typeof(Symbol.iterator) === 'symbol') {
	    Object.defineProperty(collection, Symbol.iterator, {
	      value: _iteratorProxy.default.bind(entries)
	    });
	  }
	  return collection;
	}
	return iterationDecorator;
}

var hasRequiredAriaPropsMap;

function requireAriaPropsMap () {
	if (hasRequiredAriaPropsMap) return ariaPropsMap;
	hasRequiredAriaPropsMap = 1;

	Object.defineProperty(ariaPropsMap, "__esModule", {
	  value: true
	});
	ariaPropsMap.default = undefined;
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
	function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
	function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike) { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
	function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
	function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
	var properties = [['aria-activedescendant', {
	  'type': 'id'
	}], ['aria-atomic', {
	  'type': 'boolean'
	}], ['aria-autocomplete', {
	  'type': 'token',
	  'values': ['inline', 'list', 'both', 'none']
	}], ['aria-braillelabel', {
	  'type': 'string'
	}], ['aria-brailleroledescription', {
	  'type': 'string'
	}], ['aria-busy', {
	  'type': 'boolean'
	}], ['aria-checked', {
	  'type': 'tristate'
	}], ['aria-colcount', {
	  type: 'integer'
	}], ['aria-colindex', {
	  type: 'integer'
	}], ['aria-colspan', {
	  type: 'integer'
	}], ['aria-controls', {
	  'type': 'idlist'
	}], ['aria-current', {
	  type: 'token',
	  values: ['page', 'step', 'location', 'date', 'time', true, false]
	}], ['aria-describedby', {
	  'type': 'idlist'
	}], ['aria-description', {
	  'type': 'string'
	}], ['aria-details', {
	  'type': 'id'
	}], ['aria-disabled', {
	  'type': 'boolean'
	}], ['aria-dropeffect', {
	  'type': 'tokenlist',
	  'values': ['copy', 'execute', 'link', 'move', 'none', 'popup']
	}], ['aria-errormessage', {
	  'type': 'id'
	}], ['aria-expanded', {
	  'type': 'boolean',
	  'allowundefined': true
	}], ['aria-flowto', {
	  'type': 'idlist'
	}], ['aria-grabbed', {
	  'type': 'boolean',
	  'allowundefined': true
	}], ['aria-haspopup', {
	  'type': 'token',
	  'values': [false, true, 'menu', 'listbox', 'tree', 'grid', 'dialog']
	}], ['aria-hidden', {
	  'type': 'boolean',
	  'allowundefined': true
	}], ['aria-invalid', {
	  'type': 'token',
	  'values': ['grammar', false, 'spelling', true]
	}], ['aria-keyshortcuts', {
	  type: 'string'
	}], ['aria-label', {
	  'type': 'string'
	}], ['aria-labelledby', {
	  'type': 'idlist'
	}], ['aria-level', {
	  'type': 'integer'
	}], ['aria-live', {
	  'type': 'token',
	  'values': ['assertive', 'off', 'polite']
	}], ['aria-modal', {
	  type: 'boolean'
	}], ['aria-multiline', {
	  'type': 'boolean'
	}], ['aria-multiselectable', {
	  'type': 'boolean'
	}], ['aria-orientation', {
	  'type': 'token',
	  'values': ['vertical', 'undefined', 'horizontal']
	}], ['aria-owns', {
	  'type': 'idlist'
	}], ['aria-placeholder', {
	  type: 'string'
	}], ['aria-posinset', {
	  'type': 'integer'
	}], ['aria-pressed', {
	  'type': 'tristate'
	}], ['aria-readonly', {
	  'type': 'boolean'
	}], ['aria-relevant', {
	  'type': 'tokenlist',
	  'values': ['additions', 'all', 'removals', 'text']
	}], ['aria-required', {
	  'type': 'boolean'
	}], ['aria-roledescription', {
	  type: 'string'
	}], ['aria-rowcount', {
	  type: 'integer'
	}], ['aria-rowindex', {
	  type: 'integer'
	}], ['aria-rowspan', {
	  type: 'integer'
	}], ['aria-selected', {
	  'type': 'boolean',
	  'allowundefined': true
	}], ['aria-setsize', {
	  'type': 'integer'
	}], ['aria-sort', {
	  'type': 'token',
	  'values': ['ascending', 'descending', 'none', 'other']
	}], ['aria-valuemax', {
	  'type': 'number'
	}], ['aria-valuemin', {
	  'type': 'number'
	}], ['aria-valuenow', {
	  'type': 'number'
	}], ['aria-valuetext', {
	  'type': 'string'
	}]];
	var ariaPropsMap$1 = {
	  entries: function entries() {
	    return properties;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    var _iterator = _createForOfIteratorHelper(properties),
	      _step;
	    try {
	      for (_iterator.s(); !(_step = _iterator.n()).done;) {
	        var _step$value = _slicedToArray(_step.value, 2),
	          key = _step$value[0],
	          values = _step$value[1];
	        fn.call(thisArg, values, key, properties);
	      }
	    } catch (err) {
	      _iterator.e(err);
	    } finally {
	      _iterator.f();
	    }
	  },
	  get: function get(key) {
	    var item = properties.find(function (tuple) {
	      return tuple[0] === key ? true : false;
	    });
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!ariaPropsMap$1.get(key);
	  },
	  keys: function keys() {
	    return properties.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return properties.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	var _default = (0, _iterationDecorator.default)(ariaPropsMap$1, ariaPropsMap$1.entries());
	ariaPropsMap.default = _default;
	return ariaPropsMap;
}

var domMap = {};

var hasRequiredDomMap;

function requireDomMap () {
	if (hasRequiredDomMap) return domMap;
	hasRequiredDomMap = 1;

	Object.defineProperty(domMap, "__esModule", {
	  value: true
	});
	domMap.default = undefined;
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
	function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
	function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike) { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
	function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
	function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
	var dom = [['a', {
	  reserved: false
	}], ['abbr', {
	  reserved: false
	}], ['acronym', {
	  reserved: false
	}], ['address', {
	  reserved: false
	}], ['applet', {
	  reserved: false
	}], ['area', {
	  reserved: false
	}], ['article', {
	  reserved: false
	}], ['aside', {
	  reserved: false
	}], ['audio', {
	  reserved: false
	}], ['b', {
	  reserved: false
	}], ['base', {
	  reserved: true
	}], ['bdi', {
	  reserved: false
	}], ['bdo', {
	  reserved: false
	}], ['big', {
	  reserved: false
	}], ['blink', {
	  reserved: false
	}], ['blockquote', {
	  reserved: false
	}], ['body', {
	  reserved: false
	}], ['br', {
	  reserved: false
	}], ['button', {
	  reserved: false
	}], ['canvas', {
	  reserved: false
	}], ['caption', {
	  reserved: false
	}], ['center', {
	  reserved: false
	}], ['cite', {
	  reserved: false
	}], ['code', {
	  reserved: false
	}], ['col', {
	  reserved: true
	}], ['colgroup', {
	  reserved: true
	}], ['content', {
	  reserved: false
	}], ['data', {
	  reserved: false
	}], ['datalist', {
	  reserved: false
	}], ['dd', {
	  reserved: false
	}], ['del', {
	  reserved: false
	}], ['details', {
	  reserved: false
	}], ['dfn', {
	  reserved: false
	}], ['dialog', {
	  reserved: false
	}], ['dir', {
	  reserved: false
	}], ['div', {
	  reserved: false
	}], ['dl', {
	  reserved: false
	}], ['dt', {
	  reserved: false
	}], ['em', {
	  reserved: false
	}], ['embed', {
	  reserved: false
	}], ['fieldset', {
	  reserved: false
	}], ['figcaption', {
	  reserved: false
	}], ['figure', {
	  reserved: false
	}], ['font', {
	  reserved: false
	}], ['footer', {
	  reserved: false
	}], ['form', {
	  reserved: false
	}], ['frame', {
	  reserved: false
	}], ['frameset', {
	  reserved: false
	}], ['h1', {
	  reserved: false
	}], ['h2', {
	  reserved: false
	}], ['h3', {
	  reserved: false
	}], ['h4', {
	  reserved: false
	}], ['h5', {
	  reserved: false
	}], ['h6', {
	  reserved: false
	}], ['head', {
	  reserved: true
	}], ['header', {
	  reserved: false
	}], ['hgroup', {
	  reserved: false
	}], ['hr', {
	  reserved: false
	}], ['html', {
	  reserved: true
	}], ['i', {
	  reserved: false
	}], ['iframe', {
	  reserved: false
	}], ['img', {
	  reserved: false
	}], ['input', {
	  reserved: false
	}], ['ins', {
	  reserved: false
	}], ['kbd', {
	  reserved: false
	}], ['keygen', {
	  reserved: false
	}], ['label', {
	  reserved: false
	}], ['legend', {
	  reserved: false
	}], ['li', {
	  reserved: false
	}], ['link', {
	  reserved: true
	}], ['main', {
	  reserved: false
	}], ['map', {
	  reserved: false
	}], ['mark', {
	  reserved: false
	}], ['marquee', {
	  reserved: false
	}], ['menu', {
	  reserved: false
	}], ['menuitem', {
	  reserved: false
	}], ['meta', {
	  reserved: true
	}], ['meter', {
	  reserved: false
	}], ['nav', {
	  reserved: false
	}], ['noembed', {
	  reserved: true
	}], ['noscript', {
	  reserved: true
	}], ['object', {
	  reserved: false
	}], ['ol', {
	  reserved: false
	}], ['optgroup', {
	  reserved: false
	}], ['option', {
	  reserved: false
	}], ['output', {
	  reserved: false
	}], ['p', {
	  reserved: false
	}], ['param', {
	  reserved: true
	}], ['picture', {
	  reserved: true
	}], ['pre', {
	  reserved: false
	}], ['progress', {
	  reserved: false
	}], ['q', {
	  reserved: false
	}], ['rp', {
	  reserved: false
	}], ['rt', {
	  reserved: false
	}], ['rtc', {
	  reserved: false
	}], ['ruby', {
	  reserved: false
	}], ['s', {
	  reserved: false
	}], ['samp', {
	  reserved: false
	}], ['script', {
	  reserved: true
	}], ['section', {
	  reserved: false
	}], ['select', {
	  reserved: false
	}], ['small', {
	  reserved: false
	}], ['source', {
	  reserved: true
	}], ['spacer', {
	  reserved: false
	}], ['span', {
	  reserved: false
	}], ['strike', {
	  reserved: false
	}], ['strong', {
	  reserved: false
	}], ['style', {
	  reserved: true
	}], ['sub', {
	  reserved: false
	}], ['summary', {
	  reserved: false
	}], ['sup', {
	  reserved: false
	}], ['table', {
	  reserved: false
	}], ['tbody', {
	  reserved: false
	}], ['td', {
	  reserved: false
	}], ['textarea', {
	  reserved: false
	}], ['tfoot', {
	  reserved: false
	}], ['th', {
	  reserved: false
	}], ['thead', {
	  reserved: false
	}], ['time', {
	  reserved: false
	}], ['title', {
	  reserved: true
	}], ['tr', {
	  reserved: false
	}], ['track', {
	  reserved: true
	}], ['tt', {
	  reserved: false
	}], ['u', {
	  reserved: false
	}], ['ul', {
	  reserved: false
	}], ['var', {
	  reserved: false
	}], ['video', {
	  reserved: false
	}], ['wbr', {
	  reserved: false
	}], ['xmp', {
	  reserved: false
	}]];
	var domMap$1 = {
	  entries: function entries() {
	    return dom;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    var _iterator = _createForOfIteratorHelper(dom),
	      _step;
	    try {
	      for (_iterator.s(); !(_step = _iterator.n()).done;) {
	        var _step$value = _slicedToArray(_step.value, 2),
	          key = _step$value[0],
	          values = _step$value[1];
	        fn.call(thisArg, values, key, dom);
	      }
	    } catch (err) {
	      _iterator.e(err);
	    } finally {
	      _iterator.f();
	    }
	  },
	  get: function get(key) {
	    var item = dom.find(function (tuple) {
	      return tuple[0] === key ? true : false;
	    });
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!domMap$1.get(key);
	  },
	  keys: function keys() {
	    return dom.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return dom.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	var _default = (0, _iterationDecorator.default)(domMap$1, domMap$1.entries());
	domMap.default = _default;
	return domMap;
}

var rolesMap = {};

var ariaAbstractRoles = {};

var commandRole = {};

var hasRequiredCommandRole;

function requireCommandRole () {
	if (hasRequiredCommandRole) return commandRole;
	hasRequiredCommandRole = 1;

	Object.defineProperty(commandRole, "__esModule", {
	  value: true
	});
	commandRole.default = undefined;
	var commandRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget']]
	};
	var _default = commandRole$1;
	commandRole.default = _default;
	return commandRole;
}

var compositeRole = {};

var hasRequiredCompositeRole;

function requireCompositeRole () {
	if (hasRequiredCompositeRole) return compositeRole;
	hasRequiredCompositeRole = 1;

	Object.defineProperty(compositeRole, "__esModule", {
	  value: true
	});
	compositeRole.default = undefined;
	var compositeRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-activedescendant': null,
	    'aria-disabled': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget']]
	};
	var _default = compositeRole$1;
	compositeRole.default = _default;
	return compositeRole;
}

var inputRole = {};

var hasRequiredInputRole;

function requireInputRole () {
	if (hasRequiredInputRole) return inputRole;
	hasRequiredInputRole = 1;

	Object.defineProperty(inputRole, "__esModule", {
	  value: true
	});
	inputRole.default = undefined;
	var inputRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'input'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget']]
	};
	var _default = inputRole$1;
	inputRole.default = _default;
	return inputRole;
}

var landmarkRole = {};

var hasRequiredLandmarkRole;

function requireLandmarkRole () {
	if (hasRequiredLandmarkRole) return landmarkRole;
	hasRequiredLandmarkRole = 1;

	Object.defineProperty(landmarkRole, "__esModule", {
	  value: true
	});
	landmarkRole.default = undefined;
	var landmarkRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = landmarkRole$1;
	landmarkRole.default = _default;
	return landmarkRole;
}

var rangeRole = {};

var hasRequiredRangeRole;

function requireRangeRole () {
	if (hasRequiredRangeRole) return rangeRole;
	hasRequiredRangeRole = 1;

	Object.defineProperty(rangeRole, "__esModule", {
	  value: true
	});
	rangeRole.default = undefined;
	var rangeRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-valuemax': null,
	    'aria-valuemin': null,
	    'aria-valuenow': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	var _default = rangeRole$1;
	rangeRole.default = _default;
	return rangeRole;
}

var roletypeRole = {};

var hasRequiredRoletypeRole;

function requireRoletypeRole () {
	if (hasRequiredRoletypeRole) return roletypeRole;
	hasRequiredRoletypeRole = 1;

	Object.defineProperty(roletypeRole, "__esModule", {
	  value: true
	});
	roletypeRole.default = undefined;
	var roletypeRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: [],
	  prohibitedProps: [],
	  props: {
	    'aria-atomic': null,
	    'aria-busy': null,
	    'aria-controls': null,
	    'aria-current': null,
	    'aria-describedby': null,
	    'aria-details': null,
	    'aria-dropeffect': null,
	    'aria-flowto': null,
	    'aria-grabbed': null,
	    'aria-hidden': null,
	    'aria-keyshortcuts': null,
	    'aria-label': null,
	    'aria-labelledby': null,
	    'aria-live': null,
	    'aria-owns': null,
	    'aria-relevant': null,
	    'aria-roledescription': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'role'
	    },
	    module: 'XHTML'
	  }, {
	    concept: {
	      name: 'type'
	    },
	    module: 'Dublin Core'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: []
	};
	var _default = roletypeRole$1;
	roletypeRole.default = _default;
	return roletypeRole;
}

var sectionRole = {};

var hasRequiredSectionRole;

function requireSectionRole () {
	if (hasRequiredSectionRole) return sectionRole;
	hasRequiredSectionRole = 1;

	Object.defineProperty(sectionRole, "__esModule", {
	  value: true
	});
	sectionRole.default = undefined;
	var sectionRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: [],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'frontmatter'
	    },
	    module: 'DTB'
	  }, {
	    concept: {
	      name: 'level'
	    },
	    module: 'DTB'
	  }, {
	    concept: {
	      name: 'level'
	    },
	    module: 'SMIL'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	var _default = sectionRole$1;
	sectionRole.default = _default;
	return sectionRole;
}

var sectionheadRole = {};

var hasRequiredSectionheadRole;

function requireSectionheadRole () {
	if (hasRequiredSectionheadRole) return sectionheadRole;
	hasRequiredSectionheadRole = 1;

	Object.defineProperty(sectionheadRole, "__esModule", {
	  value: true
	});
	sectionheadRole.default = undefined;
	var sectionheadRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	var _default = sectionheadRole$1;
	sectionheadRole.default = _default;
	return sectionheadRole;
}

var selectRole = {};

var hasRequiredSelectRole;

function requireSelectRole () {
	if (hasRequiredSelectRole) return selectRole;
	hasRequiredSelectRole = 1;

	Object.defineProperty(selectRole, "__esModule", {
	  value: true
	});
	selectRole.default = undefined;
	var selectRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-orientation': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite'], ['roletype', 'structure', 'section', 'group']]
	};
	var _default = selectRole$1;
	selectRole.default = _default;
	return selectRole;
}

var structureRole = {};

var hasRequiredStructureRole;

function requireStructureRole () {
	if (hasRequiredStructureRole) return structureRole;
	hasRequiredStructureRole = 1;

	Object.defineProperty(structureRole, "__esModule", {
	  value: true
	});
	structureRole.default = undefined;
	var structureRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: [],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype']]
	};
	var _default = structureRole$1;
	structureRole.default = _default;
	return structureRole;
}

var widgetRole = {};

var hasRequiredWidgetRole;

function requireWidgetRole () {
	if (hasRequiredWidgetRole) return widgetRole;
	hasRequiredWidgetRole = 1;

	Object.defineProperty(widgetRole, "__esModule", {
	  value: true
	});
	widgetRole.default = undefined;
	var widgetRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: [],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype']]
	};
	var _default = widgetRole$1;
	widgetRole.default = _default;
	return widgetRole;
}

var windowRole = {};

var hasRequiredWindowRole;

function requireWindowRole () {
	if (hasRequiredWindowRole) return windowRole;
	hasRequiredWindowRole = 1;

	Object.defineProperty(windowRole, "__esModule", {
	  value: true
	});
	windowRole.default = undefined;
	var windowRole$1 = {
	  abstract: true,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-modal': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype']]
	};
	var _default = windowRole$1;
	windowRole.default = _default;
	return windowRole;
}

var hasRequiredAriaAbstractRoles;

function requireAriaAbstractRoles () {
	if (hasRequiredAriaAbstractRoles) return ariaAbstractRoles;
	hasRequiredAriaAbstractRoles = 1;

	Object.defineProperty(ariaAbstractRoles, "__esModule", {
	  value: true
	});
	ariaAbstractRoles.default = undefined;
	var _commandRole = _interopRequireDefault(requireCommandRole());
	var _compositeRole = _interopRequireDefault(requireCompositeRole());
	var _inputRole = _interopRequireDefault(requireInputRole());
	var _landmarkRole = _interopRequireDefault(requireLandmarkRole());
	var _rangeRole = _interopRequireDefault(requireRangeRole());
	var _roletypeRole = _interopRequireDefault(requireRoletypeRole());
	var _sectionRole = _interopRequireDefault(requireSectionRole());
	var _sectionheadRole = _interopRequireDefault(requireSectionheadRole());
	var _selectRole = _interopRequireDefault(requireSelectRole());
	var _structureRole = _interopRequireDefault(requireStructureRole());
	var _widgetRole = _interopRequireDefault(requireWidgetRole());
	var _windowRole = _interopRequireDefault(requireWindowRole());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var ariaAbstractRoles$1 = [['command', _commandRole.default], ['composite', _compositeRole.default], ['input', _inputRole.default], ['landmark', _landmarkRole.default], ['range', _rangeRole.default], ['roletype', _roletypeRole.default], ['section', _sectionRole.default], ['sectionhead', _sectionheadRole.default], ['select', _selectRole.default], ['structure', _structureRole.default], ['widget', _widgetRole.default], ['window', _windowRole.default]];
	var _default = ariaAbstractRoles$1;
	ariaAbstractRoles.default = _default;
	return ariaAbstractRoles;
}

var ariaLiteralRoles = {};

var alertRole = {};

var hasRequiredAlertRole;

function requireAlertRole () {
	if (hasRequiredAlertRole) return alertRole;
	hasRequiredAlertRole = 1;

	Object.defineProperty(alertRole, "__esModule", {
	  value: true
	});
	alertRole.default = undefined;
	var alertRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-atomic': 'true',
	    'aria-live': 'assertive'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'alert'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = alertRole$1;
	alertRole.default = _default;
	return alertRole;
}

var alertdialogRole = {};

var hasRequiredAlertdialogRole;

function requireAlertdialogRole () {
	if (hasRequiredAlertdialogRole) return alertdialogRole;
	hasRequiredAlertdialogRole = 1;

	Object.defineProperty(alertdialogRole, "__esModule", {
	  value: true
	});
	alertdialogRole.default = undefined;
	var alertdialogRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'alert'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'alert'], ['roletype', 'window', 'dialog']]
	};
	var _default = alertdialogRole$1;
	alertdialogRole.default = _default;
	return alertdialogRole;
}

var applicationRole = {};

var hasRequiredApplicationRole;

function requireApplicationRole () {
	if (hasRequiredApplicationRole) return applicationRole;
	hasRequiredApplicationRole = 1;

	Object.defineProperty(applicationRole, "__esModule", {
	  value: true
	});
	applicationRole.default = undefined;
	var applicationRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-activedescendant': null,
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'Device Independence Delivery Unit'
	    }
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	var _default = applicationRole$1;
	applicationRole.default = _default;
	return applicationRole;
}

var articleRole = {};

var hasRequiredArticleRole;

function requireArticleRole () {
	if (hasRequiredArticleRole) return articleRole;
	hasRequiredArticleRole = 1;

	Object.defineProperty(articleRole, "__esModule", {
	  value: true
	});
	articleRole.default = undefined;
	var articleRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-posinset': null,
	    'aria-setsize': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'article'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'document']]
	};
	var _default = articleRole$1;
	articleRole.default = _default;
	return articleRole;
}

var bannerRole = {};

var hasRequiredBannerRole;

function requireBannerRole () {
	if (hasRequiredBannerRole) return bannerRole;
	hasRequiredBannerRole = 1;

	Object.defineProperty(bannerRole, "__esModule", {
	  value: true
	});
	bannerRole.default = undefined;
	var bannerRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      constraints: ['scoped to the body element'],
	      name: 'header'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = bannerRole$1;
	bannerRole.default = _default;
	return bannerRole;
}

var blockquoteRole = {};

var hasRequiredBlockquoteRole;

function requireBlockquoteRole () {
	if (hasRequiredBlockquoteRole) return blockquoteRole;
	hasRequiredBlockquoteRole = 1;

	Object.defineProperty(blockquoteRole, "__esModule", {
	  value: true
	});
	blockquoteRole.default = undefined;
	var blockquoteRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'blockquote'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = blockquoteRole$1;
	blockquoteRole.default = _default;
	return blockquoteRole;
}

var buttonRole = {};

var hasRequiredButtonRole;

function requireButtonRole () {
	if (hasRequiredButtonRole) return buttonRole;
	hasRequiredButtonRole = 1;

	Object.defineProperty(buttonRole, "__esModule", {
	  value: true
	});
	buttonRole.default = undefined;
	var buttonRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-pressed': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'button'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'image'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'reset'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'submit'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'button'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'trigger'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command']]
	};
	var _default = buttonRole$1;
	buttonRole.default = _default;
	return buttonRole;
}

var captionRole = {};

var hasRequiredCaptionRole;

function requireCaptionRole () {
	if (hasRequiredCaptionRole) return captionRole;
	hasRequiredCaptionRole = 1;

	Object.defineProperty(captionRole, "__esModule", {
	  value: true
	});
	captionRole.default = undefined;
	var captionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'caption'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['figure', 'grid', 'table'],
	  requiredContextRole: ['figure', 'grid', 'table'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = captionRole$1;
	captionRole.default = _default;
	return captionRole;
}

var cellRole = {};

var hasRequiredCellRole;

function requireCellRole () {
	if (hasRequiredCellRole) return cellRole;
	hasRequiredCellRole = 1;

	Object.defineProperty(cellRole, "__esModule", {
	  value: true
	});
	cellRole.default = undefined;
	var cellRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-colindex': null,
	    'aria-colspan': null,
	    'aria-rowindex': null,
	    'aria-rowspan': null
	  },
	  relatedConcepts: [{
	    concept: {
	      constraints: ['ancestor table element has table role'],
	      name: 'td'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['row'],
	  requiredContextRole: ['row'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = cellRole$1;
	cellRole.default = _default;
	return cellRole;
}

var checkboxRole = {};

var hasRequiredCheckboxRole;

function requireCheckboxRole () {
	if (hasRequiredCheckboxRole) return checkboxRole;
	hasRequiredCheckboxRole = 1;

	Object.defineProperty(checkboxRole, "__esModule", {
	  value: true
	});
	checkboxRole.default = undefined;
	var checkboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-checked': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-required': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'checkbox'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'option'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-checked': null
	  },
	  superClass: [['roletype', 'widget', 'input']]
	};
	var _default = checkboxRole$1;
	checkboxRole.default = _default;
	return checkboxRole;
}

var codeRole = {};

var hasRequiredCodeRole;

function requireCodeRole () {
	if (hasRequiredCodeRole) return codeRole;
	hasRequiredCodeRole = 1;

	Object.defineProperty(codeRole, "__esModule", {
	  value: true
	});
	codeRole.default = undefined;
	var codeRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'code'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = codeRole$1;
	codeRole.default = _default;
	return codeRole;
}

var columnheaderRole = {};

var hasRequiredColumnheaderRole;

function requireColumnheaderRole () {
	if (hasRequiredColumnheaderRole) return columnheaderRole;
	hasRequiredColumnheaderRole = 1;

	Object.defineProperty(columnheaderRole, "__esModule", {
	  value: true
	});
	columnheaderRole.default = undefined;
	var columnheaderRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-sort': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'th'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'scope',
	        value: 'col'
	      }],
	      name: 'th'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'scope',
	        value: 'colgroup'
	      }],
	      name: 'th'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['row'],
	  requiredContextRole: ['row'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'cell'], ['roletype', 'structure', 'section', 'cell', 'gridcell'], ['roletype', 'widget', 'gridcell'], ['roletype', 'structure', 'sectionhead']]
	};
	var _default = columnheaderRole$1;
	columnheaderRole.default = _default;
	return columnheaderRole;
}

var comboboxRole = {};

var hasRequiredComboboxRole;

function requireComboboxRole () {
	if (hasRequiredComboboxRole) return comboboxRole;
	hasRequiredComboboxRole = 1;

	Object.defineProperty(comboboxRole, "__esModule", {
	  value: true
	});
	comboboxRole.default = undefined;
	var comboboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-activedescendant': null,
	    'aria-autocomplete': null,
	    'aria-errormessage': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-required': null,
	    'aria-expanded': 'false',
	    'aria-haspopup': 'listbox'
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'email'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'search'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'tel'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'text'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'url'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'url'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'multiple'
	      }, {
	        constraints: ['undefined'],
	        name: 'size'
	      }],
	      constraints: ['the multiple attribute is not set and the size attribute does not have a value greater than 1'],
	      name: 'select'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'select'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-controls': null,
	    'aria-expanded': 'false'
	  },
	  superClass: [['roletype', 'widget', 'input']]
	};
	var _default = comboboxRole$1;
	comboboxRole.default = _default;
	return comboboxRole;
}

var complementaryRole = {};

var hasRequiredComplementaryRole;

function requireComplementaryRole () {
	if (hasRequiredComplementaryRole) return complementaryRole;
	hasRequiredComplementaryRole = 1;

	Object.defineProperty(complementaryRole, "__esModule", {
	  value: true
	});
	complementaryRole.default = undefined;
	var complementaryRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'aside'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-label'
	      }],
	      constraints: ['scoped to a sectioning content element', 'scoped to a sectioning root element other than body'],
	      name: 'aside'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-labelledby'
	      }],
	      constraints: ['scoped to a sectioning content element', 'scoped to a sectioning root element other than body'],
	      name: 'aside'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = complementaryRole$1;
	complementaryRole.default = _default;
	return complementaryRole;
}

var contentinfoRole = {};

var hasRequiredContentinfoRole;

function requireContentinfoRole () {
	if (hasRequiredContentinfoRole) return contentinfoRole;
	hasRequiredContentinfoRole = 1;

	Object.defineProperty(contentinfoRole, "__esModule", {
	  value: true
	});
	contentinfoRole.default = undefined;
	var contentinfoRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      constraints: ['scoped to the body element'],
	      name: 'footer'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = contentinfoRole$1;
	contentinfoRole.default = _default;
	return contentinfoRole;
}

var definitionRole = {};

var hasRequiredDefinitionRole;

function requireDefinitionRole () {
	if (hasRequiredDefinitionRole) return definitionRole;
	hasRequiredDefinitionRole = 1;

	Object.defineProperty(definitionRole, "__esModule", {
	  value: true
	});
	definitionRole.default = undefined;
	var definitionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'dd'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = definitionRole$1;
	definitionRole.default = _default;
	return definitionRole;
}

var deletionRole = {};

var hasRequiredDeletionRole;

function requireDeletionRole () {
	if (hasRequiredDeletionRole) return deletionRole;
	hasRequiredDeletionRole = 1;

	Object.defineProperty(deletionRole, "__esModule", {
	  value: true
	});
	deletionRole.default = undefined;
	var deletionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'del'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = deletionRole$1;
	deletionRole.default = _default;
	return deletionRole;
}

var dialogRole = {};

var hasRequiredDialogRole;

function requireDialogRole () {
	if (hasRequiredDialogRole) return dialogRole;
	hasRequiredDialogRole = 1;

	Object.defineProperty(dialogRole, "__esModule", {
	  value: true
	});
	dialogRole.default = undefined;
	var dialogRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'dialog'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'window']]
	};
	var _default = dialogRole$1;
	dialogRole.default = _default;
	return dialogRole;
}

var directoryRole = {};

var hasRequiredDirectoryRole;

function requireDirectoryRole () {
	if (hasRequiredDirectoryRole) return directoryRole;
	hasRequiredDirectoryRole = 1;

	Object.defineProperty(directoryRole, "__esModule", {
	  value: true
	});
	directoryRole.default = undefined;
	var directoryRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    module: 'DAISY Guide'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'list']]
	};
	var _default = directoryRole$1;
	directoryRole.default = _default;
	return directoryRole;
}

var documentRole = {};

var hasRequiredDocumentRole;

function requireDocumentRole () {
	if (hasRequiredDocumentRole) return documentRole;
	hasRequiredDocumentRole = 1;

	Object.defineProperty(documentRole, "__esModule", {
	  value: true
	});
	documentRole.default = undefined;
	var documentRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'Device Independence Delivery Unit'
	    }
	  }, {
	    concept: {
	      name: 'html'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	var _default = documentRole$1;
	documentRole.default = _default;
	return documentRole;
}

var emphasisRole = {};

var hasRequiredEmphasisRole;

function requireEmphasisRole () {
	if (hasRequiredEmphasisRole) return emphasisRole;
	hasRequiredEmphasisRole = 1;

	Object.defineProperty(emphasisRole, "__esModule", {
	  value: true
	});
	emphasisRole.default = undefined;
	var emphasisRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'em'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = emphasisRole$1;
	emphasisRole.default = _default;
	return emphasisRole;
}

var feedRole = {};

var hasRequiredFeedRole;

function requireFeedRole () {
	if (hasRequiredFeedRole) return feedRole;
	hasRequiredFeedRole = 1;

	Object.defineProperty(feedRole, "__esModule", {
	  value: true
	});
	feedRole.default = undefined;
	var feedRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['article']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'list']]
	};
	var _default = feedRole$1;
	feedRole.default = _default;
	return feedRole;
}

var figureRole = {};

var hasRequiredFigureRole;

function requireFigureRole () {
	if (hasRequiredFigureRole) return figureRole;
	hasRequiredFigureRole = 1;

	Object.defineProperty(figureRole, "__esModule", {
	  value: true
	});
	figureRole.default = undefined;
	var figureRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'figure'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = figureRole$1;
	figureRole.default = _default;
	return figureRole;
}

var formRole = {};

var hasRequiredFormRole;

function requireFormRole () {
	if (hasRequiredFormRole) return formRole;
	hasRequiredFormRole = 1;

	Object.defineProperty(formRole, "__esModule", {
	  value: true
	});
	formRole.default = undefined;
	var formRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-label'
	      }],
	      name: 'form'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-labelledby'
	      }],
	      name: 'form'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'name'
	      }],
	      name: 'form'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = formRole$1;
	formRole.default = _default;
	return formRole;
}

var genericRole = {};

var hasRequiredGenericRole;

function requireGenericRole () {
	if (hasRequiredGenericRole) return genericRole;
	hasRequiredGenericRole = 1;

	Object.defineProperty(genericRole, "__esModule", {
	  value: true
	});
	genericRole.default = undefined;
	var genericRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'a'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'area'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'aside'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'b'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'bdo'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'body'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'data'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'div'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      constraints: ['scoped to the main element', 'scoped to a sectioning content element', 'scoped to a sectioning root element other than body'],
	      name: 'footer'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      constraints: ['scoped to the main element', 'scoped to a sectioning content element', 'scoped to a sectioning root element other than body'],
	      name: 'header'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'hgroup'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'i'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'pre'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'q'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'samp'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'section'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'small'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'span'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'u'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	var _default = genericRole$1;
	genericRole.default = _default;
	return genericRole;
}

var gridRole = {};

var hasRequiredGridRole;

function requireGridRole () {
	if (hasRequiredGridRole) return gridRole;
	hasRequiredGridRole = 1;

	Object.defineProperty(gridRole, "__esModule", {
	  value: true
	});
	gridRole.default = undefined;
	var gridRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-multiselectable': null,
	    'aria-readonly': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['row'], ['row', 'rowgroup']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite'], ['roletype', 'structure', 'section', 'table']]
	};
	var _default = gridRole$1;
	gridRole.default = _default;
	return gridRole;
}

var gridcellRole = {};

var hasRequiredGridcellRole;

function requireGridcellRole () {
	if (hasRequiredGridcellRole) return gridcellRole;
	hasRequiredGridcellRole = 1;

	Object.defineProperty(gridcellRole, "__esModule", {
	  value: true
	});
	gridcellRole.default = undefined;
	var gridcellRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-required': null,
	    'aria-selected': null
	  },
	  relatedConcepts: [{
	    concept: {
	      constraints: ['ancestor table element has grid role', 'ancestor table element has treegrid role'],
	      name: 'td'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['row'],
	  requiredContextRole: ['row'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'cell'], ['roletype', 'widget']]
	};
	var _default = gridcellRole$1;
	gridcellRole.default = _default;
	return gridcellRole;
}

var groupRole = {};

var hasRequiredGroupRole;

function requireGroupRole () {
	if (hasRequiredGroupRole) return groupRole;
	hasRequiredGroupRole = 1;

	Object.defineProperty(groupRole, "__esModule", {
	  value: true
	});
	groupRole.default = undefined;
	var groupRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-activedescendant': null,
	    'aria-disabled': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'details'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'fieldset'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'optgroup'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'address'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = groupRole$1;
	groupRole.default = _default;
	return groupRole;
}

var headingRole = {};

var hasRequiredHeadingRole;

function requireHeadingRole () {
	if (hasRequiredHeadingRole) return headingRole;
	hasRequiredHeadingRole = 1;

	Object.defineProperty(headingRole, "__esModule", {
	  value: true
	});
	headingRole.default = undefined;
	var headingRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-level': '2'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'h1'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'h2'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'h3'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'h4'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'h5'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'h6'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-level': '2'
	  },
	  superClass: [['roletype', 'structure', 'sectionhead']]
	};
	var _default = headingRole$1;
	headingRole.default = _default;
	return headingRole;
}

var imgRole = {};

var hasRequiredImgRole;

function requireImgRole () {
	if (hasRequiredImgRole) return imgRole;
	hasRequiredImgRole = 1;

	Object.defineProperty(imgRole, "__esModule", {
	  value: true
	});
	imgRole.default = undefined;
	var imgRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'alt'
	      }],
	      name: 'img'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'alt'
	      }],
	      name: 'img'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'imggroup'
	    },
	    module: 'DTB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = imgRole$1;
	imgRole.default = _default;
	return imgRole;
}

var insertionRole = {};

var hasRequiredInsertionRole;

function requireInsertionRole () {
	if (hasRequiredInsertionRole) return insertionRole;
	hasRequiredInsertionRole = 1;

	Object.defineProperty(insertionRole, "__esModule", {
	  value: true
	});
	insertionRole.default = undefined;
	var insertionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'ins'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = insertionRole$1;
	insertionRole.default = _default;
	return insertionRole;
}

var linkRole = {};

var hasRequiredLinkRole;

function requireLinkRole () {
	if (hasRequiredLinkRole) return linkRole;
	hasRequiredLinkRole = 1;

	Object.defineProperty(linkRole, "__esModule", {
	  value: true
	});
	linkRole.default = undefined;
	var linkRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-expanded': null,
	    'aria-haspopup': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'href'
	      }],
	      name: 'a'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'href'
	      }],
	      name: 'area'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command']]
	};
	var _default = linkRole$1;
	linkRole.default = _default;
	return linkRole;
}

var listRole = {};

var hasRequiredListRole;

function requireListRole () {
	if (hasRequiredListRole) return listRole;
	hasRequiredListRole = 1;

	Object.defineProperty(listRole, "__esModule", {
	  value: true
	});
	listRole.default = undefined;
	var listRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'menu'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'ol'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'ul'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['listitem']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = listRole$1;
	listRole.default = _default;
	return listRole;
}

var listboxRole = {};

var hasRequiredListboxRole;

function requireListboxRole () {
	if (hasRequiredListboxRole) return listboxRole;
	hasRequiredListboxRole = 1;

	Object.defineProperty(listboxRole, "__esModule", {
	  value: true
	});
	listboxRole.default = undefined;
	var listboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-invalid': null,
	    'aria-multiselectable': null,
	    'aria-readonly': null,
	    'aria-required': null,
	    'aria-orientation': 'vertical'
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['>1'],
	        name: 'size'
	      }],
	      constraints: ['the size attribute value is greater than 1'],
	      name: 'select'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'multiple'
	      }],
	      name: 'select'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'datalist'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'list'
	    },
	    module: 'ARIA'
	  }, {
	    concept: {
	      name: 'select'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['option', 'group'], ['option']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'select'], ['roletype', 'structure', 'section', 'group', 'select']]
	};
	var _default = listboxRole$1;
	listboxRole.default = _default;
	return listboxRole;
}

var listitemRole = {};

var hasRequiredListitemRole;

function requireListitemRole () {
	if (hasRequiredListitemRole) return listitemRole;
	hasRequiredListitemRole = 1;

	Object.defineProperty(listitemRole, "__esModule", {
	  value: true
	});
	listitemRole.default = undefined;
	var listitemRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-level': null,
	    'aria-posinset': null,
	    'aria-setsize': null
	  },
	  relatedConcepts: [{
	    concept: {
	      constraints: ['direct descendant of ol', 'direct descendant of ul', 'direct descendant of menu'],
	      name: 'li'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'item'
	    },
	    module: 'XForms'
	  }],
	  requireContextRole: ['directory', 'list'],
	  requiredContextRole: ['directory', 'list'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = listitemRole$1;
	listitemRole.default = _default;
	return listitemRole;
}

var logRole = {};

var hasRequiredLogRole;

function requireLogRole () {
	if (hasRequiredLogRole) return logRole;
	hasRequiredLogRole = 1;

	Object.defineProperty(logRole, "__esModule", {
	  value: true
	});
	logRole.default = undefined;
	var logRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-live': 'polite'
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = logRole$1;
	logRole.default = _default;
	return logRole;
}

var mainRole = {};

var hasRequiredMainRole;

function requireMainRole () {
	if (hasRequiredMainRole) return mainRole;
	hasRequiredMainRole = 1;

	Object.defineProperty(mainRole, "__esModule", {
	  value: true
	});
	mainRole.default = undefined;
	var mainRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'main'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = mainRole$1;
	mainRole.default = _default;
	return mainRole;
}

var markRole = {};

var hasRequiredMarkRole;

function requireMarkRole () {
	if (hasRequiredMarkRole) return markRole;
	hasRequiredMarkRole = 1;

	Object.defineProperty(markRole, "__esModule", {
	  value: true
	});
	markRole.default = undefined;
	var markRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: [],
	  props: {
	    'aria-braillelabel': null,
	    'aria-brailleroledescription': null,
	    'aria-description': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'mark'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = markRole$1;
	markRole.default = _default;
	return markRole;
}

var marqueeRole = {};

var hasRequiredMarqueeRole;

function requireMarqueeRole () {
	if (hasRequiredMarqueeRole) return marqueeRole;
	hasRequiredMarqueeRole = 1;

	Object.defineProperty(marqueeRole, "__esModule", {
	  value: true
	});
	marqueeRole.default = undefined;
	var marqueeRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = marqueeRole$1;
	marqueeRole.default = _default;
	return marqueeRole;
}

var mathRole = {};

var hasRequiredMathRole;

function requireMathRole () {
	if (hasRequiredMathRole) return mathRole;
	hasRequiredMathRole = 1;

	Object.defineProperty(mathRole, "__esModule", {
	  value: true
	});
	mathRole.default = undefined;
	var mathRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'math'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = mathRole$1;
	mathRole.default = _default;
	return mathRole;
}

var menuRole = {};

var hasRequiredMenuRole;

function requireMenuRole () {
	if (hasRequiredMenuRole) return menuRole;
	hasRequiredMenuRole = 1;

	Object.defineProperty(menuRole, "__esModule", {
	  value: true
	});
	menuRole.default = undefined;
	var menuRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-orientation': 'vertical'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'MENU'
	    },
	    module: 'JAPI'
	  }, {
	    concept: {
	      name: 'list'
	    },
	    module: 'ARIA'
	  }, {
	    concept: {
	      name: 'select'
	    },
	    module: 'XForms'
	  }, {
	    concept: {
	      name: 'sidebar'
	    },
	    module: 'DTB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['menuitem', 'group'], ['menuitemradio', 'group'], ['menuitemcheckbox', 'group'], ['menuitem'], ['menuitemcheckbox'], ['menuitemradio']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'select'], ['roletype', 'structure', 'section', 'group', 'select']]
	};
	var _default = menuRole$1;
	menuRole.default = _default;
	return menuRole;
}

var menubarRole = {};

var hasRequiredMenubarRole;

function requireMenubarRole () {
	if (hasRequiredMenubarRole) return menubarRole;
	hasRequiredMenubarRole = 1;

	Object.defineProperty(menubarRole, "__esModule", {
	  value: true
	});
	menubarRole.default = undefined;
	var menubarRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-orientation': 'horizontal'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'toolbar'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['menuitem', 'group'], ['menuitemradio', 'group'], ['menuitemcheckbox', 'group'], ['menuitem'], ['menuitemcheckbox'], ['menuitemradio']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'select', 'menu'], ['roletype', 'structure', 'section', 'group', 'select', 'menu']]
	};
	var _default = menubarRole$1;
	menubarRole.default = _default;
	return menubarRole;
}

var menuitemRole = {};

var hasRequiredMenuitemRole;

function requireMenuitemRole () {
	if (hasRequiredMenuitemRole) return menuitemRole;
	hasRequiredMenuitemRole = 1;

	Object.defineProperty(menuitemRole, "__esModule", {
	  value: true
	});
	menuitemRole.default = undefined;
	var menuitemRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-posinset': null,
	    'aria-setsize': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'MENU_ITEM'
	    },
	    module: 'JAPI'
	  }, {
	    concept: {
	      name: 'listitem'
	    },
	    module: 'ARIA'
	  }, {
	    concept: {
	      name: 'option'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: ['group', 'menu', 'menubar'],
	  requiredContextRole: ['group', 'menu', 'menubar'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command']]
	};
	var _default = menuitemRole$1;
	menuitemRole.default = _default;
	return menuitemRole;
}

var menuitemcheckboxRole = {};

var hasRequiredMenuitemcheckboxRole;

function requireMenuitemcheckboxRole () {
	if (hasRequiredMenuitemcheckboxRole) return menuitemcheckboxRole;
	hasRequiredMenuitemcheckboxRole = 1;

	Object.defineProperty(menuitemcheckboxRole, "__esModule", {
	  value: true
	});
	menuitemcheckboxRole.default = undefined;
	var menuitemcheckboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'menuitem'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: ['group', 'menu', 'menubar'],
	  requiredContextRole: ['group', 'menu', 'menubar'],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-checked': null
	  },
	  superClass: [['roletype', 'widget', 'input', 'checkbox'], ['roletype', 'widget', 'command', 'menuitem']]
	};
	var _default = menuitemcheckboxRole$1;
	menuitemcheckboxRole.default = _default;
	return menuitemcheckboxRole;
}

var menuitemradioRole = {};

var hasRequiredMenuitemradioRole;

function requireMenuitemradioRole () {
	if (hasRequiredMenuitemradioRole) return menuitemradioRole;
	hasRequiredMenuitemradioRole = 1;

	Object.defineProperty(menuitemradioRole, "__esModule", {
	  value: true
	});
	menuitemradioRole.default = undefined;
	var menuitemradioRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'menuitem'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: ['group', 'menu', 'menubar'],
	  requiredContextRole: ['group', 'menu', 'menubar'],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-checked': null
	  },
	  superClass: [['roletype', 'widget', 'input', 'checkbox', 'menuitemcheckbox'], ['roletype', 'widget', 'command', 'menuitem', 'menuitemcheckbox'], ['roletype', 'widget', 'input', 'radio']]
	};
	var _default = menuitemradioRole$1;
	menuitemradioRole.default = _default;
	return menuitemradioRole;
}

var meterRole = {};

var hasRequiredMeterRole;

function requireMeterRole () {
	if (hasRequiredMeterRole) return meterRole;
	hasRequiredMeterRole = 1;

	Object.defineProperty(meterRole, "__esModule", {
	  value: true
	});
	meterRole.default = undefined;
	var meterRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-valuetext': null,
	    'aria-valuemax': '100',
	    'aria-valuemin': '0'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'meter'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-valuenow': null
	  },
	  superClass: [['roletype', 'structure', 'range']]
	};
	var _default = meterRole$1;
	meterRole.default = _default;
	return meterRole;
}

var navigationRole = {};

var hasRequiredNavigationRole;

function requireNavigationRole () {
	if (hasRequiredNavigationRole) return navigationRole;
	hasRequiredNavigationRole = 1;

	Object.defineProperty(navigationRole, "__esModule", {
	  value: true
	});
	navigationRole.default = undefined;
	var navigationRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'nav'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = navigationRole$1;
	navigationRole.default = _default;
	return navigationRole;
}

var noneRole = {};

var hasRequiredNoneRole;

function requireNoneRole () {
	if (hasRequiredNoneRole) return noneRole;
	hasRequiredNoneRole = 1;

	Object.defineProperty(noneRole, "__esModule", {
	  value: true
	});
	noneRole.default = undefined;
	var noneRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: [],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: []
	};
	var _default = noneRole$1;
	noneRole.default = _default;
	return noneRole;
}

var noteRole = {};

var hasRequiredNoteRole;

function requireNoteRole () {
	if (hasRequiredNoteRole) return noteRole;
	hasRequiredNoteRole = 1;

	Object.defineProperty(noteRole, "__esModule", {
	  value: true
	});
	noteRole.default = undefined;
	var noteRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = noteRole$1;
	noteRole.default = _default;
	return noteRole;
}

var optionRole = {};

var hasRequiredOptionRole;

function requireOptionRole () {
	if (hasRequiredOptionRole) return optionRole;
	hasRequiredOptionRole = 1;

	Object.defineProperty(optionRole, "__esModule", {
	  value: true
	});
	optionRole.default = undefined;
	var optionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-checked': null,
	    'aria-posinset': null,
	    'aria-setsize': null,
	    'aria-selected': 'false'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'item'
	    },
	    module: 'XForms'
	  }, {
	    concept: {
	      name: 'listitem'
	    },
	    module: 'ARIA'
	  }, {
	    concept: {
	      name: 'option'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-selected': 'false'
	  },
	  superClass: [['roletype', 'widget', 'input']]
	};
	var _default = optionRole$1;
	optionRole.default = _default;
	return optionRole;
}

var paragraphRole = {};

var hasRequiredParagraphRole;

function requireParagraphRole () {
	if (hasRequiredParagraphRole) return paragraphRole;
	hasRequiredParagraphRole = 1;

	Object.defineProperty(paragraphRole, "__esModule", {
	  value: true
	});
	paragraphRole.default = undefined;
	var paragraphRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'p'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = paragraphRole$1;
	paragraphRole.default = _default;
	return paragraphRole;
}

var presentationRole = {};

var hasRequiredPresentationRole;

function requirePresentationRole () {
	if (hasRequiredPresentationRole) return presentationRole;
	hasRequiredPresentationRole = 1;

	Object.defineProperty(presentationRole, "__esModule", {
	  value: true
	});
	presentationRole.default = undefined;
	var presentationRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'alt',
	        value: ''
	      }],
	      name: 'img'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	var _default = presentationRole$1;
	presentationRole.default = _default;
	return presentationRole;
}

var progressbarRole = {};

var hasRequiredProgressbarRole;

function requireProgressbarRole () {
	if (hasRequiredProgressbarRole) return progressbarRole;
	hasRequiredProgressbarRole = 1;

	Object.defineProperty(progressbarRole, "__esModule", {
	  value: true
	});
	progressbarRole.default = undefined;
	var progressbarRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-valuetext': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'progress'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'status'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'range'], ['roletype', 'widget']]
	};
	var _default = progressbarRole$1;
	progressbarRole.default = _default;
	return progressbarRole;
}

var radioRole = {};

var hasRequiredRadioRole;

function requireRadioRole () {
	if (hasRequiredRadioRole) return radioRole;
	hasRequiredRadioRole = 1;

	Object.defineProperty(radioRole, "__esModule", {
	  value: true
	});
	radioRole.default = undefined;
	var radioRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-checked': null,
	    'aria-posinset': null,
	    'aria-setsize': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'radio'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-checked': null
	  },
	  superClass: [['roletype', 'widget', 'input']]
	};
	var _default = radioRole$1;
	radioRole.default = _default;
	return radioRole;
}

var radiogroupRole = {};

var hasRequiredRadiogroupRole;

function requireRadiogroupRole () {
	if (hasRequiredRadiogroupRole) return radiogroupRole;
	hasRequiredRadiogroupRole = 1;

	Object.defineProperty(radiogroupRole, "__esModule", {
	  value: true
	});
	radiogroupRole.default = undefined;
	var radiogroupRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-required': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'list'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['radio']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'select'], ['roletype', 'structure', 'section', 'group', 'select']]
	};
	var _default = radiogroupRole$1;
	radiogroupRole.default = _default;
	return radiogroupRole;
}

var regionRole = {};

var hasRequiredRegionRole;

function requireRegionRole () {
	if (hasRequiredRegionRole) return regionRole;
	hasRequiredRegionRole = 1;

	Object.defineProperty(regionRole, "__esModule", {
	  value: true
	});
	regionRole.default = undefined;
	var regionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-label'
	      }],
	      name: 'section'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['set'],
	        name: 'aria-labelledby'
	      }],
	      name: 'section'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'Device Independence Glossart perceivable unit'
	    }
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = regionRole$1;
	regionRole.default = _default;
	return regionRole;
}

var rowRole = {};

var hasRequiredRowRole;

function requireRowRole () {
	if (hasRequiredRowRole) return rowRole;
	hasRequiredRowRole = 1;

	Object.defineProperty(rowRole, "__esModule", {
	  value: true
	});
	rowRole.default = undefined;
	var rowRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-colindex': null,
	    'aria-expanded': null,
	    'aria-level': null,
	    'aria-posinset': null,
	    'aria-rowindex': null,
	    'aria-selected': null,
	    'aria-setsize': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'tr'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['grid', 'rowgroup', 'table', 'treegrid'],
	  requiredContextRole: ['grid', 'rowgroup', 'table', 'treegrid'],
	  requiredOwnedElements: [['cell'], ['columnheader'], ['gridcell'], ['rowheader']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'group'], ['roletype', 'widget']]
	};
	var _default = rowRole$1;
	rowRole.default = _default;
	return rowRole;
}

var rowgroupRole = {};

var hasRequiredRowgroupRole;

function requireRowgroupRole () {
	if (hasRequiredRowgroupRole) return rowgroupRole;
	hasRequiredRowgroupRole = 1;

	Object.defineProperty(rowgroupRole, "__esModule", {
	  value: true
	});
	rowgroupRole.default = undefined;
	var rowgroupRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'tbody'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'tfoot'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'thead'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['grid', 'table', 'treegrid'],
	  requiredContextRole: ['grid', 'table', 'treegrid'],
	  requiredOwnedElements: [['row']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	var _default = rowgroupRole$1;
	rowgroupRole.default = _default;
	return rowgroupRole;
}

var rowheaderRole = {};

var hasRequiredRowheaderRole;

function requireRowheaderRole () {
	if (hasRequiredRowheaderRole) return rowheaderRole;
	hasRequiredRowheaderRole = 1;

	Object.defineProperty(rowheaderRole, "__esModule", {
	  value: true
	});
	rowheaderRole.default = undefined;
	var rowheaderRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-sort': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'scope',
	        value: 'row'
	      }],
	      name: 'th'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        name: 'scope',
	        value: 'rowgroup'
	      }],
	      name: 'th'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: ['row', 'rowgroup'],
	  requiredContextRole: ['row', 'rowgroup'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'cell'], ['roletype', 'structure', 'section', 'cell', 'gridcell'], ['roletype', 'widget', 'gridcell'], ['roletype', 'structure', 'sectionhead']]
	};
	var _default = rowheaderRole$1;
	rowheaderRole.default = _default;
	return rowheaderRole;
}

var scrollbarRole = {};

var hasRequiredScrollbarRole;

function requireScrollbarRole () {
	if (hasRequiredScrollbarRole) return scrollbarRole;
	hasRequiredScrollbarRole = 1;

	Object.defineProperty(scrollbarRole, "__esModule", {
	  value: true
	});
	scrollbarRole.default = undefined;
	var scrollbarRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-valuetext': null,
	    'aria-orientation': 'vertical',
	    'aria-valuemax': '100',
	    'aria-valuemin': '0'
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-controls': null,
	    'aria-valuenow': null
	  },
	  superClass: [['roletype', 'structure', 'range'], ['roletype', 'widget']]
	};
	var _default = scrollbarRole$1;
	scrollbarRole.default = _default;
	return scrollbarRole;
}

var searchRole = {};

var hasRequiredSearchRole;

function requireSearchRole () {
	if (hasRequiredSearchRole) return searchRole;
	hasRequiredSearchRole = 1;

	Object.defineProperty(searchRole, "__esModule", {
	  value: true
	});
	searchRole.default = undefined;
	var searchRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = searchRole$1;
	searchRole.default = _default;
	return searchRole;
}

var searchboxRole = {};

var hasRequiredSearchboxRole;

function requireSearchboxRole () {
	if (hasRequiredSearchboxRole) return searchboxRole;
	hasRequiredSearchboxRole = 1;

	Object.defineProperty(searchboxRole, "__esModule", {
	  value: true
	});
	searchboxRole.default = undefined;
	var searchboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'search'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'input', 'textbox']]
	};
	var _default = searchboxRole$1;
	searchboxRole.default = _default;
	return searchboxRole;
}

var separatorRole = {};

var hasRequiredSeparatorRole;

function requireSeparatorRole () {
	if (hasRequiredSeparatorRole) return separatorRole;
	hasRequiredSeparatorRole = 1;

	Object.defineProperty(separatorRole, "__esModule", {
	  value: true
	});
	separatorRole.default = undefined;
	var separatorRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-orientation': 'horizontal',
	    'aria-valuemax': '100',
	    'aria-valuemin': '0',
	    'aria-valuenow': null,
	    'aria-valuetext': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'hr'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure']]
	};
	var _default = separatorRole$1;
	separatorRole.default = _default;
	return separatorRole;
}

var sliderRole = {};

var hasRequiredSliderRole;

function requireSliderRole () {
	if (hasRequiredSliderRole) return sliderRole;
	hasRequiredSliderRole = 1;

	Object.defineProperty(sliderRole, "__esModule", {
	  value: true
	});
	sliderRole.default = undefined;
	var sliderRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-haspopup': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-valuetext': null,
	    'aria-orientation': 'horizontal',
	    'aria-valuemax': '100',
	    'aria-valuemin': '0'
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'range'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-valuenow': null
	  },
	  superClass: [['roletype', 'widget', 'input'], ['roletype', 'structure', 'range']]
	};
	var _default = sliderRole$1;
	sliderRole.default = _default;
	return sliderRole;
}

var spinbuttonRole = {};

var hasRequiredSpinbuttonRole;

function requireSpinbuttonRole () {
	if (hasRequiredSpinbuttonRole) return spinbuttonRole;
	hasRequiredSpinbuttonRole = 1;

	Object.defineProperty(spinbuttonRole, "__esModule", {
	  value: true
	});
	spinbuttonRole.default = undefined;
	var spinbuttonRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null,
	    'aria-readonly': null,
	    'aria-required': null,
	    'aria-valuetext': null,
	    'aria-valuenow': '0'
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        name: 'type',
	        value: 'number'
	      }],
	      name: 'input'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite'], ['roletype', 'widget', 'input'], ['roletype', 'structure', 'range']]
	};
	var _default = spinbuttonRole$1;
	spinbuttonRole.default = _default;
	return spinbuttonRole;
}

var statusRole = {};

var hasRequiredStatusRole;

function requireStatusRole () {
	if (hasRequiredStatusRole) return statusRole;
	hasRequiredStatusRole = 1;

	Object.defineProperty(statusRole, "__esModule", {
	  value: true
	});
	statusRole.default = undefined;
	var statusRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-atomic': 'true',
	    'aria-live': 'polite'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'output'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = statusRole$1;
	statusRole.default = _default;
	return statusRole;
}

var strongRole = {};

var hasRequiredStrongRole;

function requireStrongRole () {
	if (hasRequiredStrongRole) return strongRole;
	hasRequiredStrongRole = 1;

	Object.defineProperty(strongRole, "__esModule", {
	  value: true
	});
	strongRole.default = undefined;
	var strongRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'strong'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = strongRole$1;
	strongRole.default = _default;
	return strongRole;
}

var subscriptRole = {};

var hasRequiredSubscriptRole;

function requireSubscriptRole () {
	if (hasRequiredSubscriptRole) return subscriptRole;
	hasRequiredSubscriptRole = 1;

	Object.defineProperty(subscriptRole, "__esModule", {
	  value: true
	});
	subscriptRole.default = undefined;
	var subscriptRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'sub'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = subscriptRole$1;
	subscriptRole.default = _default;
	return subscriptRole;
}

var superscriptRole = {};

var hasRequiredSuperscriptRole;

function requireSuperscriptRole () {
	if (hasRequiredSuperscriptRole) return superscriptRole;
	hasRequiredSuperscriptRole = 1;

	Object.defineProperty(superscriptRole, "__esModule", {
	  value: true
	});
	superscriptRole.default = undefined;
	var superscriptRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['prohibited'],
	  prohibitedProps: ['aria-label', 'aria-labelledby'],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'sup'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = superscriptRole$1;
	superscriptRole.default = _default;
	return superscriptRole;
}

var switchRole = {};

var hasRequiredSwitchRole;

function requireSwitchRole () {
	if (hasRequiredSwitchRole) return switchRole;
	hasRequiredSwitchRole = 1;

	Object.defineProperty(switchRole, "__esModule", {
	  value: true
	});
	switchRole.default = undefined;
	var switchRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'button'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-checked': null
	  },
	  superClass: [['roletype', 'widget', 'input', 'checkbox']]
	};
	var _default = switchRole$1;
	switchRole.default = _default;
	return switchRole;
}

var tabRole = {};

var hasRequiredTabRole;

function requireTabRole () {
	if (hasRequiredTabRole) return tabRole;
	hasRequiredTabRole = 1;

	Object.defineProperty(tabRole, "__esModule", {
	  value: true
	});
	tabRole.default = undefined;
	var tabRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-posinset': null,
	    'aria-setsize': null,
	    'aria-selected': 'false'
	  },
	  relatedConcepts: [],
	  requireContextRole: ['tablist'],
	  requiredContextRole: ['tablist'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'sectionhead'], ['roletype', 'widget']]
	};
	var _default = tabRole$1;
	tabRole.default = _default;
	return tabRole;
}

var tableRole = {};

var hasRequiredTableRole;

function requireTableRole () {
	if (hasRequiredTableRole) return tableRole;
	hasRequiredTableRole = 1;

	Object.defineProperty(tableRole, "__esModule", {
	  value: true
	});
	tableRole.default = undefined;
	var tableRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-colcount': null,
	    'aria-rowcount': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'table'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['row'], ['row', 'rowgroup']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = tableRole$1;
	tableRole.default = _default;
	return tableRole;
}

var tablistRole = {};

var hasRequiredTablistRole;

function requireTablistRole () {
	if (hasRequiredTablistRole) return tablistRole;
	hasRequiredTablistRole = 1;

	Object.defineProperty(tablistRole, "__esModule", {
	  value: true
	});
	tablistRole.default = undefined;
	var tablistRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-level': null,
	    'aria-multiselectable': null,
	    'aria-orientation': 'horizontal'
	  },
	  relatedConcepts: [{
	    module: 'DAISY',
	    concept: {
	      name: 'guide'
	    }
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['tab']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite']]
	};
	var _default = tablistRole$1;
	tablistRole.default = _default;
	return tablistRole;
}

var tabpanelRole = {};

var hasRequiredTabpanelRole;

function requireTabpanelRole () {
	if (hasRequiredTabpanelRole) return tabpanelRole;
	hasRequiredTabpanelRole = 1;

	Object.defineProperty(tabpanelRole, "__esModule", {
	  value: true
	});
	tabpanelRole.default = undefined;
	var tabpanelRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = tabpanelRole$1;
	tabpanelRole.default = _default;
	return tabpanelRole;
}

var termRole = {};

var hasRequiredTermRole;

function requireTermRole () {
	if (hasRequiredTermRole) return termRole;
	hasRequiredTermRole = 1;

	Object.defineProperty(termRole, "__esModule", {
	  value: true
	});
	termRole.default = undefined;
	var termRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'dfn'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'dt'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = termRole$1;
	termRole.default = _default;
	return termRole;
}

var textboxRole = {};

var hasRequiredTextboxRole;

function requireTextboxRole () {
	if (hasRequiredTextboxRole) return textboxRole;
	hasRequiredTextboxRole = 1;

	Object.defineProperty(textboxRole, "__esModule", {
	  value: true
	});
	textboxRole.default = undefined;
	var textboxRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-activedescendant': null,
	    'aria-autocomplete': null,
	    'aria-errormessage': null,
	    'aria-haspopup': null,
	    'aria-invalid': null,
	    'aria-multiline': null,
	    'aria-placeholder': null,
	    'aria-readonly': null,
	    'aria-required': null
	  },
	  relatedConcepts: [{
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'type'
	      }, {
	        constraints: ['undefined'],
	        name: 'list'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'email'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'tel'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'text'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      attributes: [{
	        constraints: ['undefined'],
	        name: 'list'
	      }, {
	        name: 'type',
	        value: 'url'
	      }],
	      constraints: ['the list attribute is not set'],
	      name: 'input'
	    },
	    module: 'HTML'
	  }, {
	    concept: {
	      name: 'input'
	    },
	    module: 'XForms'
	  }, {
	    concept: {
	      name: 'textarea'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'input']]
	};
	var _default = textboxRole$1;
	textboxRole.default = _default;
	return textboxRole;
}

var timeRole = {};

var hasRequiredTimeRole;

function requireTimeRole () {
	if (hasRequiredTimeRole) return timeRole;
	hasRequiredTimeRole = 1;

	Object.defineProperty(timeRole, "__esModule", {
	  value: true
	});
	timeRole.default = undefined;
	var timeRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'time'
	    },
	    module: 'HTML'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = timeRole$1;
	timeRole.default = _default;
	return timeRole;
}

var timerRole = {};

var hasRequiredTimerRole;

function requireTimerRole () {
	if (hasRequiredTimerRole) return timerRole;
	hasRequiredTimerRole = 1;

	Object.defineProperty(timerRole, "__esModule", {
	  value: true
	});
	timerRole.default = undefined;
	var timerRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'status']]
	};
	var _default = timerRole$1;
	timerRole.default = _default;
	return timerRole;
}

var toolbarRole = {};

var hasRequiredToolbarRole;

function requireToolbarRole () {
	if (hasRequiredToolbarRole) return toolbarRole;
	hasRequiredToolbarRole = 1;

	Object.defineProperty(toolbarRole, "__esModule", {
	  value: true
	});
	toolbarRole.default = undefined;
	var toolbarRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-orientation': 'horizontal'
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'menubar'
	    },
	    module: 'ARIA'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'group']]
	};
	var _default = toolbarRole$1;
	toolbarRole.default = _default;
	return toolbarRole;
}

var tooltipRole = {};

var hasRequiredTooltipRole;

function requireTooltipRole () {
	if (hasRequiredTooltipRole) return tooltipRole;
	hasRequiredTooltipRole = 1;

	Object.defineProperty(tooltipRole, "__esModule", {
	  value: true
	});
	tooltipRole.default = undefined;
	var tooltipRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = tooltipRole$1;
	tooltipRole.default = _default;
	return tooltipRole;
}

var treeRole = {};

var hasRequiredTreeRole;

function requireTreeRole () {
	if (hasRequiredTreeRole) return treeRole;
	hasRequiredTreeRole = 1;

	Object.defineProperty(treeRole, "__esModule", {
	  value: true
	});
	treeRole.default = undefined;
	var treeRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null,
	    'aria-multiselectable': null,
	    'aria-required': null,
	    'aria-orientation': 'vertical'
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['treeitem', 'group'], ['treeitem']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'select'], ['roletype', 'structure', 'section', 'group', 'select']]
	};
	var _default = treeRole$1;
	treeRole.default = _default;
	return treeRole;
}

var treegridRole = {};

var hasRequiredTreegridRole;

function requireTreegridRole () {
	if (hasRequiredTreegridRole) return treegridRole;
	hasRequiredTreegridRole = 1;

	Object.defineProperty(treegridRole, "__esModule", {
	  value: true
	});
	treegridRole.default = undefined;
	var treegridRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['row'], ['row', 'rowgroup']],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'composite', 'grid'], ['roletype', 'structure', 'section', 'table', 'grid'], ['roletype', 'widget', 'composite', 'select', 'tree'], ['roletype', 'structure', 'section', 'group', 'select', 'tree']]
	};
	var _default = treegridRole$1;
	treegridRole.default = _default;
	return treegridRole;
}

var treeitemRole = {};

var hasRequiredTreeitemRole;

function requireTreeitemRole () {
	if (hasRequiredTreeitemRole) return treeitemRole;
	hasRequiredTreeitemRole = 1;

	Object.defineProperty(treeitemRole, "__esModule", {
	  value: true
	});
	treeitemRole.default = undefined;
	var treeitemRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-expanded': null,
	    'aria-haspopup': null
	  },
	  relatedConcepts: [],
	  requireContextRole: ['group', 'tree'],
	  requiredContextRole: ['group', 'tree'],
	  requiredOwnedElements: [],
	  requiredProps: {
	    'aria-selected': null
	  },
	  superClass: [['roletype', 'structure', 'section', 'listitem'], ['roletype', 'widget', 'input', 'option']]
	};
	var _default = treeitemRole$1;
	treeitemRole.default = _default;
	return treeitemRole;
}

var hasRequiredAriaLiteralRoles;

function requireAriaLiteralRoles () {
	if (hasRequiredAriaLiteralRoles) return ariaLiteralRoles;
	hasRequiredAriaLiteralRoles = 1;

	Object.defineProperty(ariaLiteralRoles, "__esModule", {
	  value: true
	});
	ariaLiteralRoles.default = undefined;
	var _alertRole = _interopRequireDefault(requireAlertRole());
	var _alertdialogRole = _interopRequireDefault(requireAlertdialogRole());
	var _applicationRole = _interopRequireDefault(requireApplicationRole());
	var _articleRole = _interopRequireDefault(requireArticleRole());
	var _bannerRole = _interopRequireDefault(requireBannerRole());
	var _blockquoteRole = _interopRequireDefault(requireBlockquoteRole());
	var _buttonRole = _interopRequireDefault(requireButtonRole());
	var _captionRole = _interopRequireDefault(requireCaptionRole());
	var _cellRole = _interopRequireDefault(requireCellRole());
	var _checkboxRole = _interopRequireDefault(requireCheckboxRole());
	var _codeRole = _interopRequireDefault(requireCodeRole());
	var _columnheaderRole = _interopRequireDefault(requireColumnheaderRole());
	var _comboboxRole = _interopRequireDefault(requireComboboxRole());
	var _complementaryRole = _interopRequireDefault(requireComplementaryRole());
	var _contentinfoRole = _interopRequireDefault(requireContentinfoRole());
	var _definitionRole = _interopRequireDefault(requireDefinitionRole());
	var _deletionRole = _interopRequireDefault(requireDeletionRole());
	var _dialogRole = _interopRequireDefault(requireDialogRole());
	var _directoryRole = _interopRequireDefault(requireDirectoryRole());
	var _documentRole = _interopRequireDefault(requireDocumentRole());
	var _emphasisRole = _interopRequireDefault(requireEmphasisRole());
	var _feedRole = _interopRequireDefault(requireFeedRole());
	var _figureRole = _interopRequireDefault(requireFigureRole());
	var _formRole = _interopRequireDefault(requireFormRole());
	var _genericRole = _interopRequireDefault(requireGenericRole());
	var _gridRole = _interopRequireDefault(requireGridRole());
	var _gridcellRole = _interopRequireDefault(requireGridcellRole());
	var _groupRole = _interopRequireDefault(requireGroupRole());
	var _headingRole = _interopRequireDefault(requireHeadingRole());
	var _imgRole = _interopRequireDefault(requireImgRole());
	var _insertionRole = _interopRequireDefault(requireInsertionRole());
	var _linkRole = _interopRequireDefault(requireLinkRole());
	var _listRole = _interopRequireDefault(requireListRole());
	var _listboxRole = _interopRequireDefault(requireListboxRole());
	var _listitemRole = _interopRequireDefault(requireListitemRole());
	var _logRole = _interopRequireDefault(requireLogRole());
	var _mainRole = _interopRequireDefault(requireMainRole());
	var _markRole = _interopRequireDefault(requireMarkRole());
	var _marqueeRole = _interopRequireDefault(requireMarqueeRole());
	var _mathRole = _interopRequireDefault(requireMathRole());
	var _menuRole = _interopRequireDefault(requireMenuRole());
	var _menubarRole = _interopRequireDefault(requireMenubarRole());
	var _menuitemRole = _interopRequireDefault(requireMenuitemRole());
	var _menuitemcheckboxRole = _interopRequireDefault(requireMenuitemcheckboxRole());
	var _menuitemradioRole = _interopRequireDefault(requireMenuitemradioRole());
	var _meterRole = _interopRequireDefault(requireMeterRole());
	var _navigationRole = _interopRequireDefault(requireNavigationRole());
	var _noneRole = _interopRequireDefault(requireNoneRole());
	var _noteRole = _interopRequireDefault(requireNoteRole());
	var _optionRole = _interopRequireDefault(requireOptionRole());
	var _paragraphRole = _interopRequireDefault(requireParagraphRole());
	var _presentationRole = _interopRequireDefault(requirePresentationRole());
	var _progressbarRole = _interopRequireDefault(requireProgressbarRole());
	var _radioRole = _interopRequireDefault(requireRadioRole());
	var _radiogroupRole = _interopRequireDefault(requireRadiogroupRole());
	var _regionRole = _interopRequireDefault(requireRegionRole());
	var _rowRole = _interopRequireDefault(requireRowRole());
	var _rowgroupRole = _interopRequireDefault(requireRowgroupRole());
	var _rowheaderRole = _interopRequireDefault(requireRowheaderRole());
	var _scrollbarRole = _interopRequireDefault(requireScrollbarRole());
	var _searchRole = _interopRequireDefault(requireSearchRole());
	var _searchboxRole = _interopRequireDefault(requireSearchboxRole());
	var _separatorRole = _interopRequireDefault(requireSeparatorRole());
	var _sliderRole = _interopRequireDefault(requireSliderRole());
	var _spinbuttonRole = _interopRequireDefault(requireSpinbuttonRole());
	var _statusRole = _interopRequireDefault(requireStatusRole());
	var _strongRole = _interopRequireDefault(requireStrongRole());
	var _subscriptRole = _interopRequireDefault(requireSubscriptRole());
	var _superscriptRole = _interopRequireDefault(requireSuperscriptRole());
	var _switchRole = _interopRequireDefault(requireSwitchRole());
	var _tabRole = _interopRequireDefault(requireTabRole());
	var _tableRole = _interopRequireDefault(requireTableRole());
	var _tablistRole = _interopRequireDefault(requireTablistRole());
	var _tabpanelRole = _interopRequireDefault(requireTabpanelRole());
	var _termRole = _interopRequireDefault(requireTermRole());
	var _textboxRole = _interopRequireDefault(requireTextboxRole());
	var _timeRole = _interopRequireDefault(requireTimeRole());
	var _timerRole = _interopRequireDefault(requireTimerRole());
	var _toolbarRole = _interopRequireDefault(requireToolbarRole());
	var _tooltipRole = _interopRequireDefault(requireTooltipRole());
	var _treeRole = _interopRequireDefault(requireTreeRole());
	var _treegridRole = _interopRequireDefault(requireTreegridRole());
	var _treeitemRole = _interopRequireDefault(requireTreeitemRole());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var ariaLiteralRoles$1 = [['alert', _alertRole.default], ['alertdialog', _alertdialogRole.default], ['application', _applicationRole.default], ['article', _articleRole.default], ['banner', _bannerRole.default], ['blockquote', _blockquoteRole.default], ['button', _buttonRole.default], ['caption', _captionRole.default], ['cell', _cellRole.default], ['checkbox', _checkboxRole.default], ['code', _codeRole.default], ['columnheader', _columnheaderRole.default], ['combobox', _comboboxRole.default], ['complementary', _complementaryRole.default], ['contentinfo', _contentinfoRole.default], ['definition', _definitionRole.default], ['deletion', _deletionRole.default], ['dialog', _dialogRole.default], ['directory', _directoryRole.default], ['document', _documentRole.default], ['emphasis', _emphasisRole.default], ['feed', _feedRole.default], ['figure', _figureRole.default], ['form', _formRole.default], ['generic', _genericRole.default], ['grid', _gridRole.default], ['gridcell', _gridcellRole.default], ['group', _groupRole.default], ['heading', _headingRole.default], ['img', _imgRole.default], ['insertion', _insertionRole.default], ['link', _linkRole.default], ['list', _listRole.default], ['listbox', _listboxRole.default], ['listitem', _listitemRole.default], ['log', _logRole.default], ['main', _mainRole.default], ['mark', _markRole.default], ['marquee', _marqueeRole.default], ['math', _mathRole.default], ['menu', _menuRole.default], ['menubar', _menubarRole.default], ['menuitem', _menuitemRole.default], ['menuitemcheckbox', _menuitemcheckboxRole.default], ['menuitemradio', _menuitemradioRole.default], ['meter', _meterRole.default], ['navigation', _navigationRole.default], ['none', _noneRole.default], ['note', _noteRole.default], ['option', _optionRole.default], ['paragraph', _paragraphRole.default], ['presentation', _presentationRole.default], ['progressbar', _progressbarRole.default], ['radio', _radioRole.default], ['radiogroup', _radiogroupRole.default], ['region', _regionRole.default], ['row', _rowRole.default], ['rowgroup', _rowgroupRole.default], ['rowheader', _rowheaderRole.default], ['scrollbar', _scrollbarRole.default], ['search', _searchRole.default], ['searchbox', _searchboxRole.default], ['separator', _separatorRole.default], ['slider', _sliderRole.default], ['spinbutton', _spinbuttonRole.default], ['status', _statusRole.default], ['strong', _strongRole.default], ['subscript', _subscriptRole.default], ['superscript', _superscriptRole.default], ['switch', _switchRole.default], ['tab', _tabRole.default], ['table', _tableRole.default], ['tablist', _tablistRole.default], ['tabpanel', _tabpanelRole.default], ['term', _termRole.default], ['textbox', _textboxRole.default], ['time', _timeRole.default], ['timer', _timerRole.default], ['toolbar', _toolbarRole.default], ['tooltip', _tooltipRole.default], ['tree', _treeRole.default], ['treegrid', _treegridRole.default], ['treeitem', _treeitemRole.default]];
	var _default = ariaLiteralRoles$1;
	ariaLiteralRoles.default = _default;
	return ariaLiteralRoles;
}

var ariaDpubRoles = {};

var docAbstractRole = {};

var hasRequiredDocAbstractRole;

function requireDocAbstractRole () {
	if (hasRequiredDocAbstractRole) return docAbstractRole;
	hasRequiredDocAbstractRole = 1;

	Object.defineProperty(docAbstractRole, "__esModule", {
	  value: true
	});
	docAbstractRole.default = undefined;
	var docAbstractRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'abstract [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = docAbstractRole$1;
	docAbstractRole.default = _default;
	return docAbstractRole;
}

var docAcknowledgmentsRole = {};

var hasRequiredDocAcknowledgmentsRole;

function requireDocAcknowledgmentsRole () {
	if (hasRequiredDocAcknowledgmentsRole) return docAcknowledgmentsRole;
	hasRequiredDocAcknowledgmentsRole = 1;

	Object.defineProperty(docAcknowledgmentsRole, "__esModule", {
	  value: true
	});
	docAcknowledgmentsRole.default = undefined;
	var docAcknowledgmentsRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'acknowledgments [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docAcknowledgmentsRole$1;
	docAcknowledgmentsRole.default = _default;
	return docAcknowledgmentsRole;
}

var docAfterwordRole = {};

var hasRequiredDocAfterwordRole;

function requireDocAfterwordRole () {
	if (hasRequiredDocAfterwordRole) return docAfterwordRole;
	hasRequiredDocAfterwordRole = 1;

	Object.defineProperty(docAfterwordRole, "__esModule", {
	  value: true
	});
	docAfterwordRole.default = undefined;
	var docAfterwordRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'afterword [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docAfterwordRole$1;
	docAfterwordRole.default = _default;
	return docAfterwordRole;
}

var docAppendixRole = {};

var hasRequiredDocAppendixRole;

function requireDocAppendixRole () {
	if (hasRequiredDocAppendixRole) return docAppendixRole;
	hasRequiredDocAppendixRole = 1;

	Object.defineProperty(docAppendixRole, "__esModule", {
	  value: true
	});
	docAppendixRole.default = undefined;
	var docAppendixRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'appendix [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docAppendixRole$1;
	docAppendixRole.default = _default;
	return docAppendixRole;
}

var docBacklinkRole = {};

var hasRequiredDocBacklinkRole;

function requireDocBacklinkRole () {
	if (hasRequiredDocBacklinkRole) return docBacklinkRole;
	hasRequiredDocBacklinkRole = 1;

	Object.defineProperty(docBacklinkRole, "__esModule", {
	  value: true
	});
	docBacklinkRole.default = undefined;
	var docBacklinkRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'referrer [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command', 'link']]
	};
	var _default = docBacklinkRole$1;
	docBacklinkRole.default = _default;
	return docBacklinkRole;
}

var docBiblioentryRole = {};

var hasRequiredDocBiblioentryRole;

function requireDocBiblioentryRole () {
	if (hasRequiredDocBiblioentryRole) return docBiblioentryRole;
	hasRequiredDocBiblioentryRole = 1;

	Object.defineProperty(docBiblioentryRole, "__esModule", {
	  value: true
	});
	docBiblioentryRole.default = undefined;
	var docBiblioentryRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'EPUB biblioentry [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: ['doc-bibliography'],
	  requiredContextRole: ['doc-bibliography'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'listitem']]
	};
	var _default = docBiblioentryRole$1;
	docBiblioentryRole.default = _default;
	return docBiblioentryRole;
}

var docBibliographyRole = {};

var hasRequiredDocBibliographyRole;

function requireDocBibliographyRole () {
	if (hasRequiredDocBibliographyRole) return docBibliographyRole;
	hasRequiredDocBibliographyRole = 1;

	Object.defineProperty(docBibliographyRole, "__esModule", {
	  value: true
	});
	docBibliographyRole.default = undefined;
	var docBibliographyRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'bibliography [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['doc-biblioentry']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docBibliographyRole$1;
	docBibliographyRole.default = _default;
	return docBibliographyRole;
}

var docBibliorefRole = {};

var hasRequiredDocBibliorefRole;

function requireDocBibliorefRole () {
	if (hasRequiredDocBibliorefRole) return docBibliorefRole;
	hasRequiredDocBibliorefRole = 1;

	Object.defineProperty(docBibliorefRole, "__esModule", {
	  value: true
	});
	docBibliorefRole.default = undefined;
	var docBibliorefRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'biblioref [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command', 'link']]
	};
	var _default = docBibliorefRole$1;
	docBibliorefRole.default = _default;
	return docBibliorefRole;
}

var docChapterRole = {};

var hasRequiredDocChapterRole;

function requireDocChapterRole () {
	if (hasRequiredDocChapterRole) return docChapterRole;
	hasRequiredDocChapterRole = 1;

	Object.defineProperty(docChapterRole, "__esModule", {
	  value: true
	});
	docChapterRole.default = undefined;
	var docChapterRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'chapter [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docChapterRole$1;
	docChapterRole.default = _default;
	return docChapterRole;
}

var docColophonRole = {};

var hasRequiredDocColophonRole;

function requireDocColophonRole () {
	if (hasRequiredDocColophonRole) return docColophonRole;
	hasRequiredDocColophonRole = 1;

	Object.defineProperty(docColophonRole, "__esModule", {
	  value: true
	});
	docColophonRole.default = undefined;
	var docColophonRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'colophon [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = docColophonRole$1;
	docColophonRole.default = _default;
	return docColophonRole;
}

var docConclusionRole = {};

var hasRequiredDocConclusionRole;

function requireDocConclusionRole () {
	if (hasRequiredDocConclusionRole) return docConclusionRole;
	hasRequiredDocConclusionRole = 1;

	Object.defineProperty(docConclusionRole, "__esModule", {
	  value: true
	});
	docConclusionRole.default = undefined;
	var docConclusionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'conclusion [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docConclusionRole$1;
	docConclusionRole.default = _default;
	return docConclusionRole;
}

var docCoverRole = {};

var hasRequiredDocCoverRole;

function requireDocCoverRole () {
	if (hasRequiredDocCoverRole) return docCoverRole;
	hasRequiredDocCoverRole = 1;

	Object.defineProperty(docCoverRole, "__esModule", {
	  value: true
	});
	docCoverRole.default = undefined;
	var docCoverRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'cover [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'img']]
	};
	var _default = docCoverRole$1;
	docCoverRole.default = _default;
	return docCoverRole;
}

var docCreditRole = {};

var hasRequiredDocCreditRole;

function requireDocCreditRole () {
	if (hasRequiredDocCreditRole) return docCreditRole;
	hasRequiredDocCreditRole = 1;

	Object.defineProperty(docCreditRole, "__esModule", {
	  value: true
	});
	docCreditRole.default = undefined;
	var docCreditRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'credit [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = docCreditRole$1;
	docCreditRole.default = _default;
	return docCreditRole;
}

var docCreditsRole = {};

var hasRequiredDocCreditsRole;

function requireDocCreditsRole () {
	if (hasRequiredDocCreditsRole) return docCreditsRole;
	hasRequiredDocCreditsRole = 1;

	Object.defineProperty(docCreditsRole, "__esModule", {
	  value: true
	});
	docCreditsRole.default = undefined;
	var docCreditsRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'credits [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docCreditsRole$1;
	docCreditsRole.default = _default;
	return docCreditsRole;
}

var docDedicationRole = {};

var hasRequiredDocDedicationRole;

function requireDocDedicationRole () {
	if (hasRequiredDocDedicationRole) return docDedicationRole;
	hasRequiredDocDedicationRole = 1;

	Object.defineProperty(docDedicationRole, "__esModule", {
	  value: true
	});
	docDedicationRole.default = undefined;
	var docDedicationRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'dedication [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = docDedicationRole$1;
	docDedicationRole.default = _default;
	return docDedicationRole;
}

var docEndnoteRole = {};

var hasRequiredDocEndnoteRole;

function requireDocEndnoteRole () {
	if (hasRequiredDocEndnoteRole) return docEndnoteRole;
	hasRequiredDocEndnoteRole = 1;

	Object.defineProperty(docEndnoteRole, "__esModule", {
	  value: true
	});
	docEndnoteRole.default = undefined;
	var docEndnoteRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'rearnote [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: ['doc-endnotes'],
	  requiredContextRole: ['doc-endnotes'],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'listitem']]
	};
	var _default = docEndnoteRole$1;
	docEndnoteRole.default = _default;
	return docEndnoteRole;
}

var docEndnotesRole = {};

var hasRequiredDocEndnotesRole;

function requireDocEndnotesRole () {
	if (hasRequiredDocEndnotesRole) return docEndnotesRole;
	hasRequiredDocEndnotesRole = 1;

	Object.defineProperty(docEndnotesRole, "__esModule", {
	  value: true
	});
	docEndnotesRole.default = undefined;
	var docEndnotesRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'rearnotes [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['doc-endnote']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docEndnotesRole$1;
	docEndnotesRole.default = _default;
	return docEndnotesRole;
}

var docEpigraphRole = {};

var hasRequiredDocEpigraphRole;

function requireDocEpigraphRole () {
	if (hasRequiredDocEpigraphRole) return docEpigraphRole;
	hasRequiredDocEpigraphRole = 1;

	Object.defineProperty(docEpigraphRole, "__esModule", {
	  value: true
	});
	docEpigraphRole.default = undefined;
	var docEpigraphRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'epigraph [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = docEpigraphRole$1;
	docEpigraphRole.default = _default;
	return docEpigraphRole;
}

var docEpilogueRole = {};

var hasRequiredDocEpilogueRole;

function requireDocEpilogueRole () {
	if (hasRequiredDocEpilogueRole) return docEpilogueRole;
	hasRequiredDocEpilogueRole = 1;

	Object.defineProperty(docEpilogueRole, "__esModule", {
	  value: true
	});
	docEpilogueRole.default = undefined;
	var docEpilogueRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'epilogue [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docEpilogueRole$1;
	docEpilogueRole.default = _default;
	return docEpilogueRole;
}

var docErrataRole = {};

var hasRequiredDocErrataRole;

function requireDocErrataRole () {
	if (hasRequiredDocErrataRole) return docErrataRole;
	hasRequiredDocErrataRole = 1;

	Object.defineProperty(docErrataRole, "__esModule", {
	  value: true
	});
	docErrataRole.default = undefined;
	var docErrataRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'errata [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docErrataRole$1;
	docErrataRole.default = _default;
	return docErrataRole;
}

var docExampleRole = {};

var hasRequiredDocExampleRole;

function requireDocExampleRole () {
	if (hasRequiredDocExampleRole) return docExampleRole;
	hasRequiredDocExampleRole = 1;

	Object.defineProperty(docExampleRole, "__esModule", {
	  value: true
	});
	docExampleRole.default = undefined;
	var docExampleRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = docExampleRole$1;
	docExampleRole.default = _default;
	return docExampleRole;
}

var docFootnoteRole = {};

var hasRequiredDocFootnoteRole;

function requireDocFootnoteRole () {
	if (hasRequiredDocFootnoteRole) return docFootnoteRole;
	hasRequiredDocFootnoteRole = 1;

	Object.defineProperty(docFootnoteRole, "__esModule", {
	  value: true
	});
	docFootnoteRole.default = undefined;
	var docFootnoteRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'footnote [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = docFootnoteRole$1;
	docFootnoteRole.default = _default;
	return docFootnoteRole;
}

var docForewordRole = {};

var hasRequiredDocForewordRole;

function requireDocForewordRole () {
	if (hasRequiredDocForewordRole) return docForewordRole;
	hasRequiredDocForewordRole = 1;

	Object.defineProperty(docForewordRole, "__esModule", {
	  value: true
	});
	docForewordRole.default = undefined;
	var docForewordRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'foreword [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docForewordRole$1;
	docForewordRole.default = _default;
	return docForewordRole;
}

var docGlossaryRole = {};

var hasRequiredDocGlossaryRole;

function requireDocGlossaryRole () {
	if (hasRequiredDocGlossaryRole) return docGlossaryRole;
	hasRequiredDocGlossaryRole = 1;

	Object.defineProperty(docGlossaryRole, "__esModule", {
	  value: true
	});
	docGlossaryRole.default = undefined;
	var docGlossaryRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'glossary [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [['definition'], ['term']],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docGlossaryRole$1;
	docGlossaryRole.default = _default;
	return docGlossaryRole;
}

var docGlossrefRole = {};

var hasRequiredDocGlossrefRole;

function requireDocGlossrefRole () {
	if (hasRequiredDocGlossrefRole) return docGlossrefRole;
	hasRequiredDocGlossrefRole = 1;

	Object.defineProperty(docGlossrefRole, "__esModule", {
	  value: true
	});
	docGlossrefRole.default = undefined;
	var docGlossrefRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'glossref [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command', 'link']]
	};
	var _default = docGlossrefRole$1;
	docGlossrefRole.default = _default;
	return docGlossrefRole;
}

var docIndexRole = {};

var hasRequiredDocIndexRole;

function requireDocIndexRole () {
	if (hasRequiredDocIndexRole) return docIndexRole;
	hasRequiredDocIndexRole = 1;

	Object.defineProperty(docIndexRole, "__esModule", {
	  value: true
	});
	docIndexRole.default = undefined;
	var docIndexRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'index [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark', 'navigation']]
	};
	var _default = docIndexRole$1;
	docIndexRole.default = _default;
	return docIndexRole;
}

var docIntroductionRole = {};

var hasRequiredDocIntroductionRole;

function requireDocIntroductionRole () {
	if (hasRequiredDocIntroductionRole) return docIntroductionRole;
	hasRequiredDocIntroductionRole = 1;

	Object.defineProperty(docIntroductionRole, "__esModule", {
	  value: true
	});
	docIntroductionRole.default = undefined;
	var docIntroductionRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'introduction [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docIntroductionRole$1;
	docIntroductionRole.default = _default;
	return docIntroductionRole;
}

var docNoterefRole = {};

var hasRequiredDocNoterefRole;

function requireDocNoterefRole () {
	if (hasRequiredDocNoterefRole) return docNoterefRole;
	hasRequiredDocNoterefRole = 1;

	Object.defineProperty(docNoterefRole, "__esModule", {
	  value: true
	});
	docNoterefRole.default = undefined;
	var docNoterefRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'noteref [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'widget', 'command', 'link']]
	};
	var _default = docNoterefRole$1;
	docNoterefRole.default = _default;
	return docNoterefRole;
}

var docNoticeRole = {};

var hasRequiredDocNoticeRole;

function requireDocNoticeRole () {
	if (hasRequiredDocNoticeRole) return docNoticeRole;
	hasRequiredDocNoticeRole = 1;

	Object.defineProperty(docNoticeRole, "__esModule", {
	  value: true
	});
	docNoticeRole.default = undefined;
	var docNoticeRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'notice [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'note']]
	};
	var _default = docNoticeRole$1;
	docNoticeRole.default = _default;
	return docNoticeRole;
}

var docPagebreakRole = {};

var hasRequiredDocPagebreakRole;

function requireDocPagebreakRole () {
	if (hasRequiredDocPagebreakRole) return docPagebreakRole;
	hasRequiredDocPagebreakRole = 1;

	Object.defineProperty(docPagebreakRole, "__esModule", {
	  value: true
	});
	docPagebreakRole.default = undefined;
	var docPagebreakRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'pagebreak [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'separator']]
	};
	var _default = docPagebreakRole$1;
	docPagebreakRole.default = _default;
	return docPagebreakRole;
}

var docPagelistRole = {};

var hasRequiredDocPagelistRole;

function requireDocPagelistRole () {
	if (hasRequiredDocPagelistRole) return docPagelistRole;
	hasRequiredDocPagelistRole = 1;

	Object.defineProperty(docPagelistRole, "__esModule", {
	  value: true
	});
	docPagelistRole.default = undefined;
	var docPagelistRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'page-list [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark', 'navigation']]
	};
	var _default = docPagelistRole$1;
	docPagelistRole.default = _default;
	return docPagelistRole;
}

var docPartRole = {};

var hasRequiredDocPartRole;

function requireDocPartRole () {
	if (hasRequiredDocPartRole) return docPartRole;
	hasRequiredDocPartRole = 1;

	Object.defineProperty(docPartRole, "__esModule", {
	  value: true
	});
	docPartRole.default = undefined;
	var docPartRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'part [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docPartRole$1;
	docPartRole.default = _default;
	return docPartRole;
}

var docPrefaceRole = {};

var hasRequiredDocPrefaceRole;

function requireDocPrefaceRole () {
	if (hasRequiredDocPrefaceRole) return docPrefaceRole;
	hasRequiredDocPrefaceRole = 1;

	Object.defineProperty(docPrefaceRole, "__esModule", {
	  value: true
	});
	docPrefaceRole.default = undefined;
	var docPrefaceRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'preface [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docPrefaceRole$1;
	docPrefaceRole.default = _default;
	return docPrefaceRole;
}

var docPrologueRole = {};

var hasRequiredDocPrologueRole;

function requireDocPrologueRole () {
	if (hasRequiredDocPrologueRole) return docPrologueRole;
	hasRequiredDocPrologueRole = 1;

	Object.defineProperty(docPrologueRole, "__esModule", {
	  value: true
	});
	docPrologueRole.default = undefined;
	var docPrologueRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'prologue [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark']]
	};
	var _default = docPrologueRole$1;
	docPrologueRole.default = _default;
	return docPrologueRole;
}

var docPullquoteRole = {};

var hasRequiredDocPullquoteRole;

function requireDocPullquoteRole () {
	if (hasRequiredDocPullquoteRole) return docPullquoteRole;
	hasRequiredDocPullquoteRole = 1;

	Object.defineProperty(docPullquoteRole, "__esModule", {
	  value: true
	});
	docPullquoteRole.default = undefined;
	var docPullquoteRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {},
	  relatedConcepts: [{
	    concept: {
	      name: 'pullquote [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['none']]
	};
	var _default = docPullquoteRole$1;
	docPullquoteRole.default = _default;
	return docPullquoteRole;
}

var docQnaRole = {};

var hasRequiredDocQnaRole;

function requireDocQnaRole () {
	if (hasRequiredDocQnaRole) return docQnaRole;
	hasRequiredDocQnaRole = 1;

	Object.defineProperty(docQnaRole, "__esModule", {
	  value: true
	});
	docQnaRole.default = undefined;
	var docQnaRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'qna [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section']]
	};
	var _default = docQnaRole$1;
	docQnaRole.default = _default;
	return docQnaRole;
}

var docSubtitleRole = {};

var hasRequiredDocSubtitleRole;

function requireDocSubtitleRole () {
	if (hasRequiredDocSubtitleRole) return docSubtitleRole;
	hasRequiredDocSubtitleRole = 1;

	Object.defineProperty(docSubtitleRole, "__esModule", {
	  value: true
	});
	docSubtitleRole.default = undefined;
	var docSubtitleRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'subtitle [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'sectionhead']]
	};
	var _default = docSubtitleRole$1;
	docSubtitleRole.default = _default;
	return docSubtitleRole;
}

var docTipRole = {};

var hasRequiredDocTipRole;

function requireDocTipRole () {
	if (hasRequiredDocTipRole) return docTipRole;
	hasRequiredDocTipRole = 1;

	Object.defineProperty(docTipRole, "__esModule", {
	  value: true
	});
	docTipRole.default = undefined;
	var docTipRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'help [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'note']]
	};
	var _default = docTipRole$1;
	docTipRole.default = _default;
	return docTipRole;
}

var docTocRole = {};

var hasRequiredDocTocRole;

function requireDocTocRole () {
	if (hasRequiredDocTocRole) return docTocRole;
	hasRequiredDocTocRole = 1;

	Object.defineProperty(docTocRole, "__esModule", {
	  value: true
	});
	docTocRole.default = undefined;
	var docTocRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    concept: {
	      name: 'toc [EPUB-SSV]'
	    },
	    module: 'EPUB'
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'landmark', 'navigation']]
	};
	var _default = docTocRole$1;
	docTocRole.default = _default;
	return docTocRole;
}

var hasRequiredAriaDpubRoles;

function requireAriaDpubRoles () {
	if (hasRequiredAriaDpubRoles) return ariaDpubRoles;
	hasRequiredAriaDpubRoles = 1;

	Object.defineProperty(ariaDpubRoles, "__esModule", {
	  value: true
	});
	ariaDpubRoles.default = undefined;
	var _docAbstractRole = _interopRequireDefault(requireDocAbstractRole());
	var _docAcknowledgmentsRole = _interopRequireDefault(requireDocAcknowledgmentsRole());
	var _docAfterwordRole = _interopRequireDefault(requireDocAfterwordRole());
	var _docAppendixRole = _interopRequireDefault(requireDocAppendixRole());
	var _docBacklinkRole = _interopRequireDefault(requireDocBacklinkRole());
	var _docBiblioentryRole = _interopRequireDefault(requireDocBiblioentryRole());
	var _docBibliographyRole = _interopRequireDefault(requireDocBibliographyRole());
	var _docBibliorefRole = _interopRequireDefault(requireDocBibliorefRole());
	var _docChapterRole = _interopRequireDefault(requireDocChapterRole());
	var _docColophonRole = _interopRequireDefault(requireDocColophonRole());
	var _docConclusionRole = _interopRequireDefault(requireDocConclusionRole());
	var _docCoverRole = _interopRequireDefault(requireDocCoverRole());
	var _docCreditRole = _interopRequireDefault(requireDocCreditRole());
	var _docCreditsRole = _interopRequireDefault(requireDocCreditsRole());
	var _docDedicationRole = _interopRequireDefault(requireDocDedicationRole());
	var _docEndnoteRole = _interopRequireDefault(requireDocEndnoteRole());
	var _docEndnotesRole = _interopRequireDefault(requireDocEndnotesRole());
	var _docEpigraphRole = _interopRequireDefault(requireDocEpigraphRole());
	var _docEpilogueRole = _interopRequireDefault(requireDocEpilogueRole());
	var _docErrataRole = _interopRequireDefault(requireDocErrataRole());
	var _docExampleRole = _interopRequireDefault(requireDocExampleRole());
	var _docFootnoteRole = _interopRequireDefault(requireDocFootnoteRole());
	var _docForewordRole = _interopRequireDefault(requireDocForewordRole());
	var _docGlossaryRole = _interopRequireDefault(requireDocGlossaryRole());
	var _docGlossrefRole = _interopRequireDefault(requireDocGlossrefRole());
	var _docIndexRole = _interopRequireDefault(requireDocIndexRole());
	var _docIntroductionRole = _interopRequireDefault(requireDocIntroductionRole());
	var _docNoterefRole = _interopRequireDefault(requireDocNoterefRole());
	var _docNoticeRole = _interopRequireDefault(requireDocNoticeRole());
	var _docPagebreakRole = _interopRequireDefault(requireDocPagebreakRole());
	var _docPagelistRole = _interopRequireDefault(requireDocPagelistRole());
	var _docPartRole = _interopRequireDefault(requireDocPartRole());
	var _docPrefaceRole = _interopRequireDefault(requireDocPrefaceRole());
	var _docPrologueRole = _interopRequireDefault(requireDocPrologueRole());
	var _docPullquoteRole = _interopRequireDefault(requireDocPullquoteRole());
	var _docQnaRole = _interopRequireDefault(requireDocQnaRole());
	var _docSubtitleRole = _interopRequireDefault(requireDocSubtitleRole());
	var _docTipRole = _interopRequireDefault(requireDocTipRole());
	var _docTocRole = _interopRequireDefault(requireDocTocRole());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var ariaDpubRoles$1 = [['doc-abstract', _docAbstractRole.default], ['doc-acknowledgments', _docAcknowledgmentsRole.default], ['doc-afterword', _docAfterwordRole.default], ['doc-appendix', _docAppendixRole.default], ['doc-backlink', _docBacklinkRole.default], ['doc-biblioentry', _docBiblioentryRole.default], ['doc-bibliography', _docBibliographyRole.default], ['doc-biblioref', _docBibliorefRole.default], ['doc-chapter', _docChapterRole.default], ['doc-colophon', _docColophonRole.default], ['doc-conclusion', _docConclusionRole.default], ['doc-cover', _docCoverRole.default], ['doc-credit', _docCreditRole.default], ['doc-credits', _docCreditsRole.default], ['doc-dedication', _docDedicationRole.default], ['doc-endnote', _docEndnoteRole.default], ['doc-endnotes', _docEndnotesRole.default], ['doc-epigraph', _docEpigraphRole.default], ['doc-epilogue', _docEpilogueRole.default], ['doc-errata', _docErrataRole.default], ['doc-example', _docExampleRole.default], ['doc-footnote', _docFootnoteRole.default], ['doc-foreword', _docForewordRole.default], ['doc-glossary', _docGlossaryRole.default], ['doc-glossref', _docGlossrefRole.default], ['doc-index', _docIndexRole.default], ['doc-introduction', _docIntroductionRole.default], ['doc-noteref', _docNoterefRole.default], ['doc-notice', _docNoticeRole.default], ['doc-pagebreak', _docPagebreakRole.default], ['doc-pagelist', _docPagelistRole.default], ['doc-part', _docPartRole.default], ['doc-preface', _docPrefaceRole.default], ['doc-prologue', _docPrologueRole.default], ['doc-pullquote', _docPullquoteRole.default], ['doc-qna', _docQnaRole.default], ['doc-subtitle', _docSubtitleRole.default], ['doc-tip', _docTipRole.default], ['doc-toc', _docTocRole.default]];
	var _default = ariaDpubRoles$1;
	ariaDpubRoles.default = _default;
	return ariaDpubRoles;
}

var ariaGraphicsRoles = {};

var graphicsDocumentRole = {};

var hasRequiredGraphicsDocumentRole;

function requireGraphicsDocumentRole () {
	if (hasRequiredGraphicsDocumentRole) return graphicsDocumentRole;
	hasRequiredGraphicsDocumentRole = 1;

	Object.defineProperty(graphicsDocumentRole, "__esModule", {
	  value: true
	});
	graphicsDocumentRole.default = undefined;
	var graphicsDocumentRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    module: 'GRAPHICS',
	    concept: {
	      name: 'graphics-object'
	    }
	  }, {
	    module: 'ARIA',
	    concept: {
	      name: 'img'
	    }
	  }, {
	    module: 'ARIA',
	    concept: {
	      name: 'article'
	    }
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'document']]
	};
	var _default = graphicsDocumentRole$1;
	graphicsDocumentRole.default = _default;
	return graphicsDocumentRole;
}

var graphicsObjectRole = {};

var hasRequiredGraphicsObjectRole;

function requireGraphicsObjectRole () {
	if (hasRequiredGraphicsObjectRole) return graphicsObjectRole;
	hasRequiredGraphicsObjectRole = 1;

	Object.defineProperty(graphicsObjectRole, "__esModule", {
	  value: true
	});
	graphicsObjectRole.default = undefined;
	var graphicsObjectRole$1 = {
	  abstract: false,
	  accessibleNameRequired: false,
	  baseConcepts: [],
	  childrenPresentational: false,
	  nameFrom: ['author', 'contents'],
	  prohibitedProps: [],
	  props: {
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [{
	    module: 'GRAPHICS',
	    concept: {
	      name: 'graphics-document'
	    }
	  }, {
	    module: 'ARIA',
	    concept: {
	      name: 'group'
	    }
	  }, {
	    module: 'ARIA',
	    concept: {
	      name: 'img'
	    }
	  }, {
	    module: 'GRAPHICS',
	    concept: {
	      name: 'graphics-symbol'
	    }
	  }],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'group']]
	};
	var _default = graphicsObjectRole$1;
	graphicsObjectRole.default = _default;
	return graphicsObjectRole;
}

var graphicsSymbolRole = {};

var hasRequiredGraphicsSymbolRole;

function requireGraphicsSymbolRole () {
	if (hasRequiredGraphicsSymbolRole) return graphicsSymbolRole;
	hasRequiredGraphicsSymbolRole = 1;

	Object.defineProperty(graphicsSymbolRole, "__esModule", {
	  value: true
	});
	graphicsSymbolRole.default = undefined;
	var graphicsSymbolRole$1 = {
	  abstract: false,
	  accessibleNameRequired: true,
	  baseConcepts: [],
	  childrenPresentational: true,
	  nameFrom: ['author'],
	  prohibitedProps: [],
	  props: {
	    'aria-disabled': null,
	    'aria-errormessage': null,
	    'aria-expanded': null,
	    'aria-haspopup': null,
	    'aria-invalid': null
	  },
	  relatedConcepts: [],
	  requireContextRole: [],
	  requiredContextRole: [],
	  requiredOwnedElements: [],
	  requiredProps: {},
	  superClass: [['roletype', 'structure', 'section', 'img']]
	};
	var _default = graphicsSymbolRole$1;
	graphicsSymbolRole.default = _default;
	return graphicsSymbolRole;
}

var hasRequiredAriaGraphicsRoles;

function requireAriaGraphicsRoles () {
	if (hasRequiredAriaGraphicsRoles) return ariaGraphicsRoles;
	hasRequiredAriaGraphicsRoles = 1;

	Object.defineProperty(ariaGraphicsRoles, "__esModule", {
	  value: true
	});
	ariaGraphicsRoles.default = undefined;
	var _graphicsDocumentRole = _interopRequireDefault(requireGraphicsDocumentRole());
	var _graphicsObjectRole = _interopRequireDefault(requireGraphicsObjectRole());
	var _graphicsSymbolRole = _interopRequireDefault(requireGraphicsSymbolRole());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var ariaGraphicsRoles$1 = [['graphics-document', _graphicsDocumentRole.default], ['graphics-object', _graphicsObjectRole.default], ['graphics-symbol', _graphicsSymbolRole.default]];
	var _default = ariaGraphicsRoles$1;
	ariaGraphicsRoles.default = _default;
	return ariaGraphicsRoles;
}

var hasRequiredRolesMap;

function requireRolesMap () {
	if (hasRequiredRolesMap) return rolesMap;
	hasRequiredRolesMap = 1;

	Object.defineProperty(rolesMap, "__esModule", {
	  value: true
	});
	rolesMap.default = undefined;
	var _ariaAbstractRoles = _interopRequireDefault(requireAriaAbstractRoles());
	var _ariaLiteralRoles = _interopRequireDefault(requireAriaLiteralRoles());
	var _ariaDpubRoles = _interopRequireDefault(requireAriaDpubRoles());
	var _ariaGraphicsRoles = _interopRequireDefault(requireAriaGraphicsRoles());
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
	function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike) { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
	function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
	function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
	function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
	function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
	var roles = [].concat(_ariaAbstractRoles.default, _ariaLiteralRoles.default, _ariaDpubRoles.default, _ariaGraphicsRoles.default);
	roles.forEach(function (_ref) {
	  var _ref2 = _slicedToArray(_ref, 2),
	    roleDefinition = _ref2[1];
	  // Conglomerate the properties
	  var _iterator = _createForOfIteratorHelper(roleDefinition.superClass),
	    _step;
	  try {
	    for (_iterator.s(); !(_step = _iterator.n()).done;) {
	      var superClassIter = _step.value;
	      var _iterator2 = _createForOfIteratorHelper(superClassIter),
	        _step2;
	      try {
	        var _loop = function _loop() {
	          var superClassName = _step2.value;
	          var superClassRoleTuple = roles.find(function (_ref3) {
	            var _ref4 = _slicedToArray(_ref3, 1),
	              name = _ref4[0];
	            return name === superClassName;
	          });
	          if (superClassRoleTuple) {
	            var superClassDefinition = superClassRoleTuple[1];
	            for (var _i2 = 0, _Object$keys = Object.keys(superClassDefinition.props); _i2 < _Object$keys.length; _i2++) {
	              var prop = _Object$keys[_i2];
	              if (
	              // $FlowIssue Accessing the hasOwnProperty on the Object prototype is fine.
	              !Object.prototype.hasOwnProperty.call(roleDefinition.props, prop)) {
	                Object.assign(roleDefinition.props, _defineProperty({}, prop, superClassDefinition.props[prop]));
	              }
	            }
	          }
	        };
	        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
	          _loop();
	        }
	      } catch (err) {
	        _iterator2.e(err);
	      } finally {
	        _iterator2.f();
	      }
	    }
	  } catch (err) {
	    _iterator.e(err);
	  } finally {
	    _iterator.f();
	  }
	});
	var rolesMap$1 = {
	  entries: function entries() {
	    return roles;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    var _iterator3 = _createForOfIteratorHelper(roles),
	      _step3;
	    try {
	      for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
	        var _step3$value = _slicedToArray(_step3.value, 2),
	          key = _step3$value[0],
	          values = _step3$value[1];
	        fn.call(thisArg, values, key, roles);
	      }
	    } catch (err) {
	      _iterator3.e(err);
	    } finally {
	      _iterator3.f();
	    }
	  },
	  get: function get(key) {
	    var item = roles.find(function (tuple) {
	      return tuple[0] === key ? true : false;
	    });
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!rolesMap$1.get(key);
	  },
	  keys: function keys() {
	    return roles.map(function (_ref5) {
	      var _ref6 = _slicedToArray(_ref5, 1),
	        key = _ref6[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return roles.map(function (_ref7) {
	      var _ref8 = _slicedToArray(_ref7, 2),
	        values = _ref8[1];
	      return values;
	    });
	  }
	};
	var _default = (0, _iterationDecorator.default)(rolesMap$1, rolesMap$1.entries());
	rolesMap.default = _default;
	return rolesMap;
}

var elementRoleMap = {};

var lite = {};

var hasRequiredLite;

function requireLite () {
	if (hasRequiredLite) return lite;
	hasRequiredLite = 1;
	var has = Object.prototype.hasOwnProperty;

	function dequal(foo, bar) {
		var ctor, len;
		if (foo === bar) return true;

		if (foo && bar && (ctor=foo.constructor) === bar.constructor) {
			if (ctor === Date) return foo.getTime() === bar.getTime();
			if (ctor === RegExp) return foo.toString() === bar.toString();

			if (ctor === Array) {
				if ((len=foo.length) === bar.length) {
					while (len-- && dequal(foo[len], bar[len]));
				}
				return len === -1;
			}

			if (!ctor || typeof foo === 'object') {
				len = 0;
				for (ctor in foo) {
					if (has.call(foo, ctor) && ++len && !has.call(bar, ctor)) return false;
					if (!(ctor in bar) || !dequal(foo[ctor], bar[ctor])) return false;
				}
				return Object.keys(bar).length === len;
			}
		}

		return foo !== foo && bar !== bar;
	}

	lite.dequal = dequal;
	return lite;
}

var hasRequiredElementRoleMap;

function requireElementRoleMap () {
	if (hasRequiredElementRoleMap) return elementRoleMap;
	hasRequiredElementRoleMap = 1;

	Object.defineProperty(elementRoleMap, "__esModule", {
	  value: true
	});
	elementRoleMap.default = undefined;
	var _lite = requireLite();
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator());
	var _rolesMap = _interopRequireDefault(requireRolesMap());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
	function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
	function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike) { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
	function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
	function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
	var elementRoles = [];
	var keys = _rolesMap.default.keys();
	for (var i = 0; i < keys.length; i++) {
	  var key = keys[i];
	  var role = _rolesMap.default.get(key);
	  if (role) {
	    var concepts = [].concat(role.baseConcepts, role.relatedConcepts);
	    for (var k = 0; k < concepts.length; k++) {
	      var relation = concepts[k];
	      if (relation.module === 'HTML') {
	        (function () {
	          var concept = relation.concept;
	          if (concept) {
	            var elementRoleRelation = elementRoles.find(function (relation) {
	              return (0, _lite.dequal)(relation, concept);
	            });
	            var roles;
	            if (elementRoleRelation) {
	              roles = elementRoleRelation[1];
	            } else {
	              roles = [];
	            }
	            var isUnique = true;
	            for (var _i = 0; _i < roles.length; _i++) {
	              if (roles[_i] === key) {
	                isUnique = false;
	                break;
	              }
	            }
	            if (isUnique) {
	              roles.push(key);
	            }
	            elementRoles.push([concept, roles]);
	          }
	        })();
	      }
	    }
	  }
	}
	var elementRoleMap$1 = {
	  entries: function entries() {
	    return elementRoles;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    var _iterator = _createForOfIteratorHelper(elementRoles),
	      _step;
	    try {
	      for (_iterator.s(); !(_step = _iterator.n()).done;) {
	        var _step$value = _slicedToArray(_step.value, 2),
	          _key = _step$value[0],
	          values = _step$value[1];
	        fn.call(thisArg, values, _key, elementRoles);
	      }
	    } catch (err) {
	      _iterator.e(err);
	    } finally {
	      _iterator.f();
	    }
	  },
	  get: function get(key) {
	    var item = elementRoles.find(function (tuple) {
	      return key.name === tuple[0].name && (0, _lite.dequal)(key.attributes, tuple[0].attributes);
	    });
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!elementRoleMap$1.get(key);
	  },
	  keys: function keys() {
	    return elementRoles.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return elementRoles.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	var _default = (0, _iterationDecorator.default)(elementRoleMap$1, elementRoleMap$1.entries());
	elementRoleMap.default = _default;
	return elementRoleMap;
}

var roleElementMap = {};

var hasRequiredRoleElementMap;

function requireRoleElementMap () {
	if (hasRequiredRoleElementMap) return roleElementMap;
	hasRequiredRoleElementMap = 1;

	Object.defineProperty(roleElementMap, "__esModule", {
	  value: true
	});
	roleElementMap.default = undefined;
	var _iterationDecorator = _interopRequireDefault(requireIterationDecorator());
	var _rolesMap = _interopRequireDefault(requireRolesMap());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
	function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
	function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
	function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
	function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
	function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike) { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
	function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
	function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
	var roleElement = [];
	var keys = _rolesMap.default.keys();
	for (var i = 0; i < keys.length; i++) {
	  var key = keys[i];
	  var role = _rolesMap.default.get(key);
	  var relationConcepts = [];
	  if (role) {
	    var concepts = [].concat(role.baseConcepts, role.relatedConcepts);
	    for (var k = 0; k < concepts.length; k++) {
	      var relation = concepts[k];
	      if (relation.module === 'HTML') {
	        var concept = relation.concept;
	        if (concept != null) {
	          relationConcepts.push(concept);
	        }
	      }
	    }
	    if (relationConcepts.length > 0) {
	      roleElement.push([key, relationConcepts]);
	    }
	  }
	}
	var roleElementMap$1 = {
	  entries: function entries() {
	    return roleElement;
	  },
	  forEach: function forEach(fn) {
	    var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
	    var _iterator = _createForOfIteratorHelper(roleElement),
	      _step;
	    try {
	      for (_iterator.s(); !(_step = _iterator.n()).done;) {
	        var _step$value = _slicedToArray(_step.value, 2),
	          _key = _step$value[0],
	          values = _step$value[1];
	        fn.call(thisArg, values, _key, roleElement);
	      }
	    } catch (err) {
	      _iterator.e(err);
	    } finally {
	      _iterator.f();
	    }
	  },
	  get: function get(key) {
	    var item = roleElement.find(function (tuple) {
	      return tuple[0] === key ? true : false;
	    });
	    return item && item[1];
	  },
	  has: function has(key) {
	    return !!roleElementMap$1.get(key);
	  },
	  keys: function keys() {
	    return roleElement.map(function (_ref) {
	      var _ref2 = _slicedToArray(_ref, 1),
	        key = _ref2[0];
	      return key;
	    });
	  },
	  values: function values() {
	    return roleElement.map(function (_ref3) {
	      var _ref4 = _slicedToArray(_ref3, 2),
	        values = _ref4[1];
	      return values;
	    });
	  }
	};
	var _default = (0, _iterationDecorator.default)(roleElementMap$1, roleElementMap$1.entries());
	roleElementMap.default = _default;
	return roleElementMap;
}

var hasRequiredLib;

function requireLib () {
	if (hasRequiredLib) return lib;
	hasRequiredLib = 1;

	Object.defineProperty(lib, "__esModule", {
	  value: true
	});
	lib.roles = lib.roleElements = lib.elementRoles = lib.dom = lib.aria = undefined;
	var _ariaPropsMap = _interopRequireDefault(requireAriaPropsMap());
	var _domMap = _interopRequireDefault(requireDomMap());
	var _rolesMap = _interopRequireDefault(requireRolesMap());
	var _elementRoleMap = _interopRequireDefault(requireElementRoleMap());
	var _roleElementMap = _interopRequireDefault(requireRoleElementMap());
	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var aria = _ariaPropsMap.default;
	lib.aria = aria;
	var dom = _domMap.default;
	lib.dom = dom;
	var roles = _rolesMap.default;
	lib.roles = roles;
	var elementRoles = _elementRoleMap.default;
	lib.elementRoles = elementRoles;
	var roleElements = _roleElementMap.default;
	lib.roleElements = roleElements;
	return lib;
}

var libExports = requireLib();

var lzString$1 = {exports: {}};

lzString$1.exports;

var hasRequiredLzString;

function requireLzString () {
	if (hasRequiredLzString) return lzString$1.exports;
	hasRequiredLzString = 1;
	(function (module) {
		// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
		// This work is free. You can redistribute it and/or modify it
		// under the terms of the WTFPL, Version 2
		// For more information see LICENSE.txt or http://www.wtfpl.net/
		//
		// For more information, the home page:
		// http://pieroxy.net/blog/pages/lz-string/testing.html
		//
		// LZ-based compression algorithm, version 1.4.5
		var LZString = (function() {

		// private property
		var f = String.fromCharCode;
		var keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
		var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
		var baseReverseDic = {};

		function getBaseValue(alphabet, character) {
		  if (!baseReverseDic[alphabet]) {
		    baseReverseDic[alphabet] = {};
		    for (var i=0 ; i<alphabet.length ; i++) {
		      baseReverseDic[alphabet][alphabet.charAt(i)] = i;
		    }
		  }
		  return baseReverseDic[alphabet][character];
		}

		var LZString = {
		  compressToBase64 : function (input) {
		    if (input == null) return "";
		    var res = LZString._compress(input, 6, function(a){return keyStrBase64.charAt(a);});
		    switch (res.length % 4) { // To produce valid Base64
		    default: // When could this happen ?
		    case 0 : return res;
		    case 1 : return res+"===";
		    case 2 : return res+"==";
		    case 3 : return res+"=";
		    }
		  },

		  decompressFromBase64 : function (input) {
		    if (input == null) return "";
		    if (input == "") return null;
		    return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrBase64, input.charAt(index)); });
		  },

		  compressToUTF16 : function (input) {
		    if (input == null) return "";
		    return LZString._compress(input, 15, function(a){return f(a+32);}) + " ";
		  },

		  decompressFromUTF16: function (compressed) {
		    if (compressed == null) return "";
		    if (compressed == "") return null;
		    return LZString._decompress(compressed.length, 16384, function(index) { return compressed.charCodeAt(index) - 32; });
		  },

		  //compress into uint8array (UCS-2 big endian format)
		  compressToUint8Array: function (uncompressed) {
		    var compressed = LZString.compress(uncompressed);
		    var buf=new Uint8Array(compressed.length*2); // 2 bytes per character

		    for (var i=0, TotalLen=compressed.length; i<TotalLen; i++) {
		      var current_value = compressed.charCodeAt(i);
		      buf[i*2] = current_value >>> 8;
		      buf[i*2+1] = current_value % 256;
		    }
		    return buf;
		  },

		  //decompress from uint8array (UCS-2 big endian format)
		  decompressFromUint8Array:function (compressed) {
		    if (compressed===null || compressed===undefined){
		        return LZString.decompress(compressed);
		    } else {
		        var buf=new Array(compressed.length/2); // 2 bytes per character
		        for (var i=0, TotalLen=buf.length; i<TotalLen; i++) {
		          buf[i]=compressed[i*2]*256+compressed[i*2+1];
		        }

		        var result = [];
		        buf.forEach(function (c) {
		          result.push(f(c));
		        });
		        return LZString.decompress(result.join(''));

		    }

		  },


		  //compress into a string that is already URI encoded
		  compressToEncodedURIComponent: function (input) {
		    if (input == null) return "";
		    return LZString._compress(input, 6, function(a){return keyStrUriSafe.charAt(a);});
		  },

		  //decompress from an output of compressToEncodedURIComponent
		  decompressFromEncodedURIComponent:function (input) {
		    if (input == null) return "";
		    if (input == "") return null;
		    input = input.replace(/ /g, "+");
		    return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrUriSafe, input.charAt(index)); });
		  },

		  compress: function (uncompressed) {
		    return LZString._compress(uncompressed, 16, function(a){return f(a);});
		  },
		  _compress: function (uncompressed, bitsPerChar, getCharFromInt) {
		    if (uncompressed == null) return "";
		    var i, value,
		        context_dictionary= {},
		        context_dictionaryToCreate= {},
		        context_c="",
		        context_wc="",
		        context_w="",
		        context_enlargeIn= 2, // Compensate for the first entry which should not count
		        context_dictSize= 3,
		        context_numBits= 2,
		        context_data=[],
		        context_data_val=0,
		        context_data_position=0,
		        ii;

		    for (ii = 0; ii < uncompressed.length; ii += 1) {
		      context_c = uncompressed.charAt(ii);
		      if (!Object.prototype.hasOwnProperty.call(context_dictionary,context_c)) {
		        context_dictionary[context_c] = context_dictSize++;
		        context_dictionaryToCreate[context_c] = true;
		      }

		      context_wc = context_w + context_c;
		      if (Object.prototype.hasOwnProperty.call(context_dictionary,context_wc)) {
		        context_w = context_wc;
		      } else {
		        if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
		          if (context_w.charCodeAt(0)<256) {
		            for (i=0 ; i<context_numBits ; i++) {
		              context_data_val = (context_data_val << 1);
		              if (context_data_position == bitsPerChar-1) {
		                context_data_position = 0;
		                context_data.push(getCharFromInt(context_data_val));
		                context_data_val = 0;
		              } else {
		                context_data_position++;
		              }
		            }
		            value = context_w.charCodeAt(0);
		            for (i=0 ; i<8 ; i++) {
		              context_data_val = (context_data_val << 1) | (value&1);
		              if (context_data_position == bitsPerChar-1) {
		                context_data_position = 0;
		                context_data.push(getCharFromInt(context_data_val));
		                context_data_val = 0;
		              } else {
		                context_data_position++;
		              }
		              value = value >> 1;
		            }
		          } else {
		            value = 1;
		            for (i=0 ; i<context_numBits ; i++) {
		              context_data_val = (context_data_val << 1) | value;
		              if (context_data_position ==bitsPerChar-1) {
		                context_data_position = 0;
		                context_data.push(getCharFromInt(context_data_val));
		                context_data_val = 0;
		              } else {
		                context_data_position++;
		              }
		              value = 0;
		            }
		            value = context_w.charCodeAt(0);
		            for (i=0 ; i<16 ; i++) {
		              context_data_val = (context_data_val << 1) | (value&1);
		              if (context_data_position == bitsPerChar-1) {
		                context_data_position = 0;
		                context_data.push(getCharFromInt(context_data_val));
		                context_data_val = 0;
		              } else {
		                context_data_position++;
		              }
		              value = value >> 1;
		            }
		          }
		          context_enlargeIn--;
		          if (context_enlargeIn == 0) {
		            context_enlargeIn = Math.pow(2, context_numBits);
		            context_numBits++;
		          }
		          delete context_dictionaryToCreate[context_w];
		        } else {
		          value = context_dictionary[context_w];
		          for (i=0 ; i<context_numBits ; i++) {
		            context_data_val = (context_data_val << 1) | (value&1);
		            if (context_data_position == bitsPerChar-1) {
		              context_data_position = 0;
		              context_data.push(getCharFromInt(context_data_val));
		              context_data_val = 0;
		            } else {
		              context_data_position++;
		            }
		            value = value >> 1;
		          }


		        }
		        context_enlargeIn--;
		        if (context_enlargeIn == 0) {
		          context_enlargeIn = Math.pow(2, context_numBits);
		          context_numBits++;
		        }
		        // Add wc to the dictionary.
		        context_dictionary[context_wc] = context_dictSize++;
		        context_w = String(context_c);
		      }
		    }

		    // Output the code for w.
		    if (context_w !== "") {
		      if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
		        if (context_w.charCodeAt(0)<256) {
		          for (i=0 ; i<context_numBits ; i++) {
		            context_data_val = (context_data_val << 1);
		            if (context_data_position == bitsPerChar-1) {
		              context_data_position = 0;
		              context_data.push(getCharFromInt(context_data_val));
		              context_data_val = 0;
		            } else {
		              context_data_position++;
		            }
		          }
		          value = context_w.charCodeAt(0);
		          for (i=0 ; i<8 ; i++) {
		            context_data_val = (context_data_val << 1) | (value&1);
		            if (context_data_position == bitsPerChar-1) {
		              context_data_position = 0;
		              context_data.push(getCharFromInt(context_data_val));
		              context_data_val = 0;
		            } else {
		              context_data_position++;
		            }
		            value = value >> 1;
		          }
		        } else {
		          value = 1;
		          for (i=0 ; i<context_numBits ; i++) {
		            context_data_val = (context_data_val << 1) | value;
		            if (context_data_position == bitsPerChar-1) {
		              context_data_position = 0;
		              context_data.push(getCharFromInt(context_data_val));
		              context_data_val = 0;
		            } else {
		              context_data_position++;
		            }
		            value = 0;
		          }
		          value = context_w.charCodeAt(0);
		          for (i=0 ; i<16 ; i++) {
		            context_data_val = (context_data_val << 1) | (value&1);
		            if (context_data_position == bitsPerChar-1) {
		              context_data_position = 0;
		              context_data.push(getCharFromInt(context_data_val));
		              context_data_val = 0;
		            } else {
		              context_data_position++;
		            }
		            value = value >> 1;
		          }
		        }
		        context_enlargeIn--;
		        if (context_enlargeIn == 0) {
		          context_enlargeIn = Math.pow(2, context_numBits);
		          context_numBits++;
		        }
		        delete context_dictionaryToCreate[context_w];
		      } else {
		        value = context_dictionary[context_w];
		        for (i=0 ; i<context_numBits ; i++) {
		          context_data_val = (context_data_val << 1) | (value&1);
		          if (context_data_position == bitsPerChar-1) {
		            context_data_position = 0;
		            context_data.push(getCharFromInt(context_data_val));
		            context_data_val = 0;
		          } else {
		            context_data_position++;
		          }
		          value = value >> 1;
		        }


		      }
		      context_enlargeIn--;
		      if (context_enlargeIn == 0) {
		        context_enlargeIn = Math.pow(2, context_numBits);
		        context_numBits++;
		      }
		    }

		    // Mark the end of the stream
		    value = 2;
		    for (i=0 ; i<context_numBits ; i++) {
		      context_data_val = (context_data_val << 1) | (value&1);
		      if (context_data_position == bitsPerChar-1) {
		        context_data_position = 0;
		        context_data.push(getCharFromInt(context_data_val));
		        context_data_val = 0;
		      } else {
		        context_data_position++;
		      }
		      value = value >> 1;
		    }

		    // Flush the last char
		    while (true) {
		      context_data_val = (context_data_val << 1);
		      if (context_data_position == bitsPerChar-1) {
		        context_data.push(getCharFromInt(context_data_val));
		        break;
		      }
		      else context_data_position++;
		    }
		    return context_data.join('');
		  },

		  decompress: function (compressed) {
		    if (compressed == null) return "";
		    if (compressed == "") return null;
		    return LZString._decompress(compressed.length, 32768, function(index) { return compressed.charCodeAt(index); });
		  },

		  _decompress: function (length, resetValue, getNextValue) {
		    var dictionary = [],
		        enlargeIn = 4,
		        dictSize = 4,
		        numBits = 3,
		        entry = "",
		        result = [],
		        i,
		        w,
		        bits, resb, maxpower, power,
		        c,
		        data = {val:getNextValue(0), position:resetValue, index:1};

		    for (i = 0; i < 3; i += 1) {
		      dictionary[i] = i;
		    }

		    bits = 0;
		    maxpower = Math.pow(2,2);
		    power=1;
		    while (power!=maxpower) {
		      resb = data.val & data.position;
		      data.position >>= 1;
		      if (data.position == 0) {
		        data.position = resetValue;
		        data.val = getNextValue(data.index++);
		      }
		      bits |= (resb>0 ? 1 : 0) * power;
		      power <<= 1;
		    }

		    switch (bits) {
		      case 0:
		          bits = 0;
		          maxpower = Math.pow(2,8);
		          power=1;
		          while (power!=maxpower) {
		            resb = data.val & data.position;
		            data.position >>= 1;
		            if (data.position == 0) {
		              data.position = resetValue;
		              data.val = getNextValue(data.index++);
		            }
		            bits |= (resb>0 ? 1 : 0) * power;
		            power <<= 1;
		          }
		        c = f(bits);
		        break;
		      case 1:
		          bits = 0;
		          maxpower = Math.pow(2,16);
		          power=1;
		          while (power!=maxpower) {
		            resb = data.val & data.position;
		            data.position >>= 1;
		            if (data.position == 0) {
		              data.position = resetValue;
		              data.val = getNextValue(data.index++);
		            }
		            bits |= (resb>0 ? 1 : 0) * power;
		            power <<= 1;
		          }
		        c = f(bits);
		        break;
		      case 2:
		        return "";
		    }
		    dictionary[3] = c;
		    w = c;
		    result.push(c);
		    while (true) {
		      if (data.index > length) {
		        return "";
		      }

		      bits = 0;
		      maxpower = Math.pow(2,numBits);
		      power=1;
		      while (power!=maxpower) {
		        resb = data.val & data.position;
		        data.position >>= 1;
		        if (data.position == 0) {
		          data.position = resetValue;
		          data.val = getNextValue(data.index++);
		        }
		        bits |= (resb>0 ? 1 : 0) * power;
		        power <<= 1;
		      }

		      switch (c = bits) {
		        case 0:
		          bits = 0;
		          maxpower = Math.pow(2,8);
		          power=1;
		          while (power!=maxpower) {
		            resb = data.val & data.position;
		            data.position >>= 1;
		            if (data.position == 0) {
		              data.position = resetValue;
		              data.val = getNextValue(data.index++);
		            }
		            bits |= (resb>0 ? 1 : 0) * power;
		            power <<= 1;
		          }

		          dictionary[dictSize++] = f(bits);
		          c = dictSize-1;
		          enlargeIn--;
		          break;
		        case 1:
		          bits = 0;
		          maxpower = Math.pow(2,16);
		          power=1;
		          while (power!=maxpower) {
		            resb = data.val & data.position;
		            data.position >>= 1;
		            if (data.position == 0) {
		              data.position = resetValue;
		              data.val = getNextValue(data.index++);
		            }
		            bits |= (resb>0 ? 1 : 0) * power;
		            power <<= 1;
		          }
		          dictionary[dictSize++] = f(bits);
		          c = dictSize-1;
		          enlargeIn--;
		          break;
		        case 2:
		          return result.join('');
		      }

		      if (enlargeIn == 0) {
		        enlargeIn = Math.pow(2, numBits);
		        numBits++;
		      }

		      if (dictionary[c]) {
		        entry = dictionary[c];
		      } else {
		        if (c === dictSize) {
		          entry = w + w.charAt(0);
		        } else {
		          return null;
		        }
		      }
		      result.push(entry);

		      // Add w+entry[0] to the dictionary.
		      dictionary[dictSize++] = w + entry.charAt(0);
		      enlargeIn--;

		      w = entry;

		      if (enlargeIn == 0) {
		        enlargeIn = Math.pow(2, numBits);
		        numBits++;
		      }

		    }
		  }
		};
		  return LZString;
		})();

		if( module != null ) {
		  module.exports = LZString;
		} else if( typeof angular !== 'undefined' && angular != null ) {
		  angular.module('LZString', [])
		  .factory('LZString', function () {
		    return LZString;
		  });
		} 
	} (lzString$1));
	return lzString$1.exports;
}

var lzStringExports = requireLzString();
var lzString = /*@__PURE__*/getDefaultExportFromCjs(lzStringExports);

/**
 * Source: https://github.com/facebook/jest/blob/e7bb6a1e26ffab90611b2593912df15b69315611/packages/pretty-format/src/plugins/DOMElement.ts
 */
/* eslint-disable -- trying to stay as close to the original as possible */
/* istanbul ignore file */

function escapeHTML(str) {
  return str.replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
// Return empty string if keys is empty.
const printProps = (keys, props, config, indentation, depth, refs, printer) => {
  const indentationNext = indentation + config.indent;
  const colors = config.colors;
  return keys.map(key => {
    const value = props[key];
    let printed = printer(value, config, indentationNext, depth, refs);
    if (typeof value !== 'string') {
      if (printed.indexOf('\n') !== -1) {
        printed = config.spacingOuter + indentationNext + printed + config.spacingOuter + indentation;
      }
      printed = '{' + printed + '}';
    }
    return config.spacingInner + indentation + colors.prop.open + key + colors.prop.close + '=' + colors.value.open + printed + colors.value.close;
  }).join('');
};

// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#node_type_constants
const NodeTypeTextNode = 3;

// Return empty string if children is empty.
const printChildren = (children, config, indentation, depth, refs, printer) => children.map(child => {
  const printedChild = typeof child === 'string' ? printText(child, config) : printer(child, config, indentation, depth, refs);
  if (printedChild === '' && typeof child === 'object' && child !== null && child.nodeType !== NodeTypeTextNode) {
    // A plugin serialized this Node to '' meaning we should ignore it.
    return '';
  }
  return config.spacingOuter + indentation + printedChild;
}).join('');
const printText = (text, config) => {
  const contentColor = config.colors.content;
  return contentColor.open + escapeHTML(text) + contentColor.close;
};
const printComment = (comment, config) => {
  const commentColor = config.colors.comment;
  return commentColor.open + '<!--' + escapeHTML(comment) + '-->' + commentColor.close;
};

// Separate the functions to format props, children, and element,
// so a plugin could override a particular function, if needed.
// Too bad, so sad: the traditional (but unnecessary) space
// in a self-closing tagColor requires a second test of printedProps.
const printElement = (type, printedProps, printedChildren, config, indentation) => {
  const tagColor = config.colors.tag;
  return tagColor.open + '<' + type + (printedProps && tagColor.close + printedProps + config.spacingOuter + indentation + tagColor.open) + (printedChildren ? '>' + tagColor.close + printedChildren + config.spacingOuter + indentation + tagColor.open + '</' + type : (printedProps && !config.min ? '' : ' ') + '/') + '>' + tagColor.close;
};
const printElementAsLeaf = (type, config) => {
  const tagColor = config.colors.tag;
  return tagColor.open + '<' + type + tagColor.close + ' …' + tagColor.open + ' />' + tagColor.close;
};
const ELEMENT_NODE$1 = 1;
const TEXT_NODE$1 = 3;
const COMMENT_NODE$1 = 8;
const FRAGMENT_NODE = 11;
const ELEMENT_REGEXP = /^((HTML|SVG)\w*)?Element$/;
const isCustomElement = val => {
  const {
    tagName
  } = val;
  return Boolean(typeof tagName === 'string' && tagName.includes('-') || typeof val.hasAttribute === 'function' && val.hasAttribute('is'));
};
const testNode = val => {
  const constructorName = val.constructor.name;
  const {
    nodeType
  } = val;
  return nodeType === ELEMENT_NODE$1 && (ELEMENT_REGEXP.test(constructorName) || isCustomElement(val)) || nodeType === TEXT_NODE$1 && constructorName === 'Text' || nodeType === COMMENT_NODE$1 && constructorName === 'Comment' || nodeType === FRAGMENT_NODE && constructorName === 'DocumentFragment';
};
function nodeIsText(node) {
  return node.nodeType === TEXT_NODE$1;
}
function nodeIsComment(node) {
  return node.nodeType === COMMENT_NODE$1;
}
function nodeIsFragment(node) {
  return node.nodeType === FRAGMENT_NODE;
}
function createDOMElementFilter(filterNode) {
  return {
    test: val => {
      var _val$constructor2;
      return ((val == null || (_val$constructor2 = val.constructor) == null ? undefined : _val$constructor2.name) || isCustomElement(val)) && testNode(val);
    },
    serialize: (node, config, indentation, depth, refs, printer) => {
      if (nodeIsText(node)) {
        return printText(node.data, config);
      }
      if (nodeIsComment(node)) {
        return printComment(node.data, config);
      }
      const type = nodeIsFragment(node) ? "DocumentFragment" : node.tagName.toLowerCase();
      if (++depth > config.maxDepth) {
        return printElementAsLeaf(type, config);
      }
      return printElement(type, printProps(nodeIsFragment(node) ? [] : Array.from(node.attributes).map(attr => attr.name).sort(), nodeIsFragment(node) ? {} : Array.from(node.attributes).reduce((props, attribute) => {
        props[attribute.name] = attribute.value;
        return props;
      }, {}), config, indentation + config.indent, depth, refs, printer), printChildren(Array.prototype.slice.call(node.childNodes || node.children).filter(filterNode), config, indentation + config.indent, depth, refs, printer), config, indentation);
    }
  };
}

// We try to load node dependencies
let chalk = null;
let readFileSync = null;
let codeFrameColumns = null;
try {
  const nodeRequire = module && module.require;
  readFileSync = nodeRequire.call(module, 'fs').readFileSync;
  codeFrameColumns = nodeRequire.call(module, '@babel/code-frame').codeFrameColumns;
  chalk = nodeRequire.call(module, 'chalk');
} catch {
  // We're in a browser environment
}

// frame has the form "at myMethod (location/to/my/file.js:10:2)"
function getCodeFrame(frame) {
  const locationStart = frame.indexOf('(') + 1;
  const locationEnd = frame.indexOf(')');
  const frameLocation = frame.slice(locationStart, locationEnd);
  const frameLocationElements = frameLocation.split(':');
  const [filename, line, column] = [frameLocationElements[0], parseInt(frameLocationElements[1], 10), parseInt(frameLocationElements[2], 10)];
  let rawFileContents = '';
  try {
    rawFileContents = readFileSync(filename, 'utf-8');
  } catch {
    return '';
  }
  const codeFrame = codeFrameColumns(rawFileContents, {
    start: {
      line,
      column
    }
  }, {
    highlightCode: true,
    linesBelow: 0
  });
  return chalk.dim(frameLocation) + "\n" + codeFrame + "\n";
}
function getUserCodeFrame() {
  // If we couldn't load dependencies, we can't generate the user trace
  /* istanbul ignore next */
  if (!readFileSync || !codeFrameColumns) {
    return '';
  }
  const err = new Error();
  const firstClientCodeFrame = err.stack.split('\n').slice(1) // Remove first line which has the form "Error: TypeError"
  .find(frame => !frame.includes('node_modules/')); // Ignore frames from 3rd party libraries

  return getCodeFrame(firstClientCodeFrame);
}

// Constant node.nodeType for text nodes, see:
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#Node_type_constants
const TEXT_NODE = 3;
function jestFakeTimersAreEnabled$1() {
  /* istanbul ignore else */
  // eslint-disable-next-line
  if (typeof jest !== 'undefined' && jest !== null) {
    return (
      // legacy timers
      setTimeout._isMockFunction === true ||
      // modern timers
      // eslint-disable-next-line prefer-object-has-own -- not supported by our support matrix
      Object.prototype.hasOwnProperty.call(setTimeout, 'clock')
    );
  }
  // istanbul ignore next
  return false;
}
function getDocument$1() {
  /* istanbul ignore if */
  if (typeof window === 'undefined') {
    throw new Error('Could not find default container');
  }
  return window.document;
}
function getWindowFromNode(node) {
  if (node.defaultView) {
    // node is document
    return node.defaultView;
  } else if (node.ownerDocument && node.ownerDocument.defaultView) {
    // node is a DOM node
    return node.ownerDocument.defaultView;
  } else if (node.window) {
    // node is window
    return node.window;
  } else if (node.ownerDocument && node.ownerDocument.defaultView === null) {
    throw new Error("It looks like the window object is not available for the provided node.");
  } else if (node.then instanceof Function) {
    throw new Error("It looks like you passed a Promise object instead of a DOM node. Did you do something like `fireEvent.click(screen.findBy...` when you meant to use a `getBy` query `fireEvent.click(screen.getBy...`, or await the findBy query `fireEvent.click(await screen.findBy...`?");
  } else if (Array.isArray(node)) {
    throw new Error("It looks like you passed an Array instead of a DOM node. Did you do something like `fireEvent.click(screen.getAllBy...` when you meant to use a `getBy` query `fireEvent.click(screen.getBy...`?");
  } else if (typeof node.debug === 'function' && typeof node.logTestingPlaygroundURL === 'function') {
    throw new Error("It looks like you passed a `screen` object. Did you do something like `fireEvent.click(screen, ...` when you meant to use a query, e.g. `fireEvent.click(screen.getBy..., `?");
  } else {
    // The user passed something unusual to a calling function
    throw new Error("The given node is not an Element, the node type is: " + typeof node + ".");
  }
}
function checkContainerType(container) {
  if (!container || !(typeof container.querySelector === 'function') || !(typeof container.querySelectorAll === 'function')) {
    throw new TypeError("Expected container to be an Element, a Document or a DocumentFragment but got " + getTypeName(container) + ".");
  }
  function getTypeName(object) {
    if (typeof object === 'object') {
      return object === null ? 'null' : object.constructor.name;
    }
    return typeof object;
  }
}

const shouldHighlight = () => {
  if (typeof process === 'undefined') {
    // Don't colorize in non-node environments (e.g. Browsers)
    return false;
  }
  let colors;
  // Try to safely parse env COLORS: We will default behavior if any step fails.
  try {
    var _process$env;
    const colorsJSON = (_process$env = process.env) == null ? void 0 : _process$env.COLORS;
    if (colorsJSON) {
      colors = JSON.parse(colorsJSON);
    }
  } catch {
    // If this throws, process.env?.COLORS wasn't parsable. Since we only
    // care about `true` or `false`, we can safely ignore the error.
  }
  if (typeof colors === 'boolean') {
    // If `colors` is set explicitly (both `true` and `false`), use that value.
    return colors;
  } else {
    // If `colors` is not set, colorize if we're in node.
    return process.versions !== undefined && process.versions.node !== undefined;
  }
};
const {
  DOMCollection
} = buildExports.plugins;

// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType#node_type_constants
const ELEMENT_NODE = 1;
const COMMENT_NODE = 8;

// https://github.com/facebook/jest/blob/615084195ae1ae61ddd56162c62bbdda17587569/packages/pretty-format/src/plugins/DOMElement.ts#L50
function filterCommentsAndDefaultIgnoreTagsTags(value) {
  return value.nodeType !== COMMENT_NODE && (value.nodeType !== ELEMENT_NODE || !value.matches(getConfig().defaultIgnore));
}
function prettyDOM(dom, maxLength, options) {
  if (options === undefined) {
    options = {};
  }
  if (!dom) {
    dom = getDocument$1().body;
  }
  if (typeof maxLength !== 'number') {
    maxLength = typeof process !== 'undefined' && typeof process.env !== 'undefined' && process.env.DEBUG_PRINT_LIMIT || 7000;
  }
  if (maxLength === 0) {
    return '';
  }
  if (dom.documentElement) {
    dom = dom.documentElement;
  }
  let domTypeName = typeof dom;
  if (domTypeName === 'object') {
    domTypeName = dom.constructor.name;
  } else {
    // To don't fall with `in` operator
    dom = {};
  }
  if (!('outerHTML' in dom)) {
    throw new TypeError("Expected an element or document but got " + domTypeName);
  }
  const {
    filterNode = filterCommentsAndDefaultIgnoreTagsTags,
    ...prettyFormatOptions
  } = options;
  const debugContent = buildExports.format(dom, {
    plugins: [createDOMElementFilter(filterNode), DOMCollection],
    printFunctionName: false,
    highlight: shouldHighlight(),
    ...prettyFormatOptions
  });
  return maxLength !== undefined && dom.outerHTML.length > maxLength ? debugContent.slice(0, maxLength) + "..." : debugContent;
}
const logDOM = function () {
  const userCodeFrame = getUserCodeFrame();
  if (userCodeFrame) {
    console.log(prettyDOM(...arguments) + "\n\n" + userCodeFrame);
  } else {
    console.log(prettyDOM(...arguments));
  }
};

// It would be cleaner for this to live inside './queries', but
// other parts of the code assume that all exports from
// './queries' are query functions.
let config = {
  testIdAttribute: 'data-testid',
  asyncUtilTimeout: 1000,
  // asyncWrapper and advanceTimersWrapper is to support React's async `act` function.
  // forcing react-testing-library to wrap all async functions would've been
  // a total nightmare (consider wrapping every findBy* query and then also
  // updating `within` so those would be wrapped too. Total nightmare).
  // so we have this config option that's really only intended for
  // react-testing-library to use. For that reason, this feature will remain
  // undocumented.
  asyncWrapper: cb => cb(),
  unstable_advanceTimersWrapper: cb => cb(),
  eventWrapper: cb => cb(),
  // default value for the `hidden` option in `ByRole` queries
  defaultHidden: false,
  // default value for the `ignore` option in `ByText` queries
  defaultIgnore: 'script, style',
  // showOriginalStackTrace flag to show the full error stack traces for async errors
  showOriginalStackTrace: false,
  // throw errors w/ suggestions for better queries. Opt in so off by default.
  throwSuggestions: false,
  // called when getBy* queries fail. (message, container) => Error
  getElementError(message, container) {
    const prettifiedDOM = prettyDOM(container);
    const error = new Error([message, "Ignored nodes: comments, " + config.defaultIgnore + "\n" + prettifiedDOM].filter(Boolean).join('\n\n'));
    error.name = 'TestingLibraryElementError';
    return error;
  },
  _disableExpensiveErrorDiagnostics: false,
  computedStyleSupportsPseudoElements: false
};
function runWithExpensiveErrorDiagnosticsDisabled(callback) {
  try {
    config._disableExpensiveErrorDiagnostics = true;
    return callback();
  } finally {
    config._disableExpensiveErrorDiagnostics = false;
  }
}
function configure(newConfig) {
  if (typeof newConfig === 'function') {
    // Pass the existing config out to the provided function
    // and accept a delta in return
    newConfig = newConfig(config);
  }

  // Merge the incoming config delta
  config = {
    ...config,
    ...newConfig
  };
}
function getConfig() {
  return config;
}

const labelledNodeNames = ['button', 'meter', 'output', 'progress', 'select', 'textarea', 'input'];
function getTextContent(node) {
  if (labelledNodeNames.includes(node.nodeName.toLowerCase())) {
    return '';
  }
  if (node.nodeType === TEXT_NODE) return node.textContent;
  return Array.from(node.childNodes).map(childNode => getTextContent(childNode)).join('');
}
function getLabelContent(element) {
  let textContent;
  if (element.tagName.toLowerCase() === 'label') {
    textContent = getTextContent(element);
  } else {
    textContent = element.value || element.textContent;
  }
  return textContent;
}

// Based on https://github.com/eps1lon/dom-accessibility-api/pull/352
function getRealLabels(element) {
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- types are not aware of older browsers that don't implement `labels`
  if (element.labels !== undefined) {
    var _labels;
    return (_labels = element.labels) != null ? _labels : [];
  }
  if (!isLabelable(element)) return [];
  const labels = element.ownerDocument.querySelectorAll('label');
  return Array.from(labels).filter(label => label.control === element);
}
function isLabelable(element) {
  return /BUTTON|METER|OUTPUT|PROGRESS|SELECT|TEXTAREA/.test(element.tagName) || element.tagName === 'INPUT' && element.getAttribute('type') !== 'hidden';
}
function getLabels(container, element, _temp) {
  let {
    selector = '*'
  } = _temp === undefined ? {} : _temp;
  const ariaLabelledBy = element.getAttribute('aria-labelledby');
  const labelsId = ariaLabelledBy ? ariaLabelledBy.split(' ') : [];
  return labelsId.length ? labelsId.map(labelId => {
    const labellingElement = container.querySelector("[id=\"" + labelId + "\"]");
    return labellingElement ? {
      content: getLabelContent(labellingElement),
      formControl: null
    } : {
      content: '',
      formControl: null
    };
  }) : Array.from(getRealLabels(element)).map(label => {
    const textToMatch = getLabelContent(label);
    const formControlSelector = 'button, input, meter, output, progress, select, textarea';
    const labelledFormControl = Array.from(label.querySelectorAll(formControlSelector)).filter(formControlElement => formControlElement.matches(selector))[0];
    return {
      content: textToMatch,
      formControl: labelledFormControl
    };
  });
}

function assertNotNullOrUndefined(matcher) {
  if (matcher === null || matcher === undefined) {
    throw new Error( // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- implicitly converting `T` to `string`
    "It looks like " + matcher + " was passed instead of a matcher. Did you do something like getByText(" + matcher + ")?");
  }
}
function fuzzyMatches(textToMatch, node, matcher, normalizer) {
  if (typeof textToMatch !== 'string') {
    return false;
  }
  assertNotNullOrUndefined(matcher);
  const normalizedText = normalizer(textToMatch);
  if (typeof matcher === 'string' || typeof matcher === 'number') {
    return normalizedText.toLowerCase().includes(matcher.toString().toLowerCase());
  } else if (typeof matcher === 'function') {
    return matcher(normalizedText, node);
  } else {
    return matchRegExp(matcher, normalizedText);
  }
}
function matches(textToMatch, node, matcher, normalizer) {
  if (typeof textToMatch !== 'string') {
    return false;
  }
  assertNotNullOrUndefined(matcher);
  const normalizedText = normalizer(textToMatch);
  if (matcher instanceof Function) {
    return matcher(normalizedText, node);
  } else if (matcher instanceof RegExp) {
    return matchRegExp(matcher, normalizedText);
  } else {
    return normalizedText === String(matcher);
  }
}
function getDefaultNormalizer(_temp) {
  let {
    trim = true,
    collapseWhitespace = true
  } = _temp === undefined ? {} : _temp;
  return text => {
    let normalizedText = text;
    normalizedText = trim ? normalizedText.trim() : normalizedText;
    normalizedText = collapseWhitespace ? normalizedText.replace(/\s+/g, ' ') : normalizedText;
    return normalizedText;
  };
}

/**
 * Constructs a normalizer to pass to functions in matches.js
 * @param {boolean|undefined} trim The user-specified value for `trim`, without
 * any defaulting having been applied
 * @param {boolean|undefined} collapseWhitespace The user-specified value for
 * `collapseWhitespace`, without any defaulting having been applied
 * @param {Function|undefined} normalizer The user-specified normalizer
 * @returns {Function} A normalizer
 */

function makeNormalizer(_ref) {
  let {
    trim,
    collapseWhitespace,
    normalizer
  } = _ref;
  if (!normalizer) {
    // No custom normalizer specified. Just use default.
    return getDefaultNormalizer({
      trim,
      collapseWhitespace
    });
  }
  if (typeof trim !== 'undefined' || typeof collapseWhitespace !== 'undefined') {
    // They've also specified a value for trim or collapseWhitespace
    throw new Error('trim and collapseWhitespace are not supported with a normalizer. ' + 'If you want to use the default trim and collapseWhitespace logic in your normalizer, ' + 'use "getDefaultNormalizer({trim, collapseWhitespace})" and compose that into your normalizer');
  }
  return normalizer;
}
function matchRegExp(matcher, text) {
  const match = matcher.test(text);
  if (matcher.global && matcher.lastIndex !== 0) {
    console.warn("To match all elements we had to reset the lastIndex of the RegExp because the global flag is enabled. We encourage to remove the global flag from the RegExp.");
    matcher.lastIndex = 0;
  }
  return match;
}

function getNodeText(node) {
  if (node.matches('input[type=submit], input[type=button], input[type=reset]')) {
    return node.value;
  }
  return Array.from(node.childNodes).filter(child => child.nodeType === TEXT_NODE && Boolean(child.textContent)).map(c => c.textContent).join('');
}

const elementRoleList = buildElementRoleList(libExports.elementRoles);

/**
 * @param {Element} element -
 * @returns {boolean} - `true` if `element` and its subtree are inaccessible
 */
function isSubtreeInaccessible(element) {
  if (element.hidden === true) {
    return true;
  }
  if (element.getAttribute('aria-hidden') === 'true') {
    return true;
  }
  const window = element.ownerDocument.defaultView;
  if (window.getComputedStyle(element).display === 'none') {
    return true;
  }
  return false;
}

/**
 * Partial implementation https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
 * which should only be used for elements with a non-presentational role i.e.
 * `role="none"` and `role="presentation"` will not be excluded.
 *
 * Implements aria-hidden semantics (i.e. parent overrides child)
 * Ignores "Child Presentational: True" characteristics
 *
 * @param {Element} element -
 * @param {object} [options] -
 * @param {function (element: Element): boolean} options.isSubtreeInaccessible -
 * can be used to return cached results from previous isSubtreeInaccessible calls
 * @returns {boolean} true if excluded, otherwise false
 */
function isInaccessible(element, options) {
  if (options === undefined) {
    options = {};
  }
  const {
    isSubtreeInaccessible: isSubtreeInaccessibleImpl = isSubtreeInaccessible
  } = options;
  const window = element.ownerDocument.defaultView;
  // since visibility is inherited we can exit early
  if (window.getComputedStyle(element).visibility === 'hidden') {
    return true;
  }
  let currentElement = element;
  while (currentElement) {
    if (isSubtreeInaccessibleImpl(currentElement)) {
      return true;
    }
    currentElement = currentElement.parentElement;
  }
  return false;
}
function getImplicitAriaRoles(currentNode) {
  // eslint bug here:
  // eslint-disable-next-line no-unused-vars
  for (const {
    match,
    roles
  } of elementRoleList) {
    if (match(currentNode)) {
      return [...roles];
    }
  }
  return [];
}
function buildElementRoleList(elementRolesMap) {
  function makeElementSelector(_ref) {
    let {
      name,
      attributes
    } = _ref;
    return "" + name + attributes.map(_ref2 => {
      let {
        name: attributeName,
        value,
        constraints = []
      } = _ref2;
      const shouldNotExist = constraints.indexOf('undefined') !== -1;
      const shouldBeNonEmpty = constraints.indexOf('set') !== -1;
      const hasExplicitValue = typeof value !== 'undefined';
      if (hasExplicitValue) {
        return "[" + attributeName + "=\"" + value + "\"]";
      } else if (shouldNotExist) {
        return ":not([" + attributeName + "])";
      } else if (shouldBeNonEmpty) {
        return "[" + attributeName + "]:not([" + attributeName + "=\"\"])";
      }
      return "[" + attributeName + "]";
    }).join('');
  }
  function getSelectorSpecificity(_ref3) {
    let {
      attributes = []
    } = _ref3;
    return attributes.length;
  }
  function bySelectorSpecificity(_ref4, _ref5) {
    let {
      specificity: leftSpecificity
    } = _ref4;
    let {
      specificity: rightSpecificity
    } = _ref5;
    return rightSpecificity - leftSpecificity;
  }
  function match(element) {
    let {
      attributes = []
    } = element;

    // https://github.com/testing-library/dom-testing-library/issues/814
    const typeTextIndex = attributes.findIndex(attribute => attribute.value && attribute.name === 'type' && attribute.value === 'text');
    if (typeTextIndex >= 0) {
      // not using splice to not mutate the attributes array
      attributes = [...attributes.slice(0, typeTextIndex), ...attributes.slice(typeTextIndex + 1)];
    }
    const selector = makeElementSelector({
      ...element,
      attributes
    });
    return node => {
      if (typeTextIndex >= 0 && node.type !== 'text') {
        return false;
      }
      return node.matches(selector);
    };
  }
  let result = [];

  // eslint bug here:
  // eslint-disable-next-line no-unused-vars
  for (const [element, roles] of elementRolesMap.entries()) {
    result = [...result, {
      match: match(element),
      roles: Array.from(roles),
      specificity: getSelectorSpecificity(element)
    }];
  }
  return result.sort(bySelectorSpecificity);
}
function getRoles(container, _temp) {
  let {
    hidden = false
  } = _temp === undefined ? {} : _temp;
  function flattenDOM(node) {
    return [node, ...Array.from(node.children).reduce((acc, child) => [...acc, ...flattenDOM(child)], [])];
  }
  return flattenDOM(container).filter(element => {
    return hidden === false ? isInaccessible(element) === false : true;
  }).reduce((acc, node) => {
    let roles = [];
    // TODO: This violates html-aria which does not allow any role on every element
    if (node.hasAttribute('role')) {
      roles = node.getAttribute('role').split(' ').slice(0, 1);
    } else {
      roles = getImplicitAriaRoles(node);
    }
    return roles.reduce((rolesAcc, role) => Array.isArray(rolesAcc[role]) ? {
      ...rolesAcc,
      [role]: [...rolesAcc[role], node]
    } : {
      ...rolesAcc,
      [role]: [node]
    }, acc);
  }, {});
}
function prettyRoles(dom, _ref6) {
  let {
    hidden,
    includeDescription
  } = _ref6;
  const roles = getRoles(dom, {
    hidden
  });
  // We prefer to skip generic role, we don't recommend it
  return Object.entries(roles).filter(_ref7 => {
    let [role] = _ref7;
    return role !== 'generic';
  }).map(_ref8 => {
    let [role, elements] = _ref8;
    const delimiterBar = '-'.repeat(50);
    const elementsString = elements.map(el => {
      const nameString = "Name \"" + computeAccessibleName(el, {
        computedStyleSupportsPseudoElements: getConfig().computedStyleSupportsPseudoElements
      }) + "\":\n";
      const domString = prettyDOM(el.cloneNode(false));
      if (includeDescription) {
        const descriptionString = "Description \"" + computeAccessibleDescription(el, {
          computedStyleSupportsPseudoElements: getConfig().computedStyleSupportsPseudoElements
        }) + "\":\n";
        return "" + nameString + descriptionString + domString;
      }
      return "" + nameString + domString;
    }).join('\n\n');
    return role + ":\n\n" + elementsString + "\n\n" + delimiterBar;
  }).join('\n');
}

/**
 * @param {Element} element -
 * @returns {boolean | undefined} - false/true if (not)selected, undefined if not selectable
 */
function computeAriaSelected(element) {
  // implicit value from html-aam mappings: https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
  // https://www.w3.org/TR/html-aam-1.0/#details-id-97
  if (element.tagName === 'OPTION') {
    return element.selected;
  }

  // explicit value
  return checkBooleanAttribute(element, 'aria-selected');
}

/**
 * @param {Element} element -
 * @returns {boolean} -
 */
function computeAriaBusy(element) {
  // https://www.w3.org/TR/wai-aria-1.1/#aria-busy
  return element.getAttribute('aria-busy') === 'true';
}

/**
 * @param {Element} element -
 * @returns {boolean | undefined} - false/true if (not)checked, undefined if not checked-able
 */
function computeAriaChecked(element) {
  // implicit value from html-aam mappings: https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings
  // https://www.w3.org/TR/html-aam-1.0/#details-id-56
  // https://www.w3.org/TR/html-aam-1.0/#details-id-67
  if ('indeterminate' in element && element.indeterminate) {
    return undefined;
  }
  if ('checked' in element) {
    return element.checked;
  }

  // explicit value
  return checkBooleanAttribute(element, 'aria-checked');
}

/**
 * @param {Element} element -
 * @returns {boolean | undefined} - false/true if (not)pressed, undefined if not press-able
 */
function computeAriaPressed(element) {
  // https://www.w3.org/TR/wai-aria-1.1/#aria-pressed
  return checkBooleanAttribute(element, 'aria-pressed');
}

/**
 * @param {Element} element -
 * @returns {boolean | string | null} -
 */
function computeAriaCurrent(element) {
  var _ref9, _checkBooleanAttribut;
  // https://www.w3.org/TR/wai-aria-1.1/#aria-current
  return (_ref9 = (_checkBooleanAttribut = checkBooleanAttribute(element, 'aria-current')) != null ? _checkBooleanAttribut : element.getAttribute('aria-current')) != null ? _ref9 : false;
}

/**
 * @param {Element} element -
 * @returns {boolean | undefined} - false/true if (not)expanded, undefined if not expand-able
 */
function computeAriaExpanded(element) {
  // https://www.w3.org/TR/wai-aria-1.1/#aria-expanded
  return checkBooleanAttribute(element, 'aria-expanded');
}
function checkBooleanAttribute(element, attribute) {
  const attributeValue = element.getAttribute(attribute);
  if (attributeValue === 'true') {
    return true;
  }
  if (attributeValue === 'false') {
    return false;
  }
  return undefined;
}

/**
 * @param {Element} element -
 * @returns {number | undefined} - number if implicit heading or aria-level present, otherwise undefined
 */
function computeHeadingLevel(element) {
  // https://w3c.github.io/html-aam/#el-h1-h6
  // https://w3c.github.io/html-aam/#el-h1-h6
  const implicitHeadingLevels = {
    H1: 1,
    H2: 2,
    H3: 3,
    H4: 4,
    H5: 5,
    H6: 6
  };
  // explicit aria-level value
  // https://www.w3.org/TR/wai-aria-1.2/#aria-level
  const ariaLevelAttribute = element.getAttribute('aria-level') && Number(element.getAttribute('aria-level'));
  return ariaLevelAttribute || implicitHeadingLevels[element.tagName];
}

/**
 * @param {Element} element -
 * @returns {number | undefined} -
 */
function computeAriaValueNow(element) {
  const valueNow = element.getAttribute('aria-valuenow');
  return valueNow === null ? undefined : +valueNow;
}

/**
 * @param {Element} element -
 * @returns {number | undefined} -
 */
function computeAriaValueMax(element) {
  const valueMax = element.getAttribute('aria-valuemax');
  return valueMax === null ? undefined : +valueMax;
}

/**
 * @param {Element} element -
 * @returns {number | undefined} -
 */
function computeAriaValueMin(element) {
  const valueMin = element.getAttribute('aria-valuemin');
  return valueMin === null ? undefined : +valueMin;
}

/**
 * @param {Element} element -
 * @returns {string | undefined} -
 */
function computeAriaValueText(element) {
  const valueText = element.getAttribute('aria-valuetext');
  return valueText === null ? undefined : valueText;
}

const normalize = getDefaultNormalizer();
function escapeRegExp(string) {
  return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
function getRegExpMatcher(string) {
  return new RegExp(escapeRegExp(string.toLowerCase()), 'i');
}
function makeSuggestion(queryName, element, content, _ref) {
  let {
    variant,
    name
  } = _ref;
  let warning = '';
  const queryOptions = {};
  const queryArgs = [['Role', 'TestId'].includes(queryName) ? content : getRegExpMatcher(content)];
  if (name) {
    queryOptions.name = getRegExpMatcher(name);
  }
  if (queryName === 'Role' && isInaccessible(element)) {
    queryOptions.hidden = true;
    warning = "Element is inaccessible. This means that the element and all its children are invisible to screen readers.\n    If you are using the aria-hidden prop, make sure this is the right choice for your case.\n    ";
  }
  if (Object.keys(queryOptions).length > 0) {
    queryArgs.push(queryOptions);
  }
  const queryMethod = variant + "By" + queryName;
  return {
    queryName,
    queryMethod,
    queryArgs,
    variant,
    warning,
    toString() {
      if (warning) {
        console.warn(warning);
      }
      let [text, options] = queryArgs;
      text = typeof text === 'string' ? "'" + text + "'" : text;
      options = options ? ", { " + Object.entries(options).map(_ref2 => {
        let [k, v] = _ref2;
        return k + ": " + v;
      }).join(', ') + " }" : '';
      return queryMethod + "(" + text + options + ")";
    }
  };
}
function canSuggest(currentMethod, requestedMethod, data) {
  return data && (true);
}
function getSuggestedQuery(element, variant, method) {
  var _element$getAttribute, _getImplicitAriaRoles;
  if (variant === undefined) {
    variant = 'get';
  }
  // don't create suggestions for script and style elements
  if (element.matches(getConfig().defaultIgnore)) {
    return undefined;
  }

  //We prefer to suggest something else if the role is generic
  const role = (_element$getAttribute = element.getAttribute('role')) != null ? _element$getAttribute : (_getImplicitAriaRoles = getImplicitAriaRoles(element)) == null ? undefined : _getImplicitAriaRoles[0];
  if (role !== 'generic' && canSuggest('Role', method, role)) {
    return makeSuggestion('Role', element, role, {
      variant,
      name: computeAccessibleName(element, {
        computedStyleSupportsPseudoElements: getConfig().computedStyleSupportsPseudoElements
      })
    });
  }
  const labelText = getLabels(document, element).map(label => label.content).join(' ');
  if (canSuggest('LabelText', method, labelText)) {
    return makeSuggestion('LabelText', element, labelText, {
      variant
    });
  }
  const placeholderText = element.getAttribute('placeholder');
  if (canSuggest('PlaceholderText', method, placeholderText)) {
    return makeSuggestion('PlaceholderText', element, placeholderText, {
      variant
    });
  }
  const textContent = normalize(getNodeText(element));
  if (canSuggest('Text', method, textContent)) {
    return makeSuggestion('Text', element, textContent, {
      variant
    });
  }
  if (canSuggest('DisplayValue', method, element.value)) {
    return makeSuggestion('DisplayValue', element, normalize(element.value), {
      variant
    });
  }
  const alt = element.getAttribute('alt');
  if (canSuggest('AltText', method, alt)) {
    return makeSuggestion('AltText', element, alt, {
      variant
    });
  }
  const title = element.getAttribute('title');
  if (canSuggest('Title', method, title)) {
    return makeSuggestion('Title', element, title, {
      variant
    });
  }
  const testId = element.getAttribute(getConfig().testIdAttribute);
  if (canSuggest('TestId', method, testId)) {
    return makeSuggestion('TestId', element, testId, {
      variant
    });
  }
  return undefined;
}

// This is so the stack trace the developer sees is one that's
// closer to their code (because async stack traces are hard to follow).
function copyStackTrace(target, source) {
  target.stack = source.stack.replace(source.message, target.message);
}
function waitFor(callback, _ref) {
  let {
    container = getDocument$1(),
    timeout = getConfig().asyncUtilTimeout,
    showOriginalStackTrace = getConfig().showOriginalStackTrace,
    stackTraceError,
    interval = 50,
    onTimeout = error => {
      Object.defineProperty(error, 'message', {
        value: getConfig().getElementError(error.message, container).message
      });
      return error;
    },
    mutationObserverOptions = {
      subtree: true,
      childList: true,
      attributes: true,
      characterData: true
    }
  } = _ref;
  if (typeof callback !== 'function') {
    throw new TypeError('Received `callback` arg must be a function');
  }
  return new Promise(async (resolve, reject) => {
    let lastError, intervalId, observer;
    let finished = false;
    let promiseStatus = 'idle';
    const overallTimeoutTimer = setTimeout(handleTimeout, timeout);
    const usingJestFakeTimers = jestFakeTimersAreEnabled$1();
    if (usingJestFakeTimers) {
      const {
        unstable_advanceTimersWrapper: advanceTimersWrapper
      } = getConfig();
      checkCallback();
      // this is a dangerous rule to disable because it could lead to an
      // infinite loop. However, eslint isn't smart enough to know that we're
      // setting finished inside `onDone` which will be called when we're done
      // waiting or when we've timed out.
      // eslint-disable-next-line no-unmodified-loop-condition
      while (!finished) {
        if (!jestFakeTimersAreEnabled$1()) {
          const error = new Error("Changed from using fake timers to real timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing to real timers. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830");
          if (!showOriginalStackTrace) copyStackTrace(error, stackTraceError);
          reject(error);
          return;
        }

        // In this rare case, we *need* to wait for in-flight promises
        // to resolve before continuing. We don't need to take advantage
        // of parallelization so we're fine.
        // https://stackoverflow.com/a/59243586/971592
        // eslint-disable-next-line no-await-in-loop
        await advanceTimersWrapper(async () => {
          // we *could* (maybe should?) use `advanceTimersToNextTimer` but it's
          // possible that could make this loop go on forever if someone is using
          // third party code that's setting up recursive timers so rapidly that
          // the user's timer's don't get a chance to resolve. So we'll advance
          // by an interval instead. (We have a test for this case).
          jest.advanceTimersByTime(interval);
        });

        // Could have timed-out
        if (finished) {
          break;
        }
        // It's really important that checkCallback is run *before* we flush
        // in-flight promises. To be honest, I'm not sure why, and I can't quite
        // think of a way to reproduce the problem in a test, but I spent
        // an entire day banging my head against a wall on this.
        checkCallback();
      }
    } else {
      try {
        checkContainerType(container);
      } catch (e) {
        reject(e);
        return;
      }
      intervalId = setInterval(checkRealTimersCallback, interval);
      const {
        MutationObserver
      } = getWindowFromNode(container);
      observer = new MutationObserver(checkRealTimersCallback);
      observer.observe(container, mutationObserverOptions);
      checkCallback();
    }
    function onDone(error, result) {
      finished = true;
      clearTimeout(overallTimeoutTimer);
      if (!usingJestFakeTimers) {
        clearInterval(intervalId);
        observer.disconnect();
      }
      if (error) {
        reject(error);
      } else {
        resolve(result);
      }
    }
    function checkRealTimersCallback() {
      if (jestFakeTimersAreEnabled$1()) {
        const error = new Error("Changed from using real timers to fake timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing to fake timers. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830");
        if (!showOriginalStackTrace) copyStackTrace(error, stackTraceError);
        return reject(error);
      } else {
        return checkCallback();
      }
    }
    function checkCallback() {
      if (promiseStatus === 'pending') return;
      try {
        const result = runWithExpensiveErrorDiagnosticsDisabled(callback);
        if (typeof (result == null ? void 0 : result.then) === 'function') {
          promiseStatus = 'pending';
          result.then(resolvedValue => {
            promiseStatus = 'resolved';
            onDone(null, resolvedValue);
          }, rejectedValue => {
            promiseStatus = 'rejected';
            lastError = rejectedValue;
          });
        } else {
          onDone(null, result);
        }
        // If `callback` throws, wait for the next mutation, interval, or timeout.
      } catch (error) {
        // Save the most recent callback error to reject the promise with it in the event of a timeout
        lastError = error;
      }
    }
    function handleTimeout() {
      let error;
      if (lastError) {
        error = lastError;
        if (!showOriginalStackTrace && error.name === 'TestingLibraryElementError') {
          copyStackTrace(error, stackTraceError);
        }
      } else {
        error = new Error('Timed out in waitFor.');
        if (!showOriginalStackTrace) {
          copyStackTrace(error, stackTraceError);
        }
      }
      onDone(onTimeout(error), null);
    }
  });
}
function waitForWrapper(callback, options) {
  // create the error here so its stack trace is as close to the
  // calling code as possible
  const stackTraceError = new Error('STACK_TRACE_MESSAGE');
  return getConfig().asyncWrapper(() => waitFor(callback, {
    stackTraceError,
    ...options
  }));
}

/*
eslint
  max-lines-per-function: ["error", {"max": 200}],
*/

function getElementError(message, container) {
  return getConfig().getElementError(message, container);
}
function getMultipleElementsFoundError(message, container) {
  return getElementError(message + "\n\n(If this is intentional, then use the `*AllBy*` variant of the query (like `queryAllByText`, `getAllByText`, or `findAllByText`)).", container);
}
function queryAllByAttribute(attribute, container, text, _temp) {
  let {
    exact = true,
    collapseWhitespace,
    trim,
    normalizer
  } = _temp === undefined ? {} : _temp;
  const matcher = exact ? matches : fuzzyMatches;
  const matchNormalizer = makeNormalizer({
    collapseWhitespace,
    trim,
    normalizer
  });
  return Array.from(container.querySelectorAll("[" + attribute + "]")).filter(node => matcher(node.getAttribute(attribute), node, text, matchNormalizer));
}

// this accepts a query function and returns a function which throws an error
// if more than one elements is returned, otherwise it returns the first
// element or null
function makeSingleQuery(allQuery, getMultipleError) {
  return function (container) {
    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      args[_key - 1] = arguments[_key];
    }
    const els = allQuery(container, ...args);
    if (els.length > 1) {
      const elementStrings = els.map(element => getElementError(null, element).message).join('\n\n');
      throw getMultipleElementsFoundError(getMultipleError(container, ...args) + "\n\nHere are the matching elements:\n\n" + elementStrings, container);
    }
    return els[0] || null;
  };
}
function getSuggestionError(suggestion, container) {
  return getConfig().getElementError("A better query is available, try this:\n" + suggestion.toString() + "\n", container);
}

// this accepts a query function and returns a function which throws an error
// if an empty list of elements is returned
function makeGetAllQuery(allQuery, getMissingError) {
  return function (container) {
    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
      args[_key2 - 1] = arguments[_key2];
    }
    const els = allQuery(container, ...args);
    if (!els.length) {
      throw getConfig().getElementError(getMissingError(container, ...args), container);
    }
    return els;
  };
}

// this accepts a getter query function and returns a function which calls
// waitFor and passing a function which invokes the getter.
function makeFindQuery(getter) {
  return (container, text, options, waitForOptions) => {
    return waitForWrapper(() => {
      return getter(container, text, options);
    }, {
      container,
      ...waitForOptions
    });
  };
}
const wrapSingleQueryWithSuggestion = (query, queryAllByName, variant) => function (container) {
  for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
    args[_key3 - 1] = arguments[_key3];
  }
  const element = query(container, ...args);
  const [{
    suggest = getConfig().throwSuggestions
  } = {}] = args.slice(-1);
  if (element && suggest) {
    const suggestion = getSuggestedQuery(element, variant);
    if (suggestion && !queryAllByName.endsWith(suggestion.queryName)) {
      throw getSuggestionError(suggestion.toString(), container);
    }
  }
  return element;
};
const wrapAllByQueryWithSuggestion = (query, queryAllByName, variant) => function (container) {
  for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
    args[_key4 - 1] = arguments[_key4];
  }
  const els = query(container, ...args);
  const [{
    suggest = getConfig().throwSuggestions
  } = {}] = args.slice(-1);
  if (els.length && suggest) {
    // get a unique list of all suggestion messages.  We are only going to make a suggestion if
    // all the suggestions are the same
    const uniqueSuggestionMessages = [...new Set(els.map(element => {
      var _getSuggestedQuery;
      return (_getSuggestedQuery = getSuggestedQuery(element, variant)) == null ? undefined : _getSuggestedQuery.toString();
    }))];
    if (
    // only want to suggest if all the els have the same suggestion.
    uniqueSuggestionMessages.length === 1 && !queryAllByName.endsWith(
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- TODO: Can this be null at runtime?
    getSuggestedQuery(els[0], variant).queryName)) {
      throw getSuggestionError(uniqueSuggestionMessages[0], container);
    }
  }
  return els;
};

// TODO: This deviates from the published declarations
// However, the implementation always required a dyadic (after `container`) not variadic `queryAllBy` considering the implementation of `makeFindQuery`
// This is at least statically true and can be verified by accepting `QueryMethod<Arguments, HTMLElement[]>`
function buildQueries(queryAllBy, getMultipleError, getMissingError) {
  const queryBy = wrapSingleQueryWithSuggestion(makeSingleQuery(queryAllBy, getMultipleError), queryAllBy.name, 'query');
  const getAllBy = makeGetAllQuery(queryAllBy, getMissingError);
  const getBy = makeSingleQuery(getAllBy, getMultipleError);
  const getByWithSuggestions = wrapSingleQueryWithSuggestion(getBy, queryAllBy.name, 'get');
  const getAllWithSuggestions = wrapAllByQueryWithSuggestion(getAllBy, queryAllBy.name.replace('query', 'get'), 'getAll');
  const findAllBy = makeFindQuery(wrapAllByQueryWithSuggestion(getAllBy, queryAllBy.name, 'findAll'));
  const findBy = makeFindQuery(wrapSingleQueryWithSuggestion(getBy, queryAllBy.name, 'find'));
  return [queryBy, getAllWithSuggestions, getByWithSuggestions, findAllBy, findBy];
}

function queryAllLabels(container) {
  return Array.from(container.querySelectorAll('label,input')).map(node => {
    return {
      node,
      textToMatch: getLabelContent(node)
    };
  }).filter(_ref => {
    let {
      textToMatch
    } = _ref;
    return textToMatch !== null;
  });
}
const queryAllLabelsByText = function (container, text, _temp) {
  let {
    exact = true,
    trim,
    collapseWhitespace,
    normalizer
  } = _temp === undefined ? {} : _temp;
  const matcher = exact ? matches : fuzzyMatches;
  const matchNormalizer = makeNormalizer({
    collapseWhitespace,
    trim,
    normalizer
  });
  const textToMatchByLabels = queryAllLabels(container);
  return textToMatchByLabels.filter(_ref2 => {
    let {
      node,
      textToMatch
    } = _ref2;
    return matcher(textToMatch, node, text, matchNormalizer);
  }).map(_ref3 => {
    let {
      node
    } = _ref3;
    return node;
  });
};
const queryAllByLabelText = function (container, text, _temp2) {
  let {
    selector = '*',
    exact = true,
    collapseWhitespace,
    trim,
    normalizer
  } = _temp2 === undefined ? {} : _temp2;
  checkContainerType(container);
  const matcher = exact ? matches : fuzzyMatches;
  const matchNormalizer = makeNormalizer({
    collapseWhitespace,
    trim,
    normalizer
  });
  const matchingLabelledElements = Array.from(container.querySelectorAll('*')).filter(element => {
    return getRealLabels(element).length || element.hasAttribute('aria-labelledby');
  }).reduce((labelledElements, labelledElement) => {
    const labelList = getLabels(container, labelledElement, {
      selector
    });
    labelList.filter(label => Boolean(label.formControl)).forEach(label => {
      if (matcher(label.content, label.formControl, text, matchNormalizer) && label.formControl) {
        labelledElements.push(label.formControl);
      }
    });
    const labelsValue = labelList.filter(label => Boolean(label.content)).map(label => label.content);
    if (matcher(labelsValue.join(' '), labelledElement, text, matchNormalizer)) {
      labelledElements.push(labelledElement);
    }
    if (labelsValue.length > 1) {
      labelsValue.forEach((labelValue, index) => {
        if (matcher(labelValue, labelledElement, text, matchNormalizer)) {
          labelledElements.push(labelledElement);
        }
        const labelsFiltered = [...labelsValue];
        labelsFiltered.splice(index, 1);
        if (labelsFiltered.length > 1) {
          if (matcher(labelsFiltered.join(' '), labelledElement, text, matchNormalizer)) {
            labelledElements.push(labelledElement);
          }
        }
      });
    }
    return labelledElements;
  }, []).concat(queryAllByAttribute('aria-label', container, text, {
    exact,
    normalizer: matchNormalizer
  }));
  return Array.from(new Set(matchingLabelledElements)).filter(element => element.matches(selector));
};

// the getAll* query would normally look like this:
// const getAllByLabelText = makeGetAllQuery(
//   queryAllByLabelText,
//   (c, text) => `Unable to find a label with the text of: ${text}`,
// )
// however, we can give a more helpful error message than the generic one,
// so we're writing this one out by hand.
const getAllByLabelText = function (container, text) {
  for (var _len = arguments.length, rest = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
    rest[_key - 2] = arguments[_key];
  }
  const els = queryAllByLabelText(container, text, ...rest);
  if (!els.length) {
    const labels = queryAllLabelsByText(container, text, ...rest);
    if (labels.length) {
      const tagNames = labels.map(label => getTagNameOfElementAssociatedWithLabelViaFor(container, label)).filter(tagName => !!tagName);
      if (tagNames.length) {
        throw getConfig().getElementError(tagNames.map(tagName => "Found a label with the text of: " + text + ", however the element associated with this label (<" + tagName + " />) is non-labellable [https://html.spec.whatwg.org/multipage/forms.html#category-label]. If you really need to label a <" + tagName + " />, you can use aria-label or aria-labelledby instead.").join('\n\n'), container);
      } else {
        throw getConfig().getElementError("Found a label with the text of: " + text + ", however no form control was found associated to that label. Make sure you're using the \"for\" attribute or \"aria-labelledby\" attribute correctly.", container);
      }
    } else {
      throw getConfig().getElementError("Unable to find a label with the text of: " + text, container);
    }
  }
  return els;
};
function getTagNameOfElementAssociatedWithLabelViaFor(container, label) {
  const htmlFor = label.getAttribute('for');
  if (!htmlFor) {
    return null;
  }
  const element = container.querySelector("[id=\"" + htmlFor + "\"]");
  return element ? element.tagName.toLowerCase() : null;
}

// the reason mentioned above is the same reason we're not using buildQueries
const getMultipleError$7 = (c, text) => "Found multiple elements with the text of: " + text;
const queryByLabelText = wrapSingleQueryWithSuggestion(makeSingleQuery(queryAllByLabelText, getMultipleError$7), queryAllByLabelText.name, 'query');
const getByLabelText = makeSingleQuery(getAllByLabelText, getMultipleError$7);
const findAllByLabelText = makeFindQuery(wrapAllByQueryWithSuggestion(getAllByLabelText, getAllByLabelText.name, 'findAll'));
const findByLabelText = makeFindQuery(wrapSingleQueryWithSuggestion(getByLabelText, getAllByLabelText.name, 'find'));
const getAllByLabelTextWithSuggestions = wrapAllByQueryWithSuggestion(getAllByLabelText, getAllByLabelText.name, 'getAll');
const getByLabelTextWithSuggestions = wrapSingleQueryWithSuggestion(getByLabelText, getAllByLabelText.name, 'get');
const queryAllByLabelTextWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByLabelText, queryAllByLabelText.name, 'queryAll');

const queryAllByPlaceholderText = function () {
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
    args[_key] = arguments[_key];
  }
  checkContainerType(args[0]);
  return queryAllByAttribute('placeholder', ...args);
};
const getMultipleError$6 = (c, text) => "Found multiple elements with the placeholder text of: " + text;
const getMissingError$6 = (c, text) => "Unable to find an element with the placeholder text of: " + text;
const queryAllByPlaceholderTextWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByPlaceholderText, queryAllByPlaceholderText.name, 'queryAll');
const [queryByPlaceholderText, getAllByPlaceholderText, getByPlaceholderText, findAllByPlaceholderText, findByPlaceholderText] = buildQueries(queryAllByPlaceholderText, getMultipleError$6, getMissingError$6);

const queryAllByText = function (container, text, _temp) {
  let {
    selector = '*',
    exact = true,
    collapseWhitespace,
    trim,
    ignore = getConfig().defaultIgnore,
    normalizer
  } = _temp === undefined ? {} : _temp;
  checkContainerType(container);
  const matcher = exact ? matches : fuzzyMatches;
  const matchNormalizer = makeNormalizer({
    collapseWhitespace,
    trim,
    normalizer
  });
  let baseArray = [];
  if (typeof container.matches === 'function' && container.matches(selector)) {
    baseArray = [container];
  }
  return [...baseArray, ...Array.from(container.querySelectorAll(selector))]
  // TODO: `matches` according lib.dom.d.ts can get only `string` but according our code it can handle also boolean :)
  .filter(node => !ignore || !node.matches(ignore)).filter(node => matcher(getNodeText(node), node, text, matchNormalizer));
};
const getMultipleError$5 = (c, text) => "Found multiple elements with the text: " + text;
const getMissingError$5 = function (c, text, options) {
  if (options === undefined) {
    options = {};
  }
  const {
    collapseWhitespace,
    trim,
    normalizer,
    selector
  } = options;
  const matchNormalizer = makeNormalizer({
    collapseWhitespace,
    trim,
    normalizer
  });
  const normalizedText = matchNormalizer(text.toString());
  const isNormalizedDifferent = normalizedText !== text.toString();
  const isCustomSelector = (selector != null ? selector : '*') !== '*';
  return "Unable to find an element with the text: " + (isNormalizedDifferent ? normalizedText + " (normalized from '" + text + "')" : text) + (isCustomSelector ? ", which matches selector '" + selector + "'" : '') + ". This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.";
};
const queryAllByTextWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByText, queryAllByText.name, 'queryAll');
const [queryByText, getAllByText, getByText, findAllByText, findByText] = buildQueries(queryAllByText, getMultipleError$5, getMissingError$5);

const queryAllByDisplayValue = function (container, value, _temp) {
  let {
    exact = true,
    collapseWhitespace,
    trim,
    normalizer
  } = _temp === undefined ? {} : _temp;
  checkContainerType(container);
  const matcher = exact ? matches : fuzzyMatches;
  const matchNormalizer = makeNormalizer({
    collapseWhitespace,
    trim,
    normalizer
  });
  return Array.from(container.querySelectorAll("input,textarea,select")).filter(node => {
    if (node.tagName === 'SELECT') {
      const selectedOptions = Array.from(node.options).filter(option => option.selected);
      return selectedOptions.some(optionNode => matcher(getNodeText(optionNode), optionNode, value, matchNormalizer));
    } else {
      return matcher(node.value, node, value, matchNormalizer);
    }
  });
};
const getMultipleError$4 = (c, value) => "Found multiple elements with the display value: " + value + ".";
const getMissingError$4 = (c, value) => "Unable to find an element with the display value: " + value + ".";
const queryAllByDisplayValueWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByDisplayValue, queryAllByDisplayValue.name, 'queryAll');
const [queryByDisplayValue, getAllByDisplayValue, getByDisplayValue, findAllByDisplayValue, findByDisplayValue] = buildQueries(queryAllByDisplayValue, getMultipleError$4, getMissingError$4);

// Valid tags are img, input, area and custom elements
const VALID_TAG_REGEXP = /^(img|input|area|.+-.+)$/i;
const queryAllByAltText = function (container, alt, options) {
  if (options === undefined) {
    options = {};
  }
  checkContainerType(container);
  return queryAllByAttribute('alt', container, alt, options).filter(node => VALID_TAG_REGEXP.test(node.tagName));
};
const getMultipleError$3 = (c, alt) => "Found multiple elements with the alt text: " + alt;
const getMissingError$3 = (c, alt) => "Unable to find an element with the alt text: " + alt;
const queryAllByAltTextWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByAltText, queryAllByAltText.name, 'queryAll');
const [queryByAltText, getAllByAltText, getByAltText, findAllByAltText, findByAltText] = buildQueries(queryAllByAltText, getMultipleError$3, getMissingError$3);

const isSvgTitle = node => {
  var _node$parentElement;
  return node.tagName.toLowerCase() === 'title' && ((_node$parentElement = node.parentElement) == null ? undefined : _node$parentElement.tagName.toLowerCase()) === 'svg';
};
const queryAllByTitle = function (container, text, _temp) {
  let {
    exact = true,
    collapseWhitespace,
    trim,
    normalizer
  } = _temp === undefined ? {} : _temp;
  checkContainerType(container);
  const matcher = exact ? matches : fuzzyMatches;
  const matchNormalizer = makeNormalizer({
    collapseWhitespace,
    trim,
    normalizer
  });
  return Array.from(container.querySelectorAll('[title], svg > title')).filter(node => matcher(node.getAttribute('title'), node, text, matchNormalizer) || isSvgTitle(node) && matcher(getNodeText(node), node, text, matchNormalizer));
};
const getMultipleError$2 = (c, title) => "Found multiple elements with the title: " + title + ".";
const getMissingError$2 = (c, title) => "Unable to find an element with the title: " + title + ".";
const queryAllByTitleWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByTitle, queryAllByTitle.name, 'queryAll');
const [queryByTitle, getAllByTitle, getByTitle, findAllByTitle, findByTitle] = buildQueries(queryAllByTitle, getMultipleError$2, getMissingError$2);

/* eslint-disable complexity */
const queryAllByRole = function (container, role, _temp) {
  let {
    hidden = getConfig().defaultHidden,
    name,
    description,
    queryFallbacks = false,
    selected,
    busy,
    checked,
    pressed,
    current,
    level,
    expanded,
    value: {
      now: valueNow,
      min: valueMin,
      max: valueMax,
      text: valueText
    } = {}
  } = _temp === undefined ? {} : _temp;
  checkContainerType(container);
  if (selected !== undefined) {
    var _allRoles$get;
    // guard against unknown roles
    if (((_allRoles$get = libExports.roles.get(role)) == null ? undefined : _allRoles$get.props['aria-selected']) === undefined) {
      throw new Error("\"aria-selected\" is not supported on role \"" + role + "\".");
    }
  }
  if (busy !== undefined) {
    var _allRoles$get2;
    // guard against unknown roles
    if (((_allRoles$get2 = libExports.roles.get(role)) == null ? undefined : _allRoles$get2.props['aria-busy']) === undefined) {
      throw new Error("\"aria-busy\" is not supported on role \"" + role + "\".");
    }
  }
  if (checked !== undefined) {
    var _allRoles$get3;
    // guard against unknown roles
    if (((_allRoles$get3 = libExports.roles.get(role)) == null ? undefined : _allRoles$get3.props['aria-checked']) === undefined) {
      throw new Error("\"aria-checked\" is not supported on role \"" + role + "\".");
    }
  }
  if (pressed !== undefined) {
    var _allRoles$get4;
    // guard against unknown roles
    if (((_allRoles$get4 = libExports.roles.get(role)) == null ? undefined : _allRoles$get4.props['aria-pressed']) === undefined) {
      throw new Error("\"aria-pressed\" is not supported on role \"" + role + "\".");
    }
  }
  if (current !== undefined) {
    var _allRoles$get5;
    /* istanbul ignore next */
    // guard against unknown roles
    // All currently released ARIA versions support `aria-current` on all roles.
    // Leaving this for symmetry and forward compatibility
    if (((_allRoles$get5 = libExports.roles.get(role)) == null ? undefined : _allRoles$get5.props['aria-current']) === undefined) {
      throw new Error("\"aria-current\" is not supported on role \"" + role + "\".");
    }
  }
  if (level !== undefined) {
    // guard against using `level` option with any role other than `heading`
    if (role !== 'heading') {
      throw new Error("Role \"" + role + "\" cannot have \"level\" property.");
    }
  }
  if (valueNow !== undefined) {
    var _allRoles$get6;
    // guard against unknown roles
    if (((_allRoles$get6 = libExports.roles.get(role)) == null ? undefined : _allRoles$get6.props['aria-valuenow']) === undefined) {
      throw new Error("\"aria-valuenow\" is not supported on role \"" + role + "\".");
    }
  }
  if (valueMax !== undefined) {
    var _allRoles$get7;
    // guard against unknown roles
    if (((_allRoles$get7 = libExports.roles.get(role)) == null ? undefined : _allRoles$get7.props['aria-valuemax']) === undefined) {
      throw new Error("\"aria-valuemax\" is not supported on role \"" + role + "\".");
    }
  }
  if (valueMin !== undefined) {
    var _allRoles$get8;
    // guard against unknown roles
    if (((_allRoles$get8 = libExports.roles.get(role)) == null ? undefined : _allRoles$get8.props['aria-valuemin']) === undefined) {
      throw new Error("\"aria-valuemin\" is not supported on role \"" + role + "\".");
    }
  }
  if (valueText !== undefined) {
    var _allRoles$get9;
    // guard against unknown roles
    if (((_allRoles$get9 = libExports.roles.get(role)) == null ? undefined : _allRoles$get9.props['aria-valuetext']) === undefined) {
      throw new Error("\"aria-valuetext\" is not supported on role \"" + role + "\".");
    }
  }
  if (expanded !== undefined) {
    var _allRoles$get10;
    // guard against unknown roles
    if (((_allRoles$get10 = libExports.roles.get(role)) == null ? undefined : _allRoles$get10.props['aria-expanded']) === undefined) {
      throw new Error("\"aria-expanded\" is not supported on role \"" + role + "\".");
    }
  }
  const subtreeIsInaccessibleCache = new WeakMap();
  function cachedIsSubtreeInaccessible(element) {
    if (!subtreeIsInaccessibleCache.has(element)) {
      subtreeIsInaccessibleCache.set(element, isSubtreeInaccessible(element));
    }
    return subtreeIsInaccessibleCache.get(element);
  }
  return Array.from(container.querySelectorAll(
  // Only query elements that can be matched by the following filters
  makeRoleSelector(role))).filter(node => {
    const isRoleSpecifiedExplicitly = node.hasAttribute('role');
    if (isRoleSpecifiedExplicitly) {
      const roleValue = node.getAttribute('role');
      if (queryFallbacks) {
        return roleValue.split(' ').filter(Boolean).some(roleAttributeToken => roleAttributeToken === role);
      }
      // other wise only send the first token to match
      const [firstRoleAttributeToken] = roleValue.split(' ');
      return firstRoleAttributeToken === role;
    }
    const implicitRoles = getImplicitAriaRoles(node);
    return implicitRoles.some(implicitRole => {
      return implicitRole === role;
    });
  }).filter(element => {
    if (selected !== undefined) {
      return selected === computeAriaSelected(element);
    }
    if (busy !== undefined) {
      return busy === computeAriaBusy(element);
    }
    if (checked !== undefined) {
      return checked === computeAriaChecked(element);
    }
    if (pressed !== undefined) {
      return pressed === computeAriaPressed(element);
    }
    if (current !== undefined) {
      return current === computeAriaCurrent(element);
    }
    if (expanded !== undefined) {
      return expanded === computeAriaExpanded(element);
    }
    if (level !== undefined) {
      return level === computeHeadingLevel(element);
    }
    if (valueNow !== undefined || valueMax !== undefined || valueMin !== undefined || valueText !== undefined) {
      let valueMatches = true;
      if (valueNow !== undefined) {
        valueMatches && (valueMatches = valueNow === computeAriaValueNow(element));
      }
      if (valueMax !== undefined) {
        valueMatches && (valueMatches = valueMax === computeAriaValueMax(element));
      }
      if (valueMin !== undefined) {
        valueMatches && (valueMatches = valueMin === computeAriaValueMin(element));
      }
      if (valueText !== undefined) {
        var _computeAriaValueText;
        valueMatches && (valueMatches = matches((_computeAriaValueText = computeAriaValueText(element)) != null ? _computeAriaValueText : null, element, valueText, text => text));
      }
      return valueMatches;
    }
    // don't care if aria attributes are unspecified
    return true;
  }).filter(element => {
    if (name === undefined) {
      // Don't care
      return true;
    }
    return matches(computeAccessibleName(element, {
      computedStyleSupportsPseudoElements: getConfig().computedStyleSupportsPseudoElements
    }), element, name, text => text);
  }).filter(element => {
    if (description === undefined) {
      // Don't care
      return true;
    }
    return matches(computeAccessibleDescription(element, {
      computedStyleSupportsPseudoElements: getConfig().computedStyleSupportsPseudoElements
    }), element, description, text => text);
  }).filter(element => {
    return hidden === false ? isInaccessible(element, {
      isSubtreeInaccessible: cachedIsSubtreeInaccessible
    }) === false : true;
  });
};
function makeRoleSelector(role) {
  var _roleElements$get;
  const explicitRoleSelector = "*[role~=\"" + role + "\"]";
  const roleRelations = (_roleElements$get = libExports.roleElements.get(role)) != null ? _roleElements$get : new Set();
  const implicitRoleSelectors = new Set(Array.from(roleRelations).map(_ref => {
    let {
      name
    } = _ref;
    return name;
  }));

  // Current transpilation config sometimes assumes `...` is always applied to arrays.
  // `...` is equivalent to `Array.prototype.concat` for arrays.
  // If you replace this code with `[explicitRoleSelector, ...implicitRoleSelectors]`, make sure every transpilation target retains the `...` in favor of `Array.prototype.concat`.
  return [explicitRoleSelector].concat(Array.from(implicitRoleSelectors)).join(',');
}
const getNameHint = name => {
  let nameHint = '';
  if (name === undefined) {
    nameHint = '';
  } else if (typeof name === 'string') {
    nameHint = " and name \"" + name + "\"";
  } else {
    nameHint = " and name `" + name + "`";
  }
  return nameHint;
};
const getMultipleError$1 = function (c, role, _temp2) {
  let {
    name
  } = _temp2 === undefined ? {} : _temp2;
  return "Found multiple elements with the role \"" + role + "\"" + getNameHint(name);
};
const getMissingError$1 = function (container, role, _temp3) {
  let {
    hidden = getConfig().defaultHidden,
    name,
    description
  } = _temp3 === undefined ? {} : _temp3;
  if (getConfig()._disableExpensiveErrorDiagnostics) {
    return "Unable to find role=\"" + role + "\"" + getNameHint(name);
  }
  let roles = '';
  Array.from(container.children).forEach(childElement => {
    roles += prettyRoles(childElement, {
      hidden,
      includeDescription: description !== undefined
    });
  });
  let roleMessage;
  if (roles.length === 0) {
    if (hidden === false) {
      roleMessage = 'There are no accessible roles. But there might be some inaccessible roles. ' + 'If you wish to access them, then set the `hidden` option to `true`. ' + 'Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole';
    } else {
      roleMessage = 'There are no available roles.';
    }
  } else {
    roleMessage = ("\nHere are the " + (hidden === false ? 'accessible' : 'available') + " roles:\n\n  " + roles.replace(/\n/g, '\n  ').replace(/\n\s\s\n/g, '\n\n') + "\n").trim();
  }
  let nameHint = '';
  if (name === undefined) {
    nameHint = '';
  } else if (typeof name === 'string') {
    nameHint = " and name \"" + name + "\"";
  } else {
    nameHint = " and name `" + name + "`";
  }
  let descriptionHint = '';
  if (description === undefined) {
    descriptionHint = '';
  } else if (typeof description === 'string') {
    descriptionHint = " and description \"" + description + "\"";
  } else {
    descriptionHint = " and description `" + description + "`";
  }
  return ("\nUnable to find an " + (hidden === false ? 'accessible ' : '') + "element with the role \"" + role + "\"" + nameHint + descriptionHint + "\n\n" + roleMessage).trim();
};
const queryAllByRoleWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByRole, queryAllByRole.name, 'queryAll');
const [queryByRole, getAllByRole, getByRole, findAllByRole, findByRole] = buildQueries(queryAllByRole, getMultipleError$1, getMissingError$1);

const getTestIdAttribute = () => getConfig().testIdAttribute;
const queryAllByTestId = function () {
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
    args[_key] = arguments[_key];
  }
  checkContainerType(args[0]);
  return queryAllByAttribute(getTestIdAttribute(), ...args);
};
const getMultipleError = (c, id) => "Found multiple elements by: [" + getTestIdAttribute() + "=\"" + id + "\"]";
const getMissingError = (c, id) => "Unable to find an element by: [" + getTestIdAttribute() + "=\"" + id + "\"]";
const queryAllByTestIdWithSuggestions = wrapAllByQueryWithSuggestion(queryAllByTestId, queryAllByTestId.name, 'queryAll');
const [queryByTestId, getAllByTestId, getByTestId, findAllByTestId, findByTestId] = buildQueries(queryAllByTestId, getMultipleError, getMissingError);

var queries = /*#__PURE__*/Object.freeze({
  __proto__: null,
  queryAllByLabelText: queryAllByLabelTextWithSuggestions,
  queryByLabelText: queryByLabelText,
  getAllByLabelText: getAllByLabelTextWithSuggestions,
  getByLabelText: getByLabelTextWithSuggestions,
  findAllByLabelText: findAllByLabelText,
  findByLabelText: findByLabelText,
  queryByPlaceholderText: queryByPlaceholderText,
  queryAllByPlaceholderText: queryAllByPlaceholderTextWithSuggestions,
  getByPlaceholderText: getByPlaceholderText,
  getAllByPlaceholderText: getAllByPlaceholderText,
  findAllByPlaceholderText: findAllByPlaceholderText,
  findByPlaceholderText: findByPlaceholderText,
  queryByText: queryByText,
  queryAllByText: queryAllByTextWithSuggestions,
  getByText: getByText,
  getAllByText: getAllByText,
  findAllByText: findAllByText,
  findByText: findByText,
  queryByDisplayValue: queryByDisplayValue,
  queryAllByDisplayValue: queryAllByDisplayValueWithSuggestions,
  getByDisplayValue: getByDisplayValue,
  getAllByDisplayValue: getAllByDisplayValue,
  findAllByDisplayValue: findAllByDisplayValue,
  findByDisplayValue: findByDisplayValue,
  queryByAltText: queryByAltText,
  queryAllByAltText: queryAllByAltTextWithSuggestions,
  getByAltText: getByAltText,
  getAllByAltText: getAllByAltText,
  findAllByAltText: findAllByAltText,
  findByAltText: findByAltText,
  queryByTitle: queryByTitle,
  queryAllByTitle: queryAllByTitleWithSuggestions,
  getByTitle: getByTitle,
  getAllByTitle: getAllByTitle,
  findAllByTitle: findAllByTitle,
  findByTitle: findByTitle,
  queryByRole: queryByRole,
  queryAllByRole: queryAllByRoleWithSuggestions,
  getAllByRole: getAllByRole,
  getByRole: getByRole,
  findAllByRole: findAllByRole,
  findByRole: findByRole,
  queryByTestId: queryByTestId,
  queryAllByTestId: queryAllByTestIdWithSuggestions,
  getByTestId: getByTestId,
  getAllByTestId: getAllByTestId,
  findAllByTestId: findAllByTestId,
  findByTestId: findByTestId
});

/**
 * @typedef {{[key: string]: Function}} FuncMap
 */

/**
 * @param {HTMLElement} element container
 * @param {FuncMap} queries object of functions
 * @param {Object} initialValue for reducer
 * @returns {FuncMap} returns object of functions bound to container
 */
function getQueriesForElement(element, queries$1, initialValue) {
  if (queries$1 === undefined) {
    queries$1 = queries;
  }
  if (initialValue === undefined) {
    initialValue = {};
  }
  return Object.keys(queries$1).reduce((helpers, key) => {
    const fn = queries$1[key];
    helpers[key] = fn.bind(null, element);
    return helpers;
  }, initialValue);
}

/*
eslint
  require-await: "off"
*/

const eventMap$1 = {
  // Clipboard Events
  copy: {
    EventType: 'ClipboardEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  cut: {
    EventType: 'ClipboardEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  paste: {
    EventType: 'ClipboardEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  // Composition Events
  compositionEnd: {
    EventType: 'CompositionEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  compositionStart: {
    EventType: 'CompositionEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  compositionUpdate: {
    EventType: 'CompositionEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  // Keyboard Events
  keyDown: {
    EventType: 'KeyboardEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      charCode: 0,
      composed: true
    }
  },
  keyPress: {
    EventType: 'KeyboardEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      charCode: 0,
      composed: true
    }
  },
  keyUp: {
    EventType: 'KeyboardEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      charCode: 0,
      composed: true
    }
  },
  // Focus Events
  focus: {
    EventType: 'FocusEvent',
    defaultInit: {
      bubbles: false,
      cancelable: false,
      composed: true
    }
  },
  blur: {
    EventType: 'FocusEvent',
    defaultInit: {
      bubbles: false,
      cancelable: false,
      composed: true
    }
  },
  focusIn: {
    EventType: 'FocusEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false,
      composed: true
    }
  },
  focusOut: {
    EventType: 'FocusEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false,
      composed: true
    }
  },
  // Form Events
  change: {
    EventType: 'Event',
    defaultInit: {
      bubbles: true,
      cancelable: false
    }
  },
  input: {
    EventType: 'InputEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false,
      composed: true
    }
  },
  invalid: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: true
    }
  },
  submit: {
    EventType: 'Event',
    defaultInit: {
      bubbles: true,
      cancelable: true
    }
  },
  reset: {
    EventType: 'Event',
    defaultInit: {
      bubbles: true,
      cancelable: true
    }
  },
  // Mouse Events
  click: {
    EventType: 'MouseEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      button: 0,
      composed: true
    }
  },
  contextMenu: {
    EventType: 'MouseEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  dblClick: {
    EventType: 'MouseEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  drag: {
    EventType: 'DragEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  dragEnd: {
    EventType: 'DragEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false,
      composed: true
    }
  },
  dragEnter: {
    EventType: 'DragEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  dragExit: {
    EventType: 'DragEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false,
      composed: true
    }
  },
  dragLeave: {
    EventType: 'DragEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false,
      composed: true
    }
  },
  dragOver: {
    EventType: 'DragEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  dragStart: {
    EventType: 'DragEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  drop: {
    EventType: 'DragEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  mouseDown: {
    EventType: 'MouseEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  mouseEnter: {
    EventType: 'MouseEvent',
    defaultInit: {
      bubbles: false,
      cancelable: false,
      composed: true
    }
  },
  mouseLeave: {
    EventType: 'MouseEvent',
    defaultInit: {
      bubbles: false,
      cancelable: false,
      composed: true
    }
  },
  mouseMove: {
    EventType: 'MouseEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  mouseOut: {
    EventType: 'MouseEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  mouseOver: {
    EventType: 'MouseEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  mouseUp: {
    EventType: 'MouseEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  // Selection Events
  select: {
    EventType: 'Event',
    defaultInit: {
      bubbles: true,
      cancelable: false
    }
  },
  // Touch Events
  touchCancel: {
    EventType: 'TouchEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false,
      composed: true
    }
  },
  touchEnd: {
    EventType: 'TouchEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  touchMove: {
    EventType: 'TouchEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  touchStart: {
    EventType: 'TouchEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  // UI Events
  resize: {
    EventType: 'UIEvent',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  scroll: {
    EventType: 'UIEvent',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  // Wheel Events
  wheel: {
    EventType: 'WheelEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  // Media Events
  abort: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  canPlay: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  canPlayThrough: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  durationChange: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  emptied: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  encrypted: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  ended: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  loadedData: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  loadedMetadata: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  loadStart: {
    EventType: 'ProgressEvent',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  pause: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  play: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  playing: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  progress: {
    EventType: 'ProgressEvent',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  rateChange: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  seeked: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  seeking: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  stalled: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  suspend: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  timeUpdate: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  volumeChange: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  waiting: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  // Events
  load: {
    // TODO: load events can be UIEvent or Event depending on what generated them
    // This is where this abstraction breaks down.
    // But the common targets are <img />, <script /> and window.
    // Neither of these targets receive a UIEvent
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  error: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  // Animation Events
  animationStart: {
    EventType: 'AnimationEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false
    }
  },
  animationEnd: {
    EventType: 'AnimationEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false
    }
  },
  animationIteration: {
    EventType: 'AnimationEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false
    }
  },
  // Transition Events
  transitionCancel: {
    EventType: 'TransitionEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false
    }
  },
  transitionEnd: {
    EventType: 'TransitionEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true
    }
  },
  transitionRun: {
    EventType: 'TransitionEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false
    }
  },
  transitionStart: {
    EventType: 'TransitionEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false
    }
  },
  // pointer events
  pointerOver: {
    EventType: 'PointerEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  pointerEnter: {
    EventType: 'PointerEvent',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  pointerDown: {
    EventType: 'PointerEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  pointerMove: {
    EventType: 'PointerEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  pointerUp: {
    EventType: 'PointerEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  pointerCancel: {
    EventType: 'PointerEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false,
      composed: true
    }
  },
  pointerOut: {
    EventType: 'PointerEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true,
      composed: true
    }
  },
  pointerLeave: {
    EventType: 'PointerEvent',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  gotPointerCapture: {
    EventType: 'PointerEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false,
      composed: true
    }
  },
  lostPointerCapture: {
    EventType: 'PointerEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false,
      composed: true
    }
  },
  // history events
  popState: {
    EventType: 'PopStateEvent',
    defaultInit: {
      bubbles: true,
      cancelable: false
    }
  },
  // window events
  offline: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  online: {
    EventType: 'Event',
    defaultInit: {
      bubbles: false,
      cancelable: false
    }
  },
  pageHide: {
    EventType: 'PageTransitionEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true
    }
  },
  pageShow: {
    EventType: 'PageTransitionEvent',
    defaultInit: {
      bubbles: true,
      cancelable: true
    }
  }
};
const eventAliasMap = {
  doubleClick: 'dblClick'
};

function fireEvent$1(element, event) {
  return getConfig().eventWrapper(() => {
    if (!event) {
      throw new Error("Unable to fire an event - please provide an event object.");
    }
    if (!element) {
      throw new Error("Unable to fire a \"" + event.type + "\" event - please provide a DOM element.");
    }
    return element.dispatchEvent(event);
  });
}
function createEvent$1(eventName, node, init, _temp) {
  let {
    EventType = 'Event',
    defaultInit = {}
  } = _temp === undefined ? {} : _temp;
  if (!node) {
    throw new Error("Unable to fire a \"" + eventName + "\" event - please provide a DOM element.");
  }
  const eventInit = {
    ...defaultInit,
    ...init
  };
  const {
    target: {
      value,
      files,
      ...targetProperties
    } = {}
  } = eventInit;
  if (value !== undefined) {
    setNativeValue(node, value);
  }
  if (files !== undefined) {
    // input.files is a read-only property so this is not allowed:
    // input.files = [file]
    // so we have to use this workaround to set the property
    Object.defineProperty(node, 'files', {
      configurable: true,
      enumerable: true,
      writable: true,
      value: files
    });
  }
  Object.assign(node, targetProperties);
  const window = getWindowFromNode(node);
  const EventConstructor = window[EventType] || window.Event;
  let event;
  /* istanbul ignore else  */
  if (typeof EventConstructor === 'function') {
    event = new EventConstructor(eventName, eventInit);
  } else {
    // IE11 polyfill from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
    event = window.document.createEvent(EventType);
    const {
      bubbles,
      cancelable,
      detail,
      ...otherInit
    } = eventInit;
    event.initEvent(eventName, bubbles, cancelable, detail);
    Object.keys(otherInit).forEach(eventKey => {
      event[eventKey] = otherInit[eventKey];
    });
  }

  // DataTransfer is not supported in jsdom: https://github.com/jsdom/jsdom/issues/1568
  const dataTransferProperties = ['dataTransfer', 'clipboardData'];
  dataTransferProperties.forEach(dataTransferKey => {
    const dataTransferValue = eventInit[dataTransferKey];
    if (typeof dataTransferValue === 'object') {
      /* istanbul ignore if  */
      if (typeof window.DataTransfer === 'function') {
        Object.defineProperty(event, dataTransferKey, {
          value: Object.getOwnPropertyNames(dataTransferValue).reduce((acc, propName) => {
            Object.defineProperty(acc, propName, {
              value: dataTransferValue[propName]
            });
            return acc;
          }, new window.DataTransfer())
        });
      } else {
        Object.defineProperty(event, dataTransferKey, {
          value: dataTransferValue
        });
      }
    }
  });
  return event;
}
Object.keys(eventMap$1).forEach(key => {
  const {
    EventType,
    defaultInit
  } = eventMap$1[key];
  const eventName = key.toLowerCase();
  createEvent$1[key] = (node, init) => createEvent$1(eventName, node, init, {
    EventType,
    defaultInit
  });
  fireEvent$1[key] = (node, init) => fireEvent$1(node, createEvent$1[key](node, init));
});

// function written after some investigation here:
// https://github.com/facebook/react/issues/10135#issuecomment-401496776
function setNativeValue(element, value) {
  const {
    set: valueSetter
  } = Object.getOwnPropertyDescriptor(element, 'value') || {};
  const prototype = Object.getPrototypeOf(element);
  const {
    set: prototypeValueSetter
  } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
  if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
    prototypeValueSetter.call(element, value);
  } else {
    /* istanbul ignore if */
    // eslint-disable-next-line no-lonely-if -- Can't be ignored by istanbul otherwise
    if (valueSetter) {
      valueSetter.call(element, value);
    } else {
      throw new Error('The given element does not have a value setter');
    }
  }
}
Object.keys(eventAliasMap).forEach(aliasKey => {
  const key = eventAliasMap[aliasKey];
  fireEvent$1[aliasKey] = function () {
    return fireEvent$1[key](...arguments);
  };
});

/* eslint complexity:["error", 9] */

// WARNING: `lz-string` only has a default export but statically we assume named exports are allowed
function unindent(string) {
  // remove white spaces first, to save a few bytes.
  // testing-playground will reformat on load any ways.
  return string.replace(/[ \t]*[\n][ \t]*/g, '\n');
}
function encode(value) {
  return lzString.compressToEncodedURIComponent(unindent(value));
}
function getPlaygroundUrl(markup) {
  return "https://testing-playground.com/#markup=" + encode(markup);
}
const debug = (element, maxLength, options) => Array.isArray(element) ? element.forEach(el => logDOM(el, maxLength, options)) : logDOM(element, maxLength, options);
const logTestingPlaygroundURL = function (element) {
  if (element === undefined) {
    element = getDocument$1().body;
  }
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
  if (!element || !('innerHTML' in element)) {
    console.log("The element you're providing isn't a valid DOM element.");
    return;
  }
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
  if (!element.innerHTML) {
    console.log("The provided element doesn't have any children.");
    return;
  }
  const playgroundUrl = getPlaygroundUrl(element.innerHTML);
  console.log("Open this URL in your browser\n\n" + playgroundUrl);
  return playgroundUrl;
};
const initialValue = {
  debug,
  logTestingPlaygroundURL
};
typeof document !== 'undefined' && document.body // eslint-disable-line @typescript-eslint/no-unnecessary-condition
? getQueriesForElement(document.body, queries, initialValue) : Object.keys(queries).reduce((helpers, key) => {
  // `key` is for all intents and purposes the type of keyof `helpers`, which itself is the type of `initialValue` plus incoming properties from `queries`
  // if `Object.keys(something)` returned Array<keyof typeof something> this explicit type assertion would not be necessary
  // see https://stackoverflow.com/questions/55012174/why-doesnt-object-keys-return-a-keyof-type-in-typescript
  helpers[key] = () => {
    throw new TypeError('For queries bound to document.body a global document has to be available... Learn more: https://testing-library.com/s/screen-global-error');
  };
  return helpers;
}, initialValue);

const reactAct = typeof React__namespace.act === 'function' ? React__namespace.act : DeprecatedReactTestUtils__namespace.act;
function getGlobalThis() {
  /* istanbul ignore else */
  if (typeof globalThis !== 'undefined') {
    return globalThis;
  }
  /* istanbul ignore next */
  if (typeof self !== 'undefined') {
    return self;
  }
  /* istanbul ignore next */
  if (typeof window !== 'undefined') {
    return window;
  }
  /* istanbul ignore next */
  if (typeof global !== 'undefined') {
    return global;
  }
  /* istanbul ignore next */
  throw new Error('unable to locate global object');
}
function setIsReactActEnvironment(isReactActEnvironment) {
  getGlobalThis().IS_REACT_ACT_ENVIRONMENT = isReactActEnvironment;
}
function getIsReactActEnvironment() {
  return getGlobalThis().IS_REACT_ACT_ENVIRONMENT;
}
function withGlobalActEnvironment(actImplementation) {
  return callback => {
    const previousActEnvironment = getIsReactActEnvironment();
    setIsReactActEnvironment(true);
    try {
      // The return value of `act` is always a thenable.
      let callbackNeedsToBeAwaited = false;
      const actResult = actImplementation(() => {
        const result = callback();
        if (result !== null && typeof result === 'object' && typeof result.then === 'function') {
          callbackNeedsToBeAwaited = true;
        }
        return result;
      });
      if (callbackNeedsToBeAwaited) {
        const thenable = actResult;
        return {
          then: (resolve, reject) => {
            thenable.then(returnValue => {
              setIsReactActEnvironment(previousActEnvironment);
              resolve(returnValue);
            }, error => {
              setIsReactActEnvironment(previousActEnvironment);
              reject(error);
            });
          }
        };
      } else {
        setIsReactActEnvironment(previousActEnvironment);
        return actResult;
      }
    } catch (error) {
      // Can't be a `finally {}` block since we don't know if we have to immediately restore IS_REACT_ACT_ENVIRONMENT
      // or if we have to await the callback first.
      setIsReactActEnvironment(previousActEnvironment);
      throw error;
    }
  };
}
const act = withGlobalActEnvironment(reactAct);

/* eslint no-console:0 */

// react-testing-library's version of fireEvent will call
// dom-testing-library's version of fireEvent. The reason
// we make this distinction however is because we have
// a few extra events that work a bit differently
const fireEvent = function () {
  return fireEvent$1(...arguments);
};
Object.keys(fireEvent$1).forEach(key => {
  fireEvent[key] = function () {
    return fireEvent$1[key](...arguments);
  };
});

// React event system tracks native mouseOver/mouseOut events for
// running onMouseEnter/onMouseLeave handlers
// @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/EnterLeaveEventPlugin.js#L24-L31
const mouseEnter = fireEvent.mouseEnter;
const mouseLeave = fireEvent.mouseLeave;
fireEvent.mouseEnter = function () {
  mouseEnter(...arguments);
  return fireEvent.mouseOver(...arguments);
};
fireEvent.mouseLeave = function () {
  mouseLeave(...arguments);
  return fireEvent.mouseOut(...arguments);
};
const pointerEnter = fireEvent.pointerEnter;
const pointerLeave = fireEvent.pointerLeave;
fireEvent.pointerEnter = function () {
  pointerEnter(...arguments);
  return fireEvent.pointerOver(...arguments);
};
fireEvent.pointerLeave = function () {
  pointerLeave(...arguments);
  return fireEvent.pointerOut(...arguments);
};
const select = fireEvent.select;
fireEvent.select = (node, init) => {
  select(node, init);
  // React tracks this event only on focused inputs
  node.focus();

  // React creates this event when one of the following native events happens
  // - contextMenu
  // - mouseUp
  // - dragEnd
  // - keyUp
  // - keyDown
  // so we can use any here
  // @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/SelectEventPlugin.js#L203-L224
  fireEvent.keyUp(node, init);
};

// React event system tracks native focusout/focusin events for
// running blur/focus handlers
// @link https://github.com/facebook/react/pull/19186
const blur = fireEvent.blur;
const focus = fireEvent.focus;
fireEvent.blur = function () {
  fireEvent.focusOut(...arguments);
  return blur(...arguments);
};
fireEvent.focus = function () {
  fireEvent.focusIn(...arguments);
  return focus(...arguments);
};

function jestFakeTimersAreEnabled() {
  /* istanbul ignore else */
  if (typeof jest !== 'undefined' && jest !== null) {
    return (
      // legacy timers
      setTimeout._isMockFunction === true ||
      // modern timers
      // eslint-disable-next-line prefer-object-has-own -- No Object.hasOwn in all target environments we support.
      Object.prototype.hasOwnProperty.call(setTimeout, 'clock')
    );
  } // istanbul ignore next

  return false;
}
configure({
  unstable_advanceTimersWrapper: cb => {
    return act(cb);
  },
  // We just want to run `waitFor` without IS_REACT_ACT_ENVIRONMENT
  // But that's not necessarily how `asyncWrapper` is used since it's a public method.
  // Let's just hope nobody else is using it.
  asyncWrapper: async cb => {
    const previousActEnvironment = getIsReactActEnvironment();
    setIsReactActEnvironment(false);
    try {
      const result = await cb();
      // Drain microtask queue.
      // Otherwise we'll restore the previous act() environment, before we resolve the `waitFor` call.
      // The caller would have no chance to wrap the in-flight Promises in `act()`
      await new Promise(resolve => {
        setTimeout(() => {
          resolve();
        }, 0);
        if (jestFakeTimersAreEnabled()) {
          jest.advanceTimersByTime(0);
        }
      });
      return result;
    } finally {
      setIsReactActEnvironment(previousActEnvironment);
    }
  },
  eventWrapper: cb => {
    let result;
    act(() => {
      result = cb();
    });
    return result;
  }
});

// Ideally we'd just use a WeakMap where containers are keys and roots are values.
// We use two variables so that we can bail out in constant time when we render with a new container (most common use case)
/**
 * @type {Set<import('react-dom').Container>}
 */
const mountedContainers = new Set();
/**
 * @type Array<{container: import('react-dom').Container, root: ReturnType<typeof createConcurrentRoot>}>
 */
const mountedRootEntries = [];
function cleanup() {
  mountedRootEntries.forEach(_ref3 => {
    let {
      root,
      container
    } = _ref3;
    act(() => {
      root.unmount();
    });
    if (container.parentNode === document.body) {
      document.body.removeChild(container);
    }
  });
  mountedRootEntries.length = 0;
  mountedContainers.clear();
}

/* eslint func-name-matching:0 */

// if we're running in a test runner that supports afterEach
// or teardown then we'll automatically run cleanup afterEach test
// this ensures that tests run in isolation from each other
// if you don't like this then either import the `pure` module
// or set the RTL_SKIP_AUTO_CLEANUP env variable to 'true'.
if (typeof process === 'undefined' || !process.env?.RTL_SKIP_AUTO_CLEANUP) {
  // ignore teardown() in code coverage because Jest does not support it
  /* istanbul ignore else */
  if (typeof afterEach === 'function') {
    afterEach(() => {
      cleanup();
    });
  } else if (typeof teardown === 'function') {
    // Block is guarded by `typeof` check.
    // eslint does not support `typeof` guards.
    // eslint-disable-next-line no-undef
    teardown(() => {
      cleanup();
    });
  }

  // No test setup with other test runners available
  /* istanbul ignore else */
  if (typeof beforeAll === 'function' && typeof afterAll === 'function') {
    // This matches the behavior of React < 18.
    let previousIsReactActEnvironment = getIsReactActEnvironment();
    beforeAll(() => {
      previousIsReactActEnvironment = getIsReactActEnvironment();
      setIsReactActEnvironment(true);
    });
    afterAll(() => {
      setIsReactActEnvironment(previousIsReactActEnvironment);
    });
  }
}

function isElementType(element, tag, props) {
    if (element.namespaceURI && element.namespaceURI !== 'http://www.w3.org/1999/xhtml') {
        return false;
    }
    tag = Array.isArray(tag) ? tag : [
        tag
    ];
    // tagName is uppercase in HTMLDocument and lowercase in XMLDocument
    if (!tag.includes(element.tagName.toLowerCase())) {
        return false;
    }
    if (props) {
        return Object.entries(props).every(([k, v])=>element[k] === v);
    }
    return true;
}

var clickableInputTypes;
(function(clickableInputTypes) {
    clickableInputTypes["button"] = "button";
    clickableInputTypes["color"] = "color";
    clickableInputTypes["file"] = "file";
    clickableInputTypes["image"] = "image";
    clickableInputTypes["reset"] = "reset";
    clickableInputTypes["submit"] = "submit";
    clickableInputTypes["checkbox"] = "checkbox";
    clickableInputTypes["radio"] = "radio";
})(clickableInputTypes || (clickableInputTypes = {}));
function isClickableInput(element) {
    return isElementType(element, 'button') || isElementType(element, 'input') && element.type in clickableInputTypes;
}

function getWindow(node) {
    var _node_ownerDocument;
    if (isDocument$1(node) && node.defaultView) {
        return node.defaultView;
    } else if ((_node_ownerDocument = node.ownerDocument) === null || _node_ownerDocument === undefined ? undefined : _node_ownerDocument.defaultView) {
        return node.ownerDocument.defaultView;
    }
    throw new Error(`Could not determine window of node. Node was ${describe$1(node)}`);
}
function isDocument$1(node) {
    return node.nodeType === 9;
}
function describe$1(val) {
    return typeof val === 'function' ? `function ${val.name}` : val === null ? 'null' : String(val);
}

// jsdom does not implement Blob.text()
function readBlobText(blob, FileReader) {
    return new Promise((res, rej)=>{
        const fr = new FileReader();
        fr.onerror = rej;
        fr.onabort = rej;
        fr.onload = ()=>{
            res(String(fr.result));
        };
        fr.readAsText(blob);
    });
}

// FileList can not be created per constructor.
function createFileList(window, files) {
    const list = {
        ...files,
        length: files.length,
        item: (index)=>list[index],
        [Symbol.iterator]: function* nextFile() {
            for(let i = 0; i < list.length; i++){
                yield list[i];
            }
        }
    };
    list.constructor = window.FileList;
    // guard for environments without FileList
    /* istanbul ignore else */ if (window.FileList) {
        Object.setPrototypeOf(list, window.FileList.prototype);
    }
    Object.freeze(list);
    return list;
}

function _define_property$8(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
// DataTransfer is not implemented in jsdom.
// DataTransfer with FileList is being created by the browser on certain events.
class DataTransferItemStub {
    getAsFile() {
        return this.file;
    }
    getAsString(callback) {
        if (typeof this.data === 'string') {
            callback(this.data);
        }
    }
    /* istanbul ignore next */ webkitGetAsEntry() {
        throw new Error('not implemented');
    }
    constructor(dataOrFile, type){
        _define_property$8(this, "kind", undefined);
        _define_property$8(this, "type", undefined);
        _define_property$8(this, "file", null);
        _define_property$8(this, "data", undefined);
        if (typeof dataOrFile === 'string') {
            this.kind = 'string';
            this.type = String(type);
            this.data = dataOrFile;
        } else {
            this.kind = 'file';
            this.type = dataOrFile.type;
            this.file = dataOrFile;
        }
    }
}
class DataTransferItemListStub extends Array {
    add(...args) {
        const item = new DataTransferItemStub(args[0], args[1]);
        this.push(item);
        return item;
    }
    clear() {
        this.splice(0, this.length);
    }
    remove(index) {
        this.splice(index, 1);
    }
}
function getTypeMatcher(type, exact) {
    const [group, sub] = type.split('/');
    const isGroup = !sub || sub === '*';
    return (item)=>{
        return exact ? item.type === (isGroup ? group : type) : isGroup ? item.type.startsWith(`${group}/`) : item.type === group;
    };
}
function createDataTransferStub(window) {
    return new class DataTransferStub {
        getData(format) {
            var _this_items_find;
            const match = (_this_items_find = this.items.find(getTypeMatcher(format, true))) !== null && _this_items_find !== undefined ? _this_items_find : this.items.find(getTypeMatcher(format, false));
            let text = '';
            match === null || match === undefined ? undefined : match.getAsString((t)=>{
                text = t;
            });
            return text;
        }
        setData(format, data) {
            const matchIndex = this.items.findIndex(getTypeMatcher(format, true));
            const item = new DataTransferItemStub(data, format);
            if (matchIndex >= 0) {
                this.items.splice(matchIndex, 1, item);
            } else {
                this.items.push(item);
            }
        }
        clearData(format) {
            if (format) {
                const matchIndex = this.items.findIndex(getTypeMatcher(format, true));
                if (matchIndex >= 0) {
                    this.items.remove(matchIndex);
                }
            } else {
                this.items.clear();
            }
        }
        get types() {
            const t = [];
            if (this.files.length) {
                t.push('Files');
            }
            this.items.forEach((i)=>t.push(i.type));
            Object.freeze(t);
            return t;
        }
        /* istanbul ignore next */ setDragImage() {}
        constructor(){
            _define_property$8(this, "dropEffect", 'none');
            _define_property$8(this, "effectAllowed", 'uninitialized');
            _define_property$8(this, "items", new DataTransferItemListStub());
            _define_property$8(this, "files", createFileList(window, []));
        }
    }();
}
function createDataTransfer(window, files = []) {
    // Use real DataTransfer if available
    const dt = typeof window.DataTransfer === 'undefined' ? createDataTransferStub(window) : /* istanbul ignore next */ new window.DataTransfer();
    Object.defineProperty(dt, 'files', {
        get: ()=>createFileList(window, files)
    });
    return dt;
}
function getBlobFromDataTransferItem(window, item) {
    if (item.kind === 'file') {
        return item.getAsFile();
    }
    let data = '';
    item.getAsString((s)=>{
        data = s;
    });
    return new window.Blob([
        data
    ], {
        type: item.type
    });
}

// Clipboard is not available in jsdom
function _define_property$7(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
// MDN lists string|Blob|Promise<Blob|string> as possible types in ClipboardItemData
// lib.dom.d.ts lists only Promise<Blob|string>
// https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem/ClipboardItem#syntax
function createClipboardItem(window, ...blobs) {
    const dataMap = Object.fromEntries(blobs.map((b)=>[
            typeof b === 'string' ? 'text/plain' : b.type,
            Promise.resolve(b)
        ]));
    // use real ClipboardItem if available
    /* istanbul ignore if */ if (typeof window.ClipboardItem !== 'undefined') {
        return new window.ClipboardItem(dataMap);
    }
    return new class ClipboardItem {
        get types() {
            return Array.from(Object.keys(this.data));
        }
        async getType(type) {
            const value = await this.data[type];
            if (!value) {
                throw new Error(`${type} is not one of the available MIME types on this item.`);
            }
            return value instanceof window.Blob ? value : new window.Blob([
                value
            ], {
                type
            });
        }
        constructor(d){
            _define_property$7(this, "data", undefined);
            this.data = d;
        }
    }(dataMap);
}
const ClipboardStubControl = Symbol('Manage ClipboardSub');
function createClipboardStub(window, control) {
    return Object.assign(new class Clipboard extends window.EventTarget {
        async read() {
            return Array.from(this.items);
        }
        async readText() {
            let text = '';
            for (const item of this.items){
                const type = item.types.includes('text/plain') ? 'text/plain' : item.types.find((t)=>t.startsWith('text/'));
                if (type) {
                    text += await item.getType(type).then((b)=>readBlobText(b, window.FileReader));
                }
            }
            return text;
        }
        async write(data) {
            this.items = data;
        }
        async writeText(text) {
            this.items = [
                createClipboardItem(window, text)
            ];
        }
        constructor(...args){
            super(...args);
            _define_property$7(this, "items", []);
        }
    }(), {
        [ClipboardStubControl]: control
    });
}
function isClipboardStub(clipboard) {
    return !!(clipboard === null || clipboard === undefined ? undefined : clipboard[ClipboardStubControl]);
}
function attachClipboardStubToView(window) {
    if (isClipboardStub(window.navigator.clipboard)) {
        return window.navigator.clipboard[ClipboardStubControl];
    }
    const realClipboard = Object.getOwnPropertyDescriptor(window.navigator, 'clipboard');
    let stub;
    const control = {
        resetClipboardStub: ()=>{
            stub = createClipboardStub(window, control);
        },
        detachClipboardStub: ()=>{
            /* istanbul ignore if */ if (realClipboard) {
                Object.defineProperty(window.navigator, 'clipboard', realClipboard);
            } else {
                Object.defineProperty(window.navigator, 'clipboard', {
                    value: undefined,
                    configurable: true
                });
            }
        }
    };
    stub = createClipboardStub(window, control);
    Object.defineProperty(window.navigator, 'clipboard', {
        get: ()=>stub,
        configurable: true
    });
    return stub[ClipboardStubControl];
}
function resetClipboardStubOnView(window) {
    if (isClipboardStub(window.navigator.clipboard)) {
        window.navigator.clipboard[ClipboardStubControl].resetClipboardStub();
    }
}
function detachClipboardStubFromView(window) {
    if (isClipboardStub(window.navigator.clipboard)) {
        window.navigator.clipboard[ClipboardStubControl].detachClipboardStub();
    }
}
async function readDataTransferFromClipboard(document) {
    const window = document.defaultView;
    const clipboard = window === null || window === undefined ? undefined : window.navigator.clipboard;
    const items = clipboard && await clipboard.read();
    if (!items) {
        throw new Error('The Clipboard API is unavailable.');
    }
    const dt = createDataTransfer(window);
    for (const item of items){
        for (const type of item.types){
            dt.setData(type, await item.getType(type).then((b)=>readBlobText(b, window.FileReader)));
        }
    }
    return dt;
}
async function writeDataTransferToClipboard(document, clipboardData) {
    const window = getWindow(document);
    const clipboard = window.navigator.clipboard;
    const items = [];
    for(let i = 0; i < clipboardData.items.length; i++){
        const dtItem = clipboardData.items[i];
        const blob = getBlobFromDataTransferItem(window, dtItem);
        items.push(createClipboardItem(window, blob));
    }
    const written = clipboard && await clipboard.write(items).then(()=>true, // Can happen with other implementations that e.g. require permissions
    /* istanbul ignore next */ ()=>false);
    if (!written) {
        throw new Error('The Clipboard API is unavailable.');
    }
}
const g = globalThis;
/* istanbul ignore else */ if (typeof g.afterEach === 'function') {
    g.afterEach(()=>resetClipboardStubOnView(globalThis.window));
}
/* istanbul ignore else */ if (typeof g.afterAll === 'function') {
    g.afterAll(()=>detachClipboardStubFromView(globalThis.window));
}

//jsdom is not supporting isContentEditable
function isContentEditable(element) {
    return element.hasAttribute('contenteditable') && (element.getAttribute('contenteditable') == 'true' || element.getAttribute('contenteditable') == '');
}
/**
 * If a node is a contenteditable or inside one, return that element.
 */ function getContentEditable(node) {
    const element = getElement$1(node);
    return element && (element.closest('[contenteditable=""]') || element.closest('[contenteditable="true"]'));
}
function getElement$1(node) {
    return node.nodeType === 1 ? node : node.parentElement;
}

function isEditable(element) {
    return isEditableInputOrTextArea(element) && !element.readOnly || isContentEditable(element);
}
var editableInputTypes;
(function(editableInputTypes) {
    editableInputTypes["text"] = "text";
    editableInputTypes["date"] = "date";
    editableInputTypes["datetime-local"] = "datetime-local";
    editableInputTypes["email"] = "email";
    editableInputTypes["month"] = "month";
    editableInputTypes["number"] = "number";
    editableInputTypes["password"] = "password";
    editableInputTypes["search"] = "search";
    editableInputTypes["tel"] = "tel";
    editableInputTypes["time"] = "time";
    editableInputTypes["url"] = "url";
    editableInputTypes["week"] = "week";
})(editableInputTypes || (editableInputTypes = {}));
function isEditableInputOrTextArea(element) {
    return isElementType(element, 'textarea') || isElementType(element, 'input') && element.type in editableInputTypes;
}

var maxLengthSupportedTypes;
(function(maxLengthSupportedTypes) {
    maxLengthSupportedTypes["email"] = "email";
    maxLengthSupportedTypes["password"] = "password";
    maxLengthSupportedTypes["search"] = "search";
    maxLengthSupportedTypes["telephone"] = "telephone";
    maxLengthSupportedTypes["text"] = "text";
    maxLengthSupportedTypes["url"] = "url";
})(maxLengthSupportedTypes || (maxLengthSupportedTypes = {}));
// can't use .maxLength property because of a jsdom bug:
// https://github.com/jsdom/jsdom/issues/2927
function getMaxLength(element) {
    var _element_getAttribute;
    const attr = (_element_getAttribute = element.getAttribute('maxlength')) !== null && _element_getAttribute !== undefined ? _element_getAttribute : '';
    return /^\d+$/.test(attr) && Number(attr) >= 0 ? Number(attr) : undefined;
}
function supportsMaxLength(element) {
    return isElementType(element, 'textarea') || isElementType(element, 'input') && element.type in maxLengthSupportedTypes;
}

const FOCUSABLE_SELECTOR = [
    'input:not([type=hidden]):not([disabled])',
    'button:not([disabled])',
    'select:not([disabled])',
    'textarea:not([disabled])',
    '[contenteditable=""]',
    '[contenteditable="true"]',
    'a[href]',
    '[tabindex]:not([disabled])'
].join(', ');

function isFocusable(element) {
    return element.matches(FOCUSABLE_SELECTOR);
}

var bracketDict;
(function(bracketDict) {
    bracketDict["{"] = "}";
    bracketDict["["] = "]";
})(bracketDict || (bracketDict = {}));
/**
 * Read the next key definition from user input
 *
 * Describe key per `{descriptor}` or `[descriptor]`.
 * Everything else will be interpreted as a single character as descriptor - e.g. `a`.
 * Brackets `{` and `[` can be escaped by doubling - e.g. `foo[[bar` translates to `foo[bar`.
 * A previously pressed key can be released per `{/descriptor}`.
 * Keeping the key pressed can be written as `{descriptor>}`.
 * When keeping the key pressed you can choose how long the key is pressed `{descriptor>3}`.
 * You can then release the key per `{descriptor>3/}` or keep it pressed and continue with the next key.
 */ function readNextDescriptor(text, context) {
    let pos = 0;
    const startBracket = text[pos] in bracketDict ? text[pos] : '';
    pos += startBracket.length;
    const isEscapedChar = new RegExp(`^\\${startBracket}{2}`).test(text);
    const type = isEscapedChar ? '' : startBracket;
    return {
        type,
        ...type === '' ? readPrintableChar(text, pos, context) : readTag(text, pos, type, context)
    };
}
function readPrintableChar(text, pos, context) {
    const descriptor = text[pos];
    assertDescriptor(descriptor, text, pos, context);
    pos += descriptor.length;
    return {
        consumedLength: pos,
        descriptor,
        releasePrevious: false,
        releaseSelf: true,
        repeat: 1
    };
}
function readTag(text, pos, startBracket, context) {
    var _text_slice_match, _text_slice_match1;
    const releasePreviousModifier = text[pos] === '/' ? '/' : '';
    pos += releasePreviousModifier.length;
    const escapedDescriptor = startBracket === '{' && text[pos] === '\\';
    pos += Number(escapedDescriptor);
    const descriptor = escapedDescriptor ? text[pos] : (_text_slice_match = text.slice(pos).match(startBracket === '{' ? /^\w+|^[^}>/]/ : /^\w+/)) === null || _text_slice_match === undefined ? undefined : _text_slice_match[0];
    assertDescriptor(descriptor, text, pos, context);
    pos += descriptor.length;
    var _text_slice_match_;
    const repeatModifier = (_text_slice_match_ = (_text_slice_match1 = text.slice(pos).match(/^>\d+/)) === null || _text_slice_match1 === undefined ? undefined : _text_slice_match1[0]) !== null && _text_slice_match_ !== undefined ? _text_slice_match_ : '';
    pos += repeatModifier.length;
    const releaseSelfModifier = text[pos] === '/' || !repeatModifier && text[pos] === '>' ? text[pos] : '';
    pos += releaseSelfModifier.length;
    const expectedEndBracket = bracketDict[startBracket];
    const endBracket = text[pos] === expectedEndBracket ? expectedEndBracket : '';
    if (!endBracket) {
        throw new Error(getErrorMessage([
            !repeatModifier && 'repeat modifier',
            !releaseSelfModifier && 'release modifier',
            `"${expectedEndBracket}"`
        ].filter(Boolean).join(' or '), text[pos], text, context));
    }
    pos += endBracket.length;
    return {
        consumedLength: pos,
        descriptor,
        releasePrevious: !!releasePreviousModifier,
        repeat: repeatModifier ? Math.max(Number(repeatModifier.substr(1)), 1) : 1,
        releaseSelf: hasReleaseSelf(releaseSelfModifier, repeatModifier)
    };
}
function assertDescriptor(descriptor, text, pos, context) {
    if (!descriptor) {
        throw new Error(getErrorMessage('key descriptor', text[pos], text, context));
    }
}
function hasReleaseSelf(releaseSelfModifier, repeatModifier) {
    if (releaseSelfModifier) {
        return releaseSelfModifier === '/';
    }
    if (repeatModifier) {
        return false;
    }
}
function getErrorMessage(expected, found, text, context) {
    return `Expected ${expected} but found "${found !== null && found !== undefined ? found : ''}" in "${text}"
    See ${context === 'pointer' ? `https://testing-library.com/docs/user-event/pointer#pressing-a-button-or-touching-the-screen` : `https://testing-library.com/docs/user-event/keyboard`}
    for more information about how userEvent parses your input.`;
}

function cloneEvent(event) {
    return new event.constructor(event.type, event);
}

var ApiLevel;
(function(ApiLevel) {
    ApiLevel[ApiLevel["Trigger"] = 2] = "Trigger";
    ApiLevel[ApiLevel["Call"] = 1] = "Call";
})(ApiLevel || (ApiLevel = {}));
function setLevelRef(instance, level) {
    instance.levelRefs[level] = {};
}
function getLevelRef(instance, level) {
    return instance.levelRefs[level];
}

var PointerEventsCheckLevel;
(function(PointerEventsCheckLevel) {
    /**
   * Check pointer events on every user interaction that triggers a bunch of events.
   * E.g. once for releasing a mouse button even though this triggers `pointerup`, `mouseup`, `click`, etc...
   */ PointerEventsCheckLevel[PointerEventsCheckLevel["EachTrigger"] = 4] = "EachTrigger";
    /** Check each target once per call to pointer (related) API */ PointerEventsCheckLevel[PointerEventsCheckLevel["EachApiCall"] = 2] = "EachApiCall";
    /** Check each event target once */ PointerEventsCheckLevel[PointerEventsCheckLevel["EachTarget"] = 1] = "EachTarget";
    /** No pointer events check */ PointerEventsCheckLevel[PointerEventsCheckLevel["Never"] = 0] = "Never";
})(PointerEventsCheckLevel || (PointerEventsCheckLevel = {}));

// This should probably just rely on the :disabled pseudo-class, but JSDOM doesn't implement it properly.
function isDisabled(element) {
    for(let el = element; el; el = el.parentElement){
        if (isElementType(el, [
            'button',
            'input',
            'select',
            'textarea',
            'optgroup',
            'option'
        ])) {
            if (el.hasAttribute('disabled')) {
                return true;
            }
        } else if (isElementType(el, 'fieldset')) {
            var _el_querySelector;
            if (el.hasAttribute('disabled') && !((_el_querySelector = el.querySelector(':scope > legend')) === null || _el_querySelector === undefined ? undefined : _el_querySelector.contains(element))) {
                return true;
            }
        } else if (el.tagName.includes('-')) {
            if (el.constructor.formAssociated && el.hasAttribute('disabled')) {
                return true;
            }
        }
    }
    return false;
}

function getActiveElement(document) {
    const activeElement = document.activeElement;
    if (activeElement === null || activeElement === undefined ? undefined : activeElement.shadowRoot) {
        return getActiveElement(activeElement.shadowRoot);
    } else {
        // Browser does not yield disabled elements as document.activeElement - jsdom does
        if (isDisabled(activeElement)) {
            return document.ownerDocument ? /* istanbul ignore next */ document.ownerDocument.body : document.body;
        }
        return activeElement;
    }
}
function getActiveElementOrBody(document) {
    var _getActiveElement;
    return (_getActiveElement = getActiveElement(document)) !== null && _getActiveElement !== undefined ? _getActiveElement : /* istanbul ignore next */ document.body;
}

function findClosest(element, callback) {
    let el = element;
    do {
        if (callback(el)) {
            return el;
        }
        el = el.parentElement;
    }while (el && el !== element.ownerDocument.body)
    return undefined;
}

/**
 * Determine if the element has its own selection implementation
 * and does not interact with the Document Selection API.
 */ function hasOwnSelection(node) {
    return isElement$1(node) && isEditableInputOrTextArea(node);
}
function hasNoSelection(node) {
    return isElement$1(node) && isClickableInput(node);
}
function isElement$1(node) {
    return node.nodeType === 1;
}

/**
 * Reset the Document Selection when moving focus into an element
 * with own selection implementation.
 */ function updateSelectionOnFocus(element) {
    const selection = element.ownerDocument.getSelection();
    /* istanbul ignore if */ if (!(selection === null || selection === undefined ? undefined : selection.focusNode)) {
        return;
    }
    // If the focus moves inside an element with own selection implementation,
    // the document selection will be this element.
    // But if the focused element is inside a contenteditable,
    // 1) a collapsed selection will be retained.
    // 2) other selections will be replaced by a cursor
    //  2.a) at the start of the first child if it is a text node
    //  2.b) at the start of the contenteditable.
    if (hasOwnSelection(element)) {
        const contenteditable = getContentEditable(selection.focusNode);
        if (contenteditable) {
            if (!selection.isCollapsed) {
                var _contenteditable_firstChild;
                const focusNode = ((_contenteditable_firstChild = contenteditable.firstChild) === null || _contenteditable_firstChild === undefined ? undefined : _contenteditable_firstChild.nodeType) === 3 ? contenteditable.firstChild : contenteditable;
                selection.setBaseAndExtent(focusNode, 0, focusNode, 0);
            }
        } else {
            selection.setBaseAndExtent(element, 0, element, 0);
        }
    }
}

function wrapEvent(cb, _element) {
    return getConfig().eventWrapper(cb);
}

/**
 * Focus closest focusable element.
 */ function focusElement(element) {
    const target = findClosest(element, isFocusable);
    const activeElement = getActiveElement(element.ownerDocument);
    if ((target !== null && target !== undefined ? target : element.ownerDocument.body) === activeElement) {
        return;
    } else if (target) {
        wrapEvent(()=>target.focus());
    } else {
        wrapEvent(()=>activeElement === null || activeElement === undefined ? undefined : activeElement.blur());
    }
    updateSelectionOnFocus(target !== null && target !== undefined ? target : element.ownerDocument.body);
}
function blurElement(element) {
    if (!isFocusable(element)) return;
    const wasActive = getActiveElement(element.ownerDocument) === element;
    if (!wasActive) return;
    wrapEvent(()=>element.blur());
}

const behavior = {};

behavior.click = (event, target, instance)=>{
    const context = target.closest('button,input,label,select,textarea');
    const control = context && isElementType(context, 'label') && context.control;
    if (control) {
        return ()=>{
            if (isFocusable(control)) {
                focusElement(control);
            }
            instance.dispatchEvent(control, cloneEvent(event));
        };
    } else if (isElementType(target, 'input', {
        type: 'file'
    })) {
        return ()=>{
            // blur fires when the file selector pops up
            blurElement(target);
            target.dispatchEvent(new (getWindow(target)).Event('fileDialog'));
            // focus fires after the file selector has been closed
            focusElement(target);
        };
    }
};

const UIValue = Symbol('Displayed value in UI');
const UISelection = Symbol('Displayed selection in UI');
const InitialValue = Symbol('Initial value to compare on blur');
function isUIValue(value) {
    return typeof value === 'object' && UIValue in value;
}
function isUISelectionStart(start) {
    return !!start && typeof start === 'object' && UISelection in start;
}
function setUIValue(element, value) {
    if (element[InitialValue] === undefined) {
        element[InitialValue] = element.value;
    }
    element[UIValue] = value;
    // eslint-disable-next-line no-new-wrappers
    element.value = Object.assign(new String(value), {
        [UIValue]: true
    });
}
function getUIValue(element) {
    return element[UIValue] === undefined ? element.value : String(element[UIValue]);
}
/** Flag the IDL value as clean. This does not change the value.*/ function setUIValueClean(element) {
    element[UIValue] = undefined;
}
function clearInitialValue(element) {
    element[InitialValue] = undefined;
}
function getInitialValue(element) {
    return element[InitialValue];
}
function setUISelectionRaw(element, selection) {
    element[UISelection] = selection;
}
function setUISelection(element, { focusOffset: focusOffsetParam, anchorOffset: anchorOffsetParam = focusOffsetParam }, mode = 'replace') {
    const valueLength = getUIValue(element).length;
    const sanitizeOffset = (o)=>Math.max(0, Math.min(valueLength, o));
    const anchorOffset = mode === 'replace' || element[UISelection] === undefined ? sanitizeOffset(anchorOffsetParam) : element[UISelection].anchorOffset;
    const focusOffset = sanitizeOffset(focusOffsetParam);
    const startOffset = Math.min(anchorOffset, focusOffset);
    const endOffset = Math.max(anchorOffset, focusOffset);
    element[UISelection] = {
        anchorOffset,
        focusOffset
    };
    if (element.selectionStart === startOffset && element.selectionEnd === endOffset) {
        return;
    }
    // eslint-disable-next-line no-new-wrappers
    const startObj = Object.assign(new Number(startOffset), {
        [UISelection]: true
    });
    try {
        element.setSelectionRange(startObj, endOffset);
    } catch  {
    // DOMException for invalid state is expected when calling this
    // on an element without support for setSelectionRange
    }
}
function getUISelection(element) {
    var _element_selectionStart, _element_selectionEnd, _element_UISelection;
    const sel = (_element_UISelection = element[UISelection]) !== null && _element_UISelection !== undefined ? _element_UISelection : {
        anchorOffset: (_element_selectionStart = element.selectionStart) !== null && _element_selectionStart !== undefined ? _element_selectionStart : 0,
        focusOffset: (_element_selectionEnd = element.selectionEnd) !== null && _element_selectionEnd !== undefined ? _element_selectionEnd : 0
    };
    return {
        ...sel,
        startOffset: Math.min(sel.anchorOffset, sel.focusOffset),
        endOffset: Math.max(sel.anchorOffset, sel.focusOffset)
    };
}
function hasUISelection(element) {
    return !!element[UISelection];
}
/** Flag the IDL selection as clean. This does not change the selection. */ function setUISelectionClean(element) {
    element[UISelection] = undefined;
}

const parseInt$1 = globalThis.parseInt;
function buildTimeValue(value) {
    const onlyDigitsValue = value.replace(/\D/g, '');
    if (onlyDigitsValue.length < 2) {
        return value;
    }
    const firstDigit = parseInt$1(onlyDigitsValue[0], 10);
    const secondDigit = parseInt$1(onlyDigitsValue[1], 10);
    if (firstDigit >= 3 || firstDigit === 2 && secondDigit >= 4) {
        let index;
        if (firstDigit >= 3) {
            index = 1;
        } else {
            index = 2;
        }
        return build(onlyDigitsValue, index);
    }
    if (value.length === 2) {
        return value;
    }
    return build(onlyDigitsValue, 2);
}
function build(onlyDigitsValue, index) {
    const hours = onlyDigitsValue.slice(0, index);
    const validHours = Math.min(parseInt$1(hours, 10), 23);
    const minuteCharacters = onlyDigitsValue.slice(index);
    const parsedMinutes = parseInt$1(minuteCharacters, 10);
    const validMinutes = Math.min(parsedMinutes, 59);
    return `${validHours.toString().padStart(2, '0')}:${validMinutes.toString().padStart(2, '0')}`;
}
function isValidDateOrTimeValue(element, value) {
    const clone = element.cloneNode();
    clone.value = value;
    return clone.value === value;
}

function getNextCursorPosition(node, offset, direction, inputType) {
    // The behavior at text node zero offset is inconsistent.
    // When walking backwards:
    // Firefox always moves to zero offset and jumps over last offset.
    // Chrome jumps over zero offset per default but over last offset when Shift is pressed.
    // The cursor always moves to zero offset if the focus area (contenteditable or body) ends there.
    // When walking foward both ignore zero offset.
    // When walking over input elements the cursor moves before or after that element.
    // When walking over line breaks the cursor moves inside any following text node.
    if (isTextNode(node) && offset + direction >= 0 && offset + direction <= node.nodeValue.length) {
        return {
            node,
            offset: offset + direction
        };
    }
    const nextNode = getNextCharacterContentNode(node, offset, direction);
    if (nextNode) {
        if (isTextNode(nextNode)) {
            return {
                node: nextNode,
                offset: direction > 0 ? Math.min(1, nextNode.nodeValue.length) : Math.max(nextNode.nodeValue.length - 1, 0)
            };
        } else if (isElementType(nextNode, 'br')) {
            const nextPlusOne = getNextCharacterContentNode(nextNode, undefined, direction);
            if (!nextPlusOne) {
                // The behavior when there is no possible cursor position beyond the line break is inconsistent.
                // In Chrome outside of contenteditable moving before a leading line break is possible.
                // A leading line break can still be removed per deleteContentBackward.
                // A trailing line break on the other hand is not removed by deleteContentForward.
                if (direction < 0 && inputType === 'deleteContentBackward') {
                    return {
                        node: nextNode.parentNode,
                        offset: getOffset(nextNode)
                    };
                }
                return undefined;
            } else if (isTextNode(nextPlusOne)) {
                return {
                    node: nextPlusOne,
                    offset: direction > 0 ? 0 : nextPlusOne.nodeValue.length
                };
            } else if (direction < 0 && isElementType(nextPlusOne, 'br')) {
                return {
                    node: nextNode.parentNode,
                    offset: getOffset(nextNode)
                };
            } else {
                return {
                    node: nextPlusOne.parentNode,
                    offset: getOffset(nextPlusOne) + (direction > 0 ? 0 : 1)
                };
            }
        } else {
            return {
                node: nextNode.parentNode,
                offset: getOffset(nextNode) + (direction > 0 ? 1 : 0)
            };
        }
    }
}
function getNextCharacterContentNode(node, offset, direction) {
    const nextOffset = Number(offset) + (direction < 0 ? -1 : 0);
    if (offset !== undefined && isElement(node) && nextOffset >= 0 && nextOffset < node.children.length) {
        node = node.children[nextOffset];
    }
    return walkNodes(node, direction === 1 ? 'next' : 'previous', isTreatedAsCharacterContent);
}
function isTreatedAsCharacterContent(node) {
    if (isTextNode(node)) {
        return true;
    }
    if (isElement(node)) {
        if (isElementType(node, [
            'input',
            'textarea'
        ])) {
            return node.type !== 'hidden';
        } else if (isElementType(node, 'br')) {
            return true;
        }
    }
    return false;
}
function getOffset(node) {
    let i = 0;
    while(node.previousSibling){
        i++;
        node = node.previousSibling;
    }
    return i;
}
function isElement(node) {
    return node.nodeType === 1;
}
function isTextNode(node) {
    return node.nodeType === 3;
}
function walkNodes(node, direction, callback) {
    for(;;){
        var _node_ownerDocument;
        const sibling = node[`${direction}Sibling`];
        if (sibling) {
            node = getDescendant(sibling, direction === 'next' ? 'first' : 'last');
            if (callback(node)) {
                return node;
            }
        } else if (node.parentNode && (!isElement(node.parentNode) || !isContentEditable(node.parentNode) && node.parentNode !== ((_node_ownerDocument = node.ownerDocument) === null || _node_ownerDocument === undefined ? undefined : _node_ownerDocument.body))) {
            node = node.parentNode;
        } else {
            break;
        }
    }
}
function getDescendant(node, direction) {
    while(node.hasChildNodes()){
        node = node[`${direction}Child`];
    }
    return node;
}

const TrackChanges = Symbol('Track programmatic changes for React workaround');
// When the input event happens in the browser, React executes all event handlers
// and if they change state of a controlled value, nothing happens.
// But when we trigger the event handlers in test environment with React@17,
// the changes are rolled back before the state update is applied.
// This results in a reset cursor.
// There might be a better way to work around if we figure out
// why the batched update is executed differently in our test environment.
function isReact17Element(element) {
    return Object.getOwnPropertyNames(element).some((k)=>k.startsWith('__react')) && getWindow(element).REACT_VERSION === 17;
}
function startTrackValue(element) {
    if (!isReact17Element(element)) {
        return;
    }
    element[TrackChanges] = {
        previousValue: String(element.value),
        tracked: []
    };
}
function trackOrSetValue(element, v) {
    var _element_TrackChanges_tracked, _element_TrackChanges;
    (_element_TrackChanges = element[TrackChanges]) === null || _element_TrackChanges === undefined ? undefined : (_element_TrackChanges_tracked = _element_TrackChanges.tracked) === null || _element_TrackChanges_tracked === undefined ? undefined : _element_TrackChanges_tracked.push(v);
    if (!element[TrackChanges]) {
        setUIValueClean(element);
        setUISelection(element, {
            focusOffset: v.length
        });
    }
}
function commitValueAfterInput(element, cursorOffset) {
    var _changes_tracked;
    const changes = element[TrackChanges];
    element[TrackChanges] = undefined;
    if (!(changes === null || changes === undefined ? undefined : (_changes_tracked = changes.tracked) === null || _changes_tracked === undefined ? undefined : _changes_tracked.length)) {
        return;
    }
    const isJustReactStateUpdate = changes.tracked.length === 2 && changes.tracked[0] === changes.previousValue && changes.tracked[1] === element.value;
    if (!isJustReactStateUpdate) {
        setUIValueClean(element);
    }
    if (hasUISelection(element)) {
        setUISelection(element, {
            focusOffset: isJustReactStateUpdate ? cursorOffset : element.value.length
        });
    }
}

/**
 * Determine which selection logic and selection ranges to consider.
 */ function getTargetTypeAndSelection(node) {
    const element = getElement(node);
    if (element && hasOwnSelection(element)) {
        return {
            type: 'input',
            selection: getUISelection(element)
        };
    }
    const selection = element === null || element === undefined ? undefined : element.ownerDocument.getSelection();
    // It is possible to extend a single-range selection into a contenteditable.
    // This results in the range acting like a range outside of contenteditable.
    const isCE = getContentEditable(node) && (selection === null || selection === undefined ? undefined : selection.anchorNode) && getContentEditable(selection.anchorNode);
    return {
        type: isCE ? 'contenteditable' : 'default',
        selection
    };
}
function getElement(node) {
    return node.nodeType === 1 ? node : node.parentElement;
}

/**
 * Get the range that would be overwritten by input.
 */ function getInputRange(focusNode) {
    const typeAndSelection = getTargetTypeAndSelection(focusNode);
    if (typeAndSelection.type === 'input') {
        return typeAndSelection.selection;
    } else if (typeAndSelection.type === 'contenteditable') {
        var _typeAndSelection_selection;
        // Multi-range on contenteditable edits the first selection instead of the last
        return (_typeAndSelection_selection = typeAndSelection.selection) === null || _typeAndSelection_selection === undefined ? undefined : _typeAndSelection_selection.getRangeAt(0);
    }
}

/**
 * Set the selection
 */ function setSelection({ focusNode, focusOffset, anchorNode = focusNode, anchorOffset = focusOffset }) {
    var _anchorNode_ownerDocument_getSelection, _anchorNode_ownerDocument;
    const typeAndSelection = getTargetTypeAndSelection(focusNode);
    if (typeAndSelection.type === 'input') {
        return setUISelection(focusNode, {
            anchorOffset,
            focusOffset
        });
    }
    (_anchorNode_ownerDocument = anchorNode.ownerDocument) === null || _anchorNode_ownerDocument === undefined ? undefined : (_anchorNode_ownerDocument_getSelection = _anchorNode_ownerDocument.getSelection()) === null || _anchorNode_ownerDocument_getSelection === undefined ? undefined : _anchorNode_ownerDocument_getSelection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
}

function isDateOrTime(element) {
    return isElementType(element, 'input') && [
        'date',
        'time'
    ].includes(element.type);
}
function input(instance, element, data, inputType = 'insertText') {
    const inputRange = getInputRange(element);
    /* istanbul ignore if */ if (!inputRange) {
        return;
    }
    // There is no `beforeinput` event on `date` and `time` input
    if (!isDateOrTime(element)) {
        const unprevented = instance.dispatchUIEvent(element, 'beforeinput', {
            inputType,
            data
        });
        if (!unprevented) {
            return;
        }
    }
    if ('startContainer' in inputRange) {
        editContenteditable(instance, element, inputRange, data, inputType);
    } else {
        editInputElement(instance, element, inputRange, data, inputType);
    }
}
function editContenteditable(instance, element, inputRange, data, inputType) {
    let del = false;
    if (!inputRange.collapsed) {
        del = true;
        inputRange.deleteContents();
    } else if ([
        'deleteContentBackward',
        'deleteContentForward'
    ].includes(inputType)) {
        const nextPosition = getNextCursorPosition(inputRange.startContainer, inputRange.startOffset, inputType === 'deleteContentBackward' ? -1 : 1, inputType);
        if (nextPosition) {
            del = true;
            const delRange = inputRange.cloneRange();
            if (delRange.comparePoint(nextPosition.node, nextPosition.offset) < 0) {
                delRange.setStart(nextPosition.node, nextPosition.offset);
            } else {
                delRange.setEnd(nextPosition.node, nextPosition.offset);
            }
            delRange.deleteContents();
        }
    }
    if (data) {
        if (inputRange.endContainer.nodeType === 3) {
            const offset = inputRange.endOffset;
            inputRange.endContainer.insertData(offset, data);
            inputRange.setStart(inputRange.endContainer, offset + data.length);
            inputRange.setEnd(inputRange.endContainer, offset + data.length);
        } else {
            const text = element.ownerDocument.createTextNode(data);
            inputRange.insertNode(text);
            inputRange.setStart(text, data.length);
            inputRange.setEnd(text, data.length);
        }
    }
    if (del || data) {
        instance.dispatchUIEvent(element, 'input', {
            inputType
        });
    }
}
function editInputElement(instance, element, inputRange, data, inputType) {
    let dataToInsert = data;
    if (supportsMaxLength(element)) {
        const maxLength = getMaxLength(element);
        if (maxLength !== undefined && data.length > 0) {
            const spaceUntilMaxLength = maxLength - element.value.length;
            if (spaceUntilMaxLength > 0) {
                dataToInsert = data.substring(0, spaceUntilMaxLength);
            } else {
                return;
            }
        }
    }
    const { newValue, newOffset, oldValue } = calculateNewValue(dataToInsert, element, inputRange, inputType);
    if (newValue === oldValue && newOffset === inputRange.startOffset && newOffset === inputRange.endOffset) {
        return;
    }
    if (isElementType(element, 'input', {
        type: 'number'
    }) && !isValidNumberInput(newValue)) {
        return;
    }
    setUIValue(element, newValue);
    setSelection({
        focusNode: element,
        anchorOffset: newOffset,
        focusOffset: newOffset
    });
    if (isDateOrTime(element)) {
        if (isValidDateOrTimeValue(element, newValue)) {
            commitInput(instance, element, newOffset, {});
            instance.dispatchUIEvent(element, 'change');
            clearInitialValue(element);
        }
    } else {
        commitInput(instance, element, newOffset, {
            data,
            inputType
        });
    }
}
function calculateNewValue(inputData, node, { startOffset, endOffset }, inputType) {
    const value = getUIValue(node);
    const prologEnd = Math.max(0, startOffset === endOffset && inputType === 'deleteContentBackward' ? startOffset - 1 : startOffset);
    const prolog = value.substring(0, prologEnd);
    const epilogStart = Math.min(value.length, startOffset === endOffset && inputType === 'deleteContentForward' ? startOffset + 1 : endOffset);
    const epilog = value.substring(epilogStart, value.length);
    let newValue = `${prolog}${inputData}${epilog}`;
    let newOffset = prologEnd + inputData.length;
    if (isElementType(node, 'input', {
        type: 'time'
    })) {
        const builtValue = buildTimeValue(newValue);
        if (builtValue !== '' && isValidDateOrTimeValue(node, builtValue)) {
            newValue = builtValue;
            newOffset = builtValue.length;
        }
    }
    return {
        oldValue: value,
        newValue,
        newOffset
    };
}
function commitInput(instance, element, newOffset, inputInit) {
    instance.dispatchUIEvent(element, 'input', inputInit);
    commitValueAfterInput(element, newOffset);
}
function isValidNumberInput(value) {
    var _value_match, _value_match1;
    // the browser allows some invalid input but not others
    // it allows up to two '-' at any place before any 'e' or one directly following 'e'
    // it allows one '.' at any place before e
    const valueParts = value.split('e', 2);
    return !(/[^\d.\-e]/.test(value) || Number((_value_match = value.match(/-/g)) === null || _value_match === undefined ? undefined : _value_match.length) > 2 || Number((_value_match1 = value.match(/\./g)) === null || _value_match1 === undefined ? undefined : _value_match1.length) > 1 || valueParts[1] && !/^-?\d*$/.test(valueParts[1]));
}

behavior.cut = (event, target, instance)=>{
    return ()=>{
        if (isEditable(target)) {
            input(instance, target, '', 'deleteByCut');
        }
    };
};

function getValueOrTextContent(element) {
    // istanbul ignore if
    if (!element) {
        return null;
    }
    if (isContentEditable(element)) {
        return element.textContent;
    }
    return getUIValue(element);
}

function isVisible(element) {
    const window = getWindow(element);
    for(let el = element; el === null || el === undefined ? undefined : el.ownerDocument; el = el.parentElement){
        const { display, visibility } = window.getComputedStyle(el);
        if (display === 'none') {
            return false;
        }
        if (visibility === 'hidden') {
            return false;
        }
    }
    return true;
}

function getTabDestination(activeElement, shift) {
    const document = activeElement.ownerDocument;
    const focusableElements = document.querySelectorAll(FOCUSABLE_SELECTOR);
    const enabledElements = Array.from(focusableElements).filter((el)=>el === activeElement || !(Number(el.getAttribute('tabindex')) < 0 || isDisabled(el)));
    // tabindex has no effect if the active element has negative tabindex
    if (Number(activeElement.getAttribute('tabindex')) >= 0) {
        enabledElements.sort((a, b)=>{
            const i = Number(a.getAttribute('tabindex'));
            const j = Number(b.getAttribute('tabindex'));
            if (i === j) {
                return 0;
            } else if (i === 0) {
                return 1;
            } else if (j === 0) {
                return -1;
            }
            return i - j;
        });
    }
    const checkedRadio = {};
    let prunedElements = [
        document.body
    ];
    const activeRadioGroup = isElementType(activeElement, 'input', {
        type: 'radio'
    }) ? activeElement.name : undefined;
    enabledElements.forEach((currentElement)=>{
        const el = currentElement;
        // For radio groups keep only the active radio
        // If there is no active radio, keep only the checked radio
        // If there is no checked radio, treat like everything else
        if (isElementType(el, 'input', {
            type: 'radio'
        }) && el.name) {
            // If the active element is part of the group, add only that
            if (el === activeElement) {
                prunedElements.push(el);
                return;
            } else if (el.name === activeRadioGroup) {
                return;
            }
            // If we stumble upon a checked radio, remove the others
            if (el.checked) {
                prunedElements = prunedElements.filter((e)=>!isElementType(e, 'input', {
                        type: 'radio',
                        name: el.name
                    }));
                prunedElements.push(el);
                checkedRadio[el.name] = el;
                return;
            }
            // If we already found the checked one, skip
            if (typeof checkedRadio[el.name] !== 'undefined') {
                return;
            }
        }
        prunedElements.push(el);
    });
    for(let index = prunedElements.findIndex((el)=>el === activeElement);;){
        index += shift ? -1 : 1;
        // loop at overflow
        if (index === prunedElements.length) {
            index = 0;
        } else if (index === -1) {
            index = prunedElements.length - 1;
        }
        if (prunedElements[index] === activeElement || prunedElements[index] === document.body || isVisible(prunedElements[index])) {
            return prunedElements[index];
        }
    }
}

/**
 * Move the selection
 */ function moveSelection(node, direction) {
    // TODO: implement shift
    if (hasOwnSelection(node)) {
        const selection = getUISelection(node);
        setSelection({
            focusNode: node,
            focusOffset: selection.startOffset === selection.endOffset ? selection.focusOffset + direction : direction < 0 ? selection.startOffset : selection.endOffset
        });
    } else {
        const selection = node.ownerDocument.getSelection();
        if (!(selection === null || selection === undefined ? undefined : selection.focusNode)) {
            return;
        }
        if (selection.isCollapsed) {
            const nextPosition = getNextCursorPosition(selection.focusNode, selection.focusOffset, direction);
            if (nextPosition) {
                setSelection({
                    focusNode: nextPosition.node,
                    focusOffset: nextPosition.offset
                });
            }
        } else {
            selection[direction < 0 ? 'collapseToStart' : 'collapseToEnd']();
        }
    }
}

/**
 * Expand a selection like the browser does when pressing Ctrl+A.
 */ function selectAll(target) {
    if (hasOwnSelection(target)) {
        return setSelection({
            focusNode: target,
            anchorOffset: 0,
            focusOffset: getUIValue(target).length
        });
    }
    var _getContentEditable;
    const focusNode = (_getContentEditable = getContentEditable(target)) !== null && _getContentEditable !== undefined ? _getContentEditable : target.ownerDocument.body;
    setSelection({
        focusNode,
        anchorOffset: 0,
        focusOffset: focusNode.childNodes.length
    });
}
function isAllSelected(target) {
    if (hasOwnSelection(target)) {
        return getUISelection(target).startOffset === 0 && getUISelection(target).endOffset === getUIValue(target).length;
    }
    var _getContentEditable;
    const focusNode = (_getContentEditable = getContentEditable(target)) !== null && _getContentEditable !== undefined ? _getContentEditable : target.ownerDocument.body;
    const selection = target.ownerDocument.getSelection();
    return (selection === null || selection === undefined ? undefined : selection.anchorNode) === focusNode && selection.focusNode === focusNode && selection.anchorOffset === 0 && selection.focusOffset === focusNode.childNodes.length;
}

/**
 * Backward-compatible selection.
 *
 * Handles input elements and contenteditable if it only contains a single text node.
 */ function setSelectionRange(element, anchorOffset, focusOffset) {
    var _element_firstChild;
    if (hasOwnSelection(element)) {
        return setSelection({
            focusNode: element,
            anchorOffset,
            focusOffset
        });
    }
    /* istanbul ignore else */ if (isContentEditable(element) && ((_element_firstChild = element.firstChild) === null || _element_firstChild === undefined ? undefined : _element_firstChild.nodeType) === 3) {
        return setSelection({
            focusNode: element.firstChild,
            anchorOffset,
            focusOffset
        });
    }
    /* istanbul ignore next */ throw new Error('Not implemented. The result of this interaction is unreliable.');
}

function walkRadio(instance, el, direction) {
    const window = getWindow(el);
    const group = Array.from(el.ownerDocument.querySelectorAll(el.name ? `input[type="radio"][name="${window.CSS.escape(el.name)}"]` : `input[type="radio"][name=""], input[type="radio"]:not([name])`));
    for(let i = group.findIndex((e)=>e === el) + direction;; i += direction){
        if (!group[i]) {
            i = direction > 0 ? 0 : group.length - 1;
        }
        if (group[i] === el) {
            return;
        }
        if (isDisabled(group[i])) {
            continue;
        }
        focusElement(group[i]);
        instance.dispatchUIEvent(group[i], 'click');
    }
}

behavior.keydown = (event, target, instance)=>{
    var _keydownBehavior_event_key;
    var _keydownBehavior_event_key1;
    return (_keydownBehavior_event_key1 = (_keydownBehavior_event_key = keydownBehavior[event.key]) === null || _keydownBehavior_event_key === undefined ? undefined : _keydownBehavior_event_key.call(keydownBehavior, event, target, instance)) !== null && _keydownBehavior_event_key1 !== undefined ? _keydownBehavior_event_key1 : combinationBehavior(event, target, instance);
};
const keydownBehavior = {
    ArrowDown: (event, target, instance)=>{
        /* istanbul ignore else */ if (isElementType(target, 'input', {
            type: 'radio'
        })) {
            return ()=>walkRadio(instance, target, -1);
        }
    },
    ArrowLeft: (event, target, instance)=>{
        if (isElementType(target, 'input', {
            type: 'radio'
        })) {
            return ()=>walkRadio(instance, target, -1);
        }
        return ()=>moveSelection(target, -1);
    },
    ArrowRight: (event, target, instance)=>{
        if (isElementType(target, 'input', {
            type: 'radio'
        })) {
            return ()=>walkRadio(instance, target, 1);
        }
        return ()=>moveSelection(target, 1);
    },
    ArrowUp: (event, target, instance)=>{
        /* istanbul ignore else */ if (isElementType(target, 'input', {
            type: 'radio'
        })) {
            return ()=>walkRadio(instance, target, 1);
        }
    },
    Backspace: (event, target, instance)=>{
        if (isEditable(target)) {
            return ()=>{
                input(instance, target, '', 'deleteContentBackward');
            };
        }
    },
    Delete: (event, target, instance)=>{
        if (isEditable(target)) {
            return ()=>{
                input(instance, target, '', 'deleteContentForward');
            };
        }
    },
    End: (event, target)=>{
        if (isElementType(target, [
            'input',
            'textarea'
        ]) || isContentEditable(target)) {
            return ()=>{
                var _getValueOrTextContent;
                var _getValueOrTextContent_length;
                const newPos = (_getValueOrTextContent_length = (_getValueOrTextContent = getValueOrTextContent(target)) === null || _getValueOrTextContent === undefined ? undefined : _getValueOrTextContent.length) !== null && _getValueOrTextContent_length !== undefined ? _getValueOrTextContent_length : /* istanbul ignore next */ 0;
                setSelectionRange(target, newPos, newPos);
            };
        }
    },
    Home: (event, target)=>{
        if (isElementType(target, [
            'input',
            'textarea'
        ]) || isContentEditable(target)) {
            return ()=>{
                setSelectionRange(target, 0, 0);
            };
        }
    },
    PageDown: (event, target)=>{
        if (isElementType(target, [
            'input'
        ])) {
            return ()=>{
                const newPos = getUIValue(target).length;
                setSelectionRange(target, newPos, newPos);
            };
        }
    },
    PageUp: (event, target)=>{
        if (isElementType(target, [
            'input'
        ])) {
            return ()=>{
                setSelectionRange(target, 0, 0);
            };
        }
    },
    Tab: (event, target, instance)=>{
        return ()=>{
            const dest = getTabDestination(target, instance.system.keyboard.modifiers.Shift);
            focusElement(dest);
            if (hasOwnSelection(dest)) {
                setUISelection(dest, {
                    anchorOffset: 0,
                    focusOffset: dest.value.length
                });
            }
        };
    }
};
const combinationBehavior = (event, target, instance)=>{
    if (event.code === 'KeyA' && instance.system.keyboard.modifiers.Control) {
        return ()=>selectAll(target);
    }
};

behavior.keypress = (event, target, instance)=>{
    if (event.key === 'Enter') {
        if (isElementType(target, 'button') || isElementType(target, 'input') && ClickInputOnEnter.includes(target.type) || isElementType(target, 'a') && Boolean(target.href)) {
            return ()=>{
                instance.dispatchUIEvent(target, 'click');
            };
        } else if (isElementType(target, 'input')) {
            const form = target.form;
            const submit = form === null || form === undefined ? undefined : form.querySelector('input[type="submit"], button:not([type]), button[type="submit"]');
            if (submit) {
                return ()=>instance.dispatchUIEvent(submit, 'click');
            } else if (form && SubmitSingleInputOnEnter.includes(target.type) && form.querySelectorAll('input').length === 1) {
                return ()=>instance.dispatchUIEvent(form, 'submit');
            } else {
                return;
            }
        }
    }
    if (isEditable(target)) {
        const inputType = event.key === 'Enter' ? isContentEditable(target) && !instance.system.keyboard.modifiers.Shift ? 'insertParagraph' : 'insertLineBreak' : 'insertText';
        const inputData = event.key === 'Enter' ? '\n' : event.key;
        return ()=>input(instance, target, inputData, inputType);
    }
};
const ClickInputOnEnter = [
    'button',
    'color',
    'file',
    'image',
    'reset',
    'submit'
];
const SubmitSingleInputOnEnter = [
    'email',
    'month',
    'password',
    'search',
    'tel',
    'text',
    'url',
    'week'
];

behavior.keyup = (event, target, instance)=>{
    var _keyupBehavior_event_key;
    return (_keyupBehavior_event_key = keyupBehavior[event.key]) === null || _keyupBehavior_event_key === undefined ? undefined : _keyupBehavior_event_key.call(keyupBehavior, event, target, instance);
};
const keyupBehavior = {
    ' ': (event, target, instance)=>{
        if (isClickableInput(target)) {
            return ()=>instance.dispatchUIEvent(target, 'click');
        }
    }
};

behavior.paste = (event, target, instance)=>{
    if (isEditable(target)) {
        return ()=>{
            var _event_clipboardData;
            const insertData = (_event_clipboardData = event.clipboardData) === null || _event_clipboardData === undefined ? undefined : _event_clipboardData.getData('text');
            if (insertData) {
                input(instance, target, insertData, 'insertFromPaste');
            }
        };
    }
};

const eventMap = {
    auxclick: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    beforeinput: {
        EventType: 'InputEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    click: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    contextmenu: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    copy: {
        EventType: 'ClipboardEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    change: {
        EventType: 'Event',
        defaultInit: {
            bubbles: true,
            cancelable: false
        }
    },
    cut: {
        EventType: 'ClipboardEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    dblclick: {
        EventType: 'MouseEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    keydown: {
        EventType: 'KeyboardEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    keypress: {
        EventType: 'KeyboardEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    keyup: {
        EventType: 'KeyboardEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    paste: {
        EventType: 'ClipboardEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    input: {
        EventType: 'InputEvent',
        defaultInit: {
            bubbles: true,
            cancelable: false,
            composed: true
        }
    },
    mousedown: {
        EventType: 'MouseEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    mouseenter: {
        EventType: 'MouseEvent',
        defaultInit: {
            bubbles: false,
            cancelable: false,
            composed: true
        }
    },
    mouseleave: {
        EventType: 'MouseEvent',
        defaultInit: {
            bubbles: false,
            cancelable: false,
            composed: true
        }
    },
    mousemove: {
        EventType: 'MouseEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    mouseout: {
        EventType: 'MouseEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    mouseover: {
        EventType: 'MouseEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    mouseup: {
        EventType: 'MouseEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    pointerover: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    pointerenter: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: false,
            cancelable: false
        }
    },
    pointerdown: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    pointermove: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    pointerup: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    pointercancel: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: true,
            cancelable: false,
            composed: true
        }
    },
    pointerout: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: true,
            cancelable: true,
            composed: true
        }
    },
    pointerleave: {
        EventType: 'PointerEvent',
        defaultInit: {
            bubbles: false,
            cancelable: false
        }
    },
    submit: {
        EventType: 'Event',
        defaultInit: {
            bubbles: true,
            cancelable: true
        }
    }
};
function getEventClass(type) {
    return eventMap[type].EventType;
}
const mouseEvents = [
    'MouseEvent',
    'PointerEvent'
];
function isMouseEvent(type) {
    return mouseEvents.includes(getEventClass(type));
}
function isKeyboardEvent(type) {
    return getEventClass(type) === 'KeyboardEvent';
}

const eventInitializer = {
    ClipboardEvent: [
        initClipboardEvent
    ],
    Event: [],
    InputEvent: [
        initUIEvent,
        initInputEvent
    ],
    MouseEvent: [
        initUIEvent,
        initUIEventModififiers,
        initMouseEvent
    ],
    PointerEvent: [
        initUIEvent,
        initUIEventModififiers,
        initMouseEvent,
        initPointerEvent
    ],
    KeyboardEvent: [
        initUIEvent,
        initUIEventModififiers,
        initKeyboardEvent
    ]
};
function createEvent(type, target, init) {
    const window = getWindow(target);
    const { EventType, defaultInit } = eventMap[type];
    const event = new (getEventConstructors(window))[EventType](type, defaultInit);
    eventInitializer[EventType].forEach((f)=>f(event, init !== null && init !== undefined ? init : {}));
    return event;
}
/* istanbul ignore next */ function getEventConstructors(window) {
    var _window_Event;
    /* eslint-disable @typescript-eslint/no-unnecessary-condition, @typescript-eslint/no-extraneous-class */ const Event = (_window_Event = window.Event) !== null && _window_Event !== undefined ? _window_Event : class Event {
    };
    var _window_AnimationEvent;
    const AnimationEvent = (_window_AnimationEvent = window.AnimationEvent) !== null && _window_AnimationEvent !== undefined ? _window_AnimationEvent : class AnimationEvent extends Event {
    };
    var _window_ClipboardEvent;
    const ClipboardEvent = (_window_ClipboardEvent = window.ClipboardEvent) !== null && _window_ClipboardEvent !== undefined ? _window_ClipboardEvent : class ClipboardEvent extends Event {
    };
    var _window_PopStateEvent;
    const PopStateEvent = (_window_PopStateEvent = window.PopStateEvent) !== null && _window_PopStateEvent !== undefined ? _window_PopStateEvent : class PopStateEvent extends Event {
    };
    var _window_ProgressEvent;
    const ProgressEvent = (_window_ProgressEvent = window.ProgressEvent) !== null && _window_ProgressEvent !== undefined ? _window_ProgressEvent : class ProgressEvent extends Event {
    };
    var _window_TransitionEvent;
    const TransitionEvent = (_window_TransitionEvent = window.TransitionEvent) !== null && _window_TransitionEvent !== undefined ? _window_TransitionEvent : class TransitionEvent extends Event {
    };
    var _window_UIEvent;
    const UIEvent = (_window_UIEvent = window.UIEvent) !== null && _window_UIEvent !== undefined ? _window_UIEvent : class UIEvent extends Event {
    };
    var _window_CompositionEvent;
    const CompositionEvent = (_window_CompositionEvent = window.CompositionEvent) !== null && _window_CompositionEvent !== undefined ? _window_CompositionEvent : class CompositionEvent extends UIEvent {
    };
    var _window_FocusEvent;
    const FocusEvent = (_window_FocusEvent = window.FocusEvent) !== null && _window_FocusEvent !== undefined ? _window_FocusEvent : class FocusEvent extends UIEvent {
    };
    var _window_InputEvent;
    const InputEvent = (_window_InputEvent = window.InputEvent) !== null && _window_InputEvent !== undefined ? _window_InputEvent : class InputEvent extends UIEvent {
    };
    var _window_KeyboardEvent;
    const KeyboardEvent = (_window_KeyboardEvent = window.KeyboardEvent) !== null && _window_KeyboardEvent !== undefined ? _window_KeyboardEvent : class KeyboardEvent extends UIEvent {
    };
    var _window_MouseEvent;
    const MouseEvent = (_window_MouseEvent = window.MouseEvent) !== null && _window_MouseEvent !== undefined ? _window_MouseEvent : class MouseEvent extends UIEvent {
    };
    var _window_DragEvent;
    const DragEvent = (_window_DragEvent = window.DragEvent) !== null && _window_DragEvent !== undefined ? _window_DragEvent : class DragEvent extends MouseEvent {
    };
    var _window_PointerEvent;
    const PointerEvent = (_window_PointerEvent = window.PointerEvent) !== null && _window_PointerEvent !== undefined ? _window_PointerEvent : class PointerEvent extends MouseEvent {
    };
    var _window_TouchEvent;
    const TouchEvent = (_window_TouchEvent = window.TouchEvent) !== null && _window_TouchEvent !== undefined ? _window_TouchEvent : class TouchEvent extends UIEvent {
    };
    /* eslint-enable @typescript-eslint/no-unnecessary-condition, @typescript-eslint/no-extraneous-class */ return {
        Event,
        AnimationEvent,
        ClipboardEvent,
        PopStateEvent,
        ProgressEvent,
        TransitionEvent,
        UIEvent,
        CompositionEvent,
        FocusEvent,
        InputEvent,
        KeyboardEvent,
        MouseEvent,
        DragEvent,
        PointerEvent,
        TouchEvent
    };
}
function assignProps(obj, props) {
    for (const [key, value] of Object.entries(props)){
        Object.defineProperty(obj, key, {
            get: ()=>value !== null && value !== undefined ? value : null
        });
    }
}
function sanitizeNumber(n) {
    return Number(n !== null && n !== undefined ? n : 0);
}
function initClipboardEvent(event, { clipboardData }) {
    assignProps(event, {
        clipboardData
    });
}
function initInputEvent(event, { data, inputType, isComposing }) {
    assignProps(event, {
        data,
        isComposing: Boolean(isComposing),
        inputType: String(inputType)
    });
}
function initUIEvent(event, { view, detail }) {
    assignProps(event, {
        view,
        detail: sanitizeNumber(detail !== null && detail !== undefined ? detail : 0)
    });
}
function initUIEventModififiers(event, { altKey, ctrlKey, metaKey, shiftKey, modifierAltGraph, modifierCapsLock, modifierFn, modifierFnLock, modifierNumLock, modifierScrollLock, modifierSymbol, modifierSymbolLock }) {
    assignProps(event, {
        altKey: Boolean(altKey),
        ctrlKey: Boolean(ctrlKey),
        metaKey: Boolean(metaKey),
        shiftKey: Boolean(shiftKey),
        getModifierState (k) {
            return Boolean({
                Alt: altKey,
                AltGraph: modifierAltGraph,
                CapsLock: modifierCapsLock,
                Control: ctrlKey,
                Fn: modifierFn,
                FnLock: modifierFnLock,
                Meta: metaKey,
                NumLock: modifierNumLock,
                ScrollLock: modifierScrollLock,
                Shift: shiftKey,
                Symbol: modifierSymbol,
                SymbolLock: modifierSymbolLock
            }[k]);
        }
    });
}
function initKeyboardEvent(event, { key, code, location, repeat, isComposing, charCode }) {
    assignProps(event, {
        key: String(key),
        code: String(code),
        location: sanitizeNumber(location),
        repeat: Boolean(repeat),
        isComposing: Boolean(isComposing),
        charCode
    });
}
function initMouseEvent(event, { x, y, screenX, screenY, clientX = x, clientY = y, button, buttons, relatedTarget }) {
    assignProps(event, {
        screenX: sanitizeNumber(screenX),
        screenY: sanitizeNumber(screenY),
        clientX: sanitizeNumber(clientX),
        x: sanitizeNumber(clientX),
        clientY: sanitizeNumber(clientY),
        y: sanitizeNumber(clientY),
        button: sanitizeNumber(button),
        buttons: sanitizeNumber(buttons),
        relatedTarget
    });
}
function initPointerEvent(event, { pointerId, width, height, pressure, tangentialPressure, tiltX, tiltY, twist, pointerType, isPrimary }) {
    assignProps(event, {
        pointerId: sanitizeNumber(pointerId),
        width: sanitizeNumber(width),
        height: sanitizeNumber(height),
        pressure: sanitizeNumber(pressure),
        tangentialPressure: sanitizeNumber(tangentialPressure),
        tiltX: sanitizeNumber(tiltX),
        tiltY: sanitizeNumber(tiltY),
        twist: sanitizeNumber(twist),
        pointerType: String(pointerType),
        isPrimary: Boolean(isPrimary)
    });
}

function dispatchUIEvent(target, type, init, preventDefault = false) {
    if (isMouseEvent(type) || isKeyboardEvent(type)) {
        init = {
            ...init,
            ...this.system.getUIEventModifiers()
        };
    }
    const event = createEvent(type, target, init);
    return dispatchEvent.call(this, target, event, preventDefault);
}
function dispatchEvent(target, event, preventDefault = false) {
    var _behavior_type;
    const type = event.type;
    const behaviorImplementation = preventDefault ? ()=>{} : (_behavior_type = behavior[type]) === null || _behavior_type === undefined ? undefined : _behavior_type.call(behavior, event, target, this);
    if (behaviorImplementation) {
        event.preventDefault();
        let defaultPrevented = false;
        Object.defineProperty(event, 'defaultPrevented', {
            get: ()=>defaultPrevented
        });
        Object.defineProperty(event, 'preventDefault', {
            value: ()=>{
                defaultPrevented = event.cancelable;
            }
        });
        wrapEvent(()=>target.dispatchEvent(event));
        if (!defaultPrevented) {
            behaviorImplementation();
        }
        return !defaultPrevented;
    }
    return wrapEvent(()=>target.dispatchEvent(event));
}
function dispatchDOMEvent(target, type, init) {
    const event = createEvent(type, target, init);
    wrapEvent(()=>target.dispatchEvent(event));
}

const Interceptor = Symbol('Interceptor for programmatical calls');
function prepareInterceptor(element, propName, interceptorImpl) {
    const prototypeDescriptor = Object.getOwnPropertyDescriptor(element.constructor.prototype, propName);
    const objectDescriptor = Object.getOwnPropertyDescriptor(element, propName);
    const target = (prototypeDescriptor === null || prototypeDescriptor === undefined ? undefined : prototypeDescriptor.set) ? 'set' : 'value';
    /* istanbul ignore if */ if (typeof (prototypeDescriptor === null || prototypeDescriptor === undefined ? undefined : prototypeDescriptor[target]) !== 'function' || prototypeDescriptor[target][Interceptor]) {
        throw new Error(`Element ${element.tagName} does not implement "${String(propName)}".`);
    }
    function intercept(...args) {
        const { applyNative = false, realArgs, then } = interceptorImpl.call(this, ...args);
        const realFunc = (!applyNative && objectDescriptor || prototypeDescriptor)[target];
        if (target === 'set') {
            realFunc.call(this, realArgs);
        } else {
            realFunc.call(this, ...realArgs);
        }
        then === null || then === undefined ? undefined : then();
    }
    intercept[Interceptor] = Interceptor;
    Object.defineProperty(element, propName, {
        ...objectDescriptor !== null && objectDescriptor !== undefined ? objectDescriptor : prototypeDescriptor,
        [target]: intercept
    });
}
function prepareValueInterceptor(element) {
    prepareInterceptor(element, 'value', function interceptorImpl(v) {
        const isUI = isUIValue(v);
        if (isUI) {
            startTrackValue(this);
        }
        return {
            applyNative: !!isUI,
            realArgs: sanitizeValue(this, v),
            then: isUI ? undefined : ()=>trackOrSetValue(this, String(v))
        };
    });
}
function sanitizeValue(element, v) {
    // Workaround for JSDOM
    if (isElementType(element, 'input', {
        type: 'number'
    }) && String(v) !== '' && !Number.isNaN(Number(v))) {
        // Setting value to "1." results in `null` in JSDOM
        return String(Number(v));
    }
    return String(v);
}
function prepareSelectionInterceptor(element) {
    prepareInterceptor(element, 'setSelectionRange', function interceptorImpl(start, ...others) {
        const isUI = isUISelectionStart(start);
        return {
            applyNative: !!isUI,
            realArgs: [
                Number(start),
                ...others
            ],
            then: ()=>isUI ? undefined : setUISelectionClean(element)
        };
    });
    prepareInterceptor(element, 'selectionStart', function interceptorImpl(v) {
        return {
            realArgs: v,
            then: ()=>setUISelectionClean(element)
        };
    });
    prepareInterceptor(element, 'selectionEnd', function interceptorImpl(v) {
        return {
            realArgs: v,
            then: ()=>setUISelectionClean(element)
        };
    });
    prepareInterceptor(element, 'select', function interceptorImpl() {
        return {
            realArgs: [],
            then: ()=>setUISelectionRaw(element, {
                    anchorOffset: 0,
                    focusOffset: getUIValue(element).length
                })
        };
    });
}
function prepareRangeTextInterceptor(element) {
    prepareInterceptor(element, 'setRangeText', function interceptorImpl(...realArgs) {
        return {
            realArgs,
            then: ()=>{
                setUIValueClean(element);
                setUISelectionClean(element);
            }
        };
    });
}

const isPrepared = Symbol('Node prepared with document state workarounds');
function prepareDocument(document) {
    if (document[isPrepared]) {
        return;
    }
    document.addEventListener('focus', (e)=>{
        const el = e.target;
        prepareElement(el);
    }, {
        capture: true,
        passive: true
    });
    // Our test environment defaults to `document.body` as `activeElement`.
    // In other environments this might be `null` when preparing.
    // istanbul ignore else
    if (document.activeElement) {
        prepareElement(document.activeElement);
    }
    document.addEventListener('blur', (e)=>{
        const el = e.target;
        const initialValue = getInitialValue(el);
        if (initialValue !== undefined) {
            if (el.value !== initialValue) {
                dispatchDOMEvent(el, 'change');
            }
            clearInitialValue(el);
        }
    }, {
        capture: true,
        passive: true
    });
    document[isPrepared] = isPrepared;
}
function prepareElement(el) {
    if (el[isPrepared]) {
        return;
    }
    if (isElementType(el, [
        'input',
        'textarea'
    ])) {
        prepareValueInterceptor(el);
        prepareSelectionInterceptor(el);
        prepareRangeTextInterceptor(el);
    }
    el[isPrepared] = isPrepared;
}

function getDocumentFromNode(el) {
    return isDocument(el) ? el : el.ownerDocument;
}
function isDocument(node) {
    return node.nodeType === 9;
}

function wait(config) {
    const delay = config.delay;
    if (typeof delay !== 'number') {
        return;
    }
    return Promise.all([
        new Promise((resolve)=>globalThis.setTimeout(()=>resolve(), delay)),
        config.advanceTimers(delay)
    ]);
}

function _define_property$6(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
var DOM_KEY_LOCATION;
(function(DOM_KEY_LOCATION) {
    DOM_KEY_LOCATION[DOM_KEY_LOCATION["STANDARD"] = 0] = "STANDARD";
    DOM_KEY_LOCATION[DOM_KEY_LOCATION["LEFT"] = 1] = "LEFT";
    DOM_KEY_LOCATION[DOM_KEY_LOCATION["RIGHT"] = 2] = "RIGHT";
    DOM_KEY_LOCATION[DOM_KEY_LOCATION["NUMPAD"] = 3] = "NUMPAD";
})(DOM_KEY_LOCATION || (DOM_KEY_LOCATION = {}));
const modifierKeys = [
    'Alt',
    'AltGraph',
    'Control',
    'Fn',
    'Meta',
    'Shift',
    'Symbol'
];
function isModifierKey(key) {
    return modifierKeys.includes(key);
}
const modifierLocks = [
    'CapsLock',
    'FnLock',
    'NumLock',
    'ScrollLock',
    'SymbolLock'
];
function isModifierLock(key) {
    return modifierLocks.includes(key);
}
class KeyboardHost {
    isKeyPressed(keyDef) {
        return !!this.pressed[String(keyDef.code)];
    }
    getPressedKeys() {
        return Object.values(this.pressed).map((p)=>p.keyDef);
    }
    /** Press a key */ async keydown(instance, keyDef) {
        var // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
        _this_pressed, _code, _this_pressed_code;
        const key = String(keyDef.key);
        const code = String(keyDef.code);
        const target = getActiveElementOrBody(instance.config.document);
        this.setKeydownTarget(target);
        var _;
        (_ = (_this_pressed = this.pressed)[_code = code]) !== null && _ !== undefined ? _ : _this_pressed[_code] = {
            keyDef,
            unpreventedDefault: false
        };
        if (isModifierKey(key)) {
            this.modifiers[key] = true;
        }
        const unprevented = instance.dispatchUIEvent(target, 'keydown', {
            key,
            code
        });
        if (isModifierLock(key) && !this.modifiers[key]) {
            this.modifiers[key] = true;
            this.modifierLockStart[key] = true;
        }
        (_this_pressed_code = this.pressed[code]).unpreventedDefault || (_this_pressed_code.unpreventedDefault = unprevented);
        if (unprevented && this.hasKeyPress(key)) {
            instance.dispatchUIEvent(getActiveElementOrBody(instance.config.document), 'keypress', {
                key,
                code,
                charCode: keyDef.key === 'Enter' ? 13 : String(keyDef.key).charCodeAt(0)
            });
        }
    }
    /** Release a key */ async keyup(instance, keyDef) {
        const key = String(keyDef.key);
        const code = String(keyDef.code);
        const unprevented = this.pressed[code].unpreventedDefault;
        // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
        delete this.pressed[code];
        if (isModifierKey(key) && !Object.values(this.pressed).find((p)=>p.keyDef.key === key)) {
            this.modifiers[key] = false;
        }
        instance.dispatchUIEvent(getActiveElementOrBody(instance.config.document), 'keyup', {
            key,
            code
        }, !unprevented);
        if (isModifierLock(key) && this.modifiers[key]) {
            if (this.modifierLockStart[key]) {
                this.modifierLockStart[key] = false;
            } else {
                this.modifiers[key] = false;
            }
        }
    }
    setKeydownTarget(target) {
        if (target !== this.lastKeydownTarget) {
            this.carryChar = '';
        }
        this.lastKeydownTarget = target;
    }
    hasKeyPress(key) {
        return (key.length === 1 || key === 'Enter') && !this.modifiers.Control && !this.modifiers.Alt;
    }
    constructor(system){
        _define_property$6(this, "system", undefined);
        _define_property$6(this, "modifiers", {
            Alt: false,
            AltGraph: false,
            CapsLock: false,
            Control: false,
            Fn: false,
            FnLock: false,
            Meta: false,
            NumLock: false,
            ScrollLock: false,
            Shift: false,
            Symbol: false,
            SymbolLock: false
        });
        _define_property$6(this, "pressed", {});
        _define_property$6(this, "carryChar", '');
        _define_property$6(this, "lastKeydownTarget", undefined);
        _define_property$6(this, "modifierLockStart", {});
        this.system = system;
    }
}

/**
 * Mapping for a default US-104-QWERTY keyboard
 */ const defaultKeyMap$1 = [
    // alphanumeric keys
    ...'0123456789'.split('').map((c)=>({
            code: `Digit${c}`,
            key: c
        })),
    ...')!@#$%^&*('.split('').map((c, i)=>({
            code: `Digit${i}`,
            key: c,
            shiftKey: true
        })),
    ...'abcdefghijklmnopqrstuvwxyz'.split('').map((c)=>({
            code: `Key${c.toUpperCase()}`,
            key: c
        })),
    ...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').map((c)=>({
            code: `Key${c}`,
            key: c,
            shiftKey: true
        })),
    // alphanumeric block - functional
    {
        code: 'Space',
        key: ' '
    },
    {
        code: 'AltLeft',
        key: 'Alt',
        location: DOM_KEY_LOCATION.LEFT
    },
    {
        code: 'AltRight',
        key: 'Alt',
        location: DOM_KEY_LOCATION.RIGHT
    },
    {
        code: 'ShiftLeft',
        key: 'Shift',
        location: DOM_KEY_LOCATION.LEFT
    },
    {
        code: 'ShiftRight',
        key: 'Shift',
        location: DOM_KEY_LOCATION.RIGHT
    },
    {
        code: 'ControlLeft',
        key: 'Control',
        location: DOM_KEY_LOCATION.LEFT
    },
    {
        code: 'ControlRight',
        key: 'Control',
        location: DOM_KEY_LOCATION.RIGHT
    },
    {
        code: 'MetaLeft',
        key: 'Meta',
        location: DOM_KEY_LOCATION.LEFT
    },
    {
        code: 'MetaRight',
        key: 'Meta',
        location: DOM_KEY_LOCATION.RIGHT
    },
    {
        code: 'OSLeft',
        key: 'OS',
        location: DOM_KEY_LOCATION.LEFT
    },
    {
        code: 'OSRight',
        key: 'OS',
        location: DOM_KEY_LOCATION.RIGHT
    },
    {
        code: 'Tab',
        key: 'Tab'
    },
    {
        code: 'CapsLock',
        key: 'CapsLock'
    },
    {
        code: 'Backspace',
        key: 'Backspace'
    },
    {
        code: 'Enter',
        key: 'Enter'
    },
    // function
    {
        code: 'Escape',
        key: 'Escape'
    },
    // arrows
    {
        code: 'ArrowUp',
        key: 'ArrowUp'
    },
    {
        code: 'ArrowDown',
        key: 'ArrowDown'
    },
    {
        code: 'ArrowLeft',
        key: 'ArrowLeft'
    },
    {
        code: 'ArrowRight',
        key: 'ArrowRight'
    },
    // control pad
    {
        code: 'Home',
        key: 'Home'
    },
    {
        code: 'End',
        key: 'End'
    },
    {
        code: 'Delete',
        key: 'Delete'
    },
    {
        code: 'PageUp',
        key: 'PageUp'
    },
    {
        code: 'PageDown',
        key: 'PageDown'
    },
    // Special keys that are not part of a default US-layout but included for specific behavior
    {
        code: 'Fn',
        key: 'Fn'
    },
    {
        code: 'Symbol',
        key: 'Symbol'
    },
    {
        code: 'AltRight',
        key: 'AltGraph'
    }
];

const defaultKeyMap = [
    {
        name: 'MouseLeft',
        pointerType: 'mouse',
        button: 'primary'
    },
    {
        name: 'MouseRight',
        pointerType: 'mouse',
        button: 'secondary'
    },
    {
        name: 'MouseMiddle',
        pointerType: 'mouse',
        button: 'auxiliary'
    },
    {
        name: 'TouchA',
        pointerType: 'touch'
    },
    {
        name: 'TouchB',
        pointerType: 'touch'
    },
    {
        name: 'TouchC',
        pointerType: 'touch'
    }
];

function _define_property$5(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
class Buttons {
    getButtons() {
        let v = 0;
        for (const button of Object.keys(this.pressed)){
            // eslint-disable-next-line no-bitwise
            v |= 2 ** Number(button);
        }
        return v;
    }
    down(keyDef) {
        const button = getMouseButtonId(keyDef.button);
        if (button in this.pressed) {
            this.pressed[button].push(keyDef);
            return undefined;
        }
        this.pressed[button] = [
            keyDef
        ];
        return button;
    }
    up(keyDef) {
        const button = getMouseButtonId(keyDef.button);
        if (button in this.pressed) {
            this.pressed[button] = this.pressed[button].filter((k)=>k.name !== keyDef.name);
            if (this.pressed[button].length === 0) {
                // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
                delete this.pressed[button];
                return button;
            }
        }
        return undefined;
    }
    constructor(){
        _define_property$5(this, "pressed", {});
    }
}
const MouseButton = {
    primary: 0,
    secondary: 1,
    auxiliary: 2,
    back: 3,
    X1: 3,
    forward: 4,
    X2: 4
};
function getMouseButtonId(button = 0) {
    if (button in MouseButton) {
        return MouseButton[button];
    }
    return Number(button);
}
// On the `MouseEvent.button` property auxiliary and secondary button are flipped compared to `MouseEvent.buttons`.
const MouseButtonFlip = {
    1: 2,
    2: 1
};
function getMouseEventButton(button) {
    button = getMouseButtonId(button);
    if (button in MouseButtonFlip) {
        return MouseButtonFlip[button];
    }
    return button;
}

function _define_property$4(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
class Device {
    get countPressed() {
        return this.pressedKeys.size;
    }
    isPressed(keyDef) {
        return this.pressedKeys.has(keyDef.name);
    }
    addPressed(keyDef) {
        return this.pressedKeys.add(keyDef.name);
    }
    removePressed(keyDef) {
        return this.pressedKeys.delete(keyDef.name);
    }
    constructor(){
        _define_property$4(this, "pressedKeys", new Set());
    }
}

function getTreeDiff(a, b) {
    const treeA = [];
    for(let el = a; el; el = el.parentElement){
        treeA.push(el);
    }
    const treeB = [];
    for(let el = b; el; el = el.parentElement){
        treeB.push(el);
    }
    let i = 0;
    for(;; i++){
        if (i >= treeA.length || i >= treeB.length || treeA[treeA.length - 1 - i] !== treeB[treeB.length - 1 - i]) {
            break;
        }
    }
    return [
        treeA.slice(0, treeA.length - i),
        treeB.slice(0, treeB.length - i),
        treeB.slice(treeB.length - i)
    ];
}

function resolveCaretPosition({ target, node, offset }) {
    if (hasOwnSelection(target)) {
        return {
            node: target,
            offset: offset !== null && offset !== undefined ? offset : getUIValue(target).length
        };
    } else if (node) {
        return {
            node,
            offset: offset !== null && offset !== undefined ? offset : node.nodeType === 3 ? node.nodeValue.length : node.childNodes.length
        };
    }
    return findNodeAtTextOffset(target, offset);
}
function findNodeAtTextOffset(node, offset, isRoot = true) {
    // When clicking after the content the browser behavior can be complicated:
    // 1. If there is textContent after the last element child,
    // the cursor is moved there.
    // 2. If there is textContent in the last element child,
    // the browser moves the cursor to the last non-empty text node inside this element.
    // 3. Otherwise the cursor is moved to the end of the target.
    let i = offset === undefined ? node.childNodes.length - 1 : 0;
    const step = offset === undefined ? -1 : 1;
    while(offset === undefined ? i >= (isRoot ? Math.max(node.childNodes.length - 1, 0) : 0) : i <= node.childNodes.length){
        if (offset && i === node.childNodes.length) {
            throw new Error('The given offset is out of bounds.');
        }
        const c = node.childNodes.item(i);
        const text = String(c.textContent);
        if (text.length) {
            if (offset !== undefined && text.length < offset) {
                offset -= text.length;
            } else if (c.nodeType === 1) {
                return findNodeAtTextOffset(c, offset, false);
            } else {
                // The pre-commit hooks keeps changing this
                // See https://github.com/kentcdodds/kcd-scripts/issues/218
                /* istanbul ignore else */ // eslint-disable-next-line no-lonely-if
                if (c.nodeType === 3) {
                    return {
                        node: c,
                        offset: offset !== null && offset !== undefined ? offset : c.nodeValue.length
                    };
                }
            }
        }
        i += step;
    }
    return {
        node,
        offset: node.childNodes.length
    };
}

function setSelectionPerMouseDown({ document, target, clickCount, node, offset }) {
    if (hasNoSelection(target)) {
        return;
    }
    const targetHasOwnSelection = hasOwnSelection(target);
    // On non-input elements the text selection per multiple click
    // can extend beyond the target boundaries.
    // The exact mechanism what is considered in the same line is unclear.
    // Looks it might be every inline element.
    // TODO: Check what might be considered part of the same line of text.
    const text = String(targetHasOwnSelection ? getUIValue(target) : target.textContent);
    const [start, end] = node ? // which elements might be considered in the same line of text.
    // TODO: support expanding initial range on multiple clicks if node is given
    [
        offset,
        offset
    ] : getTextRange(text, offset, clickCount);
    // TODO: implement modifying selection per shift/ctrl+mouse
    if (targetHasOwnSelection) {
        setUISelection(target, {
            anchorOffset: start !== null && start !== undefined ? start : text.length,
            focusOffset: end !== null && end !== undefined ? end : text.length
        });
        return {
            node: target,
            start: start !== null && start !== undefined ? start : 0,
            end: end !== null && end !== undefined ? end : text.length
        };
    } else {
        const { node: startNode, offset: startOffset } = resolveCaretPosition({
            target,
            node,
            offset: start
        });
        const { node: endNode, offset: endOffset } = resolveCaretPosition({
            target,
            node,
            offset: end
        });
        const range = target.ownerDocument.createRange();
        try {
            range.setStart(startNode, startOffset);
            range.setEnd(endNode, endOffset);
        } catch (e) {
            throw new Error('The given offset is out of bounds.');
        }
        const selection = document.getSelection();
        selection === null || selection === undefined ? undefined : selection.removeAllRanges();
        selection === null || selection === undefined ? undefined : selection.addRange(range.cloneRange());
        return range;
    }
}
function getTextRange(text, pos, clickCount) {
    if (clickCount % 3 === 1 || text.length === 0) {
        return [
            pos,
            pos
        ];
    }
    const textPos = pos !== null && pos !== undefined ? pos : text.length;
    if (clickCount % 3 === 2) {
        return [
            textPos - text.substr(0, pos).match(/(\w+|\s+|\W)?$/)[0].length,
            pos === undefined ? pos : pos + text.substr(pos).match(/^(\w+|\s+|\W)?/)[0].length
        ];
    }
    // triple click
    return [
        textPos - text.substr(0, pos).match(/[^\r\n]*$/)[0].length,
        pos === undefined ? pos : pos + text.substr(pos).match(/^[^\r\n]*/)[0].length
    ];
}

function modifySelectionPerMouseMove(selectionRange, { document, target, node, offset }) {
    const selectionFocus = resolveCaretPosition({
        target,
        node,
        offset
    });
    if ('node' in selectionRange) {
        // When the mouse is dragged outside of an input/textarea,
        // the selection is extended to the beginning or end of the input
        // depending on pointer position.
        // TODO: extend selection according to pointer position
        /* istanbul ignore else */ if (selectionFocus.node === selectionRange.node) {
            const anchorOffset = selectionFocus.offset < selectionRange.start ? selectionRange.end : selectionRange.start;
            const focusOffset = selectionFocus.offset > selectionRange.end || selectionFocus.offset < selectionRange.start ? selectionFocus.offset : selectionRange.end;
            setUISelection(selectionRange.node, {
                anchorOffset,
                focusOffset
            });
        }
    } else {
        const range = selectionRange.cloneRange();
        const cmp = range.comparePoint(selectionFocus.node, selectionFocus.offset);
        if (cmp < 0) {
            range.setStart(selectionFocus.node, selectionFocus.offset);
        } else if (cmp > 0) {
            range.setEnd(selectionFocus.node, selectionFocus.offset);
        }
        const selection = document.getSelection();
        selection === null || selection === undefined ? undefined : selection.removeAllRanges();
        selection === null || selection === undefined ? undefined : selection.addRange(range.cloneRange());
    }
}

function isDifferentPointerPosition(positionA, positionB) {
    var _positionA_coords, _positionB_coords, _positionA_coords1, _positionB_coords1, _positionA_caret, _positionB_caret, _positionA_caret1, _positionB_caret1;
    return positionA.target !== positionB.target || ((_positionA_coords = positionA.coords) === null || _positionA_coords === undefined ? undefined : _positionA_coords.x) !== ((_positionB_coords = positionB.coords) === null || _positionB_coords === undefined ? undefined : _positionB_coords.y) || ((_positionA_coords1 = positionA.coords) === null || _positionA_coords1 === undefined ? undefined : _positionA_coords1.y) !== ((_positionB_coords1 = positionB.coords) === null || _positionB_coords1 === undefined ? undefined : _positionB_coords1.y) || ((_positionA_caret = positionA.caret) === null || _positionA_caret === undefined ? undefined : _positionA_caret.node) !== ((_positionB_caret = positionB.caret) === null || _positionB_caret === undefined ? undefined : _positionB_caret.node) || ((_positionA_caret1 = positionA.caret) === null || _positionA_caret1 === undefined ? undefined : _positionA_caret1.offset) !== ((_positionB_caret1 = positionB.caret) === null || _positionB_caret1 === undefined ? undefined : _positionB_caret1.offset);
}

function _define_property$3(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
/**
 * This object is the single "virtual" mouse that might be controlled by multiple different pointer devices.
 */ class Mouse {
    move(instance, position) {
        const prevPosition = this.position;
        const prevTarget = this.getTarget(instance);
        this.position = position;
        if (!isDifferentPointerPosition(prevPosition, position)) {
            return;
        }
        const nextTarget = this.getTarget(instance);
        const init = this.getEventInit('mousemove');
        const [leave, enter] = getTreeDiff(prevTarget, nextTarget);
        return {
            leave: ()=>{
                if (prevTarget !== nextTarget) {
                    instance.dispatchUIEvent(prevTarget, 'mouseout', init);
                    leave.forEach((el)=>instance.dispatchUIEvent(el, 'mouseleave', init));
                }
            },
            enter: ()=>{
                if (prevTarget !== nextTarget) {
                    instance.dispatchUIEvent(nextTarget, 'mouseover', init);
                    enter.forEach((el)=>instance.dispatchUIEvent(el, 'mouseenter', init));
                }
            },
            move: ()=>{
                instance.dispatchUIEvent(nextTarget, 'mousemove', init);
                this.modifySelecting(instance);
            }
        };
    }
    down(instance, keyDef, pointer) {
        const button = this.buttons.down(keyDef);
        if (button === undefined) {
            return;
        }
        const target = this.getTarget(instance);
        this.buttonDownTarget[button] = target;
        const disabled = isDisabled(target);
        const init = this.getEventInit('mousedown', keyDef.button);
        if (disabled || instance.dispatchUIEvent(target, 'mousedown', init)) {
            this.startSelecting(instance, init.detail);
            focusElement(target);
        }
        if (!disabled && getMouseEventButton(keyDef.button) === 2) {
            instance.dispatchUIEvent(target, 'contextmenu', this.getEventInit('contextmenu', keyDef.button, pointer));
        }
    }
    up(instance, keyDef, pointer) {
        const button = this.buttons.up(keyDef);
        if (button === undefined) {
            return;
        }
        const target = this.getTarget(instance);
        if (!isDisabled(target)) {
            instance.dispatchUIEvent(target, 'mouseup', this.getEventInit('mouseup', keyDef.button));
            this.endSelecting();
            const clickTarget = getTreeDiff(this.buttonDownTarget[button], target)[2][0];
            if (clickTarget) {
                const init = this.getEventInit('click', keyDef.button, pointer);
                if (init.detail) {
                    instance.dispatchUIEvent(clickTarget, init.button === 0 ? 'click' : 'auxclick', init);
                    if (init.button === 0 && init.detail === 2) {
                        instance.dispatchUIEvent(clickTarget, 'dblclick', {
                            ...this.getEventInit('dblclick', keyDef.button),
                            detail: init.detail
                        });
                    }
                }
            }
        }
    }
    resetClickCount() {
        this.clickCount.reset();
    }
    getEventInit(type, button, pointer) {
        const init = {
            ...this.position.coords
        };
        if (pointer) {
            init.pointerId = pointer.pointerId;
            init.pointerType = pointer.pointerType;
            init.isPrimary = pointer.isPrimary;
        }
        init.button = getMouseEventButton(button);
        init.buttons = this.buttons.getButtons();
        if (type === 'mousedown') {
            init.detail = this.clickCount.getOnDown(init.button);
        } else if (type === 'mouseup') {
            init.detail = this.clickCount.getOnUp(init.button);
        } else if (type === 'click' || type === 'auxclick') {
            init.detail = this.clickCount.incOnClick(init.button);
        }
        return init;
    }
    getTarget(instance) {
        var _this_position_target;
        return (_this_position_target = this.position.target) !== null && _this_position_target !== undefined ? _this_position_target : instance.config.document.body;
    }
    startSelecting(instance, clickCount) {
        var _this_position_caret, _this_position_caret1;
        // TODO: support extending range (shift)
        this.selecting = setSelectionPerMouseDown({
            document: instance.config.document,
            target: this.getTarget(instance),
            node: (_this_position_caret = this.position.caret) === null || _this_position_caret === undefined ? undefined : _this_position_caret.node,
            offset: (_this_position_caret1 = this.position.caret) === null || _this_position_caret1 === undefined ? undefined : _this_position_caret1.offset,
            clickCount
        });
    }
    modifySelecting(instance) {
        var _this_position_caret, _this_position_caret1;
        if (!this.selecting) {
            return;
        }
        modifySelectionPerMouseMove(this.selecting, {
            document: instance.config.document,
            target: this.getTarget(instance),
            node: (_this_position_caret = this.position.caret) === null || _this_position_caret === undefined ? undefined : _this_position_caret.node,
            offset: (_this_position_caret1 = this.position.caret) === null || _this_position_caret1 === undefined ? undefined : _this_position_caret1.offset
        });
    }
    endSelecting() {
        this.selecting = undefined;
    }
    constructor(){
        _define_property$3(this, "position", {});
        _define_property$3(this, "buttons", new Buttons());
        _define_property$3(this, "selecting", undefined);
        _define_property$3(this, "buttonDownTarget", {});
        // According to spec the `detail` on click events should be the number
        // of *consecutive* clicks with a specific button.
        // On `mousedown` and `mouseup` it should be this number increased by one.
        // But the browsers don't implement it this way.
        // If another button is pressed,
        //   in Webkit: the `mouseup` on the previously pressed button has `detail: 0` and no `click`/`auxclick`.
        //   in Gecko: the `mouseup` and click events have the same detail as the `mousedown`.
        // If there is a delay while a button is pressed,
        // the `mouseup` and `click` are normal, but a following `mousedown` starts a new click count.
        // We'll follow the minimal implementation of Webkit.
        _define_property$3(this, "clickCount", new class {
            incOnClick(button) {
                const current = this.down[button] === undefined ? undefined : Number(this.down[button]) + 1;
                this.count = this.count[button] === undefined ? {} : {
                    [button]: Number(this.count[button]) + 1
                };
                return current;
            }
            getOnDown(button) {
                var _this_count_button;
                this.down = {
                    [button]: (_this_count_button = this.count[button]) !== null && _this_count_button !== undefined ? _this_count_button : 0
                };
                var _this_count_button1;
                this.count = {
                    [button]: (_this_count_button1 = this.count[button]) !== null && _this_count_button1 !== undefined ? _this_count_button1 : 0
                };
                return Number(this.count[button]) + 1;
            }
            getOnUp(button) {
                return this.down[button] === undefined ? undefined : Number(this.down[button]) + 1;
            }
            reset() {
                this.count = {};
            }
            constructor(){
                _define_property$3(this, "down", {});
                _define_property$3(this, "count", {});
            }
        }());
    }
}

function hasPointerEvents(instance, element) {
    var _checkPointerEvents;
    return ((_checkPointerEvents = checkPointerEvents(instance, element)) === null || _checkPointerEvents === undefined ? undefined : _checkPointerEvents.pointerEvents) !== 'none';
}
function closestPointerEventsDeclaration(element) {
    const window = getWindow(element);
    for(let el = element, tree = []; el === null || el === undefined ? undefined : el.ownerDocument; el = el.parentElement){
        tree.push(el);
        const pointerEvents = window.getComputedStyle(el).pointerEvents;
        if (pointerEvents && ![
            'inherit',
            'unset'
        ].includes(pointerEvents)) {
            return {
                pointerEvents,
                tree
            };
        }
    }
    return undefined;
}
const PointerEventsCheck = Symbol('Last check for pointer-events');
function checkPointerEvents(instance, element) {
    const lastCheck = element[PointerEventsCheck];
    const needsCheck = instance.config.pointerEventsCheck !== PointerEventsCheckLevel.Never && (!lastCheck || hasBitFlag(instance.config.pointerEventsCheck, PointerEventsCheckLevel.EachApiCall) && lastCheck[ApiLevel.Call] !== getLevelRef(instance, ApiLevel.Call) || hasBitFlag(instance.config.pointerEventsCheck, PointerEventsCheckLevel.EachTrigger) && lastCheck[ApiLevel.Trigger] !== getLevelRef(instance, ApiLevel.Trigger));
    if (!needsCheck) {
        return lastCheck === null || lastCheck === undefined ? undefined : lastCheck.result;
    }
    const declaration = closestPointerEventsDeclaration(element);
    element[PointerEventsCheck] = {
        [ApiLevel.Call]: getLevelRef(instance, ApiLevel.Call),
        [ApiLevel.Trigger]: getLevelRef(instance, ApiLevel.Trigger),
        result: declaration
    };
    return declaration;
}
function assertPointerEvents(instance, element) {
    const declaration = checkPointerEvents(instance, element);
    if ((declaration === null || declaration === undefined ? undefined : declaration.pointerEvents) === 'none') {
        throw new Error([
            `Unable to perform pointer interaction as the element ${declaration.tree.length > 1 ? 'inherits' : 'has'} \`pointer-events: none\`:`,
            '',
            printTree(declaration.tree)
        ].join('\n'));
    }
}
function printTree(tree) {
    return tree.reverse().map((el, i)=>[
            ''.padEnd(i),
            el.tagName,
            el.id && `#${el.id}`,
            el.hasAttribute('data-testid') && `(testId=${el.getAttribute('data-testid')})`,
            getLabelDescr(el),
            tree.length > 1 && i === 0 && '  <-- This element declared `pointer-events: none`',
            tree.length > 1 && i === tree.length - 1 && '  <-- Asserted pointer events here'
        ].filter(Boolean).join('')).join('\n');
}
function getLabelDescr(element) {
    var _element_labels;
    let label;
    if (element.hasAttribute('aria-label')) {
        label = element.getAttribute('aria-label');
    } else if (element.hasAttribute('aria-labelledby')) {
        var _element_ownerDocument_getElementById_textContent, _element_ownerDocument_getElementById;
        label = (_element_ownerDocument_getElementById = element.ownerDocument.getElementById(element.getAttribute('aria-labelledby'))) === null || _element_ownerDocument_getElementById === undefined ? undefined : (_element_ownerDocument_getElementById_textContent = _element_ownerDocument_getElementById.textContent) === null || _element_ownerDocument_getElementById_textContent === undefined ? undefined : _element_ownerDocument_getElementById_textContent.trim();
    } else if (isElementType(element, [
        'button',
        'input',
        'meter',
        'output',
        'progress',
        'select',
        'textarea'
    ]) && ((_element_labels = element.labels) === null || _element_labels === undefined ? undefined : _element_labels.length)) {
        label = Array.from(element.labels).map((el)=>{
            var _el_textContent;
            return (_el_textContent = el.textContent) === null || _el_textContent === undefined ? undefined : _el_textContent.trim();
        }).join('|');
    } else if (isElementType(element, 'button')) {
        var _element_textContent;
        label = (_element_textContent = element.textContent) === null || _element_textContent === undefined ? undefined : _element_textContent.trim();
    }
    label = label === null || label === undefined ? undefined : label.replace(/\n/g, '  ');
    if (Number(label === null || label === undefined ? undefined : label.length) > 30) {
        label = `${label === null || label === undefined ? undefined : label.substring(0, 29)}…`;
    }
    return label ? `(label=${label})` : '';
}
// With the eslint rule and prettier the bitwise operation isn't nice to read
function hasBitFlag(conf, flag) {
    // eslint-disable-next-line no-bitwise
    return (conf & flag) > 0;
}

function _define_property$2(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
class Pointer {
    init(instance, position) {
        this.position = position;
        const target = this.getTarget(instance);
        const [, enter] = getTreeDiff(null, target);
        const init = this.getEventInit();
        assertPointerEvents(instance, target);
        instance.dispatchUIEvent(target, 'pointerover', init);
        enter.forEach((el)=>instance.dispatchUIEvent(el, 'pointerenter', init));
        return this;
    }
    move(instance, position) {
        const prevPosition = this.position;
        const prevTarget = this.getTarget(instance);
        this.position = position;
        if (!isDifferentPointerPosition(prevPosition, position)) {
            return;
        }
        const nextTarget = this.getTarget(instance);
        const init = this.getEventInit();
        const [leave, enter] = getTreeDiff(prevTarget, nextTarget);
        return {
            leave: ()=>{
                if (hasPointerEvents(instance, prevTarget)) {
                    if (prevTarget !== nextTarget) {
                        instance.dispatchUIEvent(prevTarget, 'pointerout', init);
                        leave.forEach((el)=>instance.dispatchUIEvent(el, 'pointerleave', init));
                    }
                }
            },
            enter: ()=>{
                assertPointerEvents(instance, nextTarget);
                if (prevTarget !== nextTarget) {
                    instance.dispatchUIEvent(nextTarget, 'pointerover', init);
                    enter.forEach((el)=>instance.dispatchUIEvent(el, 'pointerenter', init));
                }
            },
            move: ()=>{
                instance.dispatchUIEvent(nextTarget, 'pointermove', init);
            }
        };
    }
    down(instance, _keyDef) {
        if (this.isDown) {
            return;
        }
        const target = this.getTarget(instance);
        assertPointerEvents(instance, target);
        this.isDown = true;
        this.isPrevented = !instance.dispatchUIEvent(target, 'pointerdown', this.getEventInit());
    }
    up(instance, _keyDef) {
        if (!this.isDown) {
            return;
        }
        const target = this.getTarget(instance);
        assertPointerEvents(instance, target);
        this.isDown = false;
        instance.dispatchUIEvent(target, 'pointerup', this.getEventInit());
    }
    release(instance) {
        const target = this.getTarget(instance);
        const [leave] = getTreeDiff(target, null);
        const init = this.getEventInit();
        // Currently there is no PointerEventsCheckLevel that would
        // make this check not use the *asserted* cached value from `up`.
        /* istanbul ignore else */ if (hasPointerEvents(instance, target)) {
            instance.dispatchUIEvent(target, 'pointerout', init);
            leave.forEach((el)=>instance.dispatchUIEvent(el, 'pointerleave', init));
        }
        this.isCancelled = true;
    }
    getTarget(instance) {
        var _this_position_target;
        return (_this_position_target = this.position.target) !== null && _this_position_target !== undefined ? _this_position_target : instance.config.document.body;
    }
    getEventInit() {
        return {
            ...this.position.coords,
            pointerId: this.pointerId,
            pointerType: this.pointerType,
            isPrimary: this.isPrimary
        };
    }
    constructor({ pointerId, pointerType, isPrimary }){
        _define_property$2(this, "pointerId", undefined);
        _define_property$2(this, "pointerType", undefined);
        _define_property$2(this, "isPrimary", undefined);
        _define_property$2(this, "isMultitouch", false);
        _define_property$2(this, "isCancelled", false);
        _define_property$2(this, "isDown", false);
        _define_property$2(this, "isPrevented", false);
        _define_property$2(this, "position", {});
        this.pointerId = pointerId;
        this.pointerType = pointerType;
        this.isPrimary = isPrimary;
        this.isMultitouch = !isPrimary;
    }
}

function _define_property$1(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
class PointerHost {
    isKeyPressed(keyDef) {
        return this.devices.get(keyDef.pointerType).isPressed(keyDef);
    }
    async press(instance, keyDef, position) {
        const pointerName = this.getPointerName(keyDef);
        const pointer = keyDef.pointerType === 'touch' ? this.pointers.new(pointerName, keyDef).init(instance, position) : this.pointers.get(pointerName);
        // TODO: deprecate the following implicit setting of position
        pointer.position = position;
        if (pointer.pointerType !== 'touch') {
            this.mouse.position = position;
        }
        this.devices.get(keyDef.pointerType).addPressed(keyDef);
        this.buttons.down(keyDef);
        pointer.down(instance, keyDef);
        if (pointer.pointerType !== 'touch' && !pointer.isPrevented) {
            this.mouse.down(instance, keyDef, pointer);
        }
    }
    async move(instance, pointerName, position) {
        const pointer = this.pointers.get(pointerName);
        // In (some?) browsers this order of events can be observed.
        // This interweaving of events is probably unnecessary.
        // While the order of mouse (or pointer) events is defined per spec,
        // the order in which they interweave/follow on a user interaction depends on the implementation.
        const pointermove = pointer.move(instance, position);
        const mousemove = pointer.pointerType === 'touch' || pointer.isPrevented && pointer.isDown ? undefined : this.mouse.move(instance, position);
        pointermove === null || pointermove === undefined ? undefined : pointermove.leave();
        mousemove === null || mousemove === undefined ? undefined : mousemove.leave();
        pointermove === null || pointermove === undefined ? undefined : pointermove.enter();
        mousemove === null || mousemove === undefined ? undefined : mousemove.enter();
        pointermove === null || pointermove === undefined ? undefined : pointermove.move();
        mousemove === null || mousemove === undefined ? undefined : mousemove.move();
    }
    async release(instance, keyDef, position) {
        const device = this.devices.get(keyDef.pointerType);
        device.removePressed(keyDef);
        this.buttons.up(keyDef);
        const pointer = this.pointers.get(this.getPointerName(keyDef));
        // TODO: deprecate the following implicit setting of position
        pointer.position = position;
        if (pointer.pointerType !== 'touch') {
            this.mouse.position = position;
        }
        if (device.countPressed === 0) {
            pointer.up(instance, keyDef);
        }
        if (pointer.pointerType === 'touch') {
            pointer.release(instance);
        }
        if (!pointer.isPrevented) {
            if (pointer.pointerType === 'touch' && !pointer.isMultitouch) {
                const mousemove = this.mouse.move(instance, pointer.position);
                mousemove === null || mousemove === undefined ? undefined : mousemove.leave();
                mousemove === null || mousemove === undefined ? undefined : mousemove.enter();
                mousemove === null || mousemove === undefined ? undefined : mousemove.move();
                this.mouse.down(instance, keyDef, pointer);
            }
            if (!pointer.isMultitouch) {
                const mousemove = this.mouse.move(instance, pointer.position);
                mousemove === null || mousemove === undefined ? undefined : mousemove.leave();
                mousemove === null || mousemove === undefined ? undefined : mousemove.enter();
                mousemove === null || mousemove === undefined ? undefined : mousemove.move();
                this.mouse.up(instance, keyDef, pointer);
            }
        }
    }
    getPointerName(keyDef) {
        return keyDef.pointerType === 'touch' ? keyDef.name : keyDef.pointerType;
    }
    getPreviousPosition(pointerName) {
        return this.pointers.has(pointerName) ? this.pointers.get(pointerName).position : undefined;
    }
    resetClickCount() {
        this.mouse.resetClickCount();
    }
    getMouseTarget(instance) {
        var _this_mouse_position_target;
        return (_this_mouse_position_target = this.mouse.position.target) !== null && _this_mouse_position_target !== undefined ? _this_mouse_position_target : instance.config.document.body;
    }
    setMousePosition(position) {
        this.mouse.position = position;
        this.pointers.get('mouse').position = position;
    }
    constructor(system){
        _define_property$1(this, "system", undefined);
        _define_property$1(this, "mouse", undefined);
        _define_property$1(this, "buttons", undefined);
        _define_property$1(this, "devices", new class {
            get(k) {
                var // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
                _this_registry, _k;
                var _;
                (_ = (_this_registry = this.registry)[_k = k]) !== null && _ !== undefined ? _ : _this_registry[_k] = new Device();
                return this.registry[k];
            }
            constructor(){
                _define_property$1(this, "registry", {});
            }
        }());
        _define_property$1(this, "pointers", new class {
            new(pointerName, keyDef) {
                const isPrimary = keyDef.pointerType !== 'touch' || !Object.values(this.registry).some((p)=>p.pointerType === 'touch' && !p.isCancelled);
                if (!isPrimary) {
                    Object.values(this.registry).forEach((p)=>{
                        if (p.pointerType === keyDef.pointerType && !p.isCancelled) {
                            p.isMultitouch = true;
                        }
                    });
                }
                this.registry[pointerName] = new Pointer({
                    pointerId: this.nextId++,
                    pointerType: keyDef.pointerType,
                    isPrimary
                });
                return this.registry[pointerName];
            }
            get(pointerName) {
                if (!this.has(pointerName)) {
                    throw new Error(`Trying to access pointer "${pointerName}" which does not exist.`);
                }
                return this.registry[pointerName];
            }
            has(pointerName) {
                return pointerName in this.registry;
            }
            constructor(){
                _define_property$1(this, "registry", {
                    mouse: new Pointer({
                        pointerId: 1,
                        pointerType: 'mouse',
                        isPrimary: true
                    })
                });
                _define_property$1(this, "nextId", 2);
            }
        }());
        this.system = system;
        this.buttons = new Buttons();
        this.mouse = new Mouse();
    }
}

function _define_property(obj, key, value) {
    if (key in obj) {
        Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
        });
    } else {
        obj[key] = value;
    }
    return obj;
}
/**
 * @internal Do not create/alter this by yourself as this type might be subject to changes.
 */ class System {
    getUIEventModifiers() {
        return {
            altKey: this.keyboard.modifiers.Alt,
            ctrlKey: this.keyboard.modifiers.Control,
            metaKey: this.keyboard.modifiers.Meta,
            shiftKey: this.keyboard.modifiers.Shift,
            modifierAltGraph: this.keyboard.modifiers.AltGraph,
            modifierCapsLock: this.keyboard.modifiers.CapsLock,
            modifierFn: this.keyboard.modifiers.Fn,
            modifierFnLock: this.keyboard.modifiers.FnLock,
            modifierNumLock: this.keyboard.modifiers.NumLock,
            modifierScrollLock: this.keyboard.modifiers.ScrollLock,
            modifierSymbol: this.keyboard.modifiers.Symbol,
            modifierSymbolLock: this.keyboard.modifiers.SymbolLock
        };
    }
    constructor(){
        _define_property(this, "keyboard", new KeyboardHost(this));
        _define_property(this, "pointer", new PointerHost(this));
    }
}

async function click$1(element) {
    const pointerIn = [];
    if (!this.config.skipHover) {
        pointerIn.push({
            target: element
        });
    }
    pointerIn.push({
        keys: '[MouseLeft]',
        target: element
    });
    return this.pointer(pointerIn);
}
async function dblClick$1(element) {
    return this.pointer([
        {
            target: element
        },
        '[MouseLeft][MouseLeft]'
    ]);
}
async function tripleClick$1(element) {
    return this.pointer([
        {
            target: element
        },
        '[MouseLeft][MouseLeft][MouseLeft]'
    ]);
}

async function hover$1(element) {
    return this.pointer({
        target: element
    });
}
async function unhover$1(element) {
    assertPointerEvents(this, this.system.pointer.getMouseTarget(this));
    return this.pointer({
        target: element.ownerDocument.body
    });
}

async function tab$1({ shift } = {}) {
    return this.keyboard(shift === true ? '{Shift>}{Tab}{/Shift}' : shift === false ? '[/ShiftLeft][/ShiftRight]{Tab}' : '{Tab}');
}

/**
 * Parse key defintions per `keyboardMap`
 *
 * Keys can be referenced by `{key}` or `{special}` as well as physical locations per `[code]`.
 * Everything else will be interpreted as a typed character - e.g. `a`.
 * Brackets `{` and `[` can be escaped by doubling - e.g. `foo[[bar` translates to `foo[bar`.
 * Keeping the key pressed can be written as `{key>}`.
 * When keeping the key pressed you can choose how long (how many keydown and keypress) the key is pressed `{key>3}`.
 * You can then release the key per `{key>3/}` or keep it pressed and continue with the next key.
 */ function parseKeyDef$1(keyboardMap, text) {
    const defs = [];
    do {
        const { type, descriptor, consumedLength, releasePrevious, releaseSelf = true, repeat } = readNextDescriptor(text, 'keyboard');
        var _keyboardMap_find;
        const keyDef = (_keyboardMap_find = keyboardMap.find((def)=>{
            if (type === '[') {
                var _def_code;
                return ((_def_code = def.code) === null || _def_code === undefined ? undefined : _def_code.toLowerCase()) === descriptor.toLowerCase();
            } else if (type === '{') {
                var _def_key;
                return ((_def_key = def.key) === null || _def_key === undefined ? undefined : _def_key.toLowerCase()) === descriptor.toLowerCase();
            }
            return def.key === descriptor;
        })) !== null && _keyboardMap_find !== undefined ? _keyboardMap_find : {
            key: 'Unknown',
            code: 'Unknown',
            [type === '[' ? 'code' : 'key']: descriptor
        };
        defs.push({
            keyDef,
            releasePrevious,
            releaseSelf,
            repeat
        });
        text = text.slice(consumedLength);
    }while (text)
    return defs;
}

async function keyboard$1(text) {
    const actions = parseKeyDef$1(this.config.keyboardMap, text);
    for(let i = 0; i < actions.length; i++){
        await wait(this.config);
        await keyboardAction(this, actions[i]);
    }
}
async function keyboardAction(instance, { keyDef, releasePrevious, releaseSelf, repeat }) {
    const { system } = instance;
    // Release the key automatically if it was pressed before.
    if (system.keyboard.isKeyPressed(keyDef)) {
        await system.keyboard.keyup(instance, keyDef);
    }
    if (!releasePrevious) {
        for(let i = 1; i <= repeat; i++){
            await system.keyboard.keydown(instance, keyDef);
            if (i < repeat) {
                await wait(instance.config);
            }
        }
        // Release the key only on the last iteration on `state.repeatKey`.
        if (releaseSelf) {
            await system.keyboard.keyup(instance, keyDef);
        }
    }
}
async function releaseAllKeys(instance) {
    for (const k of instance.system.keyboard.getPressedKeys()){
        await instance.system.keyboard.keyup(instance, k);
    }
}

function copySelection(target) {
    const data = hasOwnSelection(target) ? {
        'text/plain': readSelectedValueFromInput(target)
    } : {
        'text/plain': String(target.ownerDocument.getSelection())
    };
    const dt = createDataTransfer(getWindow(target));
    for(const type in data){
        if (data[type]) {
            dt.setData(type, data[type]);
        }
    }
    return dt;
}
function readSelectedValueFromInput(target) {
    const sel = getUISelection(target);
    const val = getUIValue(target);
    return val.substring(sel.startOffset, sel.endOffset);
}

async function copy$1() {
    const doc = this.config.document;
    var _doc_activeElement;
    const target = (_doc_activeElement = doc.activeElement) !== null && _doc_activeElement !== undefined ? _doc_activeElement : /* istanbul ignore next */ doc.body;
    const clipboardData = copySelection(target);
    if (clipboardData.items.length === 0) {
        return;
    }
    if (this.dispatchUIEvent(target, 'copy', {
        clipboardData
    }) && this.config.writeToClipboard) {
        await writeDataTransferToClipboard(doc, clipboardData);
    }
    return clipboardData;
}

async function cut$1() {
    const doc = this.config.document;
    var _doc_activeElement;
    const target = (_doc_activeElement = doc.activeElement) !== null && _doc_activeElement !== undefined ? _doc_activeElement : /* istanbul ignore next */ doc.body;
    const clipboardData = copySelection(target);
    if (clipboardData.items.length === 0) {
        return;
    }
    if (this.dispatchUIEvent(target, 'cut', {
        clipboardData
    }) && this.config.writeToClipboard) {
        await writeDataTransferToClipboard(target.ownerDocument, clipboardData);
    }
    return clipboardData;
}

async function paste$1(clipboardData) {
    const doc = this.config.document;
    var _doc_activeElement;
    const target = (_doc_activeElement = doc.activeElement) !== null && _doc_activeElement !== undefined ? _doc_activeElement : /* istanbul ignore next */ doc.body;
    var _ref;
    const dataTransfer = (_ref = typeof clipboardData === 'string' ? getClipboardDataFromString(doc, clipboardData) : clipboardData) !== null && _ref !== undefined ? _ref : await readDataTransferFromClipboard(doc).catch(()=>{
        throw new Error('`userEvent.paste()` without `clipboardData` requires the `ClipboardAPI` to be available.');
    });
    this.dispatchUIEvent(target, 'paste', {
        clipboardData: dataTransfer
    });
}
function getClipboardDataFromString(doc, text) {
    const dt = createDataTransfer(getWindow(doc));
    dt.setData('text', text);
    return dt;
}

function parseKeyDef(pointerMap, keys) {
    const defs = [];
    do {
        const { descriptor, consumedLength, releasePrevious, releaseSelf = true } = readNextDescriptor(keys, 'pointer');
        const keyDef = pointerMap.find((p)=>p.name === descriptor);
        if (keyDef) {
            defs.push({
                keyDef,
                releasePrevious,
                releaseSelf
            });
        }
        keys = keys.slice(consumedLength);
    }while (keys)
    return defs;
}

async function pointer$1(input) {
    const { pointerMap } = this.config;
    const actions = [];
    (Array.isArray(input) ? input : [
        input
    ]).forEach((actionInput)=>{
        if (typeof actionInput === 'string') {
            actions.push(...parseKeyDef(pointerMap, actionInput));
        } else if ('keys' in actionInput) {
            actions.push(...parseKeyDef(pointerMap, actionInput.keys).map((i)=>({
                    ...actionInput,
                    ...i
                })));
        } else {
            actions.push(actionInput);
        }
    });
    for(let i = 0; i < actions.length; i++){
        await wait(this.config);
        await pointerAction(this, actions[i]);
    }
    this.system.pointer.resetClickCount();
}
async function pointerAction(instance, action) {
    var _previousPosition_caret, _previousPosition_caret1;
    const pointerName = 'pointerName' in action && action.pointerName ? action.pointerName : 'keyDef' in action ? instance.system.pointer.getPointerName(action.keyDef) : 'mouse';
    const previousPosition = instance.system.pointer.getPreviousPosition(pointerName);
    var _action_target, _action_coords, _action_node, _action_offset;
    const position = {
        target: (_action_target = action.target) !== null && _action_target !== undefined ? _action_target : getPrevTarget(instance, previousPosition),
        coords: (_action_coords = action.coords) !== null && _action_coords !== undefined ? _action_coords : previousPosition === null || previousPosition === undefined ? undefined : previousPosition.coords,
        caret: {
            node: (_action_node = action.node) !== null && _action_node !== undefined ? _action_node : hasCaretPosition(action) ? undefined : previousPosition === null || previousPosition === undefined ? undefined : (_previousPosition_caret = previousPosition.caret) === null || _previousPosition_caret === undefined ? undefined : _previousPosition_caret.node,
            offset: (_action_offset = action.offset) !== null && _action_offset !== undefined ? _action_offset : hasCaretPosition(action) ? undefined : previousPosition === null || previousPosition === undefined ? undefined : (_previousPosition_caret1 = previousPosition.caret) === null || _previousPosition_caret1 === undefined ? undefined : _previousPosition_caret1.offset
        }
    };
    if ('keyDef' in action) {
        if (instance.system.pointer.isKeyPressed(action.keyDef)) {
            setLevelRef(instance, ApiLevel.Trigger);
            await instance.system.pointer.release(instance, action.keyDef, position);
        }
        if (!action.releasePrevious) {
            setLevelRef(instance, ApiLevel.Trigger);
            await instance.system.pointer.press(instance, action.keyDef, position);
            if (action.releaseSelf) {
                setLevelRef(instance, ApiLevel.Trigger);
                await instance.system.pointer.release(instance, action.keyDef, position);
            }
        }
    } else {
        setLevelRef(instance, ApiLevel.Trigger);
        await instance.system.pointer.move(instance, pointerName, position);
    }
}
function hasCaretPosition(action) {
    var _action_target, _ref;
    return !!((_ref = (_action_target = action.target) !== null && _action_target !== undefined ? _action_target : action.node) !== null && _ref !== undefined ? _ref : action.offset !== undefined);
}
function getPrevTarget(instance, position) {
    if (!position) {
        throw new Error('This pointer has no previous position. Provide a target property!');
    }
    var _position_target;
    return (_position_target = position.target) !== null && _position_target !== undefined ? _position_target : instance.config.document.body;
}

async function clear$1(element) {
    if (!isEditable(element) || isDisabled(element)) {
        throw new Error('clear()` is only supported on editable elements.');
    }
    focusElement(element);
    if (element.ownerDocument.activeElement !== element) {
        throw new Error('The element to be cleared could not be focused.');
    }
    selectAll(element);
    if (!isAllSelected(element)) {
        throw new Error('The element content to be cleared could not be selected.');
    }
    input(this, element, '', 'deleteContentBackward');
}

async function selectOptions$1(select, values) {
    return selectOptionsBase.call(this, true, select, values);
}
async function deselectOptions$1(select, values) {
    return selectOptionsBase.call(this, false, select, values);
}
async function selectOptionsBase(newValue, select, values) {
    if (!newValue && !select.multiple) {
        throw getConfig().getElementError(`Unable to deselect an option in a non-multiple select. Use selectOptions to change the selection instead.`, select);
    }
    const valArray = Array.isArray(values) ? values : [
        values
    ];
    const allOptions = Array.from(select.querySelectorAll('option, [role="option"]'));
    const selectedOptions = valArray.map((val)=>{
        if (typeof val !== 'string' && allOptions.includes(val)) {
            return val;
        } else {
            const matchingOption = allOptions.find((o)=>o.value === val || o.innerHTML === val);
            if (matchingOption) {
                return matchingOption;
            } else {
                throw getConfig().getElementError(`Value "${String(val)}" not found in options`, select);
            }
        }
    }).filter((option)=>!isDisabled(option));
    if (isDisabled(select) || !selectedOptions.length) return;
    const selectOption = (option)=>{
        option.selected = newValue;
        this.dispatchUIEvent(select, 'input', {
            bubbles: true,
            cancelable: false,
            composed: true
        });
        this.dispatchUIEvent(select, 'change');
    };
    if (isElementType(select, 'select')) {
        if (select.multiple) {
            for (const option of selectedOptions){
                const withPointerEvents = this.config.pointerEventsCheck === 0 ? true : hasPointerEvents(this, option);
                // events fired for multiple select are weird. Can't use hover...
                if (withPointerEvents) {
                    this.dispatchUIEvent(option, 'pointerover');
                    this.dispatchUIEvent(select, 'pointerenter');
                    this.dispatchUIEvent(option, 'mouseover');
                    this.dispatchUIEvent(select, 'mouseenter');
                    this.dispatchUIEvent(option, 'pointermove');
                    this.dispatchUIEvent(option, 'mousemove');
                    this.dispatchUIEvent(option, 'pointerdown');
                    this.dispatchUIEvent(option, 'mousedown');
                }
                focusElement(select);
                if (withPointerEvents) {
                    this.dispatchUIEvent(option, 'pointerup');
                    this.dispatchUIEvent(option, 'mouseup');
                }
                selectOption(option);
                if (withPointerEvents) {
                    this.dispatchUIEvent(option, 'click');
                }
                await wait(this.config);
            }
        } else if (selectedOptions.length === 1) {
            const withPointerEvents = this.config.pointerEventsCheck === 0 ? true : hasPointerEvents(this, select);
            // the click to open the select options
            if (withPointerEvents) {
                await this.click(select);
            } else {
                focusElement(select);
            }
            selectOption(selectedOptions[0]);
            if (withPointerEvents) {
                // the browser triggers another click event on the select for the click on the option
                // this second click has no 'down' phase
                this.dispatchUIEvent(select, 'pointerover');
                this.dispatchUIEvent(select, 'pointerenter');
                this.dispatchUIEvent(select, 'mouseover');
                this.dispatchUIEvent(select, 'mouseenter');
                this.dispatchUIEvent(select, 'pointerup');
                this.dispatchUIEvent(select, 'mouseup');
                this.dispatchUIEvent(select, 'click');
            }
            await wait(this.config);
        } else {
            throw getConfig().getElementError(`Cannot select multiple options on a non-multiple select`, select);
        }
    } else if (select.getAttribute('role') === 'listbox') {
        for (const option of selectedOptions){
            await this.click(option);
            await this.unhover(option);
        }
    } else {
        throw getConfig().getElementError(`Cannot select options on elements that are neither select nor listbox elements`, select);
    }
}

async function type$1(element, text, { skipClick = this.config.skipClick, skipAutoClose = this.config.skipAutoClose, initialSelectionStart, initialSelectionEnd } = {}) {
    // TODO: properly type guard
    // we use this workaround for now to prevent changing behavior
    if (element.disabled) return;
    if (!skipClick) {
        await this.click(element);
    }
    if (initialSelectionStart !== undefined) {
        setSelectionRange(element, initialSelectionStart, initialSelectionEnd !== null && initialSelectionEnd !== undefined ? initialSelectionEnd : initialSelectionStart);
    }
    await this.keyboard(text);
    if (!skipAutoClose) {
        await releaseAllKeys(this);
    }
}

// It is not possible to create a real FileList programmatically.
// Therefore assigning `files` property with a programmatically created FileList results in an error.
// Just assigning the property (as per fireEvent) breaks the interweaving with the `value` property.
const fakeFiles = Symbol('files and value properties are mocked');
function restoreProperty(obj, prop, descriptor) {
    if (descriptor) {
        Object.defineProperty(obj, prop, descriptor);
    } else {
        // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
        delete obj[prop];
    }
}
function setFiles(el, files) {
    var _el_fakeFiles;
    (_el_fakeFiles = el[fakeFiles]) === null || _el_fakeFiles === undefined ? undefined : _el_fakeFiles.restore();
    const typeDescr = Object.getOwnPropertyDescriptor(el, 'type');
    const valueDescr = Object.getOwnPropertyDescriptor(el, 'value');
    const filesDescr = Object.getOwnPropertyDescriptor(el, 'files');
    function restore() {
        restoreProperty(el, 'type', typeDescr);
        restoreProperty(el, 'value', valueDescr);
        restoreProperty(el, 'files', filesDescr);
    }
    el[fakeFiles] = {
        restore
    };
    Object.defineProperties(el, {
        files: {
            configurable: true,
            get: ()=>files
        },
        value: {
            configurable: true,
            get: ()=>files.length ? `C:\\fakepath\\${files[0].name}` : '',
            set (v) {
                if (v === '') {
                    restore();
                } else {
                    var _valueDescr_set;
                    valueDescr === null || valueDescr === undefined ? undefined : (_valueDescr_set = valueDescr.set) === null || _valueDescr_set === undefined ? undefined : _valueDescr_set.call(el, v);
                }
            }
        },
        type: {
            configurable: true,
            get: ()=>'file',
            set (v) {
                if (v !== 'file') {
                    restore();
                    el.type = v;
                }
            }
        }
    });
}

async function upload$1(element, fileOrFiles) {
    const input = isElementType(element, 'label') ? element.control : element;
    if (!input || !isElementType(input, 'input', {
        type: 'file'
    })) {
        throw new TypeError(`The ${input === element ? 'given' : 'associated'} ${input === null || input === undefined ? undefined : input.tagName} element does not accept file uploads`);
    }
    if (isDisabled(element)) return;
    const files = (Array.isArray(fileOrFiles) ? fileOrFiles : [
        fileOrFiles
    ]).filter((file)=>!this.config.applyAccept || isAcceptableFile(file, input.accept)).slice(0, input.multiple ? undefined : 1);
    const fileDialog = ()=>{
        var _input_files;
        // do not fire an input event if the file selection does not change
        if (files.length === ((_input_files = input.files) === null || _input_files === undefined ? undefined : _input_files.length) && files.every((f, i)=>{
            var _input_files;
            return f === ((_input_files = input.files) === null || _input_files === undefined ? undefined : _input_files.item(i));
        })) {
            return;
        }
        setFiles(input, createFileList(getWindow(element), files));
        this.dispatchUIEvent(input, 'input');
        this.dispatchUIEvent(input, 'change');
    };
    input.addEventListener('fileDialog', fileDialog);
    await this.click(element);
    input.removeEventListener('fileDialog', fileDialog);
}
function isAcceptableFile(file, accept) {
    if (!accept) {
        return true;
    }
    const wildcards = [
        'audio/*',
        'image/*',
        'video/*'
    ];
    return accept.split(',').some((acceptToken)=>{
        if (acceptToken.startsWith('.')) {
            // tokens starting with a dot represent a file extension
            return file.name.endsWith(acceptToken);
        } else if (wildcards.includes(acceptToken)) {
            return file.type.startsWith(acceptToken.substr(0, acceptToken.length - 1));
        }
        return file.type === acceptToken;
    });
}

const userEventApi = {
    click: click$1,
    dblClick: dblClick$1,
    tripleClick: tripleClick$1,
    hover: hover$1,
    unhover: unhover$1,
    tab: tab$1,
    keyboard: keyboard$1,
    copy: copy$1,
    cut: cut$1,
    paste: paste$1,
    pointer: pointer$1,
    clear: clear$1,
    deselectOptions: deselectOptions$1,
    selectOptions: selectOptions$1,
    type: type$1,
    upload: upload$1
};

/**
 * Wrap an internal Promise
 */ function wrapAsync(implementation) {
    return getConfig().asyncWrapper(implementation);
}

/**
 * Default options applied when API is called per `userEvent.anyApi()`
 */ const defaultOptionsDirect = {
    applyAccept: true,
    autoModify: true,
    delay: 0,
    document: globalThis.document,
    keyboardMap: defaultKeyMap$1,
    pointerMap: defaultKeyMap,
    pointerEventsCheck: PointerEventsCheckLevel.EachApiCall,
    skipAutoClose: false,
    skipClick: false,
    skipHover: false,
    writeToClipboard: false,
    advanceTimers: ()=>Promise.resolve()
};
/**
 * Default options applied when API is called per `userEvent().anyApi()`
 */ const defaultOptionsSetup = {
    ...defaultOptionsDirect,
    writeToClipboard: true
};
function createConfig(options = {}, defaults = defaultOptionsSetup, node) {
    const document = getDocument(options, node, defaults);
    return {
        ...defaults,
        ...options,
        document
    };
}
/**
 * Start a "session" with userEvent.
 * All APIs returned by this function share an input device state and a default configuration.
 */ function setupMain(options = {}) {
    const config = createConfig(options);
    prepareDocument(config.document);
    var _config_document_defaultView;
    const view = (_config_document_defaultView = config.document.defaultView) !== null && _config_document_defaultView !== undefined ? _config_document_defaultView : /* istanbul ignore next */ globalThis.window;
    attachClipboardStubToView(view);
    return createInstance(config).api;
}
/**
 * Setup in direct call per `userEvent.anyApi()`
 */ function setupDirect({ keyboardState, pointerState, ...options } = {}, node) {
    const config = createConfig(options, defaultOptionsDirect, node);
    prepareDocument(config.document);
    var _ref;
    const system = (_ref = pointerState !== null && pointerState !== undefined ? pointerState : keyboardState) !== null && _ref !== undefined ? _ref : new System();
    return {
        api: createInstance(config, system).api,
        system
    };
}
/**
 * Create a set of callbacks with different default settings but the same state.
 */ function setupSub(options) {
    return createInstance({
        ...this.config,
        ...options
    }, this.system).api;
}
function wrapAndBindImpl(instance, impl) {
    function method(...args) {
        setLevelRef(instance, ApiLevel.Call);
        return wrapAsync(()=>impl.apply(instance, args).then(async (ret)=>{
                await wait(instance.config);
                return ret;
            }));
    }
    Object.defineProperty(method, 'name', {
        get: ()=>impl.name
    });
    return method;
}
function createInstance(config, system = new System()) {
    const instance = {};
    Object.assign(instance, {
        config,
        dispatchEvent: dispatchEvent.bind(instance),
        dispatchUIEvent: dispatchUIEvent.bind(instance),
        system,
        levelRefs: {},
        ...userEventApi
    });
    return {
        instance,
        api: {
            ...Object.fromEntries(Object.entries(userEventApi).map(([name, api])=>[
                    name,
                    wrapAndBindImpl(instance, api)
                ])),
            setup: setupSub.bind(instance)
        }
    };
}
function getDocument(options, node, defaults) {
    var _options_document, _ref;
    return (_ref = (_options_document = options.document) !== null && _options_document !== undefined ? _options_document : node && getDocumentFromNode(node)) !== null && _ref !== undefined ? _ref : defaults.document;
}

function clear(element) {
    return setupDirect().api.clear(element);
}
function click(element, options = {}) {
    return setupDirect(options, element).api.click(element);
}
function copy(options = {}) {
    return setupDirect(options).api.copy();
}
function cut(options = {}) {
    return setupDirect(options).api.cut();
}
function dblClick(element, options = {}) {
    return setupDirect(options).api.dblClick(element);
}
function deselectOptions(select, values, options = {}) {
    return setupDirect(options).api.deselectOptions(select, values);
}
function hover(element, options = {}) {
    return setupDirect(options).api.hover(element);
}
async function keyboard(text, options = {}) {
    const { api, system } = setupDirect(options);
    return api.keyboard(text).then(()=>system);
}
async function pointer(input, options = {}) {
    const { api, system } = setupDirect(options);
    return api.pointer(input).then(()=>system);
}
function paste(clipboardData, options) {
    return setupDirect(options).api.paste(clipboardData);
}
function selectOptions(select, values, options = {}) {
    return setupDirect(options).api.selectOptions(select, values);
}
function tripleClick(element, options = {}) {
    return setupDirect(options).api.tripleClick(element);
}
function type(element, text, options = {}) {
    return setupDirect(options, element).api.type(element, text, options);
}
function unhover(element, options = {}) {
    const { api, system } = setupDirect(options);
    system.pointer.setMousePosition({
        target: element
    });
    return api.unhover(element);
}
function upload(element, fileOrFiles, options = {}) {
    return setupDirect(options).api.upload(element, fileOrFiles);
}
function tab(options = {}) {
    return setupDirect().api.tab(options);
}

var directApi = /*#__PURE__*/Object.freeze({
  __proto__: null,
  clear: clear,
  click: click,
  copy: copy,
  cut: cut,
  dblClick: dblClick,
  deselectOptions: deselectOptions,
  hover: hover,
  keyboard: keyboard,
  paste: paste,
  pointer: pointer,
  selectOptions: selectOptions,
  tab: tab,
  tripleClick: tripleClick,
  type: type,
  unhover: unhover,
  upload: upload
});

const userEvent = {
    ...directApi,
    setup: setupMain
};

const generateBoolean = () => chanceExports.Chance().pickone([true, false]);
const undefinedOr = (fn) => chanceExports.Chance().pickone([undefined, fn()]);
const generateArrayOf = (fn, numberOf = 3) => Array.from(new Array(numberOf), () => fn());
const openSelect = (container, optionLabel) => {
  const selectInput = getQueriesForElement(container).getByRole("textbox");
  fireEvent.blur(selectInput);
  userEvent.type(selectInput, optionLabel != null ? optionLabel : "{arrowdown}");
};
const selectOption = async (container, optionLabel, typeOptionLabel) => {
  openSelect(container, typeOptionLabel ? optionLabel : undefined);
  const option = await waitForWrapper(() => getQueriesForElement(container).getByText(optionLabel));
  userEvent.click(option);
};
const generateOptions = () => {
  const numberOfOptions = 5;
  return Array.from(new Array(numberOfOptions), () => {
    const name = chanceExports.Chance().name();
    return {
      label: name,
      value: lodash.kebabCase(name)
    };
  });
};

const mockDataSourcePluginMeta = () => ({
  builtIn: generateBoolean(),
  metrics: generateBoolean(),
  logs: generateBoolean(),
  annotations: generateBoolean(),
  alerting: generateBoolean(),
  tracing: generateBoolean(),
  mixed: generateBoolean(),
  hasQueryHelp: generateBoolean(),
  category: chanceExports.Chance().word(),
  queryOptions: {
    cacheTimeout: generateBoolean(),
    maxDataPoints: generateBoolean(),
    minInterval: generateBoolean()
  },
  sort: 1,
  streaming: generateBoolean(),
  unlicensed: generateBoolean(),
  id: chanceExports.Chance().word(),
  name: chanceExports.Chance().word(),
  type: mockPluginType(),
  info: mockPluginMetaInfo(),
  module: chanceExports.Chance().word(),
  baseUrl: chanceExports.Chance().word()
});
const mockPluginMetaInfo = () => ({
  author: {
    name: chanceExports.Chance().word(),
    url: chanceExports.Chance().word()
  },
  description: chanceExports.Chance().word(),
  links: [],
  logos: {
    large: chanceExports.Chance().word(),
    small: chanceExports.Chance().word()
  },
  screenshots: [],
  updated: chanceExports.Chance().word(),
  version: chanceExports.Chance().word()
});
const mockPluginMeta = () => ({
  id: chanceExports.Chance().word(),
  name: chanceExports.Chance().word(),
  type: mockPluginType(),
  info: mockPluginMetaInfo(),
  includes: [mockPluginInclude()],
  state: mockPluginState(),
  module: chanceExports.Chance().word(),
  baseUrl: chanceExports.Chance().word(),
  dependencies: mockPluginDependencies(),
  jsonData: {},
  secureJsonData: {},
  enabled: generateBoolean(),
  defaultNavUrl: chanceExports.Chance().word(),
  hasUpdate: generateBoolean(),
  enterprise: generateBoolean(),
  latestVersion: chanceExports.Chance().word(),
  pinned: generateBoolean(),
  signature: mockPluginSignatureStatus(),
  live: generateBoolean()
});
const mockPluginInclude = () => ({
  type: mockPluginIncludeType(),
  name: chanceExports.Chance().word(),
  path: chanceExports.Chance().word(),
  icon: chanceExports.Chance().word(),
  role: chanceExports.Chance().word(),
  addToNav: generateBoolean(),
  component: chanceExports.Chance().word()
});
const mockPluginType = () => chanceExports.Chance().pickone([data.PluginType.panel, data.PluginType.datasource, data.PluginType.app, data.PluginType.renderer]);
const mockPluginIncludeType = () => chanceExports.Chance().pickone([
  data.PluginIncludeType.dashboard,
  data.PluginIncludeType.page,
  data.PluginIncludeType.panel,
  data.PluginIncludeType.datasource
]);
const mockPluginState = () => chanceExports.Chance().pickone([data.PluginState.alpha, data.PluginState.beta, data.PluginState.deprecated]);
const mockPluginDependencies = () => ({
  grafanaVersion: chanceExports.Chance().word(),
  plugins: []
});
const mockPluginSignatureStatus = () => chanceExports.Chance().pickone([
  data.PluginSignatureStatus.internal,
  data.PluginSignatureStatus.valid,
  data.PluginSignatureStatus.invalid,
  data.PluginSignatureStatus.modified,
  data.PluginSignatureStatus.missing
]);

var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
class DatasourceMock extends runtime.DataSourceWithBackend {
  constructor() {
    super(...arguments);
    // DataSourceWithBackend
    __publicField(this, "query", jest.fn());
    __publicField(this, "filterQuery", undefinedOr(generateBoolean));
    __publicField(this, "applyTemplateVariables", jest.fn());
    __publicField(this, "getResource", jest.fn());
    __publicField(this, "postResource", jest.fn());
    __publicField(this, "callHealthCheck", jest.fn());
    __publicField(this, "testDatasource", jest.fn());
    // DataSourceApi
    __publicField(this, "uid", chanceExports.Chance().guid());
    __publicField(this, "name", chanceExports.Chance().word());
    __publicField(this, "id", 1);
    __publicField(this, "type", chanceExports.Chance().word());
    __publicField(this, "interval", chanceExports.Chance().word());
    __publicField(this, "importQueries", jest.fn());
    __publicField(this, "init", jest.fn());
    __publicField(this, "getQueryHints", jest.fn().mockReturnValue([mockQueryHint()]));
    __publicField(this, "getQueryDisplayText", jest.fn().mockReturnValue(chanceExports.Chance().word()));
    __publicField(this, "metricFindQuery", jest.fn());
    __publicField(this, "getTagKeys", jest.fn());
    __publicField(this, "getTagValues", jest.fn());
    __publicField(this, "components", {});
    __publicField(this, "meta", mockDataSourcePluginMeta());
    __publicField(this, "targetContainsTemplate", jest.fn());
    __publicField(this, "modifyQuery", jest.fn());
    __publicField(this, "getHighlighterExpression", jest.fn());
    __publicField(this, "languageProvider", jest.fn());
    __publicField(this, "getVersion", jest.fn());
    __publicField(this, "interpolateVariablesInQueries", jest.fn());
    __publicField(this, "annotations", {});
    __publicField(this, "annotationQuery", jest.fn());
    __publicField(this, "streamOptionsProvider", jest.fn());
    __publicField(this, "getRef", jest.fn());
    __publicField(this, "getRequestHeaders", jest.fn());
  }
}
const mockDatasource = () => new DatasourceMock(mockDatasourceInstanceSettings());
const mockQueryHint = () => ({
  type: chanceExports.Chance().word(),
  label: chanceExports.Chance().word(),
  fix: {
    label: chanceExports.Chance().word(),
    action: {
      type: chanceExports.Chance().word(),
      query: chanceExports.Chance().word(),
      preventSubmit: generateBoolean()
    }
  }
});
const mockDatasourceInstanceSettings = () => ({
  id: chanceExports.Chance().integer(),
  uid: chanceExports.Chance().word(),
  type: chanceExports.Chance().word(),
  name: chanceExports.Chance().word(),
  meta: mockDataSourcePluginMeta(),
  url: chanceExports.Chance().word(),
  jsonData: {},
  username: chanceExports.Chance().word(),
  password: chanceExports.Chance().word(),
  database: chanceExports.Chance().word(),
  basicAuth: chanceExports.Chance().word(),
  withCredentials: generateBoolean(),
  access: chanceExports.Chance().pickone(["direct", "proxy"]),
  readOnly: false
});

const mockDataQuery = () => ({
  refId: chanceExports.Chance().word(),
  hide: false,
  key: chanceExports.Chance().guid(),
  queryType: chanceExports.Chance().word(),
  datasource: undefinedOr(() => chanceExports.Chance().word())
});

const mockQueryEditorProps = () => ({
  datasource: {},
  query: {
    refId: chanceExports.Chance().word(),
    hide: false,
    key: chanceExports.Chance().word(),
    queryType: chanceExports.Chance().word(),
    dataTopic: data.DataTopic.Annotations,
    datasource: chanceExports.Chance().pickone([chanceExports.Chance().word(), null])
  },
  onRunQuery: jest.fn(),
  onChange: jest.fn(),
  onBlur: jest.fn(),
  data: {
    state: mockLoadingState(),
    series: [],
    annotations: [],
    timeRange: mockTimeRange()
  },
  range: mockTimeRange(),
  history: []
});
const mockLoadingState = () => chanceExports.Chance().pickone([
  data.LoadingState.NotStarted,
  data.LoadingState.Loading,
  data.LoadingState.Streaming,
  data.LoadingState.Done,
  data.LoadingState.Error
]);
const mockTimeRange = () => ({
  from: data.dateTime(),
  to: data.dateTime(),
  raw: {
    from: data.dateTime(),
    to: data.dateTime()
  }
});

exports.AccessoryButton = AccessoryButton;
exports.AdvancedHttpSettings = AdvancedHttpSettings;
exports.Auth = Auth;
exports.AuthMethod = AuthMethod;
exports.BINARY_OPERATIONS_KEY = BINARY_OPERATIONS_KEY;
exports.CatalogSelector = CatalogSelector;
exports.CompletionItemInsertTextRule = CompletionItemInsertTextRule;
exports.CompletionItemKind = CompletionItemKind;
exports.CompletionItemPriority = CompletionItemPriority;
exports.ConfigDescriptionLink = ConfigDescriptionLink;
exports.ConfigSection = ConfigSection;
exports.ConfigSubSection = ConfigSubSection;
exports.ConnectionSettings = ConnectionSettings;
exports.CustomHeadersSettings = CustomHeadersSettings;
exports.DataLink = DataLink;
exports.DataLinks = DataLinks;
exports.DataSourceDescription = DataSourceDescription;
exports.DataSourcePicker = DataSourcePicker;
exports.DatasetSelector = DatasetSelector;
exports.DatePicker = DatePicker;
exports.DatePickerWithInput = DatePickerWithInput;
exports.DebounceInput = DebounceInput;
exports.EditorField = EditorField$1;
exports.EditorFieldGroup = EditorFieldGroup;
exports.EditorHeader = EditorHeader;
exports.EditorList = EditorList;
exports.EditorMode = EditorMode;
exports.EditorRow = EditorRow$1;
exports.EditorRows = EditorRows$1;
exports.EditorStack = EditorStack;
exports.EditorSwitch = EditorSwitch;
exports.FlexItem = FlexItem;
exports.GroupByRow = GroupByRow;
exports.InlineSelect = InlineSelect;
exports.InputGroup = InputGroup;
exports.LabelFilters = LabelFilters;
exports.LinkedToken = LinkedToken;
exports.MacroType = MacroType;
exports.OperationExplainedBox = OperationExplainedBox;
exports.OperationList = OperationList;
exports.OperationListExplained = OperationListExplained;
exports.OperationsEditorRow = OperationsEditorRow;
exports.OperatorType = OperatorType;
exports.QUERY_FORMAT_OPTIONS = QUERY_FORMAT_OPTIONS;
exports.QueryBuilderHints = QueryBuilderHints;
exports.QueryEditorMode = QueryEditorMode;
exports.QueryEditorModeToggle = QueryEditorModeToggle;
exports.QueryEditorRow = QueryEditorRow;
exports.QueryFormat = QueryFormat;
exports.QueryHeaderSwitch = QueryHeaderSwitch;
exports.QueryModellerBase = QueryModellerBase;
exports.QueryOptionGroup = QueryOptionGroup;
exports.RawQuery = RawQuery;
exports.RunQueryButton = RunQueryButton;
exports.SQLEditor = SQLEditor;
exports.SQLEditorMode = SQLEditorMode;
exports.SQLEditorTestUtils = SQLEditorTestUtils;
exports.SecureSocksProxyToggle = SecureSocksProxyToggle;
exports.Segment = Segment;
exports.Space = Space;
exports.SqlDatasource = SqlDatasource;
exports.SqlQueryEditor = SqlQueryEditor;
exports.StatementPosition = StatementPosition;
exports.SuggestionKind = SuggestionKind;
exports.TLSSettings = TLSSettings;
exports.TableSelector = TableSelector;
exports.TokenType = TokenType;
exports.convertLegacyAuthProps = convertLegacyAuthProps;
exports.formatDate = formatDate;
exports.generateArrayOf = generateArrayOf;
exports.generateBoolean = generateBoolean;
exports.generateOptions = generateOptions;
exports.getStandardSQLCompletionProvider = getStandardSQLCompletionProvider;
exports.grafanaStandardSQLLanguage = language;
exports.grafanaStandardSQLLanguageConf = conf;
exports.mockDataQuery = mockDataQuery;
exports.mockDataSourcePluginMeta = mockDataSourcePluginMeta;
exports.mockDatasource = mockDatasource;
exports.mockDatasourceInstanceSettings = mockDatasourceInstanceSettings;
exports.mockLoadingState = mockLoadingState;
exports.mockPluginDependencies = mockPluginDependencies;
exports.mockPluginInclude = mockPluginInclude;
exports.mockPluginIncludeType = mockPluginIncludeType;
exports.mockPluginMeta = mockPluginMeta;
exports.mockPluginMetaInfo = mockPluginMetaInfo;
exports.mockPluginSignatureStatus = mockPluginSignatureStatus;
exports.mockPluginState = mockPluginState;
exports.mockPluginType = mockPluginType;
exports.mockQueryEditorProps = mockQueryEditorProps;
exports.mockTimeRange = mockTimeRange;
exports.openSelect = openSelect;
exports.selectOption = selectOption;
exports.toOption = toOption;
exports.undefinedOr = undefinedOr;
//# sourceMappingURL=index.cjs.map
