UNPKG

@taufik-nurrohman/option-picker

Version:

Accessible custom `<select>` (and `<input list>`) element.

1,393 lines (1,372 loc) 127 kB
/*! * * The MIT License (MIT) * * Copyright © 2025 Taufik Nurrohman <https://github.com/taufik-nurrohman> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the “Software”), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * */ (function (g, f) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = f() : typeof define === 'function' && define.amd ? define(f) : (g = typeof globalThis !== 'undefined' ? globalThis : g || self, g.OptionPicker = f()); })(this, (function () { 'use strict'; function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = true, o = false; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = true, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _maybeArrayLike(r, a, e) { if (a && !Array.isArray(a) && "number" == typeof a.length) { var y = a.length; return _arrayLikeToArray(a, void 0 !== e && e < y ? e : y); } return r(a, e); } 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 _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } var isArray = function isArray(x) { return Array.isArray(x); }; var isBoolean = function isBoolean(x) { return false === x || true === x; }; var isDefined = function isDefined(x) { return 'undefined' !== typeof x; }; var isFloat = function isFloat(x) { return isNumber(x) && 0 !== x % 1; }; var isFunction = function isFunction(x) { return 'function' === typeof x; }; var isInstance = function isInstance(x, of, exact) { if (!x || 'object' !== typeof x) { return false; } if (exact) { return isSet(of) && isSet(x.constructor) && of === x.constructor; } return isSet(of) && x instanceof of ; }; var isInteger = function isInteger(x) { return isNumber(x) && 0 === x % 1; }; var isNull = function isNull(x) { return null === x; }; var isNumber = function isNumber(x) { return 'number' === typeof x && !Number.isNaN(x); }; var isNumeric = function isNumeric(x) { return /^[+-]?(?:\d*\.)?\d+$/.test(x + ""); }; var isObject = function isObject(x, isPlain) { if (isPlain === void 0) { isPlain = true; } if (!x || 'object' !== typeof x) { return false; } return isPlain ? isInstance(x, Object, 1) : true; }; var isSet = function isSet(x) { return isDefined(x) && !isNull(x); }; var isString = function isString(x) { return 'string' === typeof x; }; var hasValue = function hasValue(x, data) { return -1 !== data.indexOf(x); }; var fromJSON = function fromJSON(x) { var value = null; try { value = JSON.parse(x); } catch (e) {} return value; }; var _fromStates = function fromStates() { for (var _len = arguments.length, lot = new Array(_len), _key = 0; _key < _len; _key++) { lot[_key] = arguments[_key]; } var out = lot.shift(); for (var i = 0, j = toCount(lot); i < j; ++i) { for (var k in lot[i]) { // Assign value if (!isSet(out[k])) { out[k] = lot[i][k]; continue; } // Merge array if (isArray(out[k]) && isArray(lot[i][k])) { out[k] = [ /* Clone! */ ].concat(out[k]); for (var ii = 0, jj = toCount(lot[i][k]); ii < jj; ++ii) { if (!hasValue(lot[i][k][ii], out[k])) { out[k].push(lot[i][k][ii]); } } // Merge object recursive } else if (isObject(out[k]) && isObject(lot[i][k])) { out[k] = _fromStates({ /* Clone! */ }, out[k], lot[i][k]); // Replace value } else { out[k] = lot[i][k]; } } } return out; }; var _fromValue = function fromValue(x) { if (isArray(x)) { return x.map(function (v) { return _fromValue(x); }); } if (isObject(x)) { for (var k in x) { x[k] = _fromValue(x[k]); } return x; } if (false === x) { return 'false'; } if (null === x) { return 'null'; } if (true === x) { return 'true'; } return "" + x; }; var toCaseCamel = function toCaseCamel(x) { return x.replace(/[-_.](\w)/g, function (m0, m1) { return toCaseUpper(m1); }); }; var toCaseLower = function toCaseLower(x) { return x.toLowerCase(); }; var toCaseUpper = function toCaseUpper(x) { return x.toUpperCase(); }; var toCount = function toCount(x) { return x.length; }; var toJSON = function toJSON(x) { return JSON.stringify(x); }; var toMapCount = function toMapCount(x) { return x.size; }; var toNumber = function toNumber(x, base) { if (base === void 0) { base = 10; } return base ? parseInt(x, base) : parseFloat(x); }; var toSetCount = function toSetCount(x) { return x.size; }; var toString = function toString(x, base) { return isNumber(x) ? x.toString(base) : "" + x; }; var _toValue = function toValue(x) { if (isArray(x)) { return x.map(function (v) { return _toValue(v); }); } if (isObject(x)) { for (var k in x) { x[k] = _toValue(x[k]); } return x; } if (isString(x) && isNumeric(x)) { if ('0' === x[0] && -1 === x.indexOf('.')) { return x; } return toNumber(x); } if ('false' === x) { return false; } if ('null' === x) { return null; } if ('true' === x) { return true; } return x; }; function _toIterator(v) { return v[Symbol.iterator](); } var forEachArray = function forEachArray(array, at) { for (var i = 0, j = toCount(array), v; i < j; ++i) { v = at.call(array, array[i], i); if (-1 === v) { array.splice(i, 1); continue; } if (0 === v) { break; } if (1 === v) { continue; } } return array; }; var forEachMap = function forEachMap(map, at) { var items = _toIterator(map), item = items.next(); while (!item.done) { var _item$value = _maybeArrayLike(_slicedToArray, item.value, 2), k = _item$value[0], v = _item$value[1]; v = at.call(map, v, k); if (-1 === v) { letValueInMap(k, map); } else if (0 === v) { break; } item = items.next(); } return map; }; var forEachObject = function forEachObject(object, at) { var v; for (var k in object) { v = at.call(object, object[k], k); if (-1 === v) { delete object[k]; continue; } if (0 === v) { break; } if (1 === v) { continue; } } return object; }; var forEachSet = function forEachSet(set, at) { var items = _toIterator(set), item = items.next(); while (!item.done) { var k = void 0, v = item.value; v = at.call(set, v, k = v); if (-1 === v) { letValueInMap(k, set); } else if (0 === v) { break; } item = items.next(); } return set; }; var getPrototype = function getPrototype(of) { return of.prototype; }; var getReference = function getReference(key) { return getValueInMap(key, references) || null; }; var getValueInMap = function getValueInMap(k, map) { return map.get(k); }; var hasKeyInMap = function hasKeyInMap(k, map) { return map.has(k); }; var letReference = function letReference(k) { return letValueInMap(k, references); }; var letValueInMap = function letValueInMap(k, map) { return map.delete(k); }; var onAnimationsEnd = function onAnimationsEnd(node, task) { return isFunction(node.getAnimations) ? Promise.all(node.getAnimations().map(function (v) { return v.finished; })).then(task) : task(), node; }; var setObjectAttributes = function setObjectAttributes(of, attributes, asStaticAttributes) { if (!asStaticAttributes) { of = getPrototype(of); } return forEachObject(attributes, function (v, k) { Object.defineProperty(of, k, v); }), of; }; var setObjectMethods = function setObjectMethods(of, methods, asStaticMethods) { { of = getPrototype(of); } return forEachObject(methods, function (v, k) { of [k] = v; }), of; }; var setReference = function setReference(key, value) { return setValueInMap(key, value, references); }; var setValueInMap = function setValueInMap(k, v, map) { return map.set(k, v); }; var toValueFirstFromMap = function toValueFirstFromMap(map) { return toValuesFromMap(map).shift(); }; var toValuesFromMap = function toValuesFromMap(map) { var r = []; return forEachMap(map, function (v) { r.push(v); }), r; }; var references = new WeakMap(); function _toArray$1(iterable) { return Array.from(iterable); } var D = document; var W = window; var B = D.body; var R = D.documentElement; var getAria = function getAria(node, aria, parseValue) { if (parseValue === void 0) { parseValue = true; } return getAttribute(node, 'aria-' + aria, parseValue); }; var getAttribute = function getAttribute(node, attribute, parseValue) { if (parseValue === void 0) { parseValue = true; } if (!hasAttribute(node, attribute)) { return null; } var value = node.getAttribute(attribute); return parseValue ? _toValue(value) : value; }; var getAttributes = function getAttributes(node, parseValue) { if (parseValue === void 0) { parseValue = true; } var attributes = node.attributes, values = {}; forEachArray(attributes, function (v) { var name = v.name, value = v.value; values[name] = parseValue ? _toValue(value) : value; }); return values; }; var getChildFirst = function getChildFirst(parent, anyNode) { return parent['first' + (anyNode ? "" : 'Element') + 'Child'] || null; }; var getChildLast = function getChildLast(parent, anyNode) { return parent['last' + (anyNode ? "" : 'Element') + 'Child'] || null; }; var getChildren = function getChildren(parent, index, anyNode) { var children = _toArray$1(parent['child' + (anyNode ? 'Nodes' : 'ren')]); return isNumber(index) ? children[index] || null : children; }; var getDatum = function getDatum(node, datum, parseValue) { if (parseValue === void 0) { parseValue = true; } var value = getAttribute(node, 'data-' + datum, parseValue), v = (value + "").trim(); if (parseValue && v && ('[' === v[0] && ']' === v.slice(-1) || '{' === v[0] && '}' === v.slice(-1)) && null !== (v = fromJSON(value))) { return v; } return value; }; var getElement = function getElement(query, scope) { return (scope || D).querySelector(query); }; var getElementIndex = function getElementIndex(node, anyNode) { if (!node || !getParent(node)) { return -1; } var index = 0; while (node = getPrev(node, anyNode)) { ++index; } return index; }; var getHTML = function getHTML(node, trim) { if (trim === void 0) { trim = true; } var state = 'innerHTML'; if (!hasState(node, state)) { return false; } var content = node[state]; content = trim ? content.trim() : content; return "" !== content ? content : null; }; var getID = function getID(node, batch) { if (batch === void 0) { batch = 'e:'; } if (hasID(node)) { return getAttribute(node, 'id'); } if (!isSet(theID[batch])) { theID[batch] = 0; } return batch + toString(Date.now() + (theID[batch] += 1), 16); }; var getName = function getName(node) { return toCaseLower(node && node.nodeName || "") || null; }; var getNext = function getNext(node, anyNode) { return node['next' + (anyNode ? "" : 'Element') + 'Sibling'] || null; }; var getParent = function getParent(node, query) { if (query) { return node.closest(query) || null; } return node.parentNode || null; }; var getParentForm = function getParentForm(node) { var state = 'form'; if (hasState(node, state) && state === getName(node[state])) { return node[state]; } return getParent(node, state); }; var getPrev = function getPrev(node, anyNode) { return node['previous' + (anyNode ? "" : 'Element') + 'Sibling'] || null; }; var getRole = function getRole(node) { return getAttribute(node, 'role'); }; var getStyle = function getStyle(node, style, parseValue) { var value = W.getComputedStyle(node).getPropertyValue(style); return value || "" === value || 0 === value ? value : null; }; var getState = function getState(node, state) { return hasState(node, state) && node[state] || null; }; var getText = function getText(node, trim) { if (trim === void 0) { trim = true; } var state = 'textContent'; if (!hasState(node, state)) { return false; } var content = node[state]; content = trim ? content.trim() : content; return "" !== content ? content : null; }; var getType = function getType(node) { return node && node.nodeType || null; }; var getValue = function getValue(node, parseValue) { var value = (node.value || "").replace(/\r?\n|\r/g, '\n'); value = parseValue ? _toValue(value) : value; return "" !== value ? value : null; }; var hasAttribute = function hasAttribute(node, attribute) { return node.hasAttribute(attribute); }; var hasID = function hasID(node) { return hasAttribute(node, 'id'); }; var hasState = function hasState(node, state) { return state in node; }; var isDisabled = function isDisabled(node) { return node.disabled; }; var isReadOnly = function isReadOnly(node) { return node.readOnly; }; var isRequired = function isRequired(node) { return node.required; }; var isWindow = function isWindow(node) { return node === W; }; var letAria = function letAria(node, aria) { return letAttribute(node, 'aria-' + aria); }; var letAttribute = function letAttribute(node, attribute) { return node.removeAttribute(attribute), node; }; var letClass = function letClass(node, value) { return node.classList.remove(value), node; }; var letDatum = function letDatum(node, datum) { return letAttribute(node, 'data-' + datum); }; var letElement = function letElement(node) { var parent = getParent(node); return node.remove(), parent; }; var letHTML = function letHTML(node) { var state = 'innerHTML'; return hasState(node, state) && (node[state] = ""), node; }; var letID = function letID(node) { return letAttribute(node, 'id'); }; var letStyle = function letStyle(node, style) { return node.style[toCaseCamel(style)] = null, node; }; var setAria = function setAria(node, aria, value) { return setAttribute(node, 'aria-' + aria, true === value ? 'true' : value); }; var setArias = function setArias(node, data) { return forEachObject(data, function (v, k) { v || "" === v || 0 === v ? setAria(node, k, v) : letAria(node, k); }), node; }; var setAttribute = function setAttribute(node, attribute, value) { if (true === value) { value = attribute; } return node.setAttribute(attribute, _fromValue(value)), node; }; var setAttributes = function setAttributes(node, attributes) { return forEachObject(attributes, function (v, k) { if ('aria' === k && isObject(v)) { return setArias(node, v), 1; } if ('class' === k) { return setClasses(node, v), 1; } if ('data' === k && isObject(v)) { return setData(node, v), 1; } if ('style' === k && isObject(v)) { return setStyles(node, v), 1; } v || "" === v || 0 === v ? setAttribute(node, k, v) : letAttribute(node, k); }), node; }; var setChildLast = function setChildLast(parent, node) { return parent.append(node), node; }; var setClass = function setClass(node, value) { return node.classList.add(value), node; }; var setClasses = function setClasses(node, classes) { if (isArray(classes)) { return forEachArray(classes, function (k) { return setClass(node, k); }), node; } if (isObject(classes)) { return forEachObject(classes, function (v, k) { return v ? setClass(node, k) : letClass(node, k); }), node; } return node.className = classes, node; }; var setData = function setData(node, data) { return forEachObject(data, function (v, k) { v || "" === v || 0 === v ? setDatum(node, k, v) : letDatum(node, k); }), node; }; var setDatum = function setDatum(node, datum, value) { if (isArray(value) || isObject(value)) { value = toJSON(value); } return setAttribute(node, 'data-' + datum, true === value ? 'true' : value); }; var setElement = function setElement(node, content, attributes, options) { node = isString(node) ? D.createElement(node, isString(options) ? { is: options } : options) : node; if (isArray(content) && toCount(content)) { letHTML(node); forEachArray(content, function (v) { return setChildLast(isString(v) ? setElementText(v) : v); }); } else if (isObject(content)) { attributes = content; content = false; } if (isString(content)) { setHTML(node, content); } if (isObject(attributes)) { return setAttributes(node, attributes), node; } return node; }; var setElementText = function setElementText(text) { return isString(text) ? text = D.createTextNode(text) : text, text; }; var setHTML = function setHTML(node, content, trim) { if (trim === void 0) { trim = true; } if (null === content) { return node; } var state = 'innerHTML'; return hasState(node, state) && (node[state] = trim ? content.trim() : content), node; }; var setID = function setID(node, value, batch) { if (batch === void 0) { batch = 'e:'; } return setAttribute(node, 'id', isSet(value) ? value : getID(node, batch)); }; var setNext = function setNext(current, node) { return current.after(node), node; }; var setStyle = function setStyle(node, style, value) { if (isNumber(value)) { value += 'px'; } return node.style[toCaseCamel(style)] = _fromValue(value), node; }; var setStyles = function setStyles(node, styles) { return forEachObject(styles, function (v, k) { v || "" === v || 0 === v ? setStyle(node, k, v) : letStyle(node, k); }), node; }; var setText = function setText(node, content, trim) { if (trim === void 0) { trim = true; } if (null === content) { return node; } var state = 'textContent'; return hasState(node, state) && (node[state] = trim ? content.trim() : content), node; }; var setValue = function setValue(node, value) { if (null === value) { return letAttribute(node, 'value'); } return node.value = _fromValue(value), node; }; var theID = {}; var now = Date.now; var history = new WeakMap(); var historyIndex = new WeakMap(); var _getSelection = function _getSelection() { return D.getSelection(); }; var _setRange = function _setRange() { return D.createRange(); }; // The `node` parameter is currently not in use var hasSelection = function hasSelection(node, selection) { return (selection || _getSelection()).rangeCount > 0; }; // <https://stackoverflow.com/a/6691294/1163000> // The `node` parameter is currently not in use var insertAtSelection = function insertAtSelection(node, content, mode, selection) { selection = selection || _getSelection(); var from, range, to; if (!hasSelection(node, selection)) { return false; } range = selection.getRangeAt(0); range.deleteContents(); to = D.createDocumentFragment(); var nodeCurrent, nodeFirst, nodeLast; if (isString(content)) { from = setElement('div'); setHTML(from, content); while (nodeCurrent = getChildFirst(from, 1)) { nodeLast = setChildLast(to, nodeCurrent); } } else if (isArray(content)) { forEachArray(content, function (v) { return nodeLast = setChildLast(to, v); }); } else { nodeLast = setChildLast(to, content); } nodeFirst = getChildFirst(to, 1); range.insertNode(to); if (nodeLast) { range = range.cloneRange(); range.setStartAfter(nodeLast); range.setStartBefore(nodeFirst); { range.collapse(); } setSelection(node, range, selectToNone(node, selection)); } return selection; }; // The `node` parameter is currently not in use var letSelection = function letSelection(node, selection) { selection = selection || _getSelection(); return selection.empty(), selection; }; var redoState = function redoState(node, selection) { var _getValueInMap, _getValueInMap2; var h = (_getValueInMap = getValueInMap(node, history)) != null ? _getValueInMap : [], i = (_getValueInMap2 = getValueInMap(node, historyIndex)) != null ? _getValueInMap2 : toCount(h) - 1, j; if (!(j = h[i + 1])) { return restoreSelection(node, h[i][1], selection); } i++; setValueInMap(node, i, historyIndex); return setHTML(node, j[0]), restoreSelection(node, j[1], selection); }; var resetState = function resetState(node, selection) { letValueInMap(node, history); letValueInMap(node, historyIndex); return saveState(node, selection); }; // <https://stackoverflow.com/a/13950376/1163000> var restoreSelection = function restoreSelection(node, store, selection) { var index = 0, range = _setRange(); range.setStart(node, 0); range.collapse(true); var exit, hasStart, nodeCurrent, nodeStack = [node]; while (!exit && (nodeCurrent = nodeStack.pop())) { if (3 === getType(nodeCurrent)) { var indexNext = index + toCount(nodeCurrent); if (!hasStart && store[0] >= index && store[0] <= indexNext) { range.setStart(nodeCurrent, store[0] - index); hasStart = true; } if (hasStart && store[1] >= index && store[1] <= indexNext) { exit = true; range.setEnd(nodeCurrent, store[1] - index); } index = indexNext; } else { forEachArray(getChildren(nodeCurrent, null, 1), function (v) { return nodeStack.push(v); }); } } return setSelection(node, range, letSelection(node, selection)); }; // <https://stackoverflow.com/a/13950376/1163000> var saveSelection = function saveSelection(node, selection) { var range = (_getSelection()).getRangeAt(0), rangeClone = range.cloneRange(); rangeClone.selectNodeContents(node); rangeClone.setEnd(range.startContainer, range.startOffset); var start = toCount(rangeClone + ""); return [start, start + toCount(range + "")]; }; var saveState = function saveState(node, selection) { var _getValueInMap3, _getValueInMap4, _getHTML; var h = (_getValueInMap3 = getValueInMap(node, history)) != null ? _getValueInMap3 : [], i = (_getValueInMap4 = getValueInMap(node, historyIndex)) != null ? _getValueInMap4 : toCount(h) - 1, j, v = (_getHTML = getHTML(node)) != null ? _getHTML : ""; j = hasSelection(node, selection) ? saveSelection(node) : []; if (h[i] && v === h[i][0] && j[0] === h[i][1][0] && j[1] === h[i][1][1]) { return node; // No change } // Trim future history if `undoState()` was used if (i < toCount(h) - 1) { h.splice(i + 1); } h.push([v, j, now()]); setValueInMap(node, h, history); setValueInMap(node, ++i, historyIndex); return node; }; var selectTo = function selectTo(node, mode, selection) { selection = selection || _getSelection(); letSelection(node, selection); var range = _setRange(); range.selectNodeContents(node); selection = setSelection(node, range, selection); if (1 === mode) { selection.collapseToEnd(); } else if (-1 === mode) { selection.collapseToStart(); } else; }; // The `node` parameter is currently not in use var selectToNone = function selectToNone(node, selection) { selection = selection || _getSelection(); // selection.removeAllRanges(); if (selection.rangeCount) { selection.removeRange(selection.getRangeAt(0)); } return selection; }; // The `node` parameter is currently not in use var setSelection = function setSelection(node, range, selection) { selection = selection || _getSelection(); if (isArray(range)) { return restoreSelection(node, range, selection); } return selection.addRange(range), selection; }; var undoState = function undoState(node, selection) { var _getValueInMap5, _getValueInMap6; var h = (_getValueInMap5 = getValueInMap(node, history)) != null ? _getValueInMap5 : [], i = (_getValueInMap6 = getValueInMap(node, historyIndex)) != null ? _getValueInMap6 : toCount(h) - 1, j; if (!(j = h[i - 1])) { return restoreSelection(node, h[i][1], selection); } i--; setValueInMap(node, i, historyIndex); return setHTML(node, j[0]), restoreSelection(node, j[1], selection); }; function _toArray(iterable) { return Array.from(iterable); } var clearTimeout = W.clearTimeout, setTimeout = W.setTimeout; // For better minification var debounce = function debounce(task, time) { var stickyTime = isInteger(time) && time >= 0, timer; return [function () { var _this = this; timer && clearTimeout(timer); var lot = _toArray(arguments); if (!stickyTime) { time = lot.shift(); } timer = setTimeout(function () { return task.apply(_this, lot); }, time); }, function () { timer = clearTimeout(timer); }]; }; var delay = function delay(task, time) { var stickyTime = isInteger(time) && time >= 0, timer; return [function () { var _this2 = this; var lot = _toArray(arguments); if (!stickyTime) { time = lot.shift(); } timer = setTimeout(function () { return task.apply(_this2, lot); }, time); }, function () { timer && clearTimeout(timer); }]; }; var getRect = function getRect(node) { var h, rect, w, x, y, X, Y; if (isWindow(node)) { x = node.pageXOffset || R.scrollLeft || B.scrollLeft; y = node.pageYOffset || R.scrollTop || B.scrollTop; w = node.innerWidth; h = node.innerHeight; } else { rect = node.getBoundingClientRect(); x = rect.left; y = rect.top; w = rect.width; h = rect.height; X = rect.right; Y = rect.bottom; } return [x, y, w, h, X, Y]; }; var getScroll = function getScroll(node) { return [node.scrollLeft, node.scrollTop]; }; var setScroll = function setScroll(node, data) { node.scrollLeft = data[0]; node.scrollTop = data[1]; return node; }; function hook($, $$) { $$ = $$ || $; $$.fire = function (event, data, that) { var $ = this, hooks = $.hooks; if (!isSet(hooks[event])) { return $; } return forEachArray(hooks[event], function (v) { v.apply(that || $, data); }), $; }; $$.off = function (event, task) { var $ = this, hooks = $.hooks; if (!isSet(event)) { return hooks = {}, $; } if (isSet(hooks[event])) { if (isSet(task)) { var j = toCount(hooks[event]); // Clean-up empty hook(s) if (0 === j) { delete hooks[event]; } else { for (var i = 0; i < j; ++i) { if (task === hooks[event][i]) { hooks[event].splice(i, 1); break; } } } } else { delete hooks[event]; } } return $; }; $$.on = function (event, task) { var $ = this, hooks = $.hooks; if (!isSet(hooks[event])) { hooks[event] = []; } if (isSet(task)) { hooks[event].push(task); } return $; }; return $.hooks = {}, $; } var offEvent = function offEvent(name, node, then) { node.removeEventListener(name, then); }; var offEventDefault = function offEventDefault(e) { return e && e.preventDefault(); }; var offEventPropagation = function offEventPropagation(e) { return e && e.stopPropagation(); }; var onEvent = function onEvent(name, node, then, options) { if (options === void 0) { options = false; } node.addEventListener(name, then, options); }; var isPattern = function isPattern(pattern) { return isInstance(pattern, RegExp); }; var toPattern = function toPattern(pattern, opt) { if (isPattern(pattern)) { return pattern; } return new RegExp(pattern, isSet(opt) ? opt : 'g'); }; var EVENT_DOWN = 'down'; var EVENT_MOVE = 'move'; var EVENT_UP = 'up'; var EVENT_BLUR = 'blur'; var EVENT_CUT = 'cut'; var EVENT_FOCUS = 'focus'; var EVENT_INPUT = 'input'; var EVENT_INVALID = 'invalid'; var EVENT_KEY = 'key'; var EVENT_KEY_DOWN = EVENT_KEY + EVENT_DOWN; var EVENT_MOUSE = 'mouse'; var EVENT_MOUSE_DOWN = EVENT_MOUSE + EVENT_DOWN; var EVENT_MOUSE_MOVE = EVENT_MOUSE + EVENT_MOVE; var EVENT_MOUSE_UP = EVENT_MOUSE + EVENT_UP; var EVENT_PASTE = 'paste'; var EVENT_RESET = 'reset'; var EVENT_RESIZE = 'resize'; var EVENT_SCROLL = 'scroll'; var EVENT_SUBMIT = 'submit'; var EVENT_TOUCH = 'touch'; var EVENT_TOUCH_END = EVENT_TOUCH + 'end'; var EVENT_TOUCH_MOVE = EVENT_TOUCH + EVENT_MOVE; var EVENT_TOUCH_START = EVENT_TOUCH + 'start'; var EVENT_WHEEL = 'wheel'; var KEY_DOWN = 'Down'; var KEY_LEFT = 'Left'; var KEY_RIGHT = 'Right'; var KEY_UP = 'Up'; var KEY_ARROW = 'Arrow'; var KEY_ARROW_DOWN = KEY_ARROW + KEY_DOWN; var KEY_ARROW_LEFT = KEY_ARROW + KEY_LEFT; var KEY_ARROW_RIGHT = KEY_ARROW + KEY_RIGHT; var KEY_ARROW_UP = KEY_ARROW + KEY_UP; var KEY_BEGIN = 'Home'; var KEY_DELETE_LEFT = 'Backspace'; var KEY_DELETE_RIGHT = 'Delete'; var KEY_END = 'End'; var KEY_ENTER = 'Enter'; var KEY_ESCAPE = 'Escape'; var KEY_PAGE = 'Page'; var KEY_PAGE_DOWN = KEY_PAGE + KEY_DOWN; var KEY_PAGE_UP = KEY_PAGE + KEY_UP; var KEY_TAB = 'Tab'; var KEY_Y = 'y'; var KEY_Z = 'z'; var OPTION_SELF = 0; var OPTION_TEXT = 1; var TOKEN_CONTENTEDITABLE = 'contenteditable'; var TOKEN_DISABLED = 'disabled'; var TOKEN_FALSE = 'false'; var TOKEN_GROUP = 'group'; var TOKEN_INVALID = 'invalid'; var TOKEN_OPTGROUP = 'opt' + TOKEN_GROUP; var TOKEN_READONLY = 'readonly'; var TOKEN_READ_ONLY = 'readOnly'; var TOKEN_REQUIRED = 'required'; var TOKEN_SELECTED = 'selected'; var TOKEN_TABINDEX = 'tabindex'; var TOKEN_TAB_INDEX = 'tabIndex'; var TOKEN_TEXT = 'text'; var TOKEN_TRUE = 'true'; var TOKEN_VALUE = 'value'; var TOKEN_VALUES = TOKEN_VALUE + 's'; var TOKEN_VISIBILITY = 'visibility'; var VALUE_SELF = 0; var VALUE_TEXT = 1; var VALUE_X = 2; var filter = debounce(function ($, input, _options, selectOnly) { var query = isString(input) ? input : getText(input) || "", q = toCaseLower(query), _mask = $._mask, mask = $.mask, self = $.self, state = $.state, options = _mask.options, pattern = self.pattern, strict = state.strict, option; var count = _options.count(); if (selectOnly) { forEachMap(_options, function (v) { if ("" !== q && (q === toCaseLower(getText(v[2]).replace(/\u200C/g, "")).slice(0, toCount(q)) || q === toCaseLower(getOptionValue(v[2])).slice(0, toCount(q))) && !getAria(v[2], TOKEN_DISABLED)) { selectToOption(v[2], $); return 0; } --count; }); } else { forEachMap(_options, function (v) { if ("" === q || hasValue(q, toCaseLower(getText(v[2]).replace(/\u200C/g, "") + '\t' + getOptionValue(v[2])))) { v[2].hidden = false; } else { v[2].hidden = true; --count; } }); options.hidden = !count; selectToOptionsNone($); if (strict) { // Silently select the first option without affecting the currently typed query and focus/select state if (count && "" !== q && (option = goToOptionFirst($))) { letAria(mask, TOKEN_INVALID); setAria(option, TOKEN_SELECTED, true); option.$[OPTION_SELF][TOKEN_SELECTED] = true; setValue(self, getOptionValue(option)); } else { // No other option(s) are available to query if ("" !== q) { setAria(mask, TOKEN_INVALID, true); } else { letAria(mask, TOKEN_INVALID); } setValue(self, ""); } } else { letAria(mask, TOKEN_INVALID); setValue(self, query); if (pattern) { if (!count && "" !== q && !toPattern('^' + pattern + '$', "").test(query)) { setAria(mask, TOKEN_INVALID, true); } } } } $.fire('search', [query = "" !== query ? query : null]); var call = state.options; // Only fetch when no other option(s) are available to query, or when the current search query is empty if ((0 === count || "" === q) && isFunction(call)) { setAria(mask, 'busy', true); call = call.call($, query); if (isInstance(call, Promise)) { call.then(function (v) { createOptions($, v); letAria(mask, 'busy'); $.fire('load', [query, $[TOKEN_VALUES]])[goToOptionFirst($) ? 'enter' : 'exit']().fit(); }); } else { createOptions($, call); } } })[0]; var _delay = delay(function (picker) { letAria(picker.mask, TOKEN_INVALID); }), _delay2 = _maybeArrayLike(_slicedToArray, _delay, 2), letError = _delay2[0], letErrorAbort = _delay2[1]; var setError = function setError(picker) { var mask = picker.mask, state = picker.state, time = state.time, error = time.error; if (isInteger(error) && error > 0) { setAria(mask, TOKEN_INVALID, true); } }; var _delay3 = delay(function ($) { saveState($); }, 1), _delay4 = _maybeArrayLike(_slicedToArray, _delay3, 1), saveStateLazy = _delay4[0]; var _delay5 = delay(function (picker) { var _mask = picker._mask, input = _mask.input; toggleHintByValue(picker, getText(input, 0)); }), _delay6 = _maybeArrayLike(_slicedToArray, _delay5, 1), toggleHint = _delay6[0]; var toggleHintByValue = function toggleHintByValue(picker, value) { var _mask = picker._mask, hint = _mask.hint; value ? setStyle(hint, TOKEN_VISIBILITY, 'hidden') : letStyle(hint, TOKEN_VISIBILITY); }; var name = 'OptionPicker'; function createOptions($, options) { var map = isInstance(options, Map) ? options : new Map(); if (isArray(options)) { forEachArray(options, function (option) { if (isArray(option)) { var _option$, _option$2, _option$1$TOKEN_VALUE; option[0] = (_option$ = option[0]) != null ? _option$ : ""; option[1] = (_option$2 = option[1]) != null ? _option$2 : {}; setValueInMap(_toValue((_option$1$TOKEN_VALUE = option[1][TOKEN_VALUE]) != null ? _option$1$TOKEN_VALUE : option[0]), option, map); } else { setValueInMap(_toValue(option), [option, {}], map); } }); } else if (isObject(options, 0)) { forEachObject(options, function (v, k) { if (isArray(v)) { var _v$, _v$2, _v$1$TOKEN_VALUE; options[k][0] = (_v$ = v[0]) != null ? _v$ : ""; options[k][1] = (_v$2 = v[1]) != null ? _v$2 : {}; setValueInMap(_toValue((_v$1$TOKEN_VALUE = v[1][TOKEN_VALUE]) != null ? _v$1$TOKEN_VALUE : k), v, map); } else { setValueInMap(_toValue(k), [v, {}], map); } }); } var _options = $._options, self = $.self, state = $.state; state.n; var r = [], value = getValue(self); // Reset the option(s) data, but leave the typed query in place, and do not fire the `let.options` hook _options.let(null, 0, 0); forEachMap(map, function (v, k) { var _v$1$TOKEN_VALUE3; if (isArray(v) && v[1] && (!getState(v[1], 'active') || v[1].active) && v[1].mark) { var _v$1$TOKEN_VALUE2; r.push((_v$1$TOKEN_VALUE2 = v[1][TOKEN_VALUE]) != null ? _v$1$TOKEN_VALUE2 : k); } // Set the option data, but do not fire the `set.option` hook _options.set(_toValue(isArray(v) && v[1] ? (_v$1$TOKEN_VALUE3 = v[1][TOKEN_VALUE]) != null ? _v$1$TOKEN_VALUE3 : k : k), v, 0); }); if (!isFunction(state.options)) { state.options = map; } if (0 === toCount(r)) { // If there is no selected option(s), get it from the current value if (hasKeyInMap(_toValue(value), map)) { return [value]; } // Or get it from the first option if (value = getOptionSelected($)) { return [getOptionValue(value)]; } } return r; } function focusTo(node) { return node.focus(), node; } function focusToOption(option, picker) { if (option) { return focusTo(option), option; } } function focusToOptionFirst(picker, k) { var option; if (option = goToOptionFirst(picker, k)) { return focusToOption(option); } } function focusToOptionLast(picker) { return focusToOptionFirst(picker, 'Last'); } function getOptionNext(option) { var optionNext = getNext(option), optionParent; // Skip disabled and hidden option(s)… while (optionNext && (getAria(optionNext, TOKEN_DISABLED) || optionNext.hidden)) { optionNext = getNext(optionNext); } if (optionNext) { // Next option is a group? if (TOKEN_GROUP === getRole(optionNext)) { optionNext = getChildFirst(optionNext); } // Is the last option? } else { // Is in a group? if ((optionParent = getParent(option)) && TOKEN_GROUP === getRole(optionParent)) { optionNext = getNext(optionParent); } // Next option is a group? if (optionNext && TOKEN_GROUP === getRole(optionNext)) { optionNext = getChildFirst(optionNext); } } // Skip disabled and hidden option(s)… while (optionNext && (getAria(optionNext, TOKEN_DISABLED) || optionNext.hidden)) { optionNext = getNext(optionNext); } return optionNext; } function getOptionPrev(option) { var optionParent, optionPrev = getPrev(option); // Skip disabled and hidden option(s)… while (optionPrev && (getAria(optionPrev, TOKEN_DISABLED) || optionPrev.hidden)) { optionPrev = getPrev(optionPrev); } if (optionPrev) { // Previous option is a group? if (TOKEN_GROUP === getRole(optionPrev)) { optionPrev = getChildLast(optionPrev); } // Is the first option? } else { // Is in a group? if ((optionParent = getParent(option)) && TOKEN_GROUP === getRole(optionParent)) { optionPrev = getPrev(optionParent); } // Previous option is a group? if (optionPrev && TOKEN_GROUP === getRole(optionPrev)) { optionPrev = getChildLast(optionPrev); } } // Skip disabled and hidden option(s)… while (optionPrev && (getAria(optionPrev, TOKEN_DISABLED) || optionPrev.hidden)) { optionPrev = getPrev(optionPrev); } return optionPrev; } function getOptionSelected($, strict) { var _options = $._options, self = $.self, selected; forEachMap(_options, function (v, k) { if (isArray(v) && v[2] && !getAria(v[2], TOKEN_DISABLED) && getAria(v[2], TOKEN_SELECTED)) { return selected = v[2], 0; } }); if (!isSet(selected) && (strict || !isInput(self))) { // Select the first option forEachMap(_options, function (v, k) { return selected = v[2], 0; }); } return selected; } function getOptionValue(option, parseValue) { return getValue(option, parseValue); } function getOptions(self) { var map = new Map(); var item, items, itemsParent, selected = [], value = getValue(self); if (isInput(self)) { items = (itemsParent = self.list) ? getChildren(itemsParent) : []; } else { items = getChildren(itemsParent = self); } forEachArray(items, function (v, k) { var attributes = getAttributes(v); attributes.active = true; attributes.mark = false; if (hasState(attributes, TOKEN_DISABLED)) { attributes.active = "" === attributes[TOKEN_DISABLED] ? false : !!attributes[TOKEN_DISABLED]; delete attributes[TOKEN_DISABLED]; } else if (hasState(attributes, TOKEN_SELECTED)) { attributes.mark = "" === attributes[TOKEN_SELECTED] ? true : !!attributes[TOKEN_SELECTED]; delete attributes[TOKEN_SELECTED]; } if (TOKEN_OPTGROUP === ge