index.development.js 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847
  1. /*! @algolia/autocomplete-core 1.5.2 | MIT License | © Algolia, Inc. and contributors | https://github.com/algolia/autocomplete */
  2. (function (global, factory) {
  3. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  4. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  5. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@algolia/autocomplete-core"] = {}));
  6. })(this, (function (exports) { 'use strict';
  7. function ownKeys(object, enumerableOnly) {
  8. var keys = Object.keys(object);
  9. if (Object.getOwnPropertySymbols) {
  10. var symbols = Object.getOwnPropertySymbols(object);
  11. if (enumerableOnly) {
  12. symbols = symbols.filter(function (sym) {
  13. return Object.getOwnPropertyDescriptor(object, sym).enumerable;
  14. });
  15. }
  16. keys.push.apply(keys, symbols);
  17. }
  18. return keys;
  19. }
  20. function _objectSpread2(target) {
  21. for (var i = 1; i < arguments.length; i++) {
  22. var source = arguments[i] != null ? arguments[i] : {};
  23. if (i % 2) {
  24. ownKeys(Object(source), true).forEach(function (key) {
  25. _defineProperty(target, key, source[key]);
  26. });
  27. } else if (Object.getOwnPropertyDescriptors) {
  28. Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
  29. } else {
  30. ownKeys(Object(source)).forEach(function (key) {
  31. Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
  32. });
  33. }
  34. }
  35. return target;
  36. }
  37. function _typeof$1(obj) {
  38. "@babel/helpers - typeof";
  39. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  40. _typeof$1 = function (obj) {
  41. return typeof obj;
  42. };
  43. } else {
  44. _typeof$1 = function (obj) {
  45. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  46. };
  47. }
  48. return _typeof$1(obj);
  49. }
  50. function _defineProperty(obj, key, value) {
  51. if (key in obj) {
  52. Object.defineProperty(obj, key, {
  53. value: value,
  54. enumerable: true,
  55. configurable: true,
  56. writable: true
  57. });
  58. } else {
  59. obj[key] = value;
  60. }
  61. return obj;
  62. }
  63. function _objectWithoutPropertiesLoose(source, excluded) {
  64. if (source == null) return {};
  65. var target = {};
  66. var sourceKeys = Object.keys(source);
  67. var key, i;
  68. for (i = 0; i < sourceKeys.length; i++) {
  69. key = sourceKeys[i];
  70. if (excluded.indexOf(key) >= 0) continue;
  71. target[key] = source[key];
  72. }
  73. return target;
  74. }
  75. function _objectWithoutProperties(source, excluded) {
  76. if (source == null) return {};
  77. var target = _objectWithoutPropertiesLoose(source, excluded);
  78. var key, i;
  79. if (Object.getOwnPropertySymbols) {
  80. var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
  81. for (i = 0; i < sourceSymbolKeys.length; i++) {
  82. key = sourceSymbolKeys[i];
  83. if (excluded.indexOf(key) >= 0) continue;
  84. if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
  85. target[key] = source[key];
  86. }
  87. }
  88. return target;
  89. }
  90. function _toConsumableArray(arr) {
  91. return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray$1(arr) || _nonIterableSpread();
  92. }
  93. function _arrayWithoutHoles(arr) {
  94. if (Array.isArray(arr)) return _arrayLikeToArray$1(arr);
  95. }
  96. function _iterableToArray(iter) {
  97. if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
  98. }
  99. function _unsupportedIterableToArray$1(o, minLen) {
  100. if (!o) return;
  101. if (typeof o === "string") return _arrayLikeToArray$1(o, minLen);
  102. var n = Object.prototype.toString.call(o).slice(8, -1);
  103. if (n === "Object" && o.constructor) n = o.constructor.name;
  104. if (n === "Map" || n === "Set") return Array.from(o);
  105. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen);
  106. }
  107. function _arrayLikeToArray$1(arr, len) {
  108. if (len == null || len > arr.length) len = arr.length;
  109. for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  110. return arr2;
  111. }
  112. function _nonIterableSpread() {
  113. throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  114. }
  115. function _slicedToArray(arr, i) {
  116. return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
  117. }
  118. function _nonIterableRest() {
  119. throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  120. }
  121. function _unsupportedIterableToArray(o, minLen) {
  122. if (!o) return;
  123. if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  124. var n = Object.prototype.toString.call(o).slice(8, -1);
  125. if (n === "Object" && o.constructor) n = o.constructor.name;
  126. if (n === "Map" || n === "Set") return Array.from(o);
  127. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
  128. }
  129. function _arrayLikeToArray(arr, len) {
  130. if (len == null || len > arr.length) len = arr.length;
  131. for (var i = 0, arr2 = new Array(len); i < len; i++) {
  132. arr2[i] = arr[i];
  133. }
  134. return arr2;
  135. }
  136. function _iterableToArrayLimit(arr, i) {
  137. var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
  138. if (_i == null) return;
  139. var _arr = [];
  140. var _n = true;
  141. var _d = false;
  142. var _s, _e;
  143. try {
  144. for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
  145. _arr.push(_s.value);
  146. if (i && _arr.length === i) break;
  147. }
  148. } catch (err) {
  149. _d = true;
  150. _e = err;
  151. } finally {
  152. try {
  153. if (!_n && _i["return"] != null) _i["return"]();
  154. } finally {
  155. if (_d) throw _e;
  156. }
  157. }
  158. return _arr;
  159. }
  160. function _arrayWithHoles(arr) {
  161. if (Array.isArray(arr)) return arr;
  162. }
  163. function _typeof(obj) {
  164. "@babel/helpers - typeof";
  165. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  166. _typeof = function _typeof(obj) {
  167. return typeof obj;
  168. };
  169. } else {
  170. _typeof = function _typeof(obj) {
  171. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  172. };
  173. }
  174. return _typeof(obj);
  175. }
  176. /**
  177. * Decycles objects with circular references.
  178. * This is used to print cyclic structures in development environment only.
  179. */
  180. function decycle(obj) {
  181. var seen = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Set();
  182. if (!obj || _typeof(obj) !== 'object') {
  183. return obj;
  184. }
  185. if (seen.has(obj)) {
  186. return '[Circular]';
  187. }
  188. var newSeen = seen.add(obj);
  189. if (Array.isArray(obj)) {
  190. return obj.map(function (x) {
  191. return decycle(x, newSeen);
  192. });
  193. }
  194. return Object.fromEntries(Object.entries(obj).map(function (_ref) {
  195. var _ref2 = _slicedToArray(_ref, 2),
  196. key = _ref2[0],
  197. value = _ref2[1];
  198. return [key, decycle(value, newSeen)];
  199. }));
  200. }
  201. function flatten(values) {
  202. return values.reduce(function (a, b) {
  203. return a.concat(b);
  204. }, []);
  205. }
  206. var autocompleteId = 0;
  207. function generateAutocompleteId() {
  208. return "autocomplete-".concat(autocompleteId++);
  209. }
  210. function getItemsCount(state) {
  211. if (state.collections.length === 0) {
  212. return 0;
  213. }
  214. return state.collections.reduce(function (sum, collection) {
  215. return sum + collection.items.length;
  216. }, 0);
  217. }
  218. /**
  219. * Throws an error if the condition is not met in development mode.
  220. * This is used to make development a better experience to provide guidance as
  221. * to where the error comes from.
  222. */
  223. function invariant(condition, message) {
  224. if (!condition) {
  225. throw new Error("[Autocomplete] ".concat(typeof message === 'function' ? message() : message));
  226. }
  227. }
  228. var noop = function noop() {};
  229. var version = '1.5.2';
  230. var userAgents = [{
  231. segment: 'autocomplete-core',
  232. version: version
  233. }];
  234. var warnCache = {
  235. current: {}
  236. };
  237. /**
  238. * Logs a warning if the condition is not met.
  239. * This is used to log issues in development environment only.
  240. */
  241. function warn(condition, message) {
  242. if (condition) {
  243. return;
  244. }
  245. var sanitizedMessage = message.trim();
  246. var hasAlreadyPrinted = warnCache.current[sanitizedMessage];
  247. if (!hasAlreadyPrinted) {
  248. warnCache.current[sanitizedMessage] = true; // eslint-disable-next-line no-console
  249. console.warn("[Autocomplete] ".concat(sanitizedMessage));
  250. }
  251. }
  252. function checkOptions(options) {
  253. "development" !== 'production' ? warn(!options.debug, 'The `debug` option is meant for development debugging and should not be used in production.') : void 0;
  254. }
  255. function createInternalCancelablePromise(promise, initialState) {
  256. var state = initialState;
  257. return {
  258. then: function then(onfulfilled, onrejected) {
  259. return createInternalCancelablePromise(promise.then(createCallback(onfulfilled, state, promise), createCallback(onrejected, state, promise)), state);
  260. },
  261. catch: function _catch(onrejected) {
  262. return createInternalCancelablePromise(promise.catch(createCallback(onrejected, state, promise)), state);
  263. },
  264. finally: function _finally(onfinally) {
  265. if (onfinally) {
  266. state.onCancelList.push(onfinally);
  267. }
  268. return createInternalCancelablePromise(promise.finally(createCallback(onfinally && function () {
  269. state.onCancelList = [];
  270. return onfinally();
  271. }, state, promise)), state);
  272. },
  273. cancel: function cancel() {
  274. state.isCanceled = true;
  275. var callbacks = state.onCancelList;
  276. state.onCancelList = [];
  277. callbacks.forEach(function (callback) {
  278. callback();
  279. });
  280. },
  281. isCanceled: function isCanceled() {
  282. return state.isCanceled === true;
  283. }
  284. };
  285. }
  286. function cancelable(promise) {
  287. return createInternalCancelablePromise(promise, {
  288. isCanceled: false,
  289. onCancelList: []
  290. });
  291. }
  292. function createCallback(onResult, state, fallback) {
  293. if (!onResult) {
  294. return fallback;
  295. }
  296. return function callback(arg) {
  297. if (state.isCanceled) {
  298. return arg;
  299. }
  300. return onResult(arg);
  301. };
  302. }
  303. function createCancelablePromiseList() {
  304. var list = [];
  305. return {
  306. add: function add(cancelablePromise) {
  307. list.push(cancelablePromise);
  308. return cancelablePromise.finally(function () {
  309. list = list.filter(function (item) {
  310. return item !== cancelablePromise;
  311. });
  312. });
  313. },
  314. cancelAll: function cancelAll() {
  315. list.forEach(function (promise) {
  316. return promise.cancel();
  317. });
  318. },
  319. isEmpty: function isEmpty() {
  320. return list.length === 0;
  321. }
  322. };
  323. }
  324. /**
  325. * Creates a runner that executes promises in a concurrent-safe way.
  326. *
  327. * This is useful to prevent older promises to resolve after a newer promise,
  328. * otherwise resulting in stale resolved values.
  329. */
  330. function createConcurrentSafePromise() {
  331. var basePromiseId = -1;
  332. var latestResolvedId = -1;
  333. var latestResolvedValue = undefined;
  334. return function runConcurrentSafePromise(promise) {
  335. basePromiseId++;
  336. var currentPromiseId = basePromiseId;
  337. return Promise.resolve(promise).then(function (x) {
  338. // The promise might take too long to resolve and get outdated. This would
  339. // result in resolving stale values.
  340. // When this happens, we ignore the promise value and return the one
  341. // coming from the latest resolved value.
  342. //
  343. // +----------------------------------+
  344. // | 100ms |
  345. // | run(1) +---> R1 |
  346. // | 300ms |
  347. // | run(2) +-------------> R2 (SKIP) |
  348. // | 200ms |
  349. // | run(3) +--------> R3 |
  350. // +----------------------------------+
  351. if (latestResolvedValue && currentPromiseId < latestResolvedId) {
  352. return latestResolvedValue;
  353. }
  354. latestResolvedId = currentPromiseId;
  355. latestResolvedValue = x;
  356. return x;
  357. });
  358. };
  359. }
  360. /**
  361. * Returns the next active item ID from the current state.
  362. *
  363. * We allow circular keyboard navigation from the base index.
  364. * The base index can either be `null` (nothing is highlighted) or `0`
  365. * (the first item is highlighted).
  366. * The base index is allowed to get assigned `null` only if
  367. * `props.defaultActiveItemId` is `null`. This pattern allows to "stop"
  368. * by the actual query before navigating to other suggestions as seen on
  369. * Google or Amazon.
  370. *
  371. * @param moveAmount The offset to increment (or decrement) the last index
  372. * @param baseIndex The current index to compute the next index from
  373. * @param itemCount The number of items
  374. * @param defaultActiveItemId The default active index to fallback to
  375. */
  376. function getNextActiveItemId(moveAmount, baseIndex, itemCount, defaultActiveItemId) {
  377. if (!itemCount) {
  378. return null;
  379. }
  380. if (moveAmount < 0 && (baseIndex === null || defaultActiveItemId !== null && baseIndex === 0)) {
  381. return itemCount + moveAmount;
  382. }
  383. var numericIndex = (baseIndex === null ? -1 : baseIndex) + moveAmount;
  384. if (numericIndex <= -1 || numericIndex >= itemCount) {
  385. return defaultActiveItemId === null ? null : 0;
  386. }
  387. return numericIndex;
  388. }
  389. function getNormalizedSources(getSources, params) {
  390. var seenSourceIds = [];
  391. return Promise.resolve(getSources(params)).then(function (sources) {
  392. invariant(Array.isArray(sources), function () {
  393. return "The `getSources` function must return an array of sources but returned type ".concat(JSON.stringify(_typeof$1(sources)), ":\n\n").concat(JSON.stringify(decycle(sources), null, 2));
  394. });
  395. return Promise.all(sources // We allow `undefined` and `false` sources to allow users to use
  396. // `Boolean(query) && source` (=> `false`).
  397. // We need to remove these values at this point.
  398. .filter(function (maybeSource) {
  399. return Boolean(maybeSource);
  400. }).map(function (source) {
  401. invariant(typeof source.sourceId === 'string', 'A source must provide a `sourceId` string.');
  402. if (seenSourceIds.includes(source.sourceId)) {
  403. throw new Error("[Autocomplete] The `sourceId` ".concat(JSON.stringify(source.sourceId), " is not unique."));
  404. }
  405. seenSourceIds.push(source.sourceId);
  406. var normalizedSource = _objectSpread2({
  407. getItemInputValue: function getItemInputValue(_ref) {
  408. var state = _ref.state;
  409. return state.query;
  410. },
  411. getItemUrl: function getItemUrl() {
  412. return undefined;
  413. },
  414. onSelect: function onSelect(_ref2) {
  415. var setIsOpen = _ref2.setIsOpen;
  416. setIsOpen(false);
  417. },
  418. onActive: noop
  419. }, source);
  420. return Promise.resolve(normalizedSource);
  421. }));
  422. });
  423. }
  424. // We don't have access to the autocomplete source when we call `onKeyDown`
  425. // or `onClick` because those are native browser events.
  426. // However, we can get the source from the suggestion index.
  427. function getCollectionFromActiveItemId(state) {
  428. // Given 3 sources with respectively 1, 2 and 3 suggestions: [1, 2, 3]
  429. // We want to get the accumulated counts:
  430. // [1, 1 + 2, 1 + 2 + 3] = [1, 3, 3 + 3] = [1, 3, 6]
  431. var accumulatedCollectionsCount = state.collections.map(function (collections) {
  432. return collections.items.length;
  433. }).reduce(function (acc, collectionsCount, index) {
  434. var previousValue = acc[index - 1] || 0;
  435. var nextValue = previousValue + collectionsCount;
  436. acc.push(nextValue);
  437. return acc;
  438. }, []); // Based on the accumulated counts, we can infer the index of the suggestion.
  439. var collectionIndex = accumulatedCollectionsCount.reduce(function (acc, current) {
  440. if (current <= state.activeItemId) {
  441. return acc + 1;
  442. }
  443. return acc;
  444. }, 0);
  445. return state.collections[collectionIndex];
  446. }
  447. /**
  448. * Gets the highlighted index relative to a suggestion object (not the absolute
  449. * highlighted index).
  450. *
  451. * Example:
  452. * [['a', 'b'], ['c', 'd', 'e'], ['f']]
  453. * ↑
  454. * (absolute: 3, relative: 1)
  455. */
  456. function getRelativeActiveItemId(_ref) {
  457. var state = _ref.state,
  458. collection = _ref.collection;
  459. var isOffsetFound = false;
  460. var counter = 0;
  461. var previousItemsOffset = 0;
  462. while (isOffsetFound === false) {
  463. var currentCollection = state.collections[counter];
  464. if (currentCollection === collection) {
  465. isOffsetFound = true;
  466. break;
  467. }
  468. previousItemsOffset += currentCollection.items.length;
  469. counter++;
  470. }
  471. return state.activeItemId - previousItemsOffset;
  472. }
  473. function getActiveItem(state) {
  474. var collection = getCollectionFromActiveItemId(state);
  475. if (!collection) {
  476. return null;
  477. }
  478. var item = collection.items[getRelativeActiveItemId({
  479. state: state,
  480. collection: collection
  481. })];
  482. var source = collection.source;
  483. var itemInputValue = source.getItemInputValue({
  484. item: item,
  485. state: state
  486. });
  487. var itemUrl = source.getItemUrl({
  488. item: item,
  489. state: state
  490. });
  491. return {
  492. item: item,
  493. itemInputValue: itemInputValue,
  494. itemUrl: itemUrl,
  495. source: source
  496. };
  497. }
  498. function isOrContainsNode(parent, child) {
  499. return parent === child || parent.contains(child);
  500. }
  501. function mapToAlgoliaResponse(rawResults) {
  502. var results = rawResults.map(function (result) {
  503. var _hits;
  504. return _objectSpread2(_objectSpread2({}, result), {}, {
  505. hits: (_hits = result.hits) === null || _hits === void 0 ? void 0 : _hits.map(function (hit) {
  506. // Bring support for the Insights plugin.
  507. return _objectSpread2(_objectSpread2({}, hit), {}, {
  508. __autocomplete_indexName: result.index,
  509. __autocomplete_queryID: result.queryID
  510. });
  511. })
  512. });
  513. });
  514. return {
  515. results: results,
  516. hits: results.map(function (result) {
  517. return result.hits;
  518. }).filter(Boolean),
  519. facetHits: results.map(function (result) {
  520. var _facetHits;
  521. return (_facetHits = result.facetHits) === null || _facetHits === void 0 ? void 0 : _facetHits.map(function (facetHit) {
  522. // Bring support for the highlighting components.
  523. return {
  524. label: facetHit.value,
  525. count: facetHit.count,
  526. _highlightResult: {
  527. label: {
  528. value: facetHit.highlighted
  529. }
  530. }
  531. };
  532. });
  533. }).filter(Boolean)
  534. };
  535. }
  536. function createStore(reducer, props, onStoreStateChange) {
  537. var state = props.initialState;
  538. return {
  539. getState: function getState() {
  540. return state;
  541. },
  542. dispatch: function dispatch(action, payload) {
  543. var prevState = _objectSpread2({}, state);
  544. state = reducer(state, {
  545. type: action,
  546. props: props,
  547. payload: payload
  548. });
  549. onStoreStateChange({
  550. state: state,
  551. prevState: prevState
  552. });
  553. },
  554. pendingRequests: createCancelablePromiseList()
  555. };
  556. }
  557. function getAutocompleteSetters(_ref) {
  558. var store = _ref.store;
  559. var setActiveItemId = function setActiveItemId(value) {
  560. store.dispatch('setActiveItemId', value);
  561. };
  562. var setQuery = function setQuery(value) {
  563. store.dispatch('setQuery', value);
  564. };
  565. var setCollections = function setCollections(rawValue) {
  566. var baseItemId = 0;
  567. var value = rawValue.map(function (collection) {
  568. return _objectSpread2(_objectSpread2({}, collection), {}, {
  569. // We flatten the stored items to support calling `getAlgoliaResults`
  570. // from the source itself.
  571. items: flatten(collection.items).map(function (item) {
  572. return _objectSpread2(_objectSpread2({}, item), {}, {
  573. __autocomplete_id: baseItemId++
  574. });
  575. })
  576. });
  577. });
  578. store.dispatch('setCollections', value);
  579. };
  580. var setIsOpen = function setIsOpen(value) {
  581. store.dispatch('setIsOpen', value);
  582. };
  583. var setStatus = function setStatus(value) {
  584. store.dispatch('setStatus', value);
  585. };
  586. var setContext = function setContext(value) {
  587. store.dispatch('setContext', value);
  588. };
  589. return {
  590. setActiveItemId: setActiveItemId,
  591. setQuery: setQuery,
  592. setCollections: setCollections,
  593. setIsOpen: setIsOpen,
  594. setStatus: setStatus,
  595. setContext: setContext
  596. };
  597. }
  598. function getDefaultProps(props, pluginSubscribers) {
  599. var _props$id;
  600. /* eslint-disable no-restricted-globals */
  601. var environment = typeof window !== 'undefined' ? window : {};
  602. /* eslint-enable no-restricted-globals */
  603. var plugins = props.plugins || [];
  604. return _objectSpread2(_objectSpread2({
  605. debug: false,
  606. openOnFocus: false,
  607. placeholder: '',
  608. autoFocus: false,
  609. defaultActiveItemId: null,
  610. stallThreshold: 300,
  611. environment: environment,
  612. shouldPanelOpen: function shouldPanelOpen(_ref) {
  613. var state = _ref.state;
  614. return getItemsCount(state) > 0;
  615. },
  616. reshape: function reshape(_ref2) {
  617. var sources = _ref2.sources;
  618. return sources;
  619. }
  620. }, props), {}, {
  621. // Since `generateAutocompleteId` triggers a side effect (it increments
  622. // an internal counter), we don't want to execute it if unnecessary.
  623. id: (_props$id = props.id) !== null && _props$id !== void 0 ? _props$id : generateAutocompleteId(),
  624. plugins: plugins,
  625. // The following props need to be deeply defaulted.
  626. initialState: _objectSpread2({
  627. activeItemId: null,
  628. query: '',
  629. completion: null,
  630. collections: [],
  631. isOpen: false,
  632. status: 'idle',
  633. context: {}
  634. }, props.initialState),
  635. onStateChange: function onStateChange(params) {
  636. var _props$onStateChange;
  637. (_props$onStateChange = props.onStateChange) === null || _props$onStateChange === void 0 ? void 0 : _props$onStateChange.call(props, params);
  638. plugins.forEach(function (x) {
  639. var _x$onStateChange;
  640. return (_x$onStateChange = x.onStateChange) === null || _x$onStateChange === void 0 ? void 0 : _x$onStateChange.call(x, params);
  641. });
  642. },
  643. onSubmit: function onSubmit(params) {
  644. var _props$onSubmit;
  645. (_props$onSubmit = props.onSubmit) === null || _props$onSubmit === void 0 ? void 0 : _props$onSubmit.call(props, params);
  646. plugins.forEach(function (x) {
  647. var _x$onSubmit;
  648. return (_x$onSubmit = x.onSubmit) === null || _x$onSubmit === void 0 ? void 0 : _x$onSubmit.call(x, params);
  649. });
  650. },
  651. onReset: function onReset(params) {
  652. var _props$onReset;
  653. (_props$onReset = props.onReset) === null || _props$onReset === void 0 ? void 0 : _props$onReset.call(props, params);
  654. plugins.forEach(function (x) {
  655. var _x$onReset;
  656. return (_x$onReset = x.onReset) === null || _x$onReset === void 0 ? void 0 : _x$onReset.call(x, params);
  657. });
  658. },
  659. getSources: function getSources(params) {
  660. return Promise.all([].concat(_toConsumableArray(plugins.map(function (plugin) {
  661. return plugin.getSources;
  662. })), [props.getSources]).filter(Boolean).map(function (getSources) {
  663. return getNormalizedSources(getSources, params);
  664. })).then(function (nested) {
  665. return flatten(nested);
  666. }).then(function (sources) {
  667. return sources.map(function (source) {
  668. return _objectSpread2(_objectSpread2({}, source), {}, {
  669. onSelect: function onSelect(params) {
  670. source.onSelect(params);
  671. pluginSubscribers.forEach(function (x) {
  672. var _x$onSelect;
  673. return (_x$onSelect = x.onSelect) === null || _x$onSelect === void 0 ? void 0 : _x$onSelect.call(x, params);
  674. });
  675. },
  676. onActive: function onActive(params) {
  677. source.onActive(params);
  678. pluginSubscribers.forEach(function (x) {
  679. var _x$onActive;
  680. return (_x$onActive = x.onActive) === null || _x$onActive === void 0 ? void 0 : _x$onActive.call(x, params);
  681. });
  682. }
  683. });
  684. });
  685. });
  686. },
  687. navigator: _objectSpread2({
  688. navigate: function navigate(_ref3) {
  689. var itemUrl = _ref3.itemUrl;
  690. environment.location.assign(itemUrl);
  691. },
  692. navigateNewTab: function navigateNewTab(_ref4) {
  693. var itemUrl = _ref4.itemUrl;
  694. var windowReference = environment.open(itemUrl, '_blank', 'noopener');
  695. windowReference === null || windowReference === void 0 ? void 0 : windowReference.focus();
  696. },
  697. navigateNewWindow: function navigateNewWindow(_ref5) {
  698. var itemUrl = _ref5.itemUrl;
  699. environment.open(itemUrl, '_blank', 'noopener');
  700. }
  701. }, props.navigator)
  702. });
  703. }
  704. function reshape(_ref) {
  705. var collections = _ref.collections,
  706. props = _ref.props,
  707. state = _ref.state;
  708. // Sources are grouped by `sourceId` to conveniently pick them via destructuring.
  709. // Example: `const { recentSearchesPlugin } = sourcesBySourceId`
  710. var sourcesBySourceId = collections.reduce(function (acc, collection) {
  711. return _objectSpread2(_objectSpread2({}, acc), {}, _defineProperty({}, collection.source.sourceId, _objectSpread2(_objectSpread2({}, collection.source), {}, {
  712. getItems: function getItems() {
  713. // We provide the resolved items from the collection to the `reshape` prop.
  714. return flatten(collection.items);
  715. }
  716. })));
  717. }, {});
  718. var reshapeSources = props.reshape({
  719. sources: Object.values(sourcesBySourceId),
  720. sourcesBySourceId: sourcesBySourceId,
  721. state: state
  722. }); // We reconstruct the collections with the items modified by the `reshape` prop.
  723. return flatten(reshapeSources).filter(Boolean).map(function (source) {
  724. return {
  725. source: source,
  726. items: source.getItems()
  727. };
  728. });
  729. }
  730. function isDescription(item) {
  731. return Boolean(item.execute);
  732. }
  733. function isRequesterDescription(description) {
  734. return Boolean(description === null || description === void 0 ? void 0 : description.execute);
  735. }
  736. function preResolve(itemsOrDescription, sourceId) {
  737. if (isRequesterDescription(itemsOrDescription)) {
  738. return _objectSpread2(_objectSpread2({}, itemsOrDescription), {}, {
  739. requests: itemsOrDescription.queries.map(function (query) {
  740. return {
  741. query: query,
  742. sourceId: sourceId,
  743. transformResponse: itemsOrDescription.transformResponse
  744. };
  745. })
  746. });
  747. }
  748. return {
  749. items: itemsOrDescription,
  750. sourceId: sourceId
  751. };
  752. }
  753. function resolve(items) {
  754. var packed = items.reduce(function (acc, current) {
  755. if (!isDescription(current)) {
  756. acc.push(current);
  757. return acc;
  758. }
  759. var searchClient = current.searchClient,
  760. execute = current.execute,
  761. requests = current.requests;
  762. var container = acc.find(function (item) {
  763. return isDescription(current) && isDescription(item) && item.searchClient === searchClient && item.execute === execute;
  764. });
  765. if (container) {
  766. var _container$items;
  767. (_container$items = container.items).push.apply(_container$items, _toConsumableArray(requests));
  768. } else {
  769. var request = {
  770. execute: execute,
  771. items: requests,
  772. searchClient: searchClient
  773. };
  774. acc.push(request);
  775. }
  776. return acc;
  777. }, []);
  778. var values = packed.map(function (maybeDescription) {
  779. if (!isDescription(maybeDescription)) {
  780. return Promise.resolve(maybeDescription);
  781. }
  782. var _ref = maybeDescription,
  783. execute = _ref.execute,
  784. items = _ref.items,
  785. searchClient = _ref.searchClient;
  786. return execute({
  787. searchClient: searchClient,
  788. requests: items
  789. });
  790. });
  791. return Promise.all(values).then(function (responses) {
  792. return flatten(responses);
  793. });
  794. }
  795. function postResolve(responses, sources) {
  796. return sources.map(function (source) {
  797. var matches = responses.filter(function (response) {
  798. return response.sourceId === source.sourceId;
  799. });
  800. var results = matches.map(function (_ref2) {
  801. var items = _ref2.items;
  802. return items;
  803. });
  804. var transform = matches[0].transformResponse;
  805. var items = transform ? transform(mapToAlgoliaResponse(results)) : results;
  806. invariant(Array.isArray(items), function () {
  807. return "The `getItems` function from source \"".concat(source.sourceId, "\" must return an array of items but returned type ").concat(JSON.stringify(_typeof$1(items)), ":\n\n").concat(JSON.stringify(decycle(items), null, 2), ".\n\nSee: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/sources/#param-getitems");
  808. });
  809. invariant(items.every(Boolean), "The `getItems` function from source \"".concat(source.sourceId, "\" must return an array of items but returned ").concat(JSON.stringify(undefined), ".\n\nDid you forget to return items?\n\nSee: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/sources/#param-getitems"));
  810. return {
  811. source: source,
  812. items: items
  813. };
  814. });
  815. }
  816. var _excluded$2 = ["event", "nextState", "props", "query", "refresh", "store"];
  817. var lastStalledId = null;
  818. var runConcurrentSafePromise = createConcurrentSafePromise();
  819. function onInput(_ref) {
  820. var event = _ref.event,
  821. _ref$nextState = _ref.nextState,
  822. nextState = _ref$nextState === void 0 ? {} : _ref$nextState,
  823. props = _ref.props,
  824. query = _ref.query,
  825. refresh = _ref.refresh,
  826. store = _ref.store,
  827. setters = _objectWithoutProperties(_ref, _excluded$2);
  828. if (lastStalledId) {
  829. props.environment.clearTimeout(lastStalledId);
  830. }
  831. var setCollections = setters.setCollections,
  832. setIsOpen = setters.setIsOpen,
  833. setQuery = setters.setQuery,
  834. setActiveItemId = setters.setActiveItemId,
  835. setStatus = setters.setStatus;
  836. setQuery(query);
  837. setActiveItemId(props.defaultActiveItemId);
  838. if (!query && props.openOnFocus === false) {
  839. var _nextState$isOpen;
  840. var collections = store.getState().collections.map(function (collection) {
  841. return _objectSpread2(_objectSpread2({}, collection), {}, {
  842. items: []
  843. });
  844. });
  845. setStatus('idle');
  846. setCollections(collections);
  847. setIsOpen((_nextState$isOpen = nextState.isOpen) !== null && _nextState$isOpen !== void 0 ? _nextState$isOpen : props.shouldPanelOpen({
  848. state: store.getState()
  849. })); // We make sure to update the latest resolved value of the tracked
  850. // promises to keep late resolving promises from "cancelling" the state
  851. // updates performed in this code path.
  852. // We chain with a void promise to respect `onInput`'s expected return type.
  853. var _request = cancelable(runConcurrentSafePromise(collections).then(function () {
  854. return Promise.resolve();
  855. }));
  856. return store.pendingRequests.add(_request);
  857. }
  858. setStatus('loading');
  859. lastStalledId = props.environment.setTimeout(function () {
  860. setStatus('stalled');
  861. }, props.stallThreshold); // We track the entire promise chain triggered by `onInput` before mutating
  862. // the Autocomplete state to make sure that any state manipulation is based on
  863. // fresh data regardless of when promises individually resolve.
  864. // We don't track nested promises and only rely on the full chain resolution,
  865. // meaning we should only ever manipulate the state once this concurrent-safe
  866. // promise is resolved.
  867. var request = cancelable(runConcurrentSafePromise(props.getSources(_objectSpread2({
  868. query: query,
  869. refresh: refresh,
  870. state: store.getState()
  871. }, setters)).then(function (sources) {
  872. return Promise.all(sources.map(function (source) {
  873. return Promise.resolve(source.getItems(_objectSpread2({
  874. query: query,
  875. refresh: refresh,
  876. state: store.getState()
  877. }, setters))).then(function (itemsOrDescription) {
  878. return preResolve(itemsOrDescription, source.sourceId);
  879. });
  880. })).then(resolve).then(function (responses) {
  881. return postResolve(responses, sources);
  882. }).then(function (collections) {
  883. return reshape({
  884. collections: collections,
  885. props: props,
  886. state: store.getState()
  887. });
  888. });
  889. }))).then(function (collections) {
  890. var _nextState$isOpen2;
  891. // Parameters passed to `onInput` could be stale when the following code
  892. // executes, because `onInput` calls may not resolve in order.
  893. // If it becomes a problem we'll need to save the last passed parameters.
  894. // See: https://codesandbox.io/s/agitated-cookies-y290z
  895. setStatus('idle');
  896. setCollections(collections);
  897. var isPanelOpen = props.shouldPanelOpen({
  898. state: store.getState()
  899. });
  900. setIsOpen((_nextState$isOpen2 = nextState.isOpen) !== null && _nextState$isOpen2 !== void 0 ? _nextState$isOpen2 : props.openOnFocus && !query && isPanelOpen || isPanelOpen);
  901. var highlightedItem = getActiveItem(store.getState());
  902. if (store.getState().activeItemId !== null && highlightedItem) {
  903. var item = highlightedItem.item,
  904. itemInputValue = highlightedItem.itemInputValue,
  905. itemUrl = highlightedItem.itemUrl,
  906. source = highlightedItem.source;
  907. source.onActive(_objectSpread2({
  908. event: event,
  909. item: item,
  910. itemInputValue: itemInputValue,
  911. itemUrl: itemUrl,
  912. refresh: refresh,
  913. source: source,
  914. state: store.getState()
  915. }, setters));
  916. }
  917. }).finally(function () {
  918. setStatus('idle');
  919. if (lastStalledId) {
  920. props.environment.clearTimeout(lastStalledId);
  921. }
  922. });
  923. return store.pendingRequests.add(request);
  924. }
  925. var _excluded$1 = ["event", "props", "refresh", "store"];
  926. function onKeyDown(_ref) {
  927. var event = _ref.event,
  928. props = _ref.props,
  929. refresh = _ref.refresh,
  930. store = _ref.store,
  931. setters = _objectWithoutProperties(_ref, _excluded$1);
  932. if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
  933. // eslint-disable-next-line no-inner-declarations
  934. var triggerScrollIntoView = function triggerScrollIntoView() {
  935. var nodeItem = props.environment.document.getElementById("".concat(props.id, "-item-").concat(store.getState().activeItemId));
  936. if (nodeItem) {
  937. if (nodeItem.scrollIntoViewIfNeeded) {
  938. nodeItem.scrollIntoViewIfNeeded(false);
  939. } else {
  940. nodeItem.scrollIntoView(false);
  941. }
  942. }
  943. }; // eslint-disable-next-line no-inner-declarations
  944. var triggerOnActive = function triggerOnActive() {
  945. var highlightedItem = getActiveItem(store.getState());
  946. if (store.getState().activeItemId !== null && highlightedItem) {
  947. var item = highlightedItem.item,
  948. itemInputValue = highlightedItem.itemInputValue,
  949. itemUrl = highlightedItem.itemUrl,
  950. source = highlightedItem.source;
  951. source.onActive(_objectSpread2({
  952. event: event,
  953. item: item,
  954. itemInputValue: itemInputValue,
  955. itemUrl: itemUrl,
  956. refresh: refresh,
  957. source: source,
  958. state: store.getState()
  959. }, setters));
  960. }
  961. }; // Default browser behavior changes the caret placement on ArrowUp and
  962. // ArrowDown.
  963. event.preventDefault(); // When re-opening the panel, we need to split the logic to keep the actions
  964. // synchronized as `onInput` returns a promise.
  965. if (store.getState().isOpen === false && (props.openOnFocus || Boolean(store.getState().query))) {
  966. onInput(_objectSpread2({
  967. event: event,
  968. props: props,
  969. query: store.getState().query,
  970. refresh: refresh,
  971. store: store
  972. }, setters)).then(function () {
  973. store.dispatch(event.key, {
  974. nextActiveItemId: props.defaultActiveItemId
  975. });
  976. triggerOnActive(); // Since we rely on the DOM, we need to wait for all the micro tasks to
  977. // finish (which include re-opening the panel) to make sure all the
  978. // elements are available.
  979. setTimeout(triggerScrollIntoView, 0);
  980. });
  981. } else {
  982. store.dispatch(event.key, {});
  983. triggerOnActive();
  984. triggerScrollIntoView();
  985. }
  986. } else if (event.key === 'Escape') {
  987. // This prevents the default browser behavior on `input[type="search"]`
  988. // from removing the query right away because we first want to close the
  989. // panel.
  990. event.preventDefault();
  991. store.dispatch(event.key, null); // Hitting the `Escape` key signals the end of a user interaction with the
  992. // autocomplete. At this point, we should ignore any requests that are still
  993. // pending and could reopen the panel once they resolve, because that would
  994. // result in an unsolicited UI behavior.
  995. store.pendingRequests.cancelAll();
  996. } else if (event.key === 'Enter') {
  997. // No active item, so we let the browser handle the native `onSubmit` form
  998. // event.
  999. if (store.getState().activeItemId === null || store.getState().collections.every(function (collection) {
  1000. return collection.items.length === 0;
  1001. })) {
  1002. return;
  1003. } // This prevents the `onSubmit` event to be sent because an item is
  1004. // highlighted.
  1005. event.preventDefault();
  1006. var _ref2 = getActiveItem(store.getState()),
  1007. item = _ref2.item,
  1008. itemInputValue = _ref2.itemInputValue,
  1009. itemUrl = _ref2.itemUrl,
  1010. source = _ref2.source;
  1011. if (event.metaKey || event.ctrlKey) {
  1012. if (itemUrl !== undefined) {
  1013. source.onSelect(_objectSpread2({
  1014. event: event,
  1015. item: item,
  1016. itemInputValue: itemInputValue,
  1017. itemUrl: itemUrl,
  1018. refresh: refresh,
  1019. source: source,
  1020. state: store.getState()
  1021. }, setters));
  1022. props.navigator.navigateNewTab({
  1023. itemUrl: itemUrl,
  1024. item: item,
  1025. state: store.getState()
  1026. });
  1027. }
  1028. } else if (event.shiftKey) {
  1029. if (itemUrl !== undefined) {
  1030. source.onSelect(_objectSpread2({
  1031. event: event,
  1032. item: item,
  1033. itemInputValue: itemInputValue,
  1034. itemUrl: itemUrl,
  1035. refresh: refresh,
  1036. source: source,
  1037. state: store.getState()
  1038. }, setters));
  1039. props.navigator.navigateNewWindow({
  1040. itemUrl: itemUrl,
  1041. item: item,
  1042. state: store.getState()
  1043. });
  1044. }
  1045. } else if (event.altKey) ; else {
  1046. if (itemUrl !== undefined) {
  1047. source.onSelect(_objectSpread2({
  1048. event: event,
  1049. item: item,
  1050. itemInputValue: itemInputValue,
  1051. itemUrl: itemUrl,
  1052. refresh: refresh,
  1053. source: source,
  1054. state: store.getState()
  1055. }, setters));
  1056. props.navigator.navigate({
  1057. itemUrl: itemUrl,
  1058. item: item,
  1059. state: store.getState()
  1060. });
  1061. return;
  1062. }
  1063. onInput(_objectSpread2({
  1064. event: event,
  1065. nextState: {
  1066. isOpen: false
  1067. },
  1068. props: props,
  1069. query: itemInputValue,
  1070. refresh: refresh,
  1071. store: store
  1072. }, setters)).then(function () {
  1073. source.onSelect(_objectSpread2({
  1074. event: event,
  1075. item: item,
  1076. itemInputValue: itemInputValue,
  1077. itemUrl: itemUrl,
  1078. refresh: refresh,
  1079. source: source,
  1080. state: store.getState()
  1081. }, setters));
  1082. });
  1083. }
  1084. }
  1085. }
  1086. var _excluded = ["props", "refresh", "store"],
  1087. _excluded2 = ["inputElement", "formElement", "panelElement"],
  1088. _excluded3 = ["inputElement"],
  1089. _excluded4 = ["inputElement", "maxLength"],
  1090. _excluded5 = ["item", "source"];
  1091. function getPropGetters(_ref) {
  1092. var props = _ref.props,
  1093. refresh = _ref.refresh,
  1094. store = _ref.store,
  1095. setters = _objectWithoutProperties(_ref, _excluded);
  1096. var getEnvironmentProps = function getEnvironmentProps(providedProps) {
  1097. var inputElement = providedProps.inputElement,
  1098. formElement = providedProps.formElement,
  1099. panelElement = providedProps.panelElement,
  1100. rest = _objectWithoutProperties(providedProps, _excluded2);
  1101. return _objectSpread2({
  1102. // On touch devices, we do not rely on the native `blur` event of the
  1103. // input to close the panel, but rather on a custom `touchstart` event
  1104. // outside of the autocomplete elements.
  1105. // This ensures a working experience on mobile because we blur the input
  1106. // on touch devices when the user starts scrolling (`touchmove`).
  1107. // @TODO: support cases where there are multiple Autocomplete instances.
  1108. // Right now, a second instance makes this computation return false.
  1109. onTouchStart: function onTouchStart(event) {
  1110. // The `onTouchStart` event shouldn't trigger the `blur` handler when
  1111. // it's not an interaction with Autocomplete. We detect it with the
  1112. // following heuristics:
  1113. // - the panel is closed AND there are no pending requests
  1114. // (no interaction with the autocomplete, no future state updates)
  1115. // - OR the touched target is the input element (should open the panel)
  1116. var isAutocompleteInteraction = store.getState().isOpen || !store.pendingRequests.isEmpty();
  1117. if (!isAutocompleteInteraction || event.target === inputElement) {
  1118. return;
  1119. }
  1120. var isTargetWithinAutocomplete = [formElement, panelElement].some(function (contextNode) {
  1121. return isOrContainsNode(contextNode, event.target);
  1122. });
  1123. if (isTargetWithinAutocomplete === false) {
  1124. store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
  1125. // could reopen the panel once they resolve.
  1126. // We want to prevent any subsequent query from reopening the panel
  1127. // because it would result in an unsolicited UI behavior.
  1128. if (!props.debug) {
  1129. store.pendingRequests.cancelAll();
  1130. }
  1131. }
  1132. },
  1133. // When scrolling on touch devices (mobiles, tablets, etc.), we want to
  1134. // mimic the native platform behavior where the input is blurred to
  1135. // hide the virtual keyboard. This gives more vertical space to
  1136. // discover all the suggestions showing up in the panel.
  1137. onTouchMove: function onTouchMove(event) {
  1138. if (store.getState().isOpen === false || inputElement !== props.environment.document.activeElement || event.target === inputElement) {
  1139. return;
  1140. }
  1141. inputElement.blur();
  1142. }
  1143. }, rest);
  1144. };
  1145. var getRootProps = function getRootProps(rest) {
  1146. return _objectSpread2({
  1147. role: 'combobox',
  1148. 'aria-expanded': store.getState().isOpen,
  1149. 'aria-haspopup': 'listbox',
  1150. 'aria-owns': store.getState().isOpen ? "".concat(props.id, "-list") : undefined,
  1151. 'aria-labelledby': "".concat(props.id, "-label")
  1152. }, rest);
  1153. };
  1154. var getFormProps = function getFormProps(providedProps) {
  1155. providedProps.inputElement;
  1156. var rest = _objectWithoutProperties(providedProps, _excluded3);
  1157. return _objectSpread2({
  1158. action: '',
  1159. noValidate: true,
  1160. role: 'search',
  1161. onSubmit: function onSubmit(event) {
  1162. var _providedProps$inputE;
  1163. event.preventDefault();
  1164. props.onSubmit(_objectSpread2({
  1165. event: event,
  1166. refresh: refresh,
  1167. state: store.getState()
  1168. }, setters));
  1169. store.dispatch('submit', null);
  1170. (_providedProps$inputE = providedProps.inputElement) === null || _providedProps$inputE === void 0 ? void 0 : _providedProps$inputE.blur();
  1171. },
  1172. onReset: function onReset(event) {
  1173. var _providedProps$inputE2;
  1174. event.preventDefault();
  1175. props.onReset(_objectSpread2({
  1176. event: event,
  1177. refresh: refresh,
  1178. state: store.getState()
  1179. }, setters));
  1180. store.dispatch('reset', null);
  1181. (_providedProps$inputE2 = providedProps.inputElement) === null || _providedProps$inputE2 === void 0 ? void 0 : _providedProps$inputE2.focus();
  1182. }
  1183. }, rest);
  1184. };
  1185. var getInputProps = function getInputProps(providedProps) {
  1186. function onFocus(event) {
  1187. // We want to trigger a query when `openOnFocus` is true
  1188. // because the panel should open with the current query.
  1189. if (props.openOnFocus || Boolean(store.getState().query)) {
  1190. onInput(_objectSpread2({
  1191. event: event,
  1192. props: props,
  1193. query: store.getState().completion || store.getState().query,
  1194. refresh: refresh,
  1195. store: store
  1196. }, setters));
  1197. }
  1198. store.dispatch('focus', null);
  1199. }
  1200. var isTouchDevice = ('ontouchstart' in props.environment);
  1201. var _ref2 = providedProps || {};
  1202. _ref2.inputElement;
  1203. var _ref2$maxLength = _ref2.maxLength,
  1204. maxLength = _ref2$maxLength === void 0 ? 512 : _ref2$maxLength,
  1205. rest = _objectWithoutProperties(_ref2, _excluded4);
  1206. var activeItem = getActiveItem(store.getState());
  1207. return _objectSpread2({
  1208. 'aria-autocomplete': 'both',
  1209. 'aria-activedescendant': store.getState().isOpen && store.getState().activeItemId !== null ? "".concat(props.id, "-item-").concat(store.getState().activeItemId) : undefined,
  1210. 'aria-controls': store.getState().isOpen ? "".concat(props.id, "-list") : undefined,
  1211. 'aria-labelledby': "".concat(props.id, "-label"),
  1212. value: store.getState().completion || store.getState().query,
  1213. id: "".concat(props.id, "-input"),
  1214. autoComplete: 'off',
  1215. autoCorrect: 'off',
  1216. autoCapitalize: 'off',
  1217. enterKeyHint: activeItem !== null && activeItem !== void 0 && activeItem.itemUrl ? 'go' : 'search',
  1218. spellCheck: 'false',
  1219. autoFocus: props.autoFocus,
  1220. placeholder: props.placeholder,
  1221. maxLength: maxLength,
  1222. type: 'search',
  1223. onChange: function onChange(event) {
  1224. onInput(_objectSpread2({
  1225. event: event,
  1226. props: props,
  1227. query: event.currentTarget.value.slice(0, maxLength),
  1228. refresh: refresh,
  1229. store: store
  1230. }, setters));
  1231. },
  1232. onKeyDown: function onKeyDown$1(event) {
  1233. onKeyDown(_objectSpread2({
  1234. event: event,
  1235. props: props,
  1236. refresh: refresh,
  1237. store: store
  1238. }, setters));
  1239. },
  1240. onFocus: onFocus,
  1241. onBlur: function onBlur() {
  1242. // We do rely on the `blur` event on touch devices.
  1243. // See explanation in `onTouchStart`.
  1244. if (!isTouchDevice) {
  1245. store.dispatch('blur', null); // If requests are still pending when the user closes the panel, they
  1246. // could reopen the panel once they resolve.
  1247. // We want to prevent any subsequent query from reopening the panel
  1248. // because it would result in an unsolicited UI behavior.
  1249. if (!props.debug) {
  1250. store.pendingRequests.cancelAll();
  1251. }
  1252. }
  1253. },
  1254. onClick: function onClick(event) {
  1255. // When the panel is closed and you click on the input while
  1256. // the input is focused, the `onFocus` event is not triggered
  1257. // (default browser behavior).
  1258. // In an autocomplete context, it makes sense to open the panel in this
  1259. // case.
  1260. // We mimic this event by catching the `onClick` event which
  1261. // triggers the `onFocus` for the panel to open.
  1262. if (providedProps.inputElement === props.environment.document.activeElement && !store.getState().isOpen) {
  1263. onFocus(event);
  1264. }
  1265. }
  1266. }, rest);
  1267. };
  1268. var getLabelProps = function getLabelProps(rest) {
  1269. return _objectSpread2({
  1270. htmlFor: "".concat(props.id, "-input"),
  1271. id: "".concat(props.id, "-label")
  1272. }, rest);
  1273. };
  1274. var getListProps = function getListProps(rest) {
  1275. return _objectSpread2({
  1276. role: 'listbox',
  1277. 'aria-labelledby': "".concat(props.id, "-label"),
  1278. id: "".concat(props.id, "-list")
  1279. }, rest);
  1280. };
  1281. var getPanelProps = function getPanelProps(rest) {
  1282. return _objectSpread2({
  1283. onMouseDown: function onMouseDown(event) {
  1284. // Prevents the `activeElement` from being changed to the panel so
  1285. // that the blur event is not triggered, otherwise it closes the
  1286. // panel.
  1287. event.preventDefault();
  1288. },
  1289. onMouseLeave: function onMouseLeave() {
  1290. store.dispatch('mouseleave', null);
  1291. }
  1292. }, rest);
  1293. };
  1294. var getItemProps = function getItemProps(providedProps) {
  1295. var item = providedProps.item,
  1296. source = providedProps.source,
  1297. rest = _objectWithoutProperties(providedProps, _excluded5);
  1298. return _objectSpread2({
  1299. id: "".concat(props.id, "-item-").concat(item.__autocomplete_id),
  1300. role: 'option',
  1301. 'aria-selected': store.getState().activeItemId === item.__autocomplete_id,
  1302. onMouseMove: function onMouseMove(event) {
  1303. if (item.__autocomplete_id === store.getState().activeItemId) {
  1304. return;
  1305. }
  1306. store.dispatch('mousemove', item.__autocomplete_id);
  1307. var activeItem = getActiveItem(store.getState());
  1308. if (store.getState().activeItemId !== null && activeItem) {
  1309. var _item = activeItem.item,
  1310. itemInputValue = activeItem.itemInputValue,
  1311. itemUrl = activeItem.itemUrl,
  1312. _source = activeItem.source;
  1313. _source.onActive(_objectSpread2({
  1314. event: event,
  1315. item: _item,
  1316. itemInputValue: itemInputValue,
  1317. itemUrl: itemUrl,
  1318. refresh: refresh,
  1319. source: _source,
  1320. state: store.getState()
  1321. }, setters));
  1322. }
  1323. },
  1324. onMouseDown: function onMouseDown(event) {
  1325. // Prevents the `activeElement` from being changed to the item so it
  1326. // can remain with the current `activeElement`.
  1327. event.preventDefault();
  1328. },
  1329. onClick: function onClick(event) {
  1330. var itemInputValue = source.getItemInputValue({
  1331. item: item,
  1332. state: store.getState()
  1333. });
  1334. var itemUrl = source.getItemUrl({
  1335. item: item,
  1336. state: store.getState()
  1337. }); // If `getItemUrl` is provided, it means that the suggestion
  1338. // is a link, not plain text that aims at updating the query.
  1339. // We can therefore skip the state change because it will update
  1340. // the `activeItemId`, resulting in a UI flash, especially
  1341. // noticeable on mobile.
  1342. var runPreCommand = itemUrl ? Promise.resolve() : onInput(_objectSpread2({
  1343. event: event,
  1344. nextState: {
  1345. isOpen: false
  1346. },
  1347. props: props,
  1348. query: itemInputValue,
  1349. refresh: refresh,
  1350. store: store
  1351. }, setters));
  1352. runPreCommand.then(function () {
  1353. source.onSelect(_objectSpread2({
  1354. event: event,
  1355. item: item,
  1356. itemInputValue: itemInputValue,
  1357. itemUrl: itemUrl,
  1358. refresh: refresh,
  1359. source: source,
  1360. state: store.getState()
  1361. }, setters));
  1362. });
  1363. }
  1364. }, rest);
  1365. };
  1366. return {
  1367. getEnvironmentProps: getEnvironmentProps,
  1368. getRootProps: getRootProps,
  1369. getFormProps: getFormProps,
  1370. getLabelProps: getLabelProps,
  1371. getInputProps: getInputProps,
  1372. getPanelProps: getPanelProps,
  1373. getListProps: getListProps,
  1374. getItemProps: getItemProps
  1375. };
  1376. }
  1377. function getMetadata(_ref) {
  1378. var _, _options$__autocomple, _options$__autocomple2, _options$__autocomple3;
  1379. var plugins = _ref.plugins,
  1380. options = _ref.options;
  1381. var optionsKey = (_ = (((_options$__autocomple = options.__autocomplete_metadata) === null || _options$__autocomple === void 0 ? void 0 : _options$__autocomple.userAgents) || [])[0]) === null || _ === void 0 ? void 0 : _.segment;
  1382. var extraOptions = optionsKey ? _defineProperty({}, optionsKey, Object.keys(((_options$__autocomple2 = options.__autocomplete_metadata) === null || _options$__autocomple2 === void 0 ? void 0 : _options$__autocomple2.options) || {})) : {};
  1383. return {
  1384. plugins: plugins.map(function (plugin) {
  1385. return {
  1386. name: plugin.name,
  1387. options: Object.keys(plugin.__autocomplete_pluginOptions || [])
  1388. };
  1389. }),
  1390. options: _objectSpread2({
  1391. 'autocomplete-core': Object.keys(options)
  1392. }, extraOptions),
  1393. ua: userAgents.concat(((_options$__autocomple3 = options.__autocomplete_metadata) === null || _options$__autocomple3 === void 0 ? void 0 : _options$__autocomple3.userAgents) || [])
  1394. };
  1395. }
  1396. function injectMetadata(_ref3) {
  1397. var _environment$navigato;
  1398. var metadata = _ref3.metadata,
  1399. environment = _ref3.environment;
  1400. var isMetadataEnabled = (_environment$navigato = environment.navigator) === null || _environment$navigato === void 0 ? void 0 : _environment$navigato.userAgent.includes('Algolia Crawler');
  1401. if (isMetadataEnabled) {
  1402. var metadataContainer = environment.document.createElement('meta');
  1403. var headRef = environment.document.querySelector('head');
  1404. metadataContainer.name = 'algolia:metadata';
  1405. setTimeout(function () {
  1406. metadataContainer.content = JSON.stringify(metadata);
  1407. headRef.appendChild(metadataContainer);
  1408. }, 0);
  1409. }
  1410. }
  1411. function getCompletion(_ref) {
  1412. var _getActiveItem;
  1413. var state = _ref.state;
  1414. if (state.isOpen === false || state.activeItemId === null) {
  1415. return null;
  1416. }
  1417. return ((_getActiveItem = getActiveItem(state)) === null || _getActiveItem === void 0 ? void 0 : _getActiveItem.itemInputValue) || null;
  1418. }
  1419. var stateReducer = function stateReducer(state, action) {
  1420. switch (action.type) {
  1421. case 'setActiveItemId':
  1422. {
  1423. return _objectSpread2(_objectSpread2({}, state), {}, {
  1424. activeItemId: action.payload
  1425. });
  1426. }
  1427. case 'setQuery':
  1428. {
  1429. return _objectSpread2(_objectSpread2({}, state), {}, {
  1430. query: action.payload,
  1431. completion: null
  1432. });
  1433. }
  1434. case 'setCollections':
  1435. {
  1436. return _objectSpread2(_objectSpread2({}, state), {}, {
  1437. collections: action.payload
  1438. });
  1439. }
  1440. case 'setIsOpen':
  1441. {
  1442. return _objectSpread2(_objectSpread2({}, state), {}, {
  1443. isOpen: action.payload
  1444. });
  1445. }
  1446. case 'setStatus':
  1447. {
  1448. return _objectSpread2(_objectSpread2({}, state), {}, {
  1449. status: action.payload
  1450. });
  1451. }
  1452. case 'setContext':
  1453. {
  1454. return _objectSpread2(_objectSpread2({}, state), {}, {
  1455. context: _objectSpread2(_objectSpread2({}, state.context), action.payload)
  1456. });
  1457. }
  1458. case 'ArrowDown':
  1459. {
  1460. var nextState = _objectSpread2(_objectSpread2({}, state), {}, {
  1461. activeItemId: action.payload.hasOwnProperty('nextActiveItemId') ? action.payload.nextActiveItemId : getNextActiveItemId(1, state.activeItemId, getItemsCount(state), action.props.defaultActiveItemId)
  1462. });
  1463. return _objectSpread2(_objectSpread2({}, nextState), {}, {
  1464. completion: getCompletion({
  1465. state: nextState
  1466. })
  1467. });
  1468. }
  1469. case 'ArrowUp':
  1470. {
  1471. var _nextState = _objectSpread2(_objectSpread2({}, state), {}, {
  1472. activeItemId: getNextActiveItemId(-1, state.activeItemId, getItemsCount(state), action.props.defaultActiveItemId)
  1473. });
  1474. return _objectSpread2(_objectSpread2({}, _nextState), {}, {
  1475. completion: getCompletion({
  1476. state: _nextState
  1477. })
  1478. });
  1479. }
  1480. case 'Escape':
  1481. {
  1482. if (state.isOpen) {
  1483. return _objectSpread2(_objectSpread2({}, state), {}, {
  1484. activeItemId: null,
  1485. isOpen: false,
  1486. completion: null
  1487. });
  1488. }
  1489. return _objectSpread2(_objectSpread2({}, state), {}, {
  1490. activeItemId: null,
  1491. query: '',
  1492. status: 'idle',
  1493. collections: []
  1494. });
  1495. }
  1496. case 'submit':
  1497. {
  1498. return _objectSpread2(_objectSpread2({}, state), {}, {
  1499. activeItemId: null,
  1500. isOpen: false,
  1501. status: 'idle'
  1502. });
  1503. }
  1504. case 'reset':
  1505. {
  1506. return _objectSpread2(_objectSpread2({}, state), {}, {
  1507. activeItemId: // Since we open the panel on reset when openOnFocus=true
  1508. // we need to restore the highlighted index to the defaultActiveItemId. (DocSearch use-case)
  1509. // Since we close the panel when openOnFocus=false
  1510. // we lose track of the highlighted index. (Query-suggestions use-case)
  1511. action.props.openOnFocus === true ? action.props.defaultActiveItemId : null,
  1512. status: 'idle',
  1513. query: ''
  1514. });
  1515. }
  1516. case 'focus':
  1517. {
  1518. return _objectSpread2(_objectSpread2({}, state), {}, {
  1519. activeItemId: action.props.defaultActiveItemId,
  1520. isOpen: (action.props.openOnFocus || Boolean(state.query)) && action.props.shouldPanelOpen({
  1521. state: state
  1522. })
  1523. });
  1524. }
  1525. case 'blur':
  1526. {
  1527. if (action.props.debug) {
  1528. return state;
  1529. }
  1530. return _objectSpread2(_objectSpread2({}, state), {}, {
  1531. isOpen: false,
  1532. activeItemId: null
  1533. });
  1534. }
  1535. case 'mousemove':
  1536. {
  1537. return _objectSpread2(_objectSpread2({}, state), {}, {
  1538. activeItemId: action.payload
  1539. });
  1540. }
  1541. case 'mouseleave':
  1542. {
  1543. return _objectSpread2(_objectSpread2({}, state), {}, {
  1544. activeItemId: action.props.defaultActiveItemId
  1545. });
  1546. }
  1547. default:
  1548. invariant(false, "The reducer action ".concat(JSON.stringify(action.type), " is not supported."));
  1549. return state;
  1550. }
  1551. };
  1552. function createAutocomplete(options) {
  1553. checkOptions(options);
  1554. var subscribers = [];
  1555. var props = getDefaultProps(options, subscribers);
  1556. var store = createStore(stateReducer, props, onStoreStateChange);
  1557. var setters = getAutocompleteSetters({
  1558. store: store
  1559. });
  1560. var propGetters = getPropGetters(_objectSpread2({
  1561. props: props,
  1562. refresh: refresh,
  1563. store: store
  1564. }, setters));
  1565. function onStoreStateChange(_ref) {
  1566. var prevState = _ref.prevState,
  1567. state = _ref.state;
  1568. props.onStateChange(_objectSpread2({
  1569. prevState: prevState,
  1570. state: state,
  1571. refresh: refresh
  1572. }, setters));
  1573. }
  1574. function refresh() {
  1575. return onInput(_objectSpread2({
  1576. event: new Event('input'),
  1577. nextState: {
  1578. isOpen: store.getState().isOpen
  1579. },
  1580. props: props,
  1581. query: store.getState().query,
  1582. refresh: refresh,
  1583. store: store
  1584. }, setters));
  1585. }
  1586. props.plugins.forEach(function (plugin) {
  1587. var _plugin$subscribe;
  1588. return (_plugin$subscribe = plugin.subscribe) === null || _plugin$subscribe === void 0 ? void 0 : _plugin$subscribe.call(plugin, _objectSpread2(_objectSpread2({}, setters), {}, {
  1589. refresh: refresh,
  1590. onSelect: function onSelect(fn) {
  1591. subscribers.push({
  1592. onSelect: fn
  1593. });
  1594. },
  1595. onActive: function onActive(fn) {
  1596. subscribers.push({
  1597. onActive: fn
  1598. });
  1599. }
  1600. }));
  1601. });
  1602. injectMetadata({
  1603. metadata: getMetadata({
  1604. plugins: props.plugins,
  1605. options: options
  1606. }),
  1607. environment: props.environment
  1608. });
  1609. return _objectSpread2(_objectSpread2({
  1610. refresh: refresh
  1611. }, propGetters), setters);
  1612. }
  1613. exports.createAutocomplete = createAutocomplete;
  1614. exports.getDefaultProps = getDefaultProps;
  1615. Object.defineProperty(exports, '__esModule', { value: true });
  1616. }));
  1617. //# sourceMappingURL=index.development.js.map