gtfs-to-html 2.12.1 → 2.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2790 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
+ typeof define === 'function' && define.amd ? define(factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.MaplibreGeocoder = factory());
5
+ })(this, (function () { 'use strict';
6
+
7
+ /******************************************************************************
8
+ Copyright (c) Microsoft Corporation.
9
+
10
+ Permission to use, copy, modify, and/or distribute this software for any
11
+ purpose with or without fee is hereby granted.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19
+ PERFORMANCE OF THIS SOFTWARE.
20
+ ***************************************************************************** */
21
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
22
+
23
+
24
+ function __awaiter(thisArg, _arguments, P, generator) {
25
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
26
+ return new (P || (P = Promise))(function (resolve, reject) {
27
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
28
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
29
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
30
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
31
+ });
32
+ }
33
+
34
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
35
+ var e = new Error(message);
36
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
37
+ };
38
+
39
+ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
40
+
41
+ function getDefaultExportFromCjs (x) {
42
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
43
+ }
44
+
45
+ var immutable;
46
+ var hasRequiredImmutable;
47
+
48
+ function requireImmutable () {
49
+ if (hasRequiredImmutable) return immutable;
50
+ hasRequiredImmutable = 1;
51
+ immutable = extend;
52
+
53
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
54
+
55
+ function extend() {
56
+ var target = {};
57
+
58
+ for (var i = 0; i < arguments.length; i++) {
59
+ var source = arguments[i];
60
+
61
+ for (var key in source) {
62
+ if (hasOwnProperty.call(source, key)) {
63
+ target[key] = source[key];
64
+ }
65
+ }
66
+ }
67
+
68
+ return target
69
+ }
70
+ return immutable;
71
+ }
72
+
73
+ var fuzzy = {exports: {}};
74
+
75
+ /*
76
+ * Fuzzy
77
+ * https://github.com/myork/fuzzy
78
+ *
79
+ * Copyright (c) 2012 Matt York
80
+ * Licensed under the MIT license.
81
+ */
82
+
83
+ var hasRequiredFuzzy;
84
+
85
+ function requireFuzzy () {
86
+ if (hasRequiredFuzzy) return fuzzy.exports;
87
+ hasRequiredFuzzy = 1;
88
+ (function (module, exports) {
89
+ (function() {
90
+
91
+ var fuzzy = {};
92
+
93
+ // Use in node or in browser
94
+ {
95
+ module.exports = fuzzy;
96
+ }
97
+
98
+ // Return all elements of `array` that have a fuzzy
99
+ // match against `pattern`.
100
+ fuzzy.simpleFilter = function(pattern, array) {
101
+ return array.filter(function(str) {
102
+ return fuzzy.test(pattern, str);
103
+ });
104
+ };
105
+
106
+ // Does `pattern` fuzzy match `str`?
107
+ fuzzy.test = function(pattern, str) {
108
+ return fuzzy.match(pattern, str) !== null;
109
+ };
110
+
111
+ // If `pattern` matches `str`, wrap each matching character
112
+ // in `opts.pre` and `opts.post`. If no match, return null
113
+ fuzzy.match = function(pattern, str, opts) {
114
+ opts = opts || {};
115
+ var patternIdx = 0
116
+ , result = []
117
+ , len = str.length
118
+ , totalScore = 0
119
+ , currScore = 0
120
+ // prefix
121
+ , pre = opts.pre || ''
122
+ // suffix
123
+ , post = opts.post || ''
124
+ // String to compare against. This might be a lowercase version of the
125
+ // raw string
126
+ , compareString = opts.caseSensitive && str || str.toLowerCase()
127
+ , ch;
128
+
129
+ pattern = opts.caseSensitive && pattern || pattern.toLowerCase();
130
+
131
+ // For each character in the string, either add it to the result
132
+ // or wrap in template if it's the next string in the pattern
133
+ for(var idx = 0; idx < len; idx++) {
134
+ ch = str[idx];
135
+ if(compareString[idx] === pattern[patternIdx]) {
136
+ ch = pre + ch + post;
137
+ patternIdx += 1;
138
+
139
+ // consecutive characters should increase the score more than linearly
140
+ currScore += 1 + currScore;
141
+ } else {
142
+ currScore = 0;
143
+ }
144
+ totalScore += currScore;
145
+ result[result.length] = ch;
146
+ }
147
+
148
+ // return rendered string if we have a match for every char
149
+ if(patternIdx === pattern.length) {
150
+ // if the string is an exact match with pattern, totalScore should be maxed
151
+ totalScore = (compareString === pattern) ? Infinity : totalScore;
152
+ return {rendered: result.join(''), score: totalScore};
153
+ }
154
+
155
+ return null;
156
+ };
157
+
158
+ // The normal entry point. Filters `arr` for matches against `pattern`.
159
+ // It returns an array with matching values of the type:
160
+ //
161
+ // [{
162
+ // string: '<b>lah' // The rendered string
163
+ // , index: 2 // The index of the element in `arr`
164
+ // , original: 'blah' // The original element in `arr`
165
+ // }]
166
+ //
167
+ // `opts` is an optional argument bag. Details:
168
+ //
169
+ // opts = {
170
+ // // string to put before a matching character
171
+ // pre: '<b>'
172
+ //
173
+ // // string to put after matching character
174
+ // , post: '</b>'
175
+ //
176
+ // // Optional function. Input is an entry in the given arr`,
177
+ // // output should be the string to test `pattern` against.
178
+ // // In this example, if `arr = [{crying: 'koala'}]` we would return
179
+ // // 'koala'.
180
+ // , extract: function(arg) { return arg.crying; }
181
+ // }
182
+ fuzzy.filter = function(pattern, arr, opts) {
183
+ if(!arr || arr.length === 0) {
184
+ return [];
185
+ }
186
+ if (typeof pattern !== 'string') {
187
+ return arr;
188
+ }
189
+ opts = opts || {};
190
+ return arr
191
+ .reduce(function(prev, element, idx, arr) {
192
+ var str = element;
193
+ if(opts.extract) {
194
+ str = opts.extract(element);
195
+ }
196
+ var rendered = fuzzy.match(pattern, str, opts);
197
+ if(rendered != null) {
198
+ prev[prev.length] = {
199
+ string: rendered.rendered
200
+ , score: rendered.score
201
+ , index: idx
202
+ , original: element
203
+ };
204
+ }
205
+ return prev;
206
+ }, [])
207
+
208
+ // Sort by score. Browsers are inconsistent wrt stable/unstable
209
+ // sorting, so force stable by using the index in the case of tie.
210
+ // See http://ofb.net/~sethml/is-sort-stable.html
211
+ .sort(function(a,b) {
212
+ var compare = b.score - a.score;
213
+ if(compare) return compare;
214
+ return a.index - b.index;
215
+ });
216
+ };
217
+
218
+
219
+ }());
220
+ } (fuzzy));
221
+ return fuzzy.exports;
222
+ }
223
+
224
+ var list;
225
+ var hasRequiredList;
226
+
227
+ function requireList () {
228
+ if (hasRequiredList) return list;
229
+ hasRequiredList = 1;
230
+
231
+ var List = function(component) {
232
+ this.component = component;
233
+ this.items = [];
234
+ this.active = component.options.noInitialSelection ? -1 : 0;
235
+ this.wrapper = document.createElement('div');
236
+ this.wrapper.className = 'suggestions-wrapper';
237
+ this.element = document.createElement('ul');
238
+ this.element.className = 'suggestions';
239
+ this.wrapper.appendChild(this.element);
240
+
241
+ // selectingListItem is set to true in the time between the mousedown and mouseup when clicking an item in the list
242
+ // mousedown on a list item will cause the input to blur which normally hides the list, so this flag is used to keep
243
+ // the list open until the mouseup
244
+ this.selectingListItem = false;
245
+
246
+ component.el.parentNode.insertBefore(this.wrapper, component.el.nextSibling);
247
+ return this;
248
+ };
249
+
250
+ List.prototype.show = function() {
251
+ this.element.style.display = 'block';
252
+ };
253
+
254
+ List.prototype.hide = function() {
255
+ this.element.style.display = 'none';
256
+ };
257
+
258
+ List.prototype.add = function(item) {
259
+ this.items.push(item);
260
+ };
261
+
262
+ List.prototype.clear = function() {
263
+ this.items = [];
264
+ this.active = this.component.options.noInitialSelection ? -1 : 0;
265
+ };
266
+
267
+ List.prototype.isEmpty = function() {
268
+ return !this.items.length;
269
+ };
270
+
271
+ List.prototype.isVisible = function() {
272
+ return this.element.style.display === 'block';
273
+ };
274
+
275
+ List.prototype.draw = function() {
276
+ this.element.innerHTML = '';
277
+
278
+ if (this.items.length === 0) {
279
+ this.hide();
280
+ return;
281
+ }
282
+
283
+ for (var i = 0; i < this.items.length; i++) {
284
+ this.drawItem(this.items[i], this.active === i);
285
+ }
286
+
287
+ this.show();
288
+ };
289
+
290
+ List.prototype.drawItem = function(item, active) {
291
+ var li = document.createElement('li'),
292
+ a = document.createElement('a');
293
+
294
+ if (active) li.className += ' active';
295
+
296
+ a.innerHTML = item.string;
297
+
298
+ li.appendChild(a);
299
+ this.element.appendChild(li);
300
+
301
+ li.addEventListener('mousedown', function() {
302
+ this.selectingListItem = true;
303
+ }.bind(this));
304
+
305
+ li.addEventListener('mouseup', function() {
306
+ this.handleMouseUp.call(this, item);
307
+ }.bind(this));
308
+ };
309
+
310
+ List.prototype.handleMouseUp = function(item) {
311
+ this.selectingListItem = false;
312
+ this.component.value(item.original);
313
+ this.clear();
314
+ this.draw();
315
+ };
316
+
317
+ List.prototype.move = function(index) {
318
+ this.active = index;
319
+ this.draw();
320
+ };
321
+
322
+ List.prototype.previous = function() {
323
+ this.move(this.active <= 0 ? this.items.length - 1 : this.active - 1);
324
+ };
325
+
326
+ List.prototype.next = function() {
327
+ this.move(this.active >= this.items.length - 1 ? 0 : this.active + 1);
328
+ };
329
+
330
+ List.prototype.drawError = function(msg){
331
+ var li = document.createElement('li');
332
+
333
+ li.innerHTML = msg;
334
+
335
+ this.element.appendChild(li);
336
+ this.show();
337
+ };
338
+
339
+ list = List;
340
+ return list;
341
+ }
342
+
343
+ var suggestions;
344
+ var hasRequiredSuggestions;
345
+
346
+ function requireSuggestions () {
347
+ if (hasRequiredSuggestions) return suggestions;
348
+ hasRequiredSuggestions = 1;
349
+
350
+ var extend = requireImmutable();
351
+ var fuzzy = requireFuzzy();
352
+ var List = requireList();
353
+
354
+ var Suggestions = function(el, data, options) {
355
+ options = options || {};
356
+
357
+ this.options = extend({
358
+ minLength: 2,
359
+ limit: 5,
360
+ filter: true,
361
+ hideOnBlur: true,
362
+ noInitialSelection: true
363
+ }, options);
364
+
365
+ this.el = el;
366
+ this.data = data || [];
367
+ this.list = new List(this);
368
+
369
+ this.query = '';
370
+ this.selected = null;
371
+
372
+ this.list.draw();
373
+
374
+ this.el.addEventListener('keyup', function(e) {
375
+ this.handleKeyUp(e.keyCode, e);
376
+ }.bind(this), false);
377
+
378
+ this.el.addEventListener('keydown', function(e) {
379
+ this.handleKeyDown(e);
380
+ }.bind(this));
381
+
382
+ this.el.addEventListener('focus', function() {
383
+ this.handleFocus();
384
+ }.bind(this));
385
+
386
+ this.el.addEventListener('blur', function() {
387
+ this.handleBlur();
388
+ }.bind(this));
389
+
390
+ this.el.addEventListener('paste', function(e) {
391
+ this.handlePaste(e);
392
+ }.bind(this));
393
+
394
+ // use user-provided render function if given, otherwise just use the default
395
+ this.render = (this.options.render) ? this.options.render.bind(this) : this.render.bind(this);
396
+
397
+ this.getItemValue = (this.options.getItemValue) ? this.options.getItemValue.bind(this) : this.getItemValue.bind(this);
398
+
399
+ return this;
400
+ };
401
+
402
+ Suggestions.prototype.handleKeyUp = function(keyCode, e) {
403
+ // 40 - DOWN
404
+ // 38 - UP
405
+ // 27 - ESC
406
+ // 13 - ENTER
407
+ // 9 - TAB
408
+
409
+ if (keyCode === 40 ||
410
+ keyCode === 38 ||
411
+ keyCode === 27 ||
412
+ keyCode === 9) return;
413
+
414
+ if (keyCode === 13) {
415
+ if (this.list.items[this.list.active]) {
416
+ this.list.handleMouseUp(this.list.items[this.list.active]);
417
+ e.stopPropagation();
418
+ }
419
+ return;
420
+ }
421
+
422
+ this.handleInputChange(this.el.value);
423
+
424
+ };
425
+
426
+ Suggestions.prototype.handleKeyDown = function(e) {
427
+ switch (e.keyCode) {
428
+ case 13: // ENTER
429
+ if (this.list.active >= 0) {
430
+ this.list.selectingListItem = true;
431
+ }
432
+ break;
433
+ case 9: // TAB
434
+ if (!this.list.isEmpty()) {
435
+ if (this.list.isVisible()) {
436
+ e.preventDefault();
437
+ }
438
+ this.value(this.list.active >= 0 ? this.list.items[this.list.active].original : null);
439
+ this.list.hide();
440
+ }
441
+ break;
442
+ case 27: // ESC
443
+ if (!this.list.isEmpty()) this.list.hide();
444
+ break;
445
+ case 38: // UP
446
+ this.list.previous();
447
+ break;
448
+ case 40: // DOWN
449
+ this.list.next();
450
+ break;
451
+ }
452
+ };
453
+
454
+ Suggestions.prototype.handleBlur = function() {
455
+ if (!this.list.selectingListItem && this.options.hideOnBlur) {
456
+ this.list.hide();
457
+ }
458
+ };
459
+
460
+ Suggestions.prototype.handlePaste = function(e) {
461
+ if (e.clipboardData) {
462
+ this.handleInputChange(e.clipboardData.getData('Text'));
463
+ } else {
464
+ var self = this;
465
+ setTimeout(function () {
466
+ self.handleInputChange(e.target.value);
467
+ }, 100);
468
+ }
469
+ };
470
+
471
+ Suggestions.prototype.handleInputChange = function(query) {
472
+ this.query = this.normalize(query);
473
+
474
+ this.list.clear();
475
+
476
+ if (this.query.length < this.options.minLength) {
477
+ this.list.draw();
478
+ return;
479
+ }
480
+
481
+ this.getCandidates(function(data) {
482
+ for (var i = 0; i < data.length; i++) {
483
+ this.list.add(data[i]);
484
+ if (i === (this.options.limit - 1)) break;
485
+ }
486
+ this.list.draw();
487
+ }.bind(this));
488
+ };
489
+
490
+ Suggestions.prototype.handleFocus = function() {
491
+ if (!this.list.isEmpty()) this.list.show();
492
+ this.list.selectingListItem = false;
493
+ };
494
+
495
+ /**
496
+ * Update data previously passed
497
+ *
498
+ * @param {Array} revisedData
499
+ */
500
+ Suggestions.prototype.update = function(revisedData) {
501
+ this.data = revisedData;
502
+ this.handleKeyUp();
503
+ };
504
+
505
+ /**
506
+ * Clears data
507
+ */
508
+ Suggestions.prototype.clear = function() {
509
+ this.data = [];
510
+ this.list.clear();
511
+ };
512
+
513
+ /**
514
+ * Normalize the results list and input value for matching
515
+ *
516
+ * @param {String} value
517
+ * @return {String}
518
+ */
519
+ Suggestions.prototype.normalize = function(value) {
520
+ value = value.toLowerCase();
521
+ return value;
522
+ };
523
+
524
+ /**
525
+ * Evaluates whether an array item qualifies as a match with the current query
526
+ *
527
+ * @param {String} candidate a possible item from the array passed
528
+ * @param {String} query the current query
529
+ * @return {Boolean}
530
+ */
531
+ Suggestions.prototype.match = function(candidate, query) {
532
+ return candidate.indexOf(query) > -1;
533
+ };
534
+
535
+ Suggestions.prototype.value = function(value) {
536
+ this.selected = value;
537
+ this.el.value = this.getItemValue(value || { place_name: this.query });
538
+
539
+ if (document.createEvent) {
540
+ var e = document.createEvent('HTMLEvents');
541
+ e.initEvent('change', true, false);
542
+ this.el.dispatchEvent(e);
543
+ } else {
544
+ this.el.fireEvent('onchange');
545
+ }
546
+ };
547
+
548
+ Suggestions.prototype.getCandidates = function(callback) {
549
+ var options = {
550
+ pre: '<strong>',
551
+ post: '</strong>',
552
+ extract: function(d) { return this.getItemValue(d); }.bind(this)
553
+ };
554
+ var results;
555
+ if(this.options.filter){
556
+ results = fuzzy.filter(this.query, this.data, options);
557
+
558
+ results = results.map(function(item){
559
+ return {
560
+ original: item.original,
561
+ string: this.render(item.original, item.string)
562
+ };
563
+ }.bind(this));
564
+ }else {
565
+ results = this.data.map(function(d) {
566
+ var renderedString = this.render(d);
567
+ return {
568
+ original: d,
569
+ string: renderedString
570
+ };
571
+ }.bind(this));
572
+ }
573
+ callback(results);
574
+ };
575
+
576
+ /**
577
+ * For a given item in the data array, return what should be used as the candidate string
578
+ *
579
+ * @param {Object|String} item an item from the data array
580
+ * @return {String} item
581
+ */
582
+ Suggestions.prototype.getItemValue = function(item) {
583
+ return item;
584
+ };
585
+
586
+ /**
587
+ * For a given item in the data array, return a string of html that should be rendered in the dropdown
588
+ * @param {Object|String} item an item from the data array
589
+ * @param {String} sourceFormatting a string that has pre-formatted html that should be passed directly through the render function
590
+ * @return {String} html
591
+ */
592
+ Suggestions.prototype.render = function(item, sourceFormatting) {
593
+ if (sourceFormatting){
594
+ // use existing formatting on the source string
595
+ return sourceFormatting;
596
+ }
597
+ var boldString = (item.original) ? this.getItemValue(item.original) : this.getItemValue(item);
598
+ var indexString = this.normalize(boldString);
599
+ var indexOfQuery = indexString.lastIndexOf(this.query);
600
+ while (indexOfQuery > -1) {
601
+ var endIndexOfQuery = indexOfQuery + this.query.length;
602
+ boldString = boldString.slice(0, indexOfQuery) + '<strong>' + boldString.slice(indexOfQuery, endIndexOfQuery) + '</strong>' + boldString.slice(endIndexOfQuery);
603
+ indexOfQuery = indexString.slice(0, indexOfQuery).lastIndexOf(this.query);
604
+ }
605
+ return boldString
606
+ };
607
+
608
+ /**
609
+ * Render an custom error message in the suggestions list
610
+ * @param {String} msg An html string to render as an error message
611
+ */
612
+ Suggestions.prototype.renderError = function(msg){
613
+ this.list.drawError(msg);
614
+ };
615
+
616
+ suggestions = Suggestions;
617
+ return suggestions;
618
+ }
619
+
620
+ var suggestionsList;
621
+ var hasRequiredSuggestionsList;
622
+
623
+ function requireSuggestionsList () {
624
+ if (hasRequiredSuggestionsList) return suggestionsList;
625
+ hasRequiredSuggestionsList = 1;
626
+
627
+ /**
628
+ * A typeahead component for inputs
629
+ * @class Suggestions
630
+ *
631
+ * @param {HTMLInputElement} el A valid HTML input element
632
+ * @param {Array} data An array of data used for results
633
+ * @param {Object} options
634
+ * @param {Number} [options.limit=5] Max number of results to display in the auto suggest list.
635
+ * @param {Number} [options.minLength=2] Number of characters typed into an input to trigger suggestions.
636
+ * @param {Boolean} [options.hideOnBlur=true] If `true`, hides the suggestions when focus is lost.
637
+ * @return {Suggestions} `this`
638
+ * @example
639
+ * // in the browser
640
+ * var input = document.querySelector('input');
641
+ * var data = [
642
+ * 'Roy Eldridge',
643
+ * 'Roy Hargrove',
644
+ * 'Rex Stewart'
645
+ * ];
646
+ *
647
+ * new Suggestions(input, data);
648
+ *
649
+ * // with options
650
+ * var input = document.querySelector('input');
651
+ * var data = [{
652
+ * name: 'Roy Eldridge',
653
+ * year: 1911
654
+ * }, {
655
+ * name: 'Roy Hargrove',
656
+ * year: 1969
657
+ * }, {
658
+ * name: 'Rex Stewart',
659
+ * year: 1907
660
+ * }];
661
+ *
662
+ * var typeahead = new Suggestions(input, data, {
663
+ * filter: false, // Disable filtering
664
+ * minLength: 3, // Number of characters typed into an input to trigger suggestions.
665
+ * limit: 3, // Max number of results to display.
666
+ * hideOnBlur: false // Don't hide results when input loses focus
667
+ * });
668
+ *
669
+ * // As we're passing an object of an arrays as data, override
670
+ * // `getItemValue` by specifying the specific property to search on.
671
+ * typeahead.getItemValue = function(item) { return item.name };
672
+ *
673
+ * input.addEventListener('change', function() {
674
+ * console.log(typeahead.selected); // Current selected item.
675
+ * });
676
+ *
677
+ * // With browserify
678
+ * var Suggestions = require('suggestions');
679
+ *
680
+ * new Suggestions(input, data);
681
+ */
682
+ var Suggestions = requireSuggestions();
683
+ suggestionsList = Suggestions;
684
+
685
+ if (typeof window !== 'undefined') {
686
+ window.Suggestions = Suggestions;
687
+ }
688
+ return suggestionsList;
689
+ }
690
+
691
+ var suggestionsListExports = requireSuggestionsList();
692
+ var Typeahead = /*@__PURE__*/getDefaultExportFromCjs(suggestionsListExports);
693
+
694
+ var subtag$2 = {exports: {}};
695
+
696
+ var subtag$1 = subtag$2.exports;
697
+
698
+ var hasRequiredSubtag;
699
+
700
+ function requireSubtag () {
701
+ if (hasRequiredSubtag) return subtag$2.exports;
702
+ hasRequiredSubtag = 1;
703
+ (function (module) {
704
+ !function(root, name, make) {
705
+ if (module.exports) module.exports = make();
706
+ else root[name] = make();
707
+ }(subtag$1, 'subtag', function() {
708
+
709
+ var empty = '';
710
+ var pattern = /^([a-zA-Z]{2,3})(?:[_-]+([a-zA-Z]{3})(?=$|[_-]+))?(?:[_-]+([a-zA-Z]{4})(?=$|[_-]+))?(?:[_-]+([a-zA-Z]{2}|[0-9]{3})(?=$|[_-]+))?/;
711
+
712
+ function match(tag) {
713
+ return tag.match(pattern) || []
714
+ }
715
+
716
+ function split(tag) {
717
+ return match(tag).filter(function(v, i) { return v && i })
718
+ }
719
+
720
+ function api(tag) {
721
+ tag = match(tag);
722
+ return {
723
+ language: tag[1] || empty,
724
+ extlang: tag[2] || empty,
725
+ script: tag[3] || empty,
726
+ region: tag[4] || empty
727
+ }
728
+ }
729
+
730
+ function expose(target, key, value) {
731
+ Object.defineProperty(target, key, {
732
+ value: value,
733
+ enumerable: true
734
+ });
735
+ }
736
+
737
+ function part(position, pattern, type) {
738
+ function method(tag) {
739
+ return match(tag)[position] || empty
740
+ }
741
+ expose(method, 'pattern', pattern);
742
+ expose(api, type, method);
743
+ }
744
+
745
+ part(1, /^[a-zA-Z]{2,3}$/, 'language');
746
+ part(2, /^[a-zA-Z]{3}$/, 'extlang');
747
+ part(3, /^[a-zA-Z]{4}$/, 'script');
748
+ part(4, /^[a-zA-Z]{2}$|^[0-9]{3}$/, 'region');
749
+
750
+ expose(api, 'split', split);
751
+
752
+ return api
753
+ });
754
+ } (subtag$2));
755
+ return subtag$2.exports;
756
+ }
757
+
758
+ var subtagExports = requireSubtag();
759
+ var subtag = /*@__PURE__*/getDefaultExportFromCjs(subtagExports);
760
+
761
+ /**
762
+ * lodash (Custom Build) <https://lodash.com/>
763
+ * Build: `lodash modularize exports="npm" -o ./`
764
+ * Copyright jQuery Foundation and other contributors <https://jquery.org/>
765
+ * Released under MIT license <https://lodash.com/license>
766
+ * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
767
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
768
+ */
769
+
770
+ var lodash_debounce;
771
+ var hasRequiredLodash_debounce;
772
+
773
+ function requireLodash_debounce () {
774
+ if (hasRequiredLodash_debounce) return lodash_debounce;
775
+ hasRequiredLodash_debounce = 1;
776
+ /** Used as the `TypeError` message for "Functions" methods. */
777
+ var FUNC_ERROR_TEXT = 'Expected a function';
778
+
779
+ /** Used as references for various `Number` constants. */
780
+ var NAN = 0 / 0;
781
+
782
+ /** `Object#toString` result references. */
783
+ var symbolTag = '[object Symbol]';
784
+
785
+ /** Used to match leading and trailing whitespace. */
786
+ var reTrim = /^\s+|\s+$/g;
787
+
788
+ /** Used to detect bad signed hexadecimal string values. */
789
+ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
790
+
791
+ /** Used to detect binary string values. */
792
+ var reIsBinary = /^0b[01]+$/i;
793
+
794
+ /** Used to detect octal string values. */
795
+ var reIsOctal = /^0o[0-7]+$/i;
796
+
797
+ /** Built-in method references without a dependency on `root`. */
798
+ var freeParseInt = parseInt;
799
+
800
+ /** Detect free variable `global` from Node.js. */
801
+ var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
802
+
803
+ /** Detect free variable `self`. */
804
+ var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
805
+
806
+ /** Used as a reference to the global object. */
807
+ var root = freeGlobal || freeSelf || Function('return this')();
808
+
809
+ /** Used for built-in method references. */
810
+ var objectProto = Object.prototype;
811
+
812
+ /**
813
+ * Used to resolve the
814
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
815
+ * of values.
816
+ */
817
+ var objectToString = objectProto.toString;
818
+
819
+ /* Built-in method references for those with the same name as other `lodash` methods. */
820
+ var nativeMax = Math.max,
821
+ nativeMin = Math.min;
822
+
823
+ /**
824
+ * Gets the timestamp of the number of milliseconds that have elapsed since
825
+ * the Unix epoch (1 January 1970 00:00:00 UTC).
826
+ *
827
+ * @static
828
+ * @memberOf _
829
+ * @since 2.4.0
830
+ * @category Date
831
+ * @returns {number} Returns the timestamp.
832
+ * @example
833
+ *
834
+ * _.defer(function(stamp) {
835
+ * console.log(_.now() - stamp);
836
+ * }, _.now());
837
+ * // => Logs the number of milliseconds it took for the deferred invocation.
838
+ */
839
+ var now = function() {
840
+ return root.Date.now();
841
+ };
842
+
843
+ /**
844
+ * Creates a debounced function that delays invoking `func` until after `wait`
845
+ * milliseconds have elapsed since the last time the debounced function was
846
+ * invoked. The debounced function comes with a `cancel` method to cancel
847
+ * delayed `func` invocations and a `flush` method to immediately invoke them.
848
+ * Provide `options` to indicate whether `func` should be invoked on the
849
+ * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
850
+ * with the last arguments provided to the debounced function. Subsequent
851
+ * calls to the debounced function return the result of the last `func`
852
+ * invocation.
853
+ *
854
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is
855
+ * invoked on the trailing edge of the timeout only if the debounced function
856
+ * is invoked more than once during the `wait` timeout.
857
+ *
858
+ * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
859
+ * until to the next tick, similar to `setTimeout` with a timeout of `0`.
860
+ *
861
+ * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
862
+ * for details over the differences between `_.debounce` and `_.throttle`.
863
+ *
864
+ * @static
865
+ * @memberOf _
866
+ * @since 0.1.0
867
+ * @category Function
868
+ * @param {Function} func The function to debounce.
869
+ * @param {number} [wait=0] The number of milliseconds to delay.
870
+ * @param {Object} [options={}] The options object.
871
+ * @param {boolean} [options.leading=false]
872
+ * Specify invoking on the leading edge of the timeout.
873
+ * @param {number} [options.maxWait]
874
+ * The maximum time `func` is allowed to be delayed before it's invoked.
875
+ * @param {boolean} [options.trailing=true]
876
+ * Specify invoking on the trailing edge of the timeout.
877
+ * @returns {Function} Returns the new debounced function.
878
+ * @example
879
+ *
880
+ * // Avoid costly calculations while the window size is in flux.
881
+ * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
882
+ *
883
+ * // Invoke `sendMail` when clicked, debouncing subsequent calls.
884
+ * jQuery(element).on('click', _.debounce(sendMail, 300, {
885
+ * 'leading': true,
886
+ * 'trailing': false
887
+ * }));
888
+ *
889
+ * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
890
+ * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
891
+ * var source = new EventSource('/stream');
892
+ * jQuery(source).on('message', debounced);
893
+ *
894
+ * // Cancel the trailing debounced invocation.
895
+ * jQuery(window).on('popstate', debounced.cancel);
896
+ */
897
+ function debounce(func, wait, options) {
898
+ var lastArgs,
899
+ lastThis,
900
+ maxWait,
901
+ result,
902
+ timerId,
903
+ lastCallTime,
904
+ lastInvokeTime = 0,
905
+ leading = false,
906
+ maxing = false,
907
+ trailing = true;
908
+
909
+ if (typeof func != 'function') {
910
+ throw new TypeError(FUNC_ERROR_TEXT);
911
+ }
912
+ wait = toNumber(wait) || 0;
913
+ if (isObject(options)) {
914
+ leading = !!options.leading;
915
+ maxing = 'maxWait' in options;
916
+ maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
917
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
918
+ }
919
+
920
+ function invokeFunc(time) {
921
+ var args = lastArgs,
922
+ thisArg = lastThis;
923
+
924
+ lastArgs = lastThis = undefined;
925
+ lastInvokeTime = time;
926
+ result = func.apply(thisArg, args);
927
+ return result;
928
+ }
929
+
930
+ function leadingEdge(time) {
931
+ // Reset any `maxWait` timer.
932
+ lastInvokeTime = time;
933
+ // Start the timer for the trailing edge.
934
+ timerId = setTimeout(timerExpired, wait);
935
+ // Invoke the leading edge.
936
+ return leading ? invokeFunc(time) : result;
937
+ }
938
+
939
+ function remainingWait(time) {
940
+ var timeSinceLastCall = time - lastCallTime,
941
+ timeSinceLastInvoke = time - lastInvokeTime,
942
+ result = wait - timeSinceLastCall;
943
+
944
+ return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
945
+ }
946
+
947
+ function shouldInvoke(time) {
948
+ var timeSinceLastCall = time - lastCallTime,
949
+ timeSinceLastInvoke = time - lastInvokeTime;
950
+
951
+ // Either this is the first call, activity has stopped and we're at the
952
+ // trailing edge, the system time has gone backwards and we're treating
953
+ // it as the trailing edge, or we've hit the `maxWait` limit.
954
+ return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
955
+ (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
956
+ }
957
+
958
+ function timerExpired() {
959
+ var time = now();
960
+ if (shouldInvoke(time)) {
961
+ return trailingEdge(time);
962
+ }
963
+ // Restart the timer.
964
+ timerId = setTimeout(timerExpired, remainingWait(time));
965
+ }
966
+
967
+ function trailingEdge(time) {
968
+ timerId = undefined;
969
+
970
+ // Only invoke if we have `lastArgs` which means `func` has been
971
+ // debounced at least once.
972
+ if (trailing && lastArgs) {
973
+ return invokeFunc(time);
974
+ }
975
+ lastArgs = lastThis = undefined;
976
+ return result;
977
+ }
978
+
979
+ function cancel() {
980
+ if (timerId !== undefined) {
981
+ clearTimeout(timerId);
982
+ }
983
+ lastInvokeTime = 0;
984
+ lastArgs = lastCallTime = lastThis = timerId = undefined;
985
+ }
986
+
987
+ function flush() {
988
+ return timerId === undefined ? result : trailingEdge(now());
989
+ }
990
+
991
+ function debounced() {
992
+ var time = now(),
993
+ isInvoking = shouldInvoke(time);
994
+
995
+ lastArgs = arguments;
996
+ lastThis = this;
997
+ lastCallTime = time;
998
+
999
+ if (isInvoking) {
1000
+ if (timerId === undefined) {
1001
+ return leadingEdge(lastCallTime);
1002
+ }
1003
+ if (maxing) {
1004
+ // Handle invocations in a tight loop.
1005
+ timerId = setTimeout(timerExpired, wait);
1006
+ return invokeFunc(lastCallTime);
1007
+ }
1008
+ }
1009
+ if (timerId === undefined) {
1010
+ timerId = setTimeout(timerExpired, wait);
1011
+ }
1012
+ return result;
1013
+ }
1014
+ debounced.cancel = cancel;
1015
+ debounced.flush = flush;
1016
+ return debounced;
1017
+ }
1018
+
1019
+ /**
1020
+ * Checks if `value` is the
1021
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
1022
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
1023
+ *
1024
+ * @static
1025
+ * @memberOf _
1026
+ * @since 0.1.0
1027
+ * @category Lang
1028
+ * @param {*} value The value to check.
1029
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
1030
+ * @example
1031
+ *
1032
+ * _.isObject({});
1033
+ * // => true
1034
+ *
1035
+ * _.isObject([1, 2, 3]);
1036
+ * // => true
1037
+ *
1038
+ * _.isObject(_.noop);
1039
+ * // => true
1040
+ *
1041
+ * _.isObject(null);
1042
+ * // => false
1043
+ */
1044
+ function isObject(value) {
1045
+ var type = typeof value;
1046
+ return !!value && (type == 'object' || type == 'function');
1047
+ }
1048
+
1049
+ /**
1050
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
1051
+ * and has a `typeof` result of "object".
1052
+ *
1053
+ * @static
1054
+ * @memberOf _
1055
+ * @since 4.0.0
1056
+ * @category Lang
1057
+ * @param {*} value The value to check.
1058
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
1059
+ * @example
1060
+ *
1061
+ * _.isObjectLike({});
1062
+ * // => true
1063
+ *
1064
+ * _.isObjectLike([1, 2, 3]);
1065
+ * // => true
1066
+ *
1067
+ * _.isObjectLike(_.noop);
1068
+ * // => false
1069
+ *
1070
+ * _.isObjectLike(null);
1071
+ * // => false
1072
+ */
1073
+ function isObjectLike(value) {
1074
+ return !!value && typeof value == 'object';
1075
+ }
1076
+
1077
+ /**
1078
+ * Checks if `value` is classified as a `Symbol` primitive or object.
1079
+ *
1080
+ * @static
1081
+ * @memberOf _
1082
+ * @since 4.0.0
1083
+ * @category Lang
1084
+ * @param {*} value The value to check.
1085
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
1086
+ * @example
1087
+ *
1088
+ * _.isSymbol(Symbol.iterator);
1089
+ * // => true
1090
+ *
1091
+ * _.isSymbol('abc');
1092
+ * // => false
1093
+ */
1094
+ function isSymbol(value) {
1095
+ return typeof value == 'symbol' ||
1096
+ (isObjectLike(value) && objectToString.call(value) == symbolTag);
1097
+ }
1098
+
1099
+ /**
1100
+ * Converts `value` to a number.
1101
+ *
1102
+ * @static
1103
+ * @memberOf _
1104
+ * @since 4.0.0
1105
+ * @category Lang
1106
+ * @param {*} value The value to process.
1107
+ * @returns {number} Returns the number.
1108
+ * @example
1109
+ *
1110
+ * _.toNumber(3.2);
1111
+ * // => 3.2
1112
+ *
1113
+ * _.toNumber(Number.MIN_VALUE);
1114
+ * // => 5e-324
1115
+ *
1116
+ * _.toNumber(Infinity);
1117
+ * // => Infinity
1118
+ *
1119
+ * _.toNumber('3.2');
1120
+ * // => 3.2
1121
+ */
1122
+ function toNumber(value) {
1123
+ if (typeof value == 'number') {
1124
+ return value;
1125
+ }
1126
+ if (isSymbol(value)) {
1127
+ return NAN;
1128
+ }
1129
+ if (isObject(value)) {
1130
+ var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
1131
+ value = isObject(other) ? (other + '') : other;
1132
+ }
1133
+ if (typeof value != 'string') {
1134
+ return value === 0 ? value : +value;
1135
+ }
1136
+ value = value.replace(reTrim, '');
1137
+ var isBinary = reIsBinary.test(value);
1138
+ return (isBinary || reIsOctal.test(value))
1139
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
1140
+ : (reIsBadHex.test(value) ? NAN : +value);
1141
+ }
1142
+
1143
+ lodash_debounce = debounce;
1144
+ return lodash_debounce;
1145
+ }
1146
+
1147
+ var lodash_debounceExports = requireLodash_debounce();
1148
+ var debounce = /*@__PURE__*/getDefaultExportFromCjs(lodash_debounceExports);
1149
+
1150
+ var immutableExports = requireImmutable();
1151
+ var extend = /*@__PURE__*/getDefaultExportFromCjs(immutableExports);
1152
+
1153
+ var events = {exports: {}};
1154
+
1155
+ var hasRequiredEvents;
1156
+
1157
+ function requireEvents () {
1158
+ if (hasRequiredEvents) return events.exports;
1159
+ hasRequiredEvents = 1;
1160
+
1161
+ var R = typeof Reflect === 'object' ? Reflect : null;
1162
+ var ReflectApply = R && typeof R.apply === 'function'
1163
+ ? R.apply
1164
+ : function ReflectApply(target, receiver, args) {
1165
+ return Function.prototype.apply.call(target, receiver, args);
1166
+ };
1167
+
1168
+ var ReflectOwnKeys;
1169
+ if (R && typeof R.ownKeys === 'function') {
1170
+ ReflectOwnKeys = R.ownKeys;
1171
+ } else if (Object.getOwnPropertySymbols) {
1172
+ ReflectOwnKeys = function ReflectOwnKeys(target) {
1173
+ return Object.getOwnPropertyNames(target)
1174
+ .concat(Object.getOwnPropertySymbols(target));
1175
+ };
1176
+ } else {
1177
+ ReflectOwnKeys = function ReflectOwnKeys(target) {
1178
+ return Object.getOwnPropertyNames(target);
1179
+ };
1180
+ }
1181
+
1182
+ function ProcessEmitWarning(warning) {
1183
+ if (console && console.warn) console.warn(warning);
1184
+ }
1185
+
1186
+ var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) {
1187
+ return value !== value;
1188
+ };
1189
+
1190
+ function EventEmitter() {
1191
+ EventEmitter.init.call(this);
1192
+ }
1193
+ events.exports = EventEmitter;
1194
+ events.exports.once = once;
1195
+
1196
+ // Backwards-compat with node 0.10.x
1197
+ EventEmitter.EventEmitter = EventEmitter;
1198
+
1199
+ EventEmitter.prototype._events = undefined;
1200
+ EventEmitter.prototype._eventsCount = 0;
1201
+ EventEmitter.prototype._maxListeners = undefined;
1202
+
1203
+ // By default EventEmitters will print a warning if more than 10 listeners are
1204
+ // added to it. This is a useful default which helps finding memory leaks.
1205
+ var defaultMaxListeners = 10;
1206
+
1207
+ function checkListener(listener) {
1208
+ if (typeof listener !== 'function') {
1209
+ throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener);
1210
+ }
1211
+ }
1212
+
1213
+ Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
1214
+ enumerable: true,
1215
+ get: function() {
1216
+ return defaultMaxListeners;
1217
+ },
1218
+ set: function(arg) {
1219
+ if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) {
1220
+ throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.');
1221
+ }
1222
+ defaultMaxListeners = arg;
1223
+ }
1224
+ });
1225
+
1226
+ EventEmitter.init = function() {
1227
+
1228
+ if (this._events === undefined ||
1229
+ this._events === Object.getPrototypeOf(this)._events) {
1230
+ this._events = Object.create(null);
1231
+ this._eventsCount = 0;
1232
+ }
1233
+
1234
+ this._maxListeners = this._maxListeners || undefined;
1235
+ };
1236
+
1237
+ // Obviously not all Emitters should be limited to 10. This function allows
1238
+ // that to be increased. Set to zero for unlimited.
1239
+ EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
1240
+ if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) {
1241
+ throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
1242
+ }
1243
+ this._maxListeners = n;
1244
+ return this;
1245
+ };
1246
+
1247
+ function _getMaxListeners(that) {
1248
+ if (that._maxListeners === undefined)
1249
+ return EventEmitter.defaultMaxListeners;
1250
+ return that._maxListeners;
1251
+ }
1252
+
1253
+ EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
1254
+ return _getMaxListeners(this);
1255
+ };
1256
+
1257
+ EventEmitter.prototype.emit = function emit(type) {
1258
+ var args = [];
1259
+ for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
1260
+ var doError = (type === 'error');
1261
+
1262
+ var events = this._events;
1263
+ if (events !== undefined)
1264
+ doError = (doError && events.error === undefined);
1265
+ else if (!doError)
1266
+ return false;
1267
+
1268
+ // If there is no 'error' event listener then throw.
1269
+ if (doError) {
1270
+ var er;
1271
+ if (args.length > 0)
1272
+ er = args[0];
1273
+ if (er instanceof Error) {
1274
+ // Note: The comments on the `throw` lines are intentional, they show
1275
+ // up in Node's output if this results in an unhandled exception.
1276
+ throw er; // Unhandled 'error' event
1277
+ }
1278
+ // At least give some kind of context to the user
1279
+ var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
1280
+ err.context = er;
1281
+ throw err; // Unhandled 'error' event
1282
+ }
1283
+
1284
+ var handler = events[type];
1285
+
1286
+ if (handler === undefined)
1287
+ return false;
1288
+
1289
+ if (typeof handler === 'function') {
1290
+ ReflectApply(handler, this, args);
1291
+ } else {
1292
+ var len = handler.length;
1293
+ var listeners = arrayClone(handler, len);
1294
+ for (var i = 0; i < len; ++i)
1295
+ ReflectApply(listeners[i], this, args);
1296
+ }
1297
+
1298
+ return true;
1299
+ };
1300
+
1301
+ function _addListener(target, type, listener, prepend) {
1302
+ var m;
1303
+ var events;
1304
+ var existing;
1305
+
1306
+ checkListener(listener);
1307
+
1308
+ events = target._events;
1309
+ if (events === undefined) {
1310
+ events = target._events = Object.create(null);
1311
+ target._eventsCount = 0;
1312
+ } else {
1313
+ // To avoid recursion in the case that type === "newListener"! Before
1314
+ // adding it to the listeners, first emit "newListener".
1315
+ if (events.newListener !== undefined) {
1316
+ target.emit('newListener', type,
1317
+ listener.listener ? listener.listener : listener);
1318
+
1319
+ // Re-assign `events` because a newListener handler could have caused the
1320
+ // this._events to be assigned to a new object
1321
+ events = target._events;
1322
+ }
1323
+ existing = events[type];
1324
+ }
1325
+
1326
+ if (existing === undefined) {
1327
+ // Optimize the case of one listener. Don't need the extra array object.
1328
+ existing = events[type] = listener;
1329
+ ++target._eventsCount;
1330
+ } else {
1331
+ if (typeof existing === 'function') {
1332
+ // Adding the second element, need to change to array.
1333
+ existing = events[type] =
1334
+ prepend ? [listener, existing] : [existing, listener];
1335
+ // If we've already got an array, just append.
1336
+ } else if (prepend) {
1337
+ existing.unshift(listener);
1338
+ } else {
1339
+ existing.push(listener);
1340
+ }
1341
+
1342
+ // Check for listener leak
1343
+ m = _getMaxListeners(target);
1344
+ if (m > 0 && existing.length > m && !existing.warned) {
1345
+ existing.warned = true;
1346
+ // No error code for this since it is a Warning
1347
+ // eslint-disable-next-line no-restricted-syntax
1348
+ var w = new Error('Possible EventEmitter memory leak detected. ' +
1349
+ existing.length + ' ' + String(type) + ' listeners ' +
1350
+ 'added. Use emitter.setMaxListeners() to ' +
1351
+ 'increase limit');
1352
+ w.name = 'MaxListenersExceededWarning';
1353
+ w.emitter = target;
1354
+ w.type = type;
1355
+ w.count = existing.length;
1356
+ ProcessEmitWarning(w);
1357
+ }
1358
+ }
1359
+
1360
+ return target;
1361
+ }
1362
+
1363
+ EventEmitter.prototype.addListener = function addListener(type, listener) {
1364
+ return _addListener(this, type, listener, false);
1365
+ };
1366
+
1367
+ EventEmitter.prototype.on = EventEmitter.prototype.addListener;
1368
+
1369
+ EventEmitter.prototype.prependListener =
1370
+ function prependListener(type, listener) {
1371
+ return _addListener(this, type, listener, true);
1372
+ };
1373
+
1374
+ function onceWrapper() {
1375
+ if (!this.fired) {
1376
+ this.target.removeListener(this.type, this.wrapFn);
1377
+ this.fired = true;
1378
+ if (arguments.length === 0)
1379
+ return this.listener.call(this.target);
1380
+ return this.listener.apply(this.target, arguments);
1381
+ }
1382
+ }
1383
+
1384
+ function _onceWrap(target, type, listener) {
1385
+ var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener };
1386
+ var wrapped = onceWrapper.bind(state);
1387
+ wrapped.listener = listener;
1388
+ state.wrapFn = wrapped;
1389
+ return wrapped;
1390
+ }
1391
+
1392
+ EventEmitter.prototype.once = function once(type, listener) {
1393
+ checkListener(listener);
1394
+ this.on(type, _onceWrap(this, type, listener));
1395
+ return this;
1396
+ };
1397
+
1398
+ EventEmitter.prototype.prependOnceListener =
1399
+ function prependOnceListener(type, listener) {
1400
+ checkListener(listener);
1401
+ this.prependListener(type, _onceWrap(this, type, listener));
1402
+ return this;
1403
+ };
1404
+
1405
+ // Emits a 'removeListener' event if and only if the listener was removed.
1406
+ EventEmitter.prototype.removeListener =
1407
+ function removeListener(type, listener) {
1408
+ var list, events, position, i, originalListener;
1409
+
1410
+ checkListener(listener);
1411
+
1412
+ events = this._events;
1413
+ if (events === undefined)
1414
+ return this;
1415
+
1416
+ list = events[type];
1417
+ if (list === undefined)
1418
+ return this;
1419
+
1420
+ if (list === listener || list.listener === listener) {
1421
+ if (--this._eventsCount === 0)
1422
+ this._events = Object.create(null);
1423
+ else {
1424
+ delete events[type];
1425
+ if (events.removeListener)
1426
+ this.emit('removeListener', type, list.listener || listener);
1427
+ }
1428
+ } else if (typeof list !== 'function') {
1429
+ position = -1;
1430
+
1431
+ for (i = list.length - 1; i >= 0; i--) {
1432
+ if (list[i] === listener || list[i].listener === listener) {
1433
+ originalListener = list[i].listener;
1434
+ position = i;
1435
+ break;
1436
+ }
1437
+ }
1438
+
1439
+ if (position < 0)
1440
+ return this;
1441
+
1442
+ if (position === 0)
1443
+ list.shift();
1444
+ else {
1445
+ spliceOne(list, position);
1446
+ }
1447
+
1448
+ if (list.length === 1)
1449
+ events[type] = list[0];
1450
+
1451
+ if (events.removeListener !== undefined)
1452
+ this.emit('removeListener', type, originalListener || listener);
1453
+ }
1454
+
1455
+ return this;
1456
+ };
1457
+
1458
+ EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
1459
+
1460
+ EventEmitter.prototype.removeAllListeners =
1461
+ function removeAllListeners(type) {
1462
+ var listeners, events, i;
1463
+
1464
+ events = this._events;
1465
+ if (events === undefined)
1466
+ return this;
1467
+
1468
+ // not listening for removeListener, no need to emit
1469
+ if (events.removeListener === undefined) {
1470
+ if (arguments.length === 0) {
1471
+ this._events = Object.create(null);
1472
+ this._eventsCount = 0;
1473
+ } else if (events[type] !== undefined) {
1474
+ if (--this._eventsCount === 0)
1475
+ this._events = Object.create(null);
1476
+ else
1477
+ delete events[type];
1478
+ }
1479
+ return this;
1480
+ }
1481
+
1482
+ // emit removeListener for all listeners on all events
1483
+ if (arguments.length === 0) {
1484
+ var keys = Object.keys(events);
1485
+ var key;
1486
+ for (i = 0; i < keys.length; ++i) {
1487
+ key = keys[i];
1488
+ if (key === 'removeListener') continue;
1489
+ this.removeAllListeners(key);
1490
+ }
1491
+ this.removeAllListeners('removeListener');
1492
+ this._events = Object.create(null);
1493
+ this._eventsCount = 0;
1494
+ return this;
1495
+ }
1496
+
1497
+ listeners = events[type];
1498
+
1499
+ if (typeof listeners === 'function') {
1500
+ this.removeListener(type, listeners);
1501
+ } else if (listeners !== undefined) {
1502
+ // LIFO order
1503
+ for (i = listeners.length - 1; i >= 0; i--) {
1504
+ this.removeListener(type, listeners[i]);
1505
+ }
1506
+ }
1507
+
1508
+ return this;
1509
+ };
1510
+
1511
+ function _listeners(target, type, unwrap) {
1512
+ var events = target._events;
1513
+
1514
+ if (events === undefined)
1515
+ return [];
1516
+
1517
+ var evlistener = events[type];
1518
+ if (evlistener === undefined)
1519
+ return [];
1520
+
1521
+ if (typeof evlistener === 'function')
1522
+ return unwrap ? [evlistener.listener || evlistener] : [evlistener];
1523
+
1524
+ return unwrap ?
1525
+ unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length);
1526
+ }
1527
+
1528
+ EventEmitter.prototype.listeners = function listeners(type) {
1529
+ return _listeners(this, type, true);
1530
+ };
1531
+
1532
+ EventEmitter.prototype.rawListeners = function rawListeners(type) {
1533
+ return _listeners(this, type, false);
1534
+ };
1535
+
1536
+ EventEmitter.listenerCount = function(emitter, type) {
1537
+ if (typeof emitter.listenerCount === 'function') {
1538
+ return emitter.listenerCount(type);
1539
+ } else {
1540
+ return listenerCount.call(emitter, type);
1541
+ }
1542
+ };
1543
+
1544
+ EventEmitter.prototype.listenerCount = listenerCount;
1545
+ function listenerCount(type) {
1546
+ var events = this._events;
1547
+
1548
+ if (events !== undefined) {
1549
+ var evlistener = events[type];
1550
+
1551
+ if (typeof evlistener === 'function') {
1552
+ return 1;
1553
+ } else if (evlistener !== undefined) {
1554
+ return evlistener.length;
1555
+ }
1556
+ }
1557
+
1558
+ return 0;
1559
+ }
1560
+
1561
+ EventEmitter.prototype.eventNames = function eventNames() {
1562
+ return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
1563
+ };
1564
+
1565
+ function arrayClone(arr, n) {
1566
+ var copy = new Array(n);
1567
+ for (var i = 0; i < n; ++i)
1568
+ copy[i] = arr[i];
1569
+ return copy;
1570
+ }
1571
+
1572
+ function spliceOne(list, index) {
1573
+ for (; index + 1 < list.length; index++)
1574
+ list[index] = list[index + 1];
1575
+ list.pop();
1576
+ }
1577
+
1578
+ function unwrapListeners(arr) {
1579
+ var ret = new Array(arr.length);
1580
+ for (var i = 0; i < ret.length; ++i) {
1581
+ ret[i] = arr[i].listener || arr[i];
1582
+ }
1583
+ return ret;
1584
+ }
1585
+
1586
+ function once(emitter, name) {
1587
+ return new Promise(function (resolve, reject) {
1588
+ function errorListener(err) {
1589
+ emitter.removeListener(name, resolver);
1590
+ reject(err);
1591
+ }
1592
+
1593
+ function resolver() {
1594
+ if (typeof emitter.removeListener === 'function') {
1595
+ emitter.removeListener('error', errorListener);
1596
+ }
1597
+ resolve([].slice.call(arguments));
1598
+ }
1599
+ eventTargetAgnosticAddListener(emitter, name, resolver, { once: true });
1600
+ if (name !== 'error') {
1601
+ addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true });
1602
+ }
1603
+ });
1604
+ }
1605
+
1606
+ function addErrorHandlerIfEventEmitter(emitter, handler, flags) {
1607
+ if (typeof emitter.on === 'function') {
1608
+ eventTargetAgnosticAddListener(emitter, 'error', handler, flags);
1609
+ }
1610
+ }
1611
+
1612
+ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
1613
+ if (typeof emitter.on === 'function') {
1614
+ if (flags.once) {
1615
+ emitter.once(name, listener);
1616
+ } else {
1617
+ emitter.on(name, listener);
1618
+ }
1619
+ } else if (typeof emitter.addEventListener === 'function') {
1620
+ // EventTarget does not have `error` event semantics like Node
1621
+ // EventEmitters, we do not listen for `error` events here.
1622
+ emitter.addEventListener(name, function wrapListener(arg) {
1623
+ // IE does not have builtin `{ once: true }` support so we
1624
+ // have to do it manually.
1625
+ if (flags.once) {
1626
+ emitter.removeEventListener(name, wrapListener);
1627
+ }
1628
+ listener(arg);
1629
+ });
1630
+ } else {
1631
+ throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter);
1632
+ }
1633
+ }
1634
+ return events.exports;
1635
+ }
1636
+
1637
+ var eventsExports = requireEvents();
1638
+
1639
+ const exceptions = {
1640
+ 'fr': {
1641
+ 'name': 'France',
1642
+ 'bbox': [[-4.59235, 41.380007], [9.560016, 51.148506]]
1643
+ },
1644
+ 'us': {
1645
+ 'name': 'United States',
1646
+ 'bbox': [[-171.791111, 18.91619], [-66.96466, 71.357764]]
1647
+ },
1648
+ 'ru': {
1649
+ 'name': 'Russia',
1650
+ 'bbox': [[19.66064, 41.151416], [190.10042, 81.2504]]
1651
+ },
1652
+ 'ca': {
1653
+ 'name': 'Canada',
1654
+ 'bbox': [[-140.99778, 41.675105], [-52.648099, 83.23324]]
1655
+ }
1656
+ };
1657
+
1658
+ /**
1659
+ * Localized values for the placeholder string
1660
+ *
1661
+ * @private
1662
+ */
1663
+ const placeholder = {
1664
+ // list drawn from https://docs.mapbox.com/api/search/#language-coverage
1665
+ 'de': 'Suche', // german
1666
+ 'it': 'Ricerca', //italian
1667
+ 'en': 'Search', // english
1668
+ 'nl': 'Zoeken', //dutch
1669
+ 'fr': 'Chercher', //french
1670
+ 'ca': 'Cerca', //catalan
1671
+ 'he': 'לחפש', //hebrew
1672
+ 'ja': 'サーチ', //japanese
1673
+ 'lv': 'Meklēt', //latvian
1674
+ 'pt': 'Procurar', //portuguese
1675
+ 'sr': 'Претрага', //serbian
1676
+ 'zh': '搜索', //chinese-simplified
1677
+ 'cs': 'Vyhledávání', //czech
1678
+ 'hu': 'Keresés', //hungarian
1679
+ 'ka': 'ძიება', // georgian
1680
+ 'nb': 'Søke', //norwegian
1681
+ 'sk': 'Vyhľadávanie', //slovak
1682
+ 'th': 'ค้นหา', //thai
1683
+ 'fi': 'Hae', //finnish
1684
+ 'is': 'Leita', //icelandic
1685
+ 'ko': '수색', //korean
1686
+ 'pl': 'Szukaj', //polish
1687
+ 'sl': 'Iskanje', //slovenian
1688
+ 'fa': 'جستجو', //persian(aka farsi)
1689
+ 'ru': 'Поиск', //russian,
1690
+ 'es': 'Buscar' //spanish
1691
+ };
1692
+ const errorNoResults = {
1693
+ 'en': 'No results found',
1694
+ 'de': 'Keine Ergebnisse gefunden',
1695
+ 'es': 'No hay resultados',
1696
+ 'fr': 'Aucun résultat trouvé'
1697
+ };
1698
+ const errorConnectionFailed = {
1699
+ 'en': 'There was an error reaching the server',
1700
+ 'de': 'Verbindung fehlgeschlagen',
1701
+ 'es': 'Error al conectarse al servidor',
1702
+ 'fr': 'Une erreur est survenue lors de la connexion au serveur'
1703
+ };
1704
+ var localization = { placeholder, errorNoResults, errorConnectionFailed };
1705
+
1706
+ /**
1707
+ * A regular expression to match coordinates.
1708
+ */
1709
+ const COORDINATES_REGEXP = /(-?\d+\.?\d*)[, ]+(-?\d+\.?\d*)[ ]*$/;
1710
+ /**
1711
+ * A geocoder component that works with maplibre
1712
+ */
1713
+ class MaplibreGeocoder {
1714
+ constructor(geocoderApi, options) {
1715
+ this.options = {
1716
+ zoom: 16,
1717
+ flyTo: true,
1718
+ trackProximity: true,
1719
+ showResultsWhileTyping: false,
1720
+ minLength: 2,
1721
+ reverseGeocode: false,
1722
+ limit: 5,
1723
+ enableEventLogging: true,
1724
+ marker: true,
1725
+ popup: false,
1726
+ maplibregl: undefined,
1727
+ collapsed: false,
1728
+ clearAndBlurOnEsc: false,
1729
+ clearOnBlur: false,
1730
+ proximityMinZoom: 9,
1731
+ getItemValue: (item) => {
1732
+ return item.text !== undefined ? item.text : item.place_name;
1733
+ },
1734
+ render: function (item) {
1735
+ // Render as a suggestion
1736
+ if (!item.geometry) {
1737
+ const suggestionString = item.text;
1738
+ const indexOfMatch = suggestionString
1739
+ .toLowerCase()
1740
+ .indexOf(this.query.toLowerCase());
1741
+ const lengthOfMatch = this.query.length;
1742
+ const beforeMatch = suggestionString.substring(0, indexOfMatch);
1743
+ const match = suggestionString.substring(indexOfMatch, indexOfMatch + lengthOfMatch);
1744
+ const afterMatch = suggestionString.substring(indexOfMatch + lengthOfMatch);
1745
+ return ('<div class="maplibregl-ctrl-geocoder--suggestion">' +
1746
+ '<svg class="maplibregl-ctrl-geocoder--suggestion-icon" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="M22.8702 20.1258H21.4248L20.9125 19.6318C22.7055 17.546 23.785 14.8382 23.785 11.8925C23.785 5.32419 18.4608 0 11.8925 0C5.32419 0 0 5.32419 0 11.8925C0 18.4608 5.32419 23.785 11.8925 23.785C14.8382 23.785 17.546 22.7055 19.6318 20.9125L20.1258 21.4248V22.8702L29.2739 32L32 29.2739L22.8702 20.1258ZM11.8925 20.1258C7.33676 20.1258 3.65923 16.4483 3.65923 11.8925C3.65923 7.33676 7.33676 3.65923 11.8925 3.65923C16.4483 3.65923 20.1258 7.33676 20.1258 11.8925C20.1258 16.4483 16.4483 20.1258 11.8925 20.1258Z" fill="#687078"/></svg>' +
1747
+ '<div class="maplibregl-ctrl-geocoder--suggestion-info">' +
1748
+ '<div class="maplibregl-ctrl-geocoder--suggestion-title">' +
1749
+ beforeMatch +
1750
+ '<span class="maplibregl-ctrl-geocoder--suggestion-match">' +
1751
+ match +
1752
+ "</span>" +
1753
+ afterMatch +
1754
+ "</div>" +
1755
+ "</div>" +
1756
+ "</div>");
1757
+ }
1758
+ // render as a search result
1759
+ const placeName = item.place_name.split(",");
1760
+ return ('<div class="maplibregl-ctrl-geocoder--result">' +
1761
+ '<svg class="maplibregl-ctrl-geocoder--result-icon" viewBox="0 0 24 32" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 0C5.36571 0 0 5.38676 0 12.0471C0 21.0824 12 32 12 32C12 32 24 21.0824 24 12.0471C24 5.38676 18.6343 0 12 0ZM12 16.3496C9.63428 16.3496 7.71429 14.4221 7.71429 12.0471C7.71429 9.67207 9.63428 7.74454 12 7.74454C14.3657 7.74454 16.2857 9.67207 16.2857 12.0471C16.2857 14.4221 14.3657 16.3496 12 16.3496Z" fill="#687078"/></svg>' +
1762
+ "<div>" +
1763
+ '<div class="maplibregl-ctrl-geocoder--result-title">' +
1764
+ placeName[0] +
1765
+ "</div>" +
1766
+ '<div class="maplibregl-ctrl-geocoder--result-address">' +
1767
+ placeName.splice(1, placeName.length).join(",") +
1768
+ "</div>" +
1769
+ "</div>" +
1770
+ "</div>");
1771
+ },
1772
+ popupRender: (item) => {
1773
+ const placeName = item.place_name.split(",");
1774
+ return ('<div class="maplibregl-ctrl-geocoder--suggestion popup-suggestion"><div class="maplibregl-ctrl-geocoder--suggestion-title popup-suggestion-title">' +
1775
+ placeName[0] +
1776
+ '</div><div class="maplibregl-ctrl-geocoder--suggestion-address popup-suggestion-address">' +
1777
+ placeName.splice(1, placeName.length).join(",") +
1778
+ "</div></div>");
1779
+ },
1780
+ showResultMarkers: true,
1781
+ debounceSearch: 200,
1782
+ };
1783
+ this._eventEmitter = new eventsExports.EventEmitter();
1784
+ this.options = extend({}, this.options, options);
1785
+ this.fresh = true;
1786
+ this.lastSelected = null;
1787
+ this.geocoderApi = geocoderApi;
1788
+ }
1789
+ /**
1790
+ * Add the geocoder to a container. The container can be either a `Map`, an `HTMLElement` or a CSS selector string.
1791
+ *
1792
+ * If the container is a [`Map`](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map), this function will behave identically to [`Map.addControl(geocoder)`](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map#addcontrol).
1793
+ * If the container is an instance of [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement), then the geocoder will be appended as a child of that [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement).
1794
+ * If the container is a [CSS selector string](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors), the geocoder will be appended to the element returned from the query.
1795
+ *
1796
+ * This function will throw an error if the container is none of the above.
1797
+ * It will also throw an error if the referenced HTML element cannot be found in the `document.body`.
1798
+ *
1799
+ * For example, if the HTML body contains the element `<div id='geocoder-container'></div>`, the following script will append the geocoder to `#geocoder-container`:
1800
+ * @example
1801
+ * ```js
1802
+ * const GeoApi = {
1803
+ * forwardGeocode: (config) => { return { features: [] } },
1804
+ * reverseGeocode: (config) => { return { features: [] } }
1805
+ * }
1806
+ * const geocoder = new MaplibreGeocoder(GeoAPI, {});
1807
+ * geocoder.addTo('#geocoder-container');
1808
+ * ```
1809
+ * @param container - A reference to the container to which to add the geocoder
1810
+ */
1811
+ addTo(container) {
1812
+ function addToExistingContainer(geocoder, container) {
1813
+ if (!document.body.contains(container)) {
1814
+ throw new Error("Element provided to #addTo() exists, but is not in the DOM");
1815
+ }
1816
+ const el = geocoder.onAdd(); //returns the input elements, which are then added to the requested html container
1817
+ container.appendChild(el);
1818
+ }
1819
+ // if the container is an HTMLElement, then set the parent to be that element
1820
+ if (container instanceof HTMLElement) {
1821
+ addToExistingContainer(this, container);
1822
+ }
1823
+ // if the container is a string, treat it as a CSS query
1824
+ else if (typeof container == "string") {
1825
+ const parent = document.querySelectorAll(container);
1826
+ if (parent.length === 0) {
1827
+ throw new Error("Element " + container + "not found.");
1828
+ }
1829
+ if (parent.length > 1) {
1830
+ throw new Error("Geocoder can only be added to a single html element");
1831
+ }
1832
+ addToExistingContainer(this, parent[0]);
1833
+ }
1834
+ // if the container is a map, add the control like normal
1835
+ else if ('addControl' in container) {
1836
+ // it's a maplibre-gl map, add like normal
1837
+ container.addControl(this);
1838
+ }
1839
+ else {
1840
+ throw new Error("Error: addTo must be a maplibre-gl-js map, an html element, or a CSS selector query for a single html element");
1841
+ }
1842
+ }
1843
+ onAdd(map) {
1844
+ if (map && typeof map != "string") {
1845
+ this._map = map;
1846
+ }
1847
+ this.setLanguage();
1848
+ if (this.options.localGeocoderOnly && !this.options.localGeocoder) {
1849
+ throw new Error("A localGeocoder function must be specified to use localGeocoderOnly mode");
1850
+ }
1851
+ this._onChange = this._onChange.bind(this);
1852
+ this._onKeyDown = this._onKeyDown.bind(this);
1853
+ this._onPaste = this._onPaste.bind(this);
1854
+ this._onBlur = this._onBlur.bind(this);
1855
+ this._showButton = this._showButton.bind(this);
1856
+ this._hideButton = this._hideButton.bind(this);
1857
+ this._onQueryResult = this._onQueryResult.bind(this);
1858
+ this.clear = this.clear.bind(this);
1859
+ this._updateProximity = this._updateProximity.bind(this);
1860
+ this._collapse = this._collapse.bind(this);
1861
+ this._unCollapse = this._unCollapse.bind(this);
1862
+ this._clear = this._clear.bind(this);
1863
+ this._clearOnBlur = this._clearOnBlur.bind(this);
1864
+ const el = (this.container = document.createElement("div"));
1865
+ el.className =
1866
+ "maplibregl-ctrl-geocoder maplibregl-ctrl maplibregl-ctrl-geocoder maplibregl-ctrl";
1867
+ const searchIcon = this.createIcon("search", '<path d="M7.4 2.5c-2.7 0-4.9 2.2-4.9 4.9s2.2 4.9 4.9 4.9c1 0 1.8-.2 2.5-.8l3.7 3.7c.2.2.4.3.8.3.7 0 1.1-.4 1.1-1.1 0-.3-.1-.5-.3-.8L11.4 10c.4-.8.8-1.6.8-2.5.1-2.8-2.1-5-4.8-5zm0 1.6c1.8 0 3.2 1.4 3.2 3.2s-1.4 3.2-3.2 3.2-3.3-1.3-3.3-3.1 1.4-3.3 3.3-3.3z"/>');
1868
+ this._inputEl = document.createElement("input");
1869
+ this._inputEl.type = "search";
1870
+ this._inputEl.className =
1871
+ "maplibregl-ctrl-geocoder--input";
1872
+ this.setPlaceholder();
1873
+ if (this.options.collapsed) {
1874
+ this._collapse();
1875
+ this.container.addEventListener("mouseenter", this._unCollapse);
1876
+ this.container.addEventListener("mouseleave", this._collapse);
1877
+ this._inputEl.addEventListener("focus", this._unCollapse);
1878
+ }
1879
+ if (this.options.collapsed || this.options.clearOnBlur) {
1880
+ this._inputEl.addEventListener("blur", this._onBlur);
1881
+ }
1882
+ this._inputEl.addEventListener("keydown", debounce(this._onKeyDown, this.options.debounceSearch));
1883
+ this._inputEl.addEventListener("paste", this._onPaste);
1884
+ this._inputEl.addEventListener("change", this._onChange);
1885
+ this.container.addEventListener("mouseenter", this._showButton);
1886
+ this.container.addEventListener("mouseleave", this._hideButton);
1887
+ const actions = document.createElement("div");
1888
+ actions.classList.add("maplibregl-ctrl-geocoder--pin-right");
1889
+ this._clearEl = document.createElement("button");
1890
+ this._clearEl.setAttribute("type", "button");
1891
+ this._clearEl.setAttribute("aria-label", "Clear");
1892
+ this._clearEl.addEventListener("click", this.clear);
1893
+ this._clearEl.className = "maplibregl-ctrl-geocoder--button";
1894
+ const buttonIcon = this.createIcon("close", '<path d="M3.8 2.5c-.6 0-1.3.7-1.3 1.3 0 .3.2.7.5.8L7.2 9 3 13.2c-.3.3-.5.7-.5 1 0 .6.7 1.3 1.3 1.3.3 0 .7-.2 1-.5L9 10.8l4.2 4.2c.2.3.7.3 1 .3.6 0 1.3-.7 1.3-1.3 0-.3-.2-.7-.3-1l-4.4-4L15 4.6c.3-.2.5-.5.5-.8 0-.7-.7-1.3-1.3-1.3-.3 0-.7.2-1 .3L9 7.1 4.8 2.8c-.3-.1-.7-.3-1-.3z"/>');
1895
+ this._clearEl.appendChild(buttonIcon);
1896
+ this._loadingEl = this.createIcon("loading", '<path fill="#333" d="M4.4 4.4l.8.8c2.1-2.1 5.5-2.1 7.6 0l.8-.8c-2.5-2.5-6.7-2.5-9.2 0z"/><path opacity=".1" d="M12.8 12.9c-2.1 2.1-5.5 2.1-7.6 0-2.1-2.1-2.1-5.5 0-7.7l-.8-.8c-2.5 2.5-2.5 6.7 0 9.2s6.6 2.5 9.2 0 2.5-6.6 0-9.2l-.8.8c2.2 2.1 2.2 5.6 0 7.7z"/>');
1897
+ actions.appendChild(this._clearEl);
1898
+ actions.appendChild(this._loadingEl);
1899
+ el.appendChild(searchIcon);
1900
+ el.appendChild(this._inputEl);
1901
+ el.appendChild(actions);
1902
+ this._typeahead = new Typeahead(this._inputEl, [], {
1903
+ filter: false,
1904
+ minLength: this.options.minLength,
1905
+ limit: this.options.limit,
1906
+ noInitialSelection: true,
1907
+ });
1908
+ this.container.addEventListener("click", () => {
1909
+ this._typeahead.update(this._typeahead.data);
1910
+ });
1911
+ this.setRenderFunction(this.options.render);
1912
+ this._typeahead.getItemValue = this.options.getItemValue;
1913
+ this.mapMarker = null;
1914
+ this.resultMarkers = [];
1915
+ this._handleMarker = this._handleMarker.bind(this);
1916
+ this._handleResultMarkers = this._handleResultMarkers.bind(this);
1917
+ if (this._map) {
1918
+ if (this.options.trackProximity) {
1919
+ this._updateProximity();
1920
+ this._map.on("moveend", this._updateProximity);
1921
+ }
1922
+ this._maplibregl = this.options.maplibregl;
1923
+ if (!this._maplibregl && this.options.marker) {
1924
+ console.error("No maplibregl detected in options. Map markers are disabled. Please set options.maplibregl.");
1925
+ this.options.marker = false;
1926
+ }
1927
+ }
1928
+ return el;
1929
+ }
1930
+ createIcon(name, path) {
1931
+ const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
1932
+ icon.setAttribute("class", "maplibregl-ctrl-geocoder--icon maplibregl-ctrl-geocoder--icon-" + name);
1933
+ icon.setAttribute("viewBox", "0 0 18 18");
1934
+ icon.setAttribute("xml:space", "preserve");
1935
+ icon.setAttribute("width", "18");
1936
+ icon.setAttribute("height", "18");
1937
+ // IE does not have innerHTML for SVG nodes
1938
+ if (!("innerHTML" in icon)) {
1939
+ const SVGNodeContainer = document.createElement("div");
1940
+ SVGNodeContainer.innerHTML =
1941
+ "<svg>" + path.valueOf().toString() + "</svg>";
1942
+ const SVGNode = SVGNodeContainer.firstChild, SVGPath = SVGNode.firstChild;
1943
+ icon.appendChild(SVGPath);
1944
+ }
1945
+ else {
1946
+ icon.innerHTML = path;
1947
+ }
1948
+ return icon;
1949
+ }
1950
+ onRemove() {
1951
+ this.container.remove();
1952
+ if (this.options.trackProximity && this._map) {
1953
+ this._map.off("moveend", this._updateProximity);
1954
+ }
1955
+ this._removeMarker();
1956
+ this._map = null;
1957
+ return this;
1958
+ }
1959
+ _onPaste(e) {
1960
+ const value = (e.clipboardData || window.clipboardData).getData("text");
1961
+ if (value.length >= this.options.minLength &&
1962
+ this.options.showResultsWhileTyping) {
1963
+ this._geocode(value);
1964
+ }
1965
+ }
1966
+ _onKeyDown(e) {
1967
+ const ESC_KEY_CODE = 27;
1968
+ const TAB_KEY_CODE = 9;
1969
+ const ENTER_KEY_CODE = 13;
1970
+ if (e.keyCode === ESC_KEY_CODE && this.options.clearAndBlurOnEsc) {
1971
+ this._clear(e);
1972
+ return this._inputEl.blur();
1973
+ }
1974
+ const value = this._inputEl.value;
1975
+ if (!value) {
1976
+ this.fresh = true;
1977
+ // the user has removed all the text
1978
+ if (e.keyCode !== TAB_KEY_CODE)
1979
+ this.clear(e);
1980
+ return (this._clearEl.style.display = "none");
1981
+ }
1982
+ // TAB, ESC, LEFT, RIGHT, UP, DOWN
1983
+ if (e.metaKey ||
1984
+ [TAB_KEY_CODE, ESC_KEY_CODE, 37, 39, 38, 40].indexOf(e.keyCode) !== -1)
1985
+ return;
1986
+ // ENTER
1987
+ if (e.keyCode === ENTER_KEY_CODE) {
1988
+ if (!this.options.showResultsWhileTyping) {
1989
+ if (!this._typeahead.selected) {
1990
+ this._geocode(value);
1991
+ }
1992
+ }
1993
+ else {
1994
+ // Pressing enter on the search box will do a search for the currently string input
1995
+ if (this._typeahead.selected == null &&
1996
+ this.geocoderApi.getSuggestions) {
1997
+ this._geocode(value, true);
1998
+ // If suggestions API is not defined pressing enter while the input box is selected will try to fit the results into the current map view
1999
+ }
2000
+ else if (this._typeahead.selected == null) {
2001
+ if (this.options.showResultMarkers) {
2002
+ this._fitBoundsForMarkers();
2003
+ }
2004
+ }
2005
+ return;
2006
+ }
2007
+ }
2008
+ // Show results while typing and greater than min length
2009
+ if (value.length >= this.options.minLength &&
2010
+ this.options.showResultsWhileTyping) {
2011
+ this._geocode(value);
2012
+ }
2013
+ }
2014
+ _showButton() {
2015
+ if (this._inputEl.value.length > 0)
2016
+ this._clearEl.style.display = "block";
2017
+ }
2018
+ _hideButton() {
2019
+ if (this._typeahead.selected)
2020
+ this._clearEl.style.display = "none";
2021
+ }
2022
+ _onBlur(e) {
2023
+ if (this.options.clearOnBlur) {
2024
+ this._clearOnBlur(e);
2025
+ }
2026
+ if (this.options.collapsed) {
2027
+ this._collapse();
2028
+ }
2029
+ }
2030
+ // Change events are fire by suggestions library whenever the enter key is pressed or input is blurred
2031
+ // This can sometimes cause strange behavior as this function is called before our own onKeyDown handler and thus
2032
+ // we cannot depend on some internal values of the suggestion state like `selected` as those will change or before
2033
+ // our onKeyDown handler.
2034
+ _onChange() {
2035
+ const selected = this._typeahead.selected;
2036
+ // If a suggestion was selected
2037
+ if (selected && !selected.geometry) {
2038
+ if (selected.placeId)
2039
+ this._geocode(selected.placeId, true, true);
2040
+ else
2041
+ this._geocode(selected.text, true);
2042
+ }
2043
+ else if (selected && JSON.stringify(selected) !== this.lastSelected) {
2044
+ this._clearEl.style.display = "none";
2045
+ if (this.options.flyTo) {
2046
+ let flyOptions;
2047
+ this._removeResultMarkers();
2048
+ if (selected.properties && exceptions[selected.properties.short_code]) {
2049
+ // Certain geocoder search results return (and therefore zoom to fit)
2050
+ // an unexpectedly large bounding box: for example, both Russia and the
2051
+ // USA span both sides of -180/180, or France includes the island of
2052
+ // Reunion in the Indian Ocean. An incomplete list of these exceptions
2053
+ // at ./exceptions.json provides "reasonable" bounding boxes as a
2054
+ // short-term solution; this may be amended as necessary.
2055
+ flyOptions = extend({}, this.options.flyTo);
2056
+ if (this._map) {
2057
+ this._map.fitBounds(exceptions[selected.properties.short_code].bbox, flyOptions);
2058
+ }
2059
+ }
2060
+ else if (selected.bbox) {
2061
+ const bbox = selected.bbox;
2062
+ flyOptions = extend({}, this.options.flyTo);
2063
+ if (this._map) {
2064
+ this._map.fitBounds([
2065
+ [bbox[0], bbox[1]],
2066
+ [bbox[2], bbox[3]],
2067
+ ], flyOptions);
2068
+ }
2069
+ }
2070
+ else {
2071
+ const defaultFlyOptions = {
2072
+ zoom: this.options.zoom,
2073
+ };
2074
+ flyOptions = extend({}, defaultFlyOptions, this.options.flyTo);
2075
+ // ensure that center is not overriden by custom options
2076
+ if (selected.center) {
2077
+ flyOptions.center = selected.center;
2078
+ }
2079
+ else if (selected.geometry &&
2080
+ selected.geometry.type &&
2081
+ selected.geometry.type === "Point" &&
2082
+ selected.geometry.coordinates) {
2083
+ flyOptions.center = selected.geometry.coordinates;
2084
+ }
2085
+ if (this._map) {
2086
+ this._map.flyTo(flyOptions);
2087
+ }
2088
+ }
2089
+ }
2090
+ if (this.options.marker && this._maplibregl) {
2091
+ this._handleMarker(selected);
2092
+ }
2093
+ // After selecting a feature, re-focus the textarea and set
2094
+ // cursor at start, and reset the selected feature.
2095
+ this._inputEl.focus();
2096
+ this._inputEl.scrollLeft = 0;
2097
+ this._inputEl.setSelectionRange(0, 0);
2098
+ this.lastSelected = JSON.stringify(selected);
2099
+ this._typeahead.selected = null; // reset selection current selection value and set it to last selected
2100
+ this._eventEmitter.emit("result", { result: selected });
2101
+ }
2102
+ }
2103
+ _getConfigForRequest() {
2104
+ // Possible config proprerties to pass to client
2105
+ const keys = [
2106
+ "bbox",
2107
+ "limit",
2108
+ "proximity",
2109
+ "countries",
2110
+ "types",
2111
+ "language",
2112
+ "reverseMode",
2113
+ ];
2114
+ // Create config object
2115
+ const config = keys.reduce((config, key) => {
2116
+ if (this.options[key]) {
2117
+ if (["countries", "types", "language"].indexOf(key) > -1) {
2118
+ (config[key] = this.options[key].split(/[\s,]+/));
2119
+ }
2120
+ else {
2121
+ (config[key] = this.options[key]);
2122
+ }
2123
+ if (key === "proximity" &&
2124
+ this.options[key] &&
2125
+ typeof this.options[key].longitude === "number" &&
2126
+ typeof this.options[key].latitude === "number") {
2127
+ config[key] = [
2128
+ this.options[key].longitude,
2129
+ this.options[key].latitude,
2130
+ ];
2131
+ }
2132
+ }
2133
+ return config;
2134
+ }, {});
2135
+ return config;
2136
+ }
2137
+ _geocode(searchInput_1) {
2138
+ return __awaiter(this, arguments, void 0, function* (searchInput, isSuggestion = false, isPlaceId = false) {
2139
+ this._loadingEl.style.display = "block";
2140
+ this._eventEmitter.emit("loading", { query: searchInput });
2141
+ const config = this._getConfigForRequest();
2142
+ const request = this._createGeocodeRequest(config, searchInput, isSuggestion, isPlaceId);
2143
+ const localGeocoderResults = this.options.localGeocoder
2144
+ ? (this.options.localGeocoder(searchInput) || [])
2145
+ : [];
2146
+ try {
2147
+ const response = yield request;
2148
+ yield this._handleGeocodeResponse(response, config, searchInput, isSuggestion, localGeocoderResults);
2149
+ }
2150
+ catch (err) {
2151
+ this._handleGeocodeErrorResponse(err, localGeocoderResults);
2152
+ }
2153
+ return request;
2154
+ });
2155
+ }
2156
+ _createGeocodeRequest(config, searchInput, isSuggestion, isPlaceId) {
2157
+ if (this.options.localGeocoderOnly) {
2158
+ return Promise.resolve({});
2159
+ }
2160
+ if (this.options.reverseGeocode && COORDINATES_REGEXP.test(searchInput)) {
2161
+ // searchInput resembles coordinates, make the request a reverseGeocode
2162
+ return this._createReverseGeocodeRequest(searchInput, config);
2163
+ }
2164
+ config.query = searchInput;
2165
+ if (!this.geocoderApi.getSuggestions) {
2166
+ return this.geocoderApi.forwardGeocode(config);
2167
+ }
2168
+ if (!isSuggestion) {
2169
+ // user typed in text and should receive suggestions
2170
+ return this.geocoderApi.getSuggestions(config);
2171
+ }
2172
+ // user clicked on a suggestion
2173
+ if (this.geocoderApi.searchByPlaceId && isPlaceId) {
2174
+ // suggestion has place Id
2175
+ return this.geocoderApi.searchByPlaceId(config);
2176
+ }
2177
+ return this.geocoderApi.forwardGeocode(config);
2178
+ }
2179
+ _createReverseGeocodeRequest(searchInput, config) {
2180
+ // parse coordinates
2181
+ const coords = searchInput
2182
+ .split(/[\s(,)?]+/)
2183
+ .map((c) => parseFloat(c))
2184
+ .reverse();
2185
+ // client only accepts one type for reverseGeocode, so
2186
+ // use first config type if one, if not default to poi
2187
+ config.query = coords;
2188
+ config.limit = 1;
2189
+ // drop proximity which may have been set by trackProximity since it's not supported by the reverseGeocoder
2190
+ if ("proximity" in config) {
2191
+ delete config.proximity;
2192
+ }
2193
+ return this.geocoderApi.reverseGeocode(config);
2194
+ }
2195
+ _handleGeocodeResponse(response, config, searchInput, isSuggestion, localGeocoderResults) {
2196
+ return __awaiter(this, void 0, void 0, function* () {
2197
+ this._loadingEl.style.display = "none";
2198
+ let res = {};
2199
+ if (!response) {
2200
+ res = {
2201
+ type: "FeatureCollection",
2202
+ features: [],
2203
+ };
2204
+ }
2205
+ else {
2206
+ res = response;
2207
+ }
2208
+ res.config = config;
2209
+ if (this.fresh) {
2210
+ this.fresh = false;
2211
+ }
2212
+ // supplement Maplibre Geocoding API results with locally populated results
2213
+ res.features = res.features
2214
+ ? localGeocoderResults.concat(res.features)
2215
+ : localGeocoderResults;
2216
+ const externalGeocoderResultsPromise = this.options.externalGeocoder
2217
+ ? (this.options.externalGeocoder(searchInput, res.features, config) || Promise.resolve([]))
2218
+ : Promise.resolve([]);
2219
+ // supplement Geocoding API results with features returned by a promise
2220
+ try {
2221
+ const features = yield externalGeocoderResultsPromise;
2222
+ res.features = res.features
2223
+ ? features.concat(res.features)
2224
+ : features;
2225
+ }
2226
+ catch (_a) {
2227
+ // on error, display the original result
2228
+ }
2229
+ // apply results filter if provided
2230
+ if (this.options.filter && res.features.length) {
2231
+ res.features = res.features.filter(this.options.filter);
2232
+ }
2233
+ let results = [];
2234
+ if ('suggestions' in res) {
2235
+ results = res.suggestions;
2236
+ }
2237
+ else if ('place' in res) {
2238
+ results = [res.place];
2239
+ }
2240
+ else {
2241
+ results = res.features;
2242
+ }
2243
+ if (results.length) {
2244
+ this._clearEl.style.display = "block";
2245
+ this._typeahead.update(results);
2246
+ if ((!this.options.showResultsWhileTyping || isSuggestion) &&
2247
+ this.options.showResultMarkers &&
2248
+ (res.features.length > 0 || 'place' in res)) {
2249
+ this._fitBoundsForMarkers();
2250
+ }
2251
+ this._eventEmitter.emit("results", res);
2252
+ }
2253
+ else {
2254
+ this._clearEl.style.display = "none";
2255
+ this._typeahead.selected = null;
2256
+ this._renderNoResults();
2257
+ this._eventEmitter.emit("results", res);
2258
+ }
2259
+ });
2260
+ }
2261
+ _handleGeocodeErrorResponse(error, localGeocoderResults) {
2262
+ this._loadingEl.style.display = "none";
2263
+ // in the event of an error in the Geocoding API still display results from the localGeocoder
2264
+ if (localGeocoderResults.length && this.options.localGeocoder) {
2265
+ this._clearEl.style.display = "block";
2266
+ this._typeahead.update(localGeocoderResults);
2267
+ }
2268
+ else {
2269
+ this._clearEl.style.display = "none";
2270
+ this._typeahead.selected = null;
2271
+ this._renderError();
2272
+ }
2273
+ this._eventEmitter.emit("results", { features: localGeocoderResults });
2274
+ this._eventEmitter.emit("error", { error });
2275
+ }
2276
+ /**
2277
+ * Shared logic for clearing input
2278
+ * @param ev - the event that triggered the clear, if available
2279
+ */
2280
+ _clear(ev) {
2281
+ if (ev)
2282
+ ev.preventDefault();
2283
+ this._inputEl.value = "";
2284
+ this._typeahead.selected = null;
2285
+ this._typeahead.clear();
2286
+ this._onChange();
2287
+ this._clearEl.style.display = "none";
2288
+ this._removeMarker();
2289
+ this._removeResultMarkers();
2290
+ this.lastSelected = null;
2291
+ this._eventEmitter.emit("clear");
2292
+ this.fresh = true;
2293
+ }
2294
+ /**
2295
+ * Clear and then focus the input.
2296
+ * @param ev - the event that triggered the clear, if available
2297
+ *
2298
+ */
2299
+ clear(ev) {
2300
+ this._clear(ev);
2301
+ this._inputEl.focus();
2302
+ }
2303
+ /**
2304
+ * Clear the input, without refocusing it. Used to implement clearOnBlur
2305
+ * constructor option.
2306
+ * @param ev - the blur event
2307
+ */
2308
+ _clearOnBlur(ev) {
2309
+ /*
2310
+ * If relatedTarget is not found, assume user targeted the suggestions list.
2311
+ * In that case, do not clear on blur. There are other edge cases where
2312
+ * ev.relatedTarget could be null. Clicking on list always results in null
2313
+ * relatedtarget because of upstream behavior in `suggestions`.
2314
+ *
2315
+ * The ideal solution would be to check if ev.relatedTarget is a child of
2316
+ * the list. See issue #258 for details on why we can't do that yet.
2317
+ */
2318
+ if (ev.relatedTarget) {
2319
+ this._clear(ev);
2320
+ }
2321
+ }
2322
+ _onQueryResult(results) {
2323
+ if (!('features' in results)) {
2324
+ return;
2325
+ }
2326
+ if (!results.features.length)
2327
+ return;
2328
+ const result = results.features[0];
2329
+ this._typeahead.selected = result;
2330
+ this._inputEl.value = result.place_name;
2331
+ this._onChange();
2332
+ }
2333
+ _updateProximity() {
2334
+ // proximity is designed for local scale, if the user is looking at the whole world,
2335
+ // it doesn't make sense to factor in the arbitrary centre of the map
2336
+ if (!this._map) {
2337
+ return;
2338
+ }
2339
+ if (this._map.getZoom() > this.options.proximityMinZoom) {
2340
+ const center = this._map.getCenter().wrap();
2341
+ this.setProximity({ longitude: center.lng, latitude: center.lat });
2342
+ }
2343
+ else {
2344
+ this.setProximity(null);
2345
+ }
2346
+ }
2347
+ _collapse() {
2348
+ // do not collapse if input is in focus
2349
+ if (!this._inputEl.value && this._inputEl !== document.activeElement)
2350
+ this.container.classList.add("maplibregl-ctrl-geocoder--collapsed");
2351
+ }
2352
+ _unCollapse() {
2353
+ this.container.classList.remove("maplibregl-ctrl-geocoder--collapsed");
2354
+ }
2355
+ /**
2356
+ * Set & query the input
2357
+ * @param searchInput - location name or other search input
2358
+ */
2359
+ query(searchInput) {
2360
+ return __awaiter(this, void 0, void 0, function* () {
2361
+ const results = yield this._geocode(searchInput);
2362
+ this._onQueryResult(results);
2363
+ });
2364
+ }
2365
+ _renderError() {
2366
+ const errorMessage = `<div class='maplibre-gl-geocoder--error'>${this._localize("errorConnectionFailed")}</div>`;
2367
+ this._renderMessage(errorMessage);
2368
+ }
2369
+ _renderNoResults() {
2370
+ const errorMessage = `<div class='maplibre-gl-geocoder--error maplibre-gl-geocoder--no-results'>
2371
+ ${this._localize("errorNoResults")}</div>`;
2372
+ this._renderMessage(errorMessage);
2373
+ }
2374
+ _renderMessage(msg) {
2375
+ this._typeahead.update([]);
2376
+ this._typeahead.selected = null;
2377
+ this._typeahead.clear();
2378
+ this._typeahead.renderError(msg);
2379
+ }
2380
+ /**
2381
+ * Get a localised string for a given key
2382
+ *
2383
+ * If language is provided in options, attempt to return localized string (defaults to English)
2384
+ * @param key - key in the localization object
2385
+ * @returns localized string
2386
+ */
2387
+ _localize(key) {
2388
+ const language = subtag.language(this.options.language.split(',')[0]);
2389
+ return this.options.language && (localization === null || localization === void 0 ? void 0 : localization[key][language]) ? localization[key][language] : localization[key]['en'];
2390
+ }
2391
+ /**
2392
+ * Fits the map to the current bounds for the searched results
2393
+ */
2394
+ _fitBoundsForMarkers() {
2395
+ if (this._typeahead.data.length < 1)
2396
+ return;
2397
+ // Filter out suggestions and restrict to limit
2398
+ const results = this._typeahead.data
2399
+ .filter((result) => {
2400
+ return typeof result === "string" ? false : true;
2401
+ })
2402
+ .slice(0, this.options.limit);
2403
+ this._clearEl.style.display = "none";
2404
+ if (this.options.flyTo && this._maplibregl) {
2405
+ if (this._map) {
2406
+ const defaultFlyOptions = { padding: 100 };
2407
+ const flyOptions = extend({}, defaultFlyOptions, this.options.flyTo);
2408
+ const bounds = new this._maplibregl.LngLatBounds();
2409
+ for (const feature of results) {
2410
+ bounds.extend(feature.geometry.coordinates);
2411
+ }
2412
+ this._map.fitBounds(bounds, flyOptions);
2413
+ }
2414
+ }
2415
+ if (results.length > 0 && this._maplibregl) {
2416
+ this._handleResultMarkers(results);
2417
+ }
2418
+ return this;
2419
+ }
2420
+ /**
2421
+ * Set input
2422
+ * @param searchInput - location name or other search input
2423
+ */
2424
+ setInput(searchInput) {
2425
+ // Set input value to passed value and clear everything else.
2426
+ this._inputEl.value = searchInput;
2427
+ this._typeahead.selected = null;
2428
+ this._typeahead.clear();
2429
+ if (searchInput.length >= this.options.minLength &&
2430
+ this.options.showResultsWhileTyping) {
2431
+ this._geocode(searchInput);
2432
+ }
2433
+ return this;
2434
+ }
2435
+ /**
2436
+ * Set proximity
2437
+ * @param proximity - The new `options.proximity` value. This is a geographical point given as an object with `latitude` and `longitude` properties.
2438
+ */
2439
+ setProximity(proximity) {
2440
+ this.options.proximity = proximity;
2441
+ return this;
2442
+ }
2443
+ /**
2444
+ * Get proximity
2445
+ * @returns The geocoder proximity
2446
+ */
2447
+ getProximity() {
2448
+ return this.options.proximity;
2449
+ }
2450
+ /**
2451
+ * Set the render function used in the results dropdown
2452
+ * @param fn - The function to use as a render function. This function accepts a single {@link CarmenGeojsonFeature} object as input and returns a string.
2453
+ */
2454
+ setRenderFunction(fn) {
2455
+ if (fn && typeof fn == "function") {
2456
+ this._typeahead.render = fn;
2457
+ }
2458
+ return this;
2459
+ }
2460
+ /**
2461
+ * Get the function used to render the results dropdown
2462
+ *
2463
+ * @returns the render function
2464
+ */
2465
+ getRenderFunction() {
2466
+ return this._typeahead.render;
2467
+ }
2468
+ /**
2469
+ * Get the language to use in UI elements and when making search requests
2470
+ *
2471
+ * Look first at the explicitly set options otherwise use the browser's language settings
2472
+ * @param language - Specify the language to use for response text and query result weighting. Options are IETF language tags comprised of a mandatory ISO 639-1 language code and optionally one or more IETF subtags for country or script. More than one value can also be specified, separated by commas.
2473
+ */
2474
+ setLanguage(language) {
2475
+ this.options.language = language || this.options.language || navigator.language;
2476
+ return this;
2477
+ }
2478
+ /**
2479
+ * Get the language to use in UI elements and when making search requests
2480
+ * @returns The language(s) used by the plugin, if any
2481
+ */
2482
+ getLanguage() {
2483
+ return this.options.language;
2484
+ }
2485
+ /**
2486
+ * Get the zoom level the map will move to when there is no bounding box on the selected result
2487
+ * @returns the map zoom
2488
+ */
2489
+ getZoom() {
2490
+ return this.options.zoom;
2491
+ }
2492
+ /**
2493
+ * Set the zoom level
2494
+ * @param zoom - The zoom level that the map should animate to when a `bbox` isn't found in the response. If a `bbox` is found the map will fit to the `bbox`.
2495
+ * @returns this
2496
+ */
2497
+ setZoom(zoom) {
2498
+ this.options.zoom = zoom;
2499
+ return this;
2500
+ }
2501
+ /**
2502
+ * Get the parameters used to fly to the selected response, if any
2503
+ * @returns The `flyTo` option
2504
+ */
2505
+ getFlyTo() {
2506
+ return this.options.flyTo;
2507
+ }
2508
+ /**
2509
+ * Set the flyTo options
2510
+ * @param flyTo - If false, animating the map to a selected result is disabled. If true, animating the map will use the default animation parameters. If an object, it will be passed as `options` to the map [`flyTo`](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map#flyto) or [`fitBounds`](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map#fitbounds) method providing control over the animation of the transition.
2511
+ */
2512
+ setFlyTo(flyTo) {
2513
+ this.options.flyTo = flyTo;
2514
+ return this;
2515
+ }
2516
+ /**
2517
+ * Get the value of the placeholder string
2518
+ * @returns The input element's placeholder value
2519
+ */
2520
+ getPlaceholder() {
2521
+ return this.options.placeholder;
2522
+ }
2523
+ /**
2524
+ * Set the value of the input element's placeholder
2525
+ * @param placeholder - the text to use as the input element's placeholder
2526
+ */
2527
+ setPlaceholder(placeholder) {
2528
+ this.placeholder = placeholder ? placeholder : this.options.placeholder || this._localize("placeholder");
2529
+ this._inputEl.placeholder = this.placeholder;
2530
+ this._inputEl.setAttribute("aria-label", this.placeholder);
2531
+ return this;
2532
+ }
2533
+ /**
2534
+ * Get the bounding box used by the plugin
2535
+ * @returns the bounding box, if any
2536
+ */
2537
+ getBbox() {
2538
+ return this.options.bbox;
2539
+ }
2540
+ /**
2541
+ * Set the bounding box to limit search results to
2542
+ * @param bbox - a bounding box given as an array in the format [minX, minY, maxX, maxY].
2543
+ */
2544
+ setBbox(bbox) {
2545
+ this.options.bbox = bbox;
2546
+ return this;
2547
+ }
2548
+ /**
2549
+ * Get a list of the countries to limit search results to
2550
+ * @returns a comma separated list of countries to limit to, if any
2551
+ */
2552
+ getCountries() {
2553
+ return this.options.countries;
2554
+ }
2555
+ /**
2556
+ * Set the countries to limit search results to
2557
+ * @param countries - a comma separated list of countries to limit to
2558
+ */
2559
+ setCountries(countries) {
2560
+ this.options.countries = countries;
2561
+ return this;
2562
+ }
2563
+ /**
2564
+ * Get a list of the types to limit search results to
2565
+ * @returns a comma separated list of types to limit to
2566
+ */
2567
+ getTypes() {
2568
+ return this.options.types;
2569
+ }
2570
+ /**
2571
+ * Set the types to limit search results to
2572
+ * @param types - a comma separated list of types to limit to
2573
+ */
2574
+ setTypes(types) {
2575
+ this.options.types = types;
2576
+ return this;
2577
+ }
2578
+ /**
2579
+ * Get the minimum number of characters typed to trigger results used in the plugin
2580
+ * @returns The minimum length in characters before a search is triggered
2581
+ */
2582
+ getMinLength() {
2583
+ return this.options.minLength;
2584
+ }
2585
+ /**
2586
+ * Set the minimum number of characters typed to trigger results used by the plugin
2587
+ * @param minLength - the minimum length in characters
2588
+ */
2589
+ setMinLength(minLength) {
2590
+ this.options.minLength = minLength;
2591
+ if (this._typeahead)
2592
+ this._typeahead.options.minLength = minLength;
2593
+ return this;
2594
+ }
2595
+ /**
2596
+ * Get the limit value for the number of results to display used by the plugin
2597
+ * @returns The limit value for the number of results to display used by the plugin
2598
+ */
2599
+ getLimit() {
2600
+ return this.options.limit;
2601
+ }
2602
+ /**
2603
+ * Set the limit value for the number of results to display used by the plugin
2604
+ * @param limit - the number of search results to return
2605
+ */
2606
+ setLimit(limit) {
2607
+ this.options.limit = limit;
2608
+ if (this._typeahead)
2609
+ this._typeahead.options.limit = limit;
2610
+ return this;
2611
+ }
2612
+ /**
2613
+ * Get the filter function used by the plugin
2614
+ * @returns the filter function
2615
+ */
2616
+ getFilter() {
2617
+ return this.options.filter;
2618
+ }
2619
+ /**
2620
+ * Set the filter function used by the plugin.
2621
+ * @param filter - A function which accepts a {@link CarmenGeojsonFeature} to filter out results from the Geocoding API response before they are included in the suggestions list. Return `true` to keep the item, `false` otherwise.
2622
+ */
2623
+ setFilter(filter) {
2624
+ this.options.filter = filter;
2625
+ return this;
2626
+ }
2627
+ /**
2628
+ * Set the geocoding api used by the plugin.
2629
+ */
2630
+ setGeocoderApi(geocoderApi) {
2631
+ this.geocoderApi = geocoderApi;
2632
+ return this;
2633
+ }
2634
+ /**
2635
+ * Get the geocoding endpoint the plugin is currently set to
2636
+ * @returns the geocoding API
2637
+ */
2638
+ getGeocoderApi() {
2639
+ return this.geocoderApi;
2640
+ }
2641
+ /**
2642
+ * Handle the placement of a result marking the selected result
2643
+ * @param selected - the selected geojson feature
2644
+ */
2645
+ _handleMarker(selected) {
2646
+ // clean up any old marker that might be present
2647
+ if (!this._map) {
2648
+ return;
2649
+ }
2650
+ this._removeMarker();
2651
+ const defaultMarkerOptions = {
2652
+ color: "#4668F2",
2653
+ };
2654
+ const markerOptions = extend({}, defaultMarkerOptions, this.options.marker);
2655
+ this.mapMarker = new this._maplibregl.Marker(markerOptions);
2656
+ let popup;
2657
+ if (this.options.popup) {
2658
+ const defaultPopupOptions = {};
2659
+ const popupOptions = extend({}, defaultPopupOptions, this.options.popup);
2660
+ popup = new this._maplibregl.Popup(popupOptions).setHTML(this.options.popupRender(selected));
2661
+ }
2662
+ if (selected.center) {
2663
+ this.mapMarker.setLngLat(selected.center).addTo(this._map);
2664
+ if (this.options.popup)
2665
+ this.mapMarker.setPopup(popup);
2666
+ }
2667
+ else if (selected.geometry &&
2668
+ selected.geometry.type &&
2669
+ selected.geometry.type === "Point" &&
2670
+ selected.geometry.coordinates) {
2671
+ this.mapMarker.setLngLat(selected.geometry.coordinates).addTo(this._map);
2672
+ if (this.options.popup)
2673
+ this.mapMarker.setPopup(popup);
2674
+ }
2675
+ return this;
2676
+ }
2677
+ /**
2678
+ * Handle the removal of a result marker
2679
+ */
2680
+ _removeMarker() {
2681
+ if (this.mapMarker) {
2682
+ this.mapMarker.remove();
2683
+ this.mapMarker = null;
2684
+ }
2685
+ }
2686
+ /**
2687
+ * Handle the placement of a result marking the selected result
2688
+ * @param results - the top results to display on the map
2689
+ */
2690
+ _handleResultMarkers(results) {
2691
+ // clean up any old marker that might be present
2692
+ if (!this._map) {
2693
+ return;
2694
+ }
2695
+ this._removeResultMarkers();
2696
+ const defaultMarkerOptions = {
2697
+ color: "#4668F2",
2698
+ };
2699
+ let markerOptions = extend({}, defaultMarkerOptions, this.options.showResultMarkers);
2700
+ for (const result of results) {
2701
+ let el;
2702
+ if (this.options.showResultMarkers) {
2703
+ if (this.options.showResultMarkers &&
2704
+ this.options.showResultMarkers.element) {
2705
+ el = this.options.showResultMarkers.element.cloneNode(true);
2706
+ markerOptions = extend(markerOptions, { element: el });
2707
+ }
2708
+ const marker = new this._maplibregl.Marker(extend({}, markerOptions, { element: el }));
2709
+ let popup;
2710
+ if (this.options.popup) {
2711
+ const defaultPopupOptions = {};
2712
+ const popupOptions = extend({}, defaultPopupOptions, this.options.popup);
2713
+ popup = new this._maplibregl.Popup(popupOptions).setHTML(this.options.popupRender(result));
2714
+ }
2715
+ if (result.center) {
2716
+ marker.setLngLat(result.center).addTo(this._map);
2717
+ if (this.options.popup)
2718
+ marker.setPopup(popup);
2719
+ }
2720
+ else if (result.geometry &&
2721
+ result.geometry.type &&
2722
+ result.geometry.type === "Point" &&
2723
+ result.geometry.coordinates) {
2724
+ marker.setLngLat(result.geometry.coordinates).addTo(this._map);
2725
+ if (this.options.popup)
2726
+ marker.setPopup(popup);
2727
+ }
2728
+ this.resultMarkers.push(marker);
2729
+ }
2730
+ }
2731
+ return this;
2732
+ }
2733
+ /**
2734
+ * Handle the removal of a result marker
2735
+ */
2736
+ _removeResultMarkers() {
2737
+ if (this.resultMarkers && this.resultMarkers.length > 0) {
2738
+ this.resultMarkers.forEach(function (marker) {
2739
+ marker.remove();
2740
+ });
2741
+ this.resultMarkers = [];
2742
+ }
2743
+ }
2744
+ /**
2745
+ * Subscribe to events that happen within the plugin.
2746
+ * @param type - name of event. Available events and the data passed into their respective event objects are:
2747
+ *
2748
+ * - __clear__ `Emitted when the input is cleared`
2749
+ * - __loading__ `{ query } Emitted when the geocoder is looking up a query`
2750
+ * - __results__ `{ results } Fired when the geocoder returns a response`
2751
+ * - __result__ `{ result } Fired when input is set`
2752
+ * - __error__ `{ error } Error as string`
2753
+ * @param fn - function that's called when the event is emitted.
2754
+ */
2755
+ on(type, fn) {
2756
+ this._eventEmitter.on(type, fn);
2757
+ return this;
2758
+ }
2759
+ /**
2760
+ * Subscribe to events that happen within the plugin only once.
2761
+ * @param type - Event name.
2762
+ * Available events and the data passed into their respective event objects are:
2763
+ *
2764
+ * - __clear__ `Emitted when the input is cleared`
2765
+ * - __loading__ `{ query } Emitted when the geocoder is looking up a query`
2766
+ * - __results__ `{ results } Fired when the geocoder returns a response`
2767
+ * - __result__ `{ result } Fired when input is set`
2768
+ * - __error__ `{ error } Error as string`
2769
+ * @returns a Promise that resolves when the event is emitted.
2770
+ */
2771
+ once(type) {
2772
+ return new Promise((resolve) => {
2773
+ this._eventEmitter.once(type, resolve);
2774
+ });
2775
+ }
2776
+ /**
2777
+ * Remove an event
2778
+ * @param type - Event name.
2779
+ * @param fn - Function that should unsubscribe to the event emitted.
2780
+ */
2781
+ off(type, fn) {
2782
+ this._eventEmitter.removeListener(type, fn);
2783
+ return this;
2784
+ }
2785
+ }
2786
+
2787
+ return MaplibreGeocoder;
2788
+
2789
+ }));
2790
+ //# sourceMappingURL=maplibre-gl-geocoder.js.map