vrembem 1.42.1 → 3.0.1

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.
@@ -1,18 +1,714 @@
1
- var setInert = function setInert(state, selector) {
2
- if (selector) {
3
- var els = document.querySelectorAll(selector);
4
- els.forEach(function (el) {
5
- if (state) {
6
- el.inert = true;
7
- el.setAttribute('aria-hidden', true);
1
+ function _defineProperties(target, props) {
2
+ for (var i = 0; i < props.length; i++) {
3
+ var descriptor = props[i];
4
+ descriptor.enumerable = descriptor.enumerable || false;
5
+ descriptor.configurable = true;
6
+ if ("value" in descriptor) descriptor.writable = true;
7
+ Object.defineProperty(target, descriptor.key, descriptor);
8
+ }
9
+ }
10
+
11
+ function _createClass(Constructor, protoProps, staticProps) {
12
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
13
+ if (staticProps) _defineProperties(Constructor, staticProps);
14
+ Object.defineProperty(Constructor, "prototype", {
15
+ writable: false
16
+ });
17
+ return Constructor;
18
+ }
19
+
20
+ function _extends() {
21
+ _extends = Object.assign || function (target) {
22
+ for (var i = 1; i < arguments.length; i++) {
23
+ var source = arguments[i];
24
+
25
+ for (var key in source) {
26
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
27
+ target[key] = source[key];
28
+ }
29
+ }
30
+ }
31
+
32
+ return target;
33
+ };
34
+
35
+ return _extends.apply(this, arguments);
36
+ }
37
+
38
+ function _inheritsLoose(subClass, superClass) {
39
+ subClass.prototype = Object.create(superClass.prototype);
40
+ subClass.prototype.constructor = subClass;
41
+
42
+ _setPrototypeOf(subClass, superClass);
43
+ }
44
+
45
+ function _setPrototypeOf(o, p) {
46
+ _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
47
+ o.__proto__ = p;
48
+ return o;
49
+ };
50
+
51
+ return _setPrototypeOf(o, p);
52
+ }
53
+
54
+ function _assertThisInitialized(self) {
55
+ if (self === void 0) {
56
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
57
+ }
58
+
59
+ return self;
60
+ }
61
+
62
+ var id = 0;
63
+
64
+ function _classPrivateFieldLooseKey(name) {
65
+ return "__private_" + id++ + "_" + name;
66
+ }
67
+
68
+ function _classPrivateFieldLooseBase(receiver, privateKey) {
69
+ if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
70
+ throw new TypeError("attempted to use private field on non-instance");
71
+ }
72
+
73
+ return receiver;
74
+ }
75
+
76
+ var _handler = /*#__PURE__*/_classPrivateFieldLooseKey("handler");
77
+
78
+ var Breakpoint = /*#__PURE__*/function () {
79
+ function Breakpoint(value, handler) {
80
+ Object.defineProperty(this, _handler, {
81
+ writable: true,
82
+ value: void 0
83
+ });
84
+ this.value = value;
85
+ _classPrivateFieldLooseBase(this, _handler)[_handler] = handler;
86
+ this.mql = null;
87
+ }
88
+
89
+ var _proto = Breakpoint.prototype;
90
+
91
+ _proto.mount = function mount(value, handler) {
92
+ // Update passed params.
93
+ if (value) this.value = value;
94
+ if (handler) _classPrivateFieldLooseBase(this, _handler)[_handler] = handler; // Guard if no breakpoint was set.
95
+
96
+ if (!this.value) return this; // Setup and store the MediaQueryList instance.
97
+
98
+ this.mql = window.matchMedia("(min-width: " + this.value + ")"); // Conditionally use addListener() for IE11 support.
99
+
100
+ if (typeof this.mql.addEventListener === 'function') {
101
+ this.mql.addEventListener('change', _classPrivateFieldLooseBase(this, _handler)[_handler]);
102
+ } else {
103
+ this.mql.addListener(_classPrivateFieldLooseBase(this, _handler)[_handler]);
104
+ } // Run the handler.
105
+
106
+
107
+ _classPrivateFieldLooseBase(this, _handler)[_handler](this.mql);
108
+
109
+ return this;
110
+ };
111
+
112
+ _proto.unmount = function unmount() {
113
+ // Guard if no MediaQueryList instance exists.
114
+ if (!this.mql) return this; // Conditionally use removeListener() for IE11 support.
115
+
116
+ if (typeof this.mql.removeEventListener === 'function') {
117
+ this.mql.removeEventListener('change', _classPrivateFieldLooseBase(this, _handler)[_handler]);
118
+ } else {
119
+ this.mql.removeListener(_classPrivateFieldLooseBase(this, _handler)[_handler]);
120
+ } // Set value, handler and MediaQueryList to null.
121
+
122
+
123
+ this.value = null;
124
+ _classPrivateFieldLooseBase(this, _handler)[_handler] = null;
125
+ this.mql = null;
126
+ return this;
127
+ };
128
+
129
+ _createClass(Breakpoint, [{
130
+ key: "handler",
131
+ get: function get() {
132
+ return _classPrivateFieldLooseBase(this, _handler)[_handler];
133
+ } // Unmount existing handler before setting a new one.
134
+ ,
135
+ set: function set(func) {
136
+ if (this.mql) {
137
+ // Conditionally use removeListener() for IE11 support.
138
+ if (typeof this.mql.removeEventListener === 'function') {
139
+ this.mql.removeEventListener('change', _classPrivateFieldLooseBase(this, _handler)[_handler]);
140
+ } else {
141
+ this.mql.removeListener(_classPrivateFieldLooseBase(this, _handler)[_handler]);
142
+ }
143
+ }
144
+
145
+ _classPrivateFieldLooseBase(this, _handler)[_handler] = func;
146
+ }
147
+ }]);
148
+
149
+ return Breakpoint;
150
+ }();
151
+
152
+ function _settle(pact, state, value) {
153
+ if (!pact.s) {
154
+ if (value instanceof _Pact) {
155
+ if (value.s) {
156
+ if (state & 1) {
157
+ state = value.s;
158
+ }
159
+
160
+ value = value.v;
8
161
  } else {
9
- el.inert = null;
10
- el.removeAttribute('aria-hidden');
162
+ value.o = _settle.bind(null, pact, state);
163
+ return;
11
164
  }
165
+ }
166
+
167
+ if (value && value.then) {
168
+ value.then(_settle.bind(null, pact, state), _settle.bind(null, pact, 2));
169
+ return;
170
+ }
171
+
172
+ pact.s = state;
173
+ pact.v = value;
174
+ var observer = pact.o;
175
+
176
+ if (observer) {
177
+ observer(pact);
178
+ }
179
+ }
180
+ }
181
+
182
+ var _Pact = /*#__PURE__*/function () {
183
+ function _Pact() {}
184
+
185
+ _Pact.prototype.then = function (onFulfilled, onRejected) {
186
+ var result = new _Pact();
187
+ var state = this.s;
188
+
189
+ if (state) {
190
+ var callback = state & 1 ? onFulfilled : onRejected;
191
+
192
+ if (callback) {
193
+ try {
194
+ _settle(result, 1, callback(this.v));
195
+ } catch (e) {
196
+ _settle(result, 2, e);
197
+ }
198
+
199
+ return result;
200
+ } else {
201
+ return this;
202
+ }
203
+ }
204
+
205
+ this.o = function (_this) {
206
+ try {
207
+ var value = _this.v;
208
+
209
+ if (_this.s & 1) {
210
+ _settle(result, 1, onFulfilled ? onFulfilled(value) : value);
211
+ } else if (onRejected) {
212
+ _settle(result, 1, onRejected(value));
213
+ } else {
214
+ _settle(result, 2, value);
215
+ }
216
+ } catch (e) {
217
+ _settle(result, 2, e);
218
+ }
219
+ };
220
+
221
+ return result;
222
+ };
223
+
224
+ return _Pact;
225
+ }();
226
+
227
+ function _isSettledPact(thenable) {
228
+ return thenable instanceof _Pact && thenable.s & 1;
229
+ }
230
+
231
+ function _for(test, update, body) {
232
+ var stage;
233
+
234
+ for (;;) {
235
+ var shouldContinue = test();
236
+
237
+ if (_isSettledPact(shouldContinue)) {
238
+ shouldContinue = shouldContinue.v;
239
+ }
240
+
241
+ if (!shouldContinue) {
242
+ return result;
243
+ }
244
+
245
+ if (shouldContinue.then) {
246
+ stage = 0;
247
+ break;
248
+ }
249
+
250
+ var result = body();
251
+
252
+ if (result && result.then) {
253
+ if (_isSettledPact(result)) {
254
+ result = result.s;
255
+ } else {
256
+ stage = 1;
257
+ break;
258
+ }
259
+ }
260
+
261
+ if (update) {
262
+ var updateValue = update();
263
+
264
+ if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
265
+ stage = 2;
266
+ break;
267
+ }
268
+ }
269
+ }
270
+
271
+ var pact = new _Pact();
272
+
273
+ var reject = _settle.bind(null, pact, 2);
274
+
275
+ (stage === 0 ? shouldContinue.then(_resumeAfterTest) : stage === 1 ? result.then(_resumeAfterBody) : updateValue.then(_resumeAfterUpdate)).then(void 0, reject);
276
+ return pact;
277
+
278
+ function _resumeAfterBody(value) {
279
+ result = value;
280
+
281
+ do {
282
+ if (update) {
283
+ updateValue = update();
284
+
285
+ if (updateValue && updateValue.then && !_isSettledPact(updateValue)) {
286
+ updateValue.then(_resumeAfterUpdate).then(void 0, reject);
287
+ return;
288
+ }
289
+ }
290
+
291
+ shouldContinue = test();
292
+
293
+ if (!shouldContinue || _isSettledPact(shouldContinue) && !shouldContinue.v) {
294
+ _settle(pact, 1, result);
295
+
296
+ return;
297
+ }
298
+
299
+ if (shouldContinue.then) {
300
+ shouldContinue.then(_resumeAfterTest).then(void 0, reject);
301
+ return;
302
+ }
303
+
304
+ result = body();
305
+
306
+ if (_isSettledPact(result)) {
307
+ result = result.v;
308
+ }
309
+ } while (!result || !result.then);
310
+
311
+ result.then(_resumeAfterBody).then(void 0, reject);
312
+ }
313
+
314
+ function _resumeAfterTest(shouldContinue) {
315
+ if (shouldContinue) {
316
+ result = body();
317
+
318
+ if (result && result.then) {
319
+ result.then(_resumeAfterBody).then(void 0, reject);
320
+ } else {
321
+ _resumeAfterBody(result);
322
+ }
323
+ } else {
324
+ _settle(pact, 1, result);
325
+ }
326
+ }
327
+
328
+ function _resumeAfterUpdate() {
329
+ if (shouldContinue = test()) {
330
+ if (shouldContinue.then) {
331
+ shouldContinue.then(_resumeAfterTest).then(void 0, reject);
332
+ } else {
333
+ _resumeAfterTest(shouldContinue);
334
+ }
335
+ } else {
336
+ _settle(pact, 1, result);
337
+ }
338
+ }
339
+ }
340
+
341
+ var Collection = /*#__PURE__*/function () {
342
+ function Collection() {
343
+ this.collection = [];
344
+ }
345
+
346
+ var _proto = Collection.prototype;
347
+
348
+ _proto.register = function register(item) {
349
+ try {
350
+ var _this2 = this;
351
+
352
+ return Promise.resolve(_this2.deregister(item)).then(function () {
353
+ _this2.collection.push(item);
354
+
355
+ return _this2.collection;
356
+ });
357
+ } catch (e) {
358
+ return Promise.reject(e);
359
+ }
360
+ };
361
+
362
+ _proto.deregister = function deregister(ref) {
363
+ try {
364
+ var _this4 = this;
365
+
366
+ var index = _this4.collection.findIndex(function (entry) {
367
+ return entry === ref;
368
+ });
369
+
370
+ if (index >= 0) {
371
+ var entry = _this4.collection[index];
372
+ Object.getOwnPropertyNames(entry).forEach(function (prop) {
373
+ delete entry[prop];
374
+ });
375
+
376
+ _this4.collection.splice(index, 1);
377
+ }
378
+
379
+ return Promise.resolve(_this4.collection);
380
+ } catch (e) {
381
+ return Promise.reject(e);
382
+ }
383
+ };
384
+
385
+ _proto.registerCollection = function registerCollection(items) {
386
+ try {
387
+ var _this6 = this;
388
+
389
+ return Promise.resolve(Promise.all(Array.from(items, function (item) {
390
+ _this6.register(item);
391
+ }))).then(function () {
392
+ return _this6.collection;
393
+ });
394
+ } catch (e) {
395
+ return Promise.reject(e);
396
+ }
397
+ };
398
+
399
+ _proto.deregisterCollection = function deregisterCollection() {
400
+ try {
401
+ var _temp3 = function _temp3() {
402
+ return _this8.collection;
403
+ };
404
+
405
+ var _this8 = this;
406
+
407
+ var _temp4 = _for(function () {
408
+ return _this8.collection.length > 0;
409
+ }, void 0, function () {
410
+ return Promise.resolve(_this8.deregister(_this8.collection[0])).then(function () {});
411
+ });
412
+
413
+ return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(_temp3) : _temp3(_temp4));
414
+ } catch (e) {
415
+ return Promise.reject(e);
416
+ }
417
+ };
418
+
419
+ _proto.get = function get(value, key) {
420
+ if (key === void 0) {
421
+ key = 'id';
422
+ }
423
+
424
+ return this.collection.find(function (item) {
425
+ return item[key] === value;
12
426
  });
427
+ };
428
+
429
+ return Collection;
430
+ }();
431
+
432
+ var focusableSelectors = ['a[href]:not([tabindex^="-"])', 'area[href]:not([tabindex^="-"])', 'input:not([type="hidden"]):not([type="radio"]):not([disabled]):not([tabindex^="-"])', 'input[type="radio"]:not([disabled]):not([tabindex^="-"])', 'select:not([disabled]):not([tabindex^="-"])', 'textarea:not([disabled]):not([tabindex^="-"])', 'button:not([disabled]):not([tabindex^="-"])', 'iframe:not([tabindex^="-"])', 'audio[controls]:not([tabindex^="-"])', 'video[controls]:not([tabindex^="-"])', '[contenteditable]:not([tabindex^="-"])', '[tabindex]:not([tabindex^="-"])'];
433
+
434
+ var _focusable = /*#__PURE__*/_classPrivateFieldLooseKey("focusable");
435
+
436
+ var _handleFocusTrap = /*#__PURE__*/_classPrivateFieldLooseKey("handleFocusTrap");
437
+
438
+ var _handleFocusLock = /*#__PURE__*/_classPrivateFieldLooseKey("handleFocusLock");
439
+
440
+ var FocusTrap = /*#__PURE__*/function () {
441
+ function FocusTrap(el, selectorFocus) {
442
+ if (el === void 0) {
443
+ el = null;
444
+ }
445
+
446
+ if (selectorFocus === void 0) {
447
+ selectorFocus = '[data-focus]';
448
+ }
449
+
450
+ Object.defineProperty(this, _focusable, {
451
+ writable: true,
452
+ value: void 0
453
+ });
454
+ Object.defineProperty(this, _handleFocusTrap, {
455
+ writable: true,
456
+ value: void 0
457
+ });
458
+ Object.defineProperty(this, _handleFocusLock, {
459
+ writable: true,
460
+ value: void 0
461
+ });
462
+ this.el = el;
463
+ this.selectorFocus = selectorFocus;
464
+ _classPrivateFieldLooseBase(this, _handleFocusTrap)[_handleFocusTrap] = handleFocusTrap.bind(this);
465
+ _classPrivateFieldLooseBase(this, _handleFocusLock)[_handleFocusLock] = handleFocusLock.bind(this);
13
466
  }
467
+
468
+ var _proto = FocusTrap.prototype;
469
+
470
+ _proto.mount = function mount(el, selectorFocus) {
471
+ // Update passed params.
472
+ if (el) this.el = el;
473
+ if (selectorFocus) this.selectorFocus = selectorFocus; // Get the focusable elements.
474
+
475
+ this.focusable = this.getFocusable(); // Set the focus on the element.
476
+
477
+ this.focus();
478
+ };
479
+
480
+ _proto.unmount = function unmount() {
481
+ // Set element to null.
482
+ this.el = null; // Apply empty array to focusable.
483
+
484
+ this.focusable = []; // Remove event listeners
485
+
486
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusTrap)[_handleFocusTrap]);
487
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusLock)[_handleFocusLock]);
488
+ };
489
+
490
+ _proto.focus = function focus(el, selectorFocus) {
491
+ if (el === void 0) {
492
+ el = this.el;
493
+ }
494
+
495
+ if (selectorFocus === void 0) {
496
+ selectorFocus = this.selectorFocus;
497
+ }
498
+
499
+ // Query for the focus selector, otherwise return this element.
500
+ var result = el.querySelector(selectorFocus) || el; // Give the returned element focus.
501
+
502
+ result.focus();
503
+ };
504
+
505
+ _proto.getFocusable = function getFocusable(el) {
506
+ if (el === void 0) {
507
+ el = this.el;
508
+ }
509
+
510
+ // Initialize the focusable array.
511
+ var focusable = []; // Store the initial focus and scroll position.
512
+
513
+ var initFocus = document.activeElement;
514
+ var initScrollTop = el.scrollTop; // Query for all the focusable elements.
515
+
516
+ var els = el.querySelectorAll(focusableSelectors.join(',')); // Loop through all focusable elements.
517
+
518
+ els.forEach(function (el) {
519
+ // Set them to focus and check
520
+ el.focus(); // Test that the element took focus.
521
+
522
+ if (document.activeElement === el) {
523
+ // Add element to the focusable array.
524
+ focusable.push(el);
525
+ }
526
+ }); // Restore the initial scroll position and focus.
527
+
528
+ el.scrollTop = initScrollTop;
529
+ initFocus.focus(); // Return the focusable array.
530
+
531
+ return focusable;
532
+ };
533
+
534
+ _createClass(FocusTrap, [{
535
+ key: "focusable",
536
+ get: function get() {
537
+ return _classPrivateFieldLooseBase(this, _focusable)[_focusable];
538
+ },
539
+ set: function set(value) {
540
+ // Update the focusable value.
541
+ _classPrivateFieldLooseBase(this, _focusable)[_focusable] = value; // Apply event listeners based on new focusable array length.
542
+
543
+ if (_classPrivateFieldLooseBase(this, _focusable)[_focusable].length) {
544
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusLock)[_handleFocusLock]);
545
+ document.addEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusTrap)[_handleFocusTrap]);
546
+ } else {
547
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusTrap)[_handleFocusTrap]);
548
+ document.addEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusLock)[_handleFocusLock]);
549
+ }
550
+ }
551
+ }, {
552
+ key: "focusableFirst",
553
+ get: function get() {
554
+ return this.focusable[0];
555
+ }
556
+ }, {
557
+ key: "focusableLast",
558
+ get: function get() {
559
+ return this.focusable[this.focusable.length - 1];
560
+ }
561
+ }]);
562
+
563
+ return FocusTrap;
564
+ }();
565
+
566
+ function handleFocusTrap(event) {
567
+ // Check if the click was a tab and return if not.
568
+ var isTab = event.key === 'Tab' || event.keyCode === 9;
569
+ if (!isTab) return; // If the shift key is pressed.
570
+
571
+ if (event.shiftKey) {
572
+ // If the active element is either the root el or first focusable.
573
+ if (document.activeElement === this.focusableFirst || document.activeElement === this.el) {
574
+ // Prevent default and focus the last focusable element instead.
575
+ event.preventDefault();
576
+ this.focusableLast.focus();
577
+ }
578
+ } else {
579
+ // If the active element is either the root el or last focusable.
580
+ if (document.activeElement === this.focusableLast || document.activeElement === this.el) {
581
+ // Prevent default and focus the first focusable element instead.
582
+ event.preventDefault();
583
+ this.focusableFirst.focus();
584
+ }
585
+ }
586
+ }
587
+
588
+ function handleFocusLock(event) {
589
+ // Ignore the tab key by preventing default.
590
+ var isTab = event.key === 'Tab' || event.keyCode === 9;
591
+ if (isTab) event.preventDefault();
592
+ }
593
+
594
+ function getConfig$1(el, dataConfig) {
595
+ var string = el.getAttribute("data-" + dataConfig) || '';
596
+ var json = string.replace(/'/g, '"');
597
+ return json ? JSON.parse(json) : {};
598
+ }
599
+
600
+ function getPrefix() {
601
+ return getComputedStyle(document.body).getPropertyValue('--vrembem-variable-prefix').trim();
602
+ }
603
+
604
+ function localStore(key, enable) {
605
+ if (enable === void 0) {
606
+ enable = true;
607
+ }
608
+
609
+ function getStore() {
610
+ var value = localStorage.getItem(key);
611
+ return value ? JSON.parse(value) : {};
612
+ }
613
+
614
+ function setStore(obj) {
615
+ localStorage.setItem(key, JSON.stringify(obj));
616
+ }
617
+
618
+ return new Proxy(getStore(), {
619
+ set: function set(target, property, value) {
620
+ target[property] = value;
621
+ if (enable) setStore(target);
622
+ return true;
623
+ },
624
+ deleteProperty: function deleteProperty(target, property) {
625
+ delete target[property];
626
+ if (enable) setStore(target);
627
+ return true;
628
+ }
629
+ });
630
+ }
631
+
632
+ /**
633
+ * Teleports an element in the DOM based on a reference and teleport method.
634
+ * Provide the comment node as the reference to teleport the element back to its
635
+ * previous location.
636
+ * @param {Node} what - What element to teleport.
637
+ * @param {String || Node} where - Where to teleport the element.
638
+ * @param {String} how - How (method) to teleport the element, e.g: 'after',
639
+ * 'before', 'append' or 'prepend'.
640
+ * @return {Node} Return the return reference if it was teleported else return
641
+ * null if it was returned to a comment reference.
642
+ */
643
+ function teleport(what, where, how) {
644
+ // Check if ref is either a comment or element node.
645
+ var isComment = where.nodeType === Node.COMMENT_NODE;
646
+ var isElement = where.nodeType === Node.ELEMENT_NODE; // Get the reference element.
647
+
648
+ where = isComment || isElement ? where : document.querySelector(where); // If ref is a comment, set teleport type to 'after'.
649
+
650
+ if (isComment) how = 'after'; // Must be a valid reference element and method.
651
+
652
+ if (!where) throw new Error("Not a valid teleport reference: '" + where + "'");
653
+ if (typeof where[how] != 'function') throw new Error("Not a valid teleport method: '" + how + "'"); // Initial return ref is null.
654
+
655
+ var returnRef = null; // If ref is not a comment, set a return reference comment.
656
+
657
+ if (!isComment) {
658
+ returnRef = document.createComment('teleported #' + what.id);
659
+ what.before(returnRef);
660
+ } // Teleport the target node.
661
+
662
+
663
+ where[how](what); // Delete the comment node if element was returned to a comment reference.
664
+
665
+ if (isComment) {
666
+ where.remove();
667
+ } // Return the return reference if it was teleported else return null if it was
668
+ // returned to a comment reference.
669
+
670
+
671
+ return returnRef;
672
+ }
673
+
674
+ var openTransition = function openTransition(el, settings) {
675
+ return new Promise(function (resolve) {
676
+ if (settings.transition) {
677
+ el.classList.remove(settings.stateClosed);
678
+ el.classList.add(settings.stateOpening);
679
+ el.addEventListener('transitionend', function _f() {
680
+ el.classList.add(settings.stateOpened);
681
+ el.classList.remove(settings.stateOpening);
682
+ resolve(el);
683
+ this.removeEventListener('transitionend', _f);
684
+ });
685
+ } else {
686
+ el.classList.add(settings.stateOpened);
687
+ el.classList.remove(settings.stateClosed);
688
+ resolve(el);
689
+ }
690
+ });
14
691
  };
15
- var setOverflowHidden = function setOverflowHidden(state, selector) {
692
+ var closeTransition = function closeTransition(el, settings) {
693
+ return new Promise(function (resolve) {
694
+ if (settings.transition) {
695
+ el.classList.add(settings.stateClosing);
696
+ el.classList.remove(settings.stateOpened);
697
+ el.addEventListener('transitionend', function _f() {
698
+ el.classList.remove(settings.stateClosing);
699
+ el.classList.add(settings.stateClosed);
700
+ resolve(el);
701
+ this.removeEventListener('transitionend', _f);
702
+ });
703
+ } else {
704
+ el.classList.add(settings.stateClosed);
705
+ el.classList.remove(settings.stateOpened);
706
+ resolve(el);
707
+ }
708
+ });
709
+ };
710
+
711
+ function setOverflowHidden(state, selector) {
16
712
  if (selector) {
17
713
  var els = document.querySelectorAll(selector);
18
714
  els.forEach(function (el) {
@@ -23,1130 +719,1295 @@ var setOverflowHidden = function setOverflowHidden(state, selector) {
23
719
  }
24
720
  });
25
721
  }
26
- };
27
- var setTabindex = function setTabindex(selector) {
722
+ }
723
+
724
+ function setInert(state, selector) {
28
725
  if (selector) {
29
726
  var els = document.querySelectorAll(selector);
30
727
  els.forEach(function (el) {
31
- el.setAttribute('tabindex', '-1');
728
+ if (state) {
729
+ el.inert = true;
730
+ el.setAttribute('aria-hidden', true);
731
+ } else {
732
+ el.inert = null;
733
+ el.removeAttribute('aria-hidden');
734
+ }
32
735
  });
33
736
  }
737
+ }
738
+
739
+ function updateGlobalState(param, config) {
740
+ // Set inert state based on if a modal is active.
741
+ setInert(!!param, config.selectorInert); // Set overflow state based on if a modal is active.
742
+
743
+ setOverflowHidden(!!param, config.selectorOverflow);
744
+ }
745
+
746
+ var index = {
747
+ __proto__: null,
748
+ Breakpoint: Breakpoint,
749
+ Collection: Collection,
750
+ FocusTrap: FocusTrap,
751
+ getConfig: getConfig$1,
752
+ getPrefix: getPrefix,
753
+ localStore: localStore,
754
+ teleport: teleport,
755
+ openTransition: openTransition,
756
+ closeTransition: closeTransition,
757
+ updateGlobalState: updateGlobalState
758
+ };
759
+
760
+ var defaults$3 = {
761
+ autoInit: false,
762
+ stateAttr: 'aria-checked',
763
+ stateValue: 'mixed'
764
+ };
765
+
766
+ var Checkbox = /*#__PURE__*/function () {
767
+ function Checkbox(options) {
768
+ this.defaults = defaults$3;
769
+ this.settings = _extends({}, this.defaults, options);
770
+ this.__handlerClick = this.handlerClick.bind(this);
771
+ if (this.settings.autoInit) this.init();
772
+ }
773
+
774
+ var _proto = Checkbox.prototype;
775
+
776
+ _proto.init = function init(options) {
777
+ if (options === void 0) {
778
+ options = null;
779
+ }
780
+
781
+ if (options) this.settings = _extends({}, this.settings, options);
782
+ var selector = "[" + this.settings.stateAttr + "=\"" + this.settings.stateValue + "\"]";
783
+ var mixed = document.querySelectorAll(selector);
784
+ this.setIndeterminate(mixed);
785
+ document.addEventListener('click', this.__handlerClick, false);
786
+ };
787
+
788
+ _proto.destroy = function destroy() {
789
+ document.removeEventListener('click', this.__handlerClick, false);
790
+ };
791
+
792
+ _proto.handlerClick = function handlerClick(event) {
793
+ var selector = "[" + this.settings.stateAttr + "=\"" + this.settings.stateValue + "\"]";
794
+ var el = event.target.closest(selector);
795
+ if (!el) return;
796
+ this.removeAriaState(el);
797
+ this.setIndeterminate(el);
798
+ };
799
+
800
+ _proto.setAriaState = function setAriaState(el, value) {
801
+ var _this = this;
802
+
803
+ if (value === void 0) {
804
+ value = this.settings.stateValue;
805
+ }
806
+
807
+ el = el.forEach ? el : [el];
808
+ el.forEach(function (el) {
809
+ el.setAttribute(_this.settings.stateAttr, value);
810
+ });
811
+ };
812
+
813
+ _proto.removeAriaState = function removeAriaState(el) {
814
+ var _this2 = this;
815
+
816
+ el = el.forEach ? el : [el];
817
+ el.forEach(function (el) {
818
+ el.removeAttribute(_this2.settings.stateAttr);
819
+ });
820
+ };
821
+
822
+ _proto.setIndeterminate = function setIndeterminate(el) {
823
+ var _this3 = this;
824
+
825
+ el = el.forEach ? el : [el];
826
+ el.forEach(function (el) {
827
+ if (el.hasAttribute(_this3.settings.stateAttr)) {
828
+ el.indeterminate = true;
829
+ } else {
830
+ el.indeterminate = false;
831
+ }
832
+ });
833
+ };
834
+
835
+ return Checkbox;
836
+ }();
837
+
838
+ var defaults$2 = {
839
+ autoInit: false,
840
+ // Data attributes
841
+ dataOpen: 'drawer-open',
842
+ dataClose: 'drawer-close',
843
+ dataToggle: 'drawer-toggle',
844
+ dataBreakpoint: 'drawer-breakpoint',
845
+ dataConfig: 'drawer-config',
846
+ // Selectors
847
+ selectorDrawer: '.drawer',
848
+ selectorDialog: '.drawer__dialog',
849
+ selectorFocus: '[data-focus]',
850
+ selectorInert: null,
851
+ selectorOverflow: 'body',
852
+ // State classes
853
+ stateOpened: 'is-opened',
854
+ stateOpening: 'is-opening',
855
+ stateClosing: 'is-closing',
856
+ stateClosed: 'is-closed',
857
+ // Classes
858
+ classModal: 'drawer_modal',
859
+ // Feature toggles
860
+ breakpoints: null,
861
+ customEventPrefix: 'drawer:',
862
+ eventListeners: true,
863
+ store: true,
864
+ storeKey: 'VB:DrawerState',
865
+ setTabindex: true,
866
+ transition: true
34
867
  };
35
868
 
36
- /**
37
- * Adds a class or classes to a Node or NodeList.
38
- * @param {Node || NodeList} el - Element(s) to add class(es) to.
39
- * @param {String || Array} cl - Class(es) to add.
40
- */
41
- var addClass = function addClass(el) {
42
- var _arguments = arguments;
43
- el = el.forEach ? el : [el];
44
- el.forEach(function (el) {
45
- var _el$classList;
869
+ function handleClick$2(event) {
870
+ var _this = this;
871
+
872
+ // If an open, close or toggle button was clicked, handle the click event.
873
+ var trigger = event.target.closest("\n [data-" + this.settings.dataOpen + "],\n [data-" + this.settings.dataToggle + "],\n [data-" + this.settings.dataClose + "]\n ");
874
+
875
+ if (trigger) {
876
+ // Prevent the default behavior of the trigger.
877
+ event.preventDefault(); // If it's a toggle trigger...
878
+
879
+ if (trigger.matches("[data-" + this.settings.dataToggle + "]")) {
880
+ var selectors = trigger.getAttribute("data-" + this.settings.dataToggle).trim().split(' ');
881
+ selectors.forEach(function (selector) {
882
+ // Get the entry from collection using the attribute value.
883
+ var entry = _this.get(selector); // Store the trigger on the entry.
884
+
885
+
886
+ entry.trigger = trigger; // Toggle the drawer
887
+
888
+ entry.toggle();
889
+ });
890
+ } // If it's a open trigger...
891
+
46
892
 
47
- (_el$classList = el.classList).add.apply(_el$classList, [].slice.call(_arguments, 1));
48
- });
49
- };
893
+ if (trigger.matches("[data-" + this.settings.dataOpen + "]")) {
894
+ var _selectors = trigger.getAttribute("data-" + this.settings.dataOpen).trim().split(' ');
50
895
 
51
- /**
52
- * Takes a hyphen cased string and converts it to camel case.
53
- * @param {String } str - the string to convert to camel case.
54
- * @returns {Boolean} - returns a camel cased string.
55
- */
56
- var camelCase = function camelCase(str) {
57
- return str.replace(/-([a-z])/g, function (g) {
58
- return g[1].toUpperCase();
59
- });
60
- };
896
+ _selectors.forEach(function (selector) {
897
+ // Get the entry from collection using the attribute value.
898
+ var entry = _this.get(selector); // Store the trigger on the entry.
61
899
 
62
- var focusableSelectors = ['a[href]:not([tabindex^="-"])', 'area[href]:not([tabindex^="-"])', 'input:not([type="hidden"]):not([type="radio"]):not([disabled]):not([tabindex^="-"])', 'input[type="radio"]:not([disabled]):not([tabindex^="-"])', 'select:not([disabled]):not([tabindex^="-"])', 'textarea:not([disabled]):not([tabindex^="-"])', 'button:not([disabled]):not([tabindex^="-"])', 'iframe:not([tabindex^="-"])', 'audio[controls]:not([tabindex^="-"])', 'video[controls]:not([tabindex^="-"])', '[contenteditable]:not([tabindex^="-"])', '[tabindex]:not([tabindex^="-"])'];
63
900
 
64
- var focusTarget = function focusTarget(target, settings) {
65
- var innerFocus = target.querySelector("[data-" + settings.dataFocus + "]");
901
+ entry.trigger = trigger; // Open the drawer.
66
902
 
67
- if (innerFocus) {
68
- innerFocus.focus();
69
- } else {
70
- var innerElement = target.querySelector('[tabindex="-1"]');
71
- if (innerElement) innerElement.focus();
903
+ entry.open();
904
+ });
905
+ } // If it's a close trigger...
906
+
907
+
908
+ if (trigger.matches("[data-" + this.settings.dataClose + "]")) {
909
+ var _selectors2 = trigger.getAttribute("data-" + this.settings.dataClose).trim().split(' ');
910
+
911
+ _selectors2.forEach(function (selector) {
912
+ if (selector) {
913
+ // Get the entry from collection using the attribute value.
914
+ var entry = _this.get(selector); // Store the trigger on the entry.
915
+
916
+
917
+ entry.trigger = trigger; // Close the drawer.
918
+
919
+ entry.close();
920
+ } else {
921
+ // If no value is set on close trigger, get the parent drawer.
922
+ var parent = event.target.closest(_this.settings.selectorDrawer); // If a parent drawer was found, close it.
923
+
924
+ if (parent) _this.close(parent);
925
+ }
926
+ });
927
+ }
928
+
929
+ return;
930
+ } // If the modal drawer screen was clicked...
931
+
932
+
933
+ if (event.target.matches(this.settings.selectorDrawer)) {
934
+ // Close the modal drawer.
935
+ this.close(event.target.id);
72
936
  }
73
- };
74
- var focusTrigger = function focusTrigger(obj) {
75
- if (obj === void 0) {
76
- obj = null;
937
+ }
938
+ function handleKeydown$2(event) {
939
+ if (event.key === 'Escape') {
940
+ var modal = this.activeModal;
941
+ if (modal) this.close(modal);
77
942
  }
943
+ }
78
944
 
79
- if (!obj || !obj.memory || !obj.memory.trigger) return;
80
- obj.memory.trigger.focus();
81
- obj.memory.trigger = null;
82
- };
83
- var FocusTrap = /*#__PURE__*/function () {
84
- function FocusTrap() {
85
- this.target = null;
86
- this.__handlerFocusTrap = this.handlerFocusTrap.bind(this);
945
+ var deregister$2 = function deregister(obj, close) {
946
+ if (close === void 0) {
947
+ close = true;
87
948
  }
88
949
 
89
- var _proto = FocusTrap.prototype;
950
+ try {
951
+ var _temp5 = function _temp5() {
952
+ // Return the modified collection.
953
+ return _this2.collection;
954
+ };
90
955
 
91
- _proto.init = function init(target) {
92
- this.target = target;
93
- this.inner = this.target.querySelector('[tabindex="-1"]');
94
- this.focusable = this.getFocusable();
956
+ var _this2 = this;
95
957
 
96
- if (this.focusable.length) {
97
- this.focusableFirst = this.focusable[0];
98
- this.focusableLast = this.focusable[this.focusable.length - 1];
99
- this.target.addEventListener('keydown', this.__handlerFocusTrap);
100
- } else {
101
- this.target.addEventListener('keydown', this.handlerFocusLock);
102
- }
103
- };
958
+ // Return collection if nothing was passed.
959
+ if (!obj) return Promise.resolve(_this2.collection); // Check if entry has been registered in the collection.
104
960
 
105
- _proto.destroy = function destroy() {
106
- if (!this.target) return;
107
- this.inner = null;
108
- this.focusable = null;
109
- this.focusableFirst = null;
110
- this.focusableLast = null;
111
- this.target.removeEventListener('keydown', this.__handlerFocusTrap);
112
- this.target.removeEventListener('keydown', this.handlerFocusLock);
113
- this.target = null;
114
- };
115
-
116
- _proto.refresh = function refresh() {
117
- // Check if a target has been set
118
- if (!this.target) return; // Remove existing events
119
-
120
- this.target.removeEventListener('keydown', this.__handlerFocusTrap);
121
- this.target.removeEventListener('keydown', this.handlerFocusLock); // Get the focusable elements
122
-
123
- this.focusable = this.getFocusable(); // Setup the focus handlers based on focusable length
124
-
125
- if (this.focusable.length) {
126
- // If there are focusable elements, setup focus trap
127
- this.focusableFirst = this.focusable[0];
128
- this.focusableLast = this.focusable[this.focusable.length - 1];
129
- this.target.addEventListener('keydown', this.__handlerFocusTrap);
130
- } else {
131
- // If there are no focusable elements, setup focus lock
132
- this.focusableFirst = null;
133
- this.focusableLast = null;
134
- this.target.addEventListener('keydown', this.handlerFocusLock);
135
- }
136
- };
961
+ var index = _this2.collection.findIndex(function (entry) {
962
+ return entry.id === obj.id;
963
+ });
137
964
 
138
- _proto.handlerFocusTrap = function handlerFocusTrap(event) {
139
- var isTab = event.key === 'Tab' || event.keyCode === 9;
140
- if (!isTab) return;
965
+ var _temp6 = function () {
966
+ if (index >= 0) {
967
+ var _temp7 = function _temp7() {
968
+ // Remove entry from local store.
969
+ delete _this2.store[_entry.id]; // Unmount the MatchMedia functionality.
141
970
 
142
- if (event.shiftKey) {
143
- if (document.activeElement === this.focusableFirst || document.activeElement === this.inner) {
144
- this.focusableLast.focus();
145
- event.preventDefault();
146
- }
147
- } else {
148
- if (document.activeElement === this.focusableLast || document.activeElement === this.inner) {
149
- this.focusableFirst.focus();
150
- event.preventDefault();
151
- }
152
- }
153
- };
971
+ _entry.unmountBreakpoint(); // Delete properties from collection entry.
154
972
 
155
- _proto.handlerFocusLock = function handlerFocusLock(event) {
156
- var isTab = event.key === 'Tab' || event.keyCode === 9;
157
- if (isTab) event.preventDefault();
158
- };
159
973
 
160
- _proto.getFocusable = function getFocusable() {
161
- var focusable = [];
162
- var initFocus = document.activeElement;
163
- var initScrollTop = this.inner ? this.inner.scrollTop : 0;
164
- this.target.querySelectorAll(focusableSelectors.join(',')).forEach(function (el) {
165
- el.focus();
974
+ Object.getOwnPropertyNames(_entry).forEach(function (prop) {
975
+ delete _entry[prop];
976
+ }); // Remove entry from collection.
166
977
 
167
- if (el === document.activeElement) {
168
- focusable.push(el);
169
- }
170
- });
171
- if (this.inner) this.inner.scrollTop = initScrollTop;
172
- initFocus.focus();
173
- return focusable;
174
- };
978
+ _this2.collection.splice(index, 1);
979
+ };
175
980
 
176
- return FocusTrap;
177
- }();
981
+ // Get the collection entry.
982
+ var _entry = _this2.collection[index]; // If entry is in the opened state.
178
983
 
179
- /**
180
- * Get an element(s) from a selector or return value if not a string.
181
- * @param {String} selector - Selector to query.
182
- * @param {Boolean} single - Whether to return a single or all matches.
183
- */
184
- var getElement = function getElement(selector, single) {
185
- if (single === void 0) {
186
- single = 0;
187
- }
984
+ var _temp8 = function () {
985
+ if (close && _entry.state === 'opened') {
986
+ // Close the drawer.
987
+ return Promise.resolve(_entry.close(false)).then(function () {});
988
+ }
989
+ }();
188
990
 
189
- if (typeof selector !== 'string') return selector;
190
- return single ? document.querySelector(selector) : document.querySelectorAll(selector);
191
- };
991
+ return _temp8 && _temp8.then ? _temp8.then(_temp7) : _temp7(_temp8);
992
+ }
993
+ }();
192
994
 
193
- /**
194
- * Checks an element or NodeList whether they contain a class or classes.
195
- * Ref: https://davidwalsh.name/nodelist-array
196
- * @param {Node} el - Element(s) to check class(es) on.
197
- * @param {String || Array} c - Class(es) to check.
198
- * @returns {Boolean} - Returns true if class exists, otherwise false.
199
- */
200
- var hasClass = function hasClass(el) {
201
- el = el.forEach ? el : [el];
202
- el = [].slice.call(el);
203
- return [].slice.call(arguments, 1).some(function (cl) {
204
- return el.some(function (el) {
205
- if (el.classList.contains(cl)) return true;
206
- });
207
- });
995
+ return Promise.resolve(_temp6 && _temp6.then ? _temp6.then(_temp5) : _temp5(_temp6));
996
+ } catch (e) {
997
+ return Promise.reject(e);
998
+ }
208
999
  };
209
1000
 
210
- /**
211
- * Takes a camel cased string and converts it to hyphen case.
212
- * @param {String } str - the string to convert to hyphen case.
213
- * @returns {Boolean} - returns a hyphen cased string.
214
- */
215
- var hyphenCase = function hyphenCase(str) {
216
- return str.replace(/([a-z][A-Z])/g, function (g) {
217
- return g[0] + '-' + g[1].toLowerCase();
218
- });
219
- };
1001
+ function L() {
1002
+ return getComputedStyle(document.body).getPropertyValue("--vrembem-variable-prefix").trim();
1003
+ }
220
1004
 
221
- /**
222
- * Moves element(s) in the DOM based on a reference and move type.
223
- * @param {String} target - The element(s) to move.
224
- * @param {String} type - Move type can be 'after', 'before', 'append' or 'prepend'.
225
- * @param {String} reference - The reference element the move is relative to.
226
- */
1005
+ function getBreakpoint(drawer) {
1006
+ var prefix = L();
1007
+ var bp = drawer.getAttribute("data-" + this.settings.dataBreakpoint);
227
1008
 
228
- function moveElement(target, type, reference) {
229
- if (reference === void 0) {
230
- reference = false;
1009
+ if (this.settings.breakpoints && this.settings.breakpoints[bp]) {
1010
+ return this.settings.breakpoints[bp];
1011
+ } else if (getComputedStyle(document.body).getPropertyValue("--" + prefix + "breakpoint-" + bp).trim()) {
1012
+ return getComputedStyle(document.body).getPropertyValue("--" + prefix + "breakpoint-" + bp).trim();
1013
+ } else {
1014
+ return bp;
231
1015
  }
1016
+ }
232
1017
 
233
- if (reference) {
234
- var els = getElement(target);
235
- if (!els.length) throw new Error("Move target element \"" + target + "\" not found!");
236
- var ref = getElement(reference, 1);
237
- if (!ref) throw new Error("Move reference element \"" + reference + "\" not found!");
238
- els.forEach(function (el) {
239
- switch (type) {
240
- case 'after':
241
- ref.after(el);
242
- return {
243
- ref: ref,
244
- el: el,
245
- type: type
246
- };
247
-
248
- case 'before':
249
- ref.before(el);
250
- return {
251
- ref: ref,
252
- el: el,
253
- type: type
254
- };
255
-
256
- case 'append':
257
- ref.append(el);
258
- return {
259
- ref: ref,
260
- el: el,
261
- type: type
262
- };
263
-
264
- case 'prepend':
265
- ref.prepend(el);
266
- return {
267
- ref: ref,
268
- el: el,
269
- type: type
270
- };
271
-
272
- default:
273
- throw new Error("Move type \"" + type + "\" does not exist!");
274
- }
275
- });
1018
+ function getDrawer(query) {
1019
+ // Get the entry from collection.
1020
+ var entry = typeof query === 'string' ? this.get(query) : this.get(query.id); // Return entry if it was resolved, otherwise throw error.
1021
+
1022
+ if (entry) {
1023
+ return entry;
1024
+ } else {
1025
+ throw new Error("Drawer not found in collection with id of \"" + (query.id || query) + "\".");
276
1026
  }
277
1027
  }
278
1028
 
279
- /**
280
- * Remove a class or classes from an element or NodeList.
281
- * @param {Node || NodeList} el - Element(s) to remove class(es) from.
282
- * @param {String || Array} cl - Class(es) to remove.
283
- */
284
- var removeClass = function removeClass(el) {
285
- var _arguments = arguments;
286
- el = el.forEach ? el : [el];
287
- el.forEach(function (el) {
288
- var _el$classList;
1029
+ function getDrawerID(obj) {
1030
+ // If it's a string, return the string.
1031
+ if (typeof obj === 'string') {
1032
+ return obj;
1033
+ } // If it's an HTML element.
1034
+ else if (typeof obj.hasAttribute === 'function') {
1035
+ // If it's a drawer open trigger, return data value.
1036
+ if (obj.hasAttribute("data-" + this.settings.dataOpen)) {
1037
+ return obj.getAttribute("data-" + this.settings.dataOpen);
1038
+ } // If it's a drawer close trigger, return data value or false.
1039
+ else if (obj.hasAttribute("data-" + this.settings.dataClose)) {
1040
+ return obj.getAttribute("data-" + this.settings.dataClose) || false;
1041
+ } // If it's a drawer toggle trigger, return data value.
1042
+ else if (obj.hasAttribute("data-" + this.settings.dataToggle)) {
1043
+ return obj.getAttribute("data-" + this.settings.dataToggle);
1044
+ } // If it's a drawer element, return the id.
1045
+ else if (obj.closest(this.settings.selectorDrawer)) {
1046
+ obj = obj.closest(this.settings.selectorDrawer);
1047
+ return obj.id || false;
1048
+ } // Return false if no id was found.
1049
+ else return false;
1050
+ } // If it has an id property, return its value.
1051
+ else if (obj.id) {
1052
+ return obj.id;
1053
+ } // Return false if no id was found.
1054
+ else return false;
1055
+ }
289
1056
 
290
- (_el$classList = el.classList).remove.apply(_el$classList, [].slice.call(_arguments, 1));
291
- });
292
- };
1057
+ function getDrawerElements(query) {
1058
+ var id = getDrawerID.call(this, query);
293
1059
 
294
- /**
295
- * Toggle a class or classes on an element or NodeList.
296
- * @param {Node || NodeList} el - Element(s) to toggle class(es) on.
297
- * @param {String || Array} cl - Class(es) to toggle.
298
- */
299
- var toggleClass = function toggleClass(el) {
300
- var _arguments = arguments;
301
- el = el.forEach ? el : [el];
302
- el.forEach(function (el) {
303
- [].slice.call(_arguments, 1).forEach(function (cl) {
304
- el.classList.toggle(cl);
305
- });
306
- });
307
- };
1060
+ if (id) {
1061
+ var drawer = document.querySelector("#" + id);
1062
+ var dialog = drawer ? drawer.querySelector(this.settings.selectorDialog) : null;
308
1063
 
309
- var openTransition = function openTransition(el, settings) {
310
- return new Promise(function (resolve) {
311
- if (settings.transition) {
312
- el.classList.remove(settings.stateClosed);
313
- el.classList.add(settings.stateOpening);
314
- el.addEventListener('transitionend', function _f() {
315
- el.classList.add(settings.stateOpened);
316
- el.classList.remove(settings.stateOpening);
317
- resolve(el);
318
- this.removeEventListener('transitionend', _f);
319
- });
1064
+ if (!drawer && !dialog) {
1065
+ return {
1066
+ error: new Error("No drawer elements found using the ID: \"" + id + "\".")
1067
+ };
1068
+ } else if (!dialog) {
1069
+ return {
1070
+ error: new Error('Drawer is missing dialog element.')
1071
+ };
320
1072
  } else {
321
- el.classList.add(settings.stateOpened);
322
- el.classList.remove(settings.stateClosed);
323
- resolve(el);
1073
+ return {
1074
+ drawer: drawer,
1075
+ dialog: dialog
1076
+ };
324
1077
  }
325
- });
1078
+ } else {
1079
+ return {
1080
+ error: new Error('Could not resolve the drawer ID.')
1081
+ };
1082
+ }
1083
+ }
1084
+
1085
+ var initialState = function initialState(entry) {
1086
+ try {
1087
+ var _this2 = this;
1088
+
1089
+ var _temp3 = function () {
1090
+ if (_this2.store[entry.id]) {
1091
+ var _temp4 = function () {
1092
+ if (_this2.store[entry.id] === 'opened') {
1093
+ return Promise.resolve(entry.open(false, false)).then(function () {});
1094
+ } else {
1095
+ return Promise.resolve(entry.close(false, false)).then(function () {});
1096
+ }
1097
+ }();
1098
+
1099
+ if (_temp4 && _temp4.then) return _temp4.then(function () {});
1100
+ } else if (entry.el.classList.contains(_this2.settings.stateOpened)) {
1101
+ // Update drawer state.
1102
+ entry.state = 'opened';
1103
+ } else {
1104
+ // Remove transition state classes.
1105
+ entry.el.classList.remove(_this2.settings.stateOpening);
1106
+ entry.el.classList.remove(_this2.settings.stateClosing); // Add closed state class.
1107
+
1108
+ entry.el.classList.add(_this2.settings.stateClosed);
1109
+ }
1110
+ }();
1111
+
1112
+ // Setup initial state using the following priority:
1113
+ // 1. If a store state is available, restore from local store.
1114
+ // 2. If opened state class is set, set state to opened.
1115
+ // 3. Else, initialize default state.
1116
+ return Promise.resolve(_temp3 && _temp3.then ? _temp3.then(function () {}) : void 0);
1117
+ } catch (e) {
1118
+ return Promise.reject(e);
1119
+ }
326
1120
  };
327
- var closeTransition = function closeTransition(el, settings) {
328
- return new Promise(function (resolve) {
329
- if (settings.transition) {
330
- el.classList.add(settings.stateClosing);
331
- el.classList.remove(settings.stateOpened);
332
- el.addEventListener('transitionend', function _f() {
333
- el.classList.remove(settings.stateClosing);
334
- el.classList.add(settings.stateClosed);
335
- resolve(el);
336
- this.removeEventListener('transitionend', _f);
337
- });
1121
+
1122
+ function updateFocusState$1(entry) {
1123
+ // Check if there's an active modal
1124
+ if (entry.state === 'opened') {
1125
+ // Mount the focus trap on the opened drawer.
1126
+ if (entry.mode === 'modal') {
1127
+ this.focusTrap.mount(entry.dialog, this.settings.selectorFocus);
338
1128
  } else {
339
- el.classList.add(settings.stateClosed);
340
- el.classList.remove(settings.stateOpened);
341
- resolve(el);
1129
+ this.focusTrap.focus(entry.dialog, this.settings.selectorFocus);
1130
+ }
1131
+ } else {
1132
+ // Set focus to root trigger and unmount the focus trap.
1133
+ if (entry.trigger) {
1134
+ entry.trigger.focus();
1135
+ entry.trigger = null;
342
1136
  }
343
- });
344
- };
345
1137
 
346
- var index = {
347
- __proto__: null,
348
- setInert: setInert,
349
- setOverflowHidden: setOverflowHidden,
350
- setTabindex: setTabindex,
351
- addClass: addClass,
352
- camelCase: camelCase,
353
- focusTarget: focusTarget,
354
- focusTrigger: focusTrigger,
355
- FocusTrap: FocusTrap,
356
- getElement: getElement,
357
- hasClass: hasClass,
358
- hyphenCase: hyphenCase,
359
- moveElement: moveElement,
360
- removeClass: removeClass,
361
- toggleClass: toggleClass,
362
- openTransition: openTransition,
363
- closeTransition: closeTransition
364
- };
1138
+ this.focusTrap.unmount();
1139
+ }
1140
+ }
365
1141
 
366
- function _extends() {
367
- _extends = Object.assign || function (target) {
368
- for (var i = 1; i < arguments.length; i++) {
369
- var source = arguments[i];
1142
+ var open$2 = function open(query, transition, focus) {
1143
+ if (focus === void 0) {
1144
+ focus = true;
1145
+ }
370
1146
 
371
- for (var key in source) {
372
- if (Object.prototype.hasOwnProperty.call(source, key)) {
373
- target[key] = source[key];
374
- }
375
- }
376
- }
1147
+ try {
1148
+ var _temp3 = function _temp3() {
1149
+ // Set focus to the drawer element if the focus param is true.
1150
+ if (focus) {
1151
+ updateFocusState$1.call(_this2, drawer);
1152
+ } // Dispatch custom opened event.
377
1153
 
378
- return target;
379
- };
380
1154
 
381
- return _extends.apply(this, arguments);
382
- }
1155
+ drawer.el.dispatchEvent(new CustomEvent(config.customEventPrefix + 'opened', {
1156
+ detail: _this2,
1157
+ bubbles: true
1158
+ })); // Return the drawer.
383
1159
 
384
- function _inheritsLoose(subClass, superClass) {
385
- subClass.prototype = Object.create(superClass.prototype);
386
- subClass.prototype.constructor = subClass;
1160
+ return drawer;
1161
+ };
387
1162
 
388
- _setPrototypeOf(subClass, superClass);
389
- }
1163
+ var _this2 = this;
390
1164
 
391
- function _setPrototypeOf(o, p) {
392
- _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
393
- o.__proto__ = p;
394
- return o;
395
- };
1165
+ // Get the drawer from collection.
1166
+ var drawer = getDrawer.call(_this2, query); // Get the modal configuration.
396
1167
 
397
- return _setPrototypeOf(o, p);
398
- }
1168
+ var config = _extends({}, _this2.settings, drawer.settings); // Add transition parameter to configuration.
399
1169
 
400
- function _assertThisInitialized(self) {
401
- if (self === void 0) {
402
- throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
403
- }
404
1170
 
405
- return self;
406
- }
1171
+ if (transition !== undefined) config.transition = transition; // If drawer is closed.
407
1172
 
408
- var defaults$3 = {
409
- autoInit: false,
410
- stateAttr: 'aria-checked',
411
- stateValue: 'mixed'
1173
+ var _temp4 = function () {
1174
+ if (drawer.state === 'closed') {
1175
+ // Update drawer state.
1176
+ drawer.state = 'opening'; // Run the open transition.
1177
+
1178
+ return Promise.resolve(openTransition(drawer.el, config)).then(function () {
1179
+ // Update the global state if mode is modal.
1180
+ if (drawer.mode === 'modal') updateGlobalState(true, config); // Update drawer state.
1181
+
1182
+ drawer.state = 'opened';
1183
+ });
1184
+ }
1185
+ }();
1186
+
1187
+ return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(_temp3) : _temp3(_temp4));
1188
+ } catch (e) {
1189
+ return Promise.reject(e);
1190
+ }
412
1191
  };
413
1192
 
414
- var Checkbox = /*#__PURE__*/function () {
415
- function Checkbox(options) {
416
- this.defaults = defaults$3;
417
- this.settings = _extends({}, this.defaults, options);
418
- this.__handlerClick = this.handlerClick.bind(this);
419
- if (this.settings.autoInit) this.init();
1193
+ var close$2 = function close(query, transition, focus) {
1194
+ if (focus === void 0) {
1195
+ focus = true;
420
1196
  }
421
1197
 
422
- var _proto = Checkbox.prototype;
1198
+ try {
1199
+ var _this2 = this;
423
1200
 
424
- _proto.init = function init(options) {
425
- if (options === void 0) {
426
- options = null;
427
- }
1201
+ // Get the drawer from collection.
1202
+ var drawer = getDrawer.call(_this2, query); // Get the modal configuration.
428
1203
 
429
- if (options) this.settings = _extends({}, this.settings, options);
430
- var selector = "[" + this.settings.stateAttr + "=\"" + this.settings.stateValue + "\"]";
431
- var mixed = document.querySelectorAll(selector);
432
- this.setIndeterminate(mixed);
433
- document.addEventListener('click', this.__handlerClick, false);
434
- };
1204
+ var config = _extends({}, _this2.settings, drawer.settings); // Add transition parameter to configuration.
435
1205
 
436
- _proto.destroy = function destroy() {
437
- document.removeEventListener('click', this.__handlerClick, false);
438
- };
439
1206
 
440
- _proto.handlerClick = function handlerClick(event) {
441
- var selector = "[" + this.settings.stateAttr + "=\"" + this.settings.stateValue + "\"]";
442
- var el = event.target.closest(selector);
443
- if (!el) return;
444
- this.removeAriaState(el);
445
- this.setIndeterminate(el);
446
- };
1207
+ if (transition !== undefined) config.transition = transition; // If drawer is opened.
1208
+
1209
+ var _temp2 = function () {
1210
+ if (drawer.state === 'opened') {
1211
+ // Update drawer state.
1212
+ drawer.state = 'closing'; // Remove focus from active element.
1213
+
1214
+ document.activeElement.blur(); // Run the close transition.
1215
+
1216
+ return Promise.resolve(closeTransition(drawer.el, config)).then(function () {
1217
+ // Update the global state if mode is modal.
1218
+ if (drawer.mode === 'modal') updateGlobalState(false, config); // Set focus to the trigger element if the focus param is true.
1219
+
1220
+ if (focus) {
1221
+ updateFocusState$1.call(_this2, drawer);
1222
+ } // Update drawer state.
1223
+
1224
+
1225
+ drawer.state = 'closed'; // Dispatch custom closed event.
1226
+
1227
+ drawer.el.dispatchEvent(new CustomEvent(config.customEventPrefix + 'closed', {
1228
+ detail: _this2,
1229
+ bubbles: true
1230
+ }));
1231
+ });
1232
+ }
1233
+ }();
1234
+
1235
+ return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {
1236
+ // Return the drawer.
1237
+ return drawer;
1238
+ }) : drawer);
1239
+ } catch (e) {
1240
+ return Promise.reject(e);
1241
+ }
1242
+ };
1243
+
1244
+ var toggle = function toggle(query, transition, focus) {
1245
+ try {
1246
+ var _this2 = this;
447
1247
 
448
- _proto.setAriaState = function setAriaState(el, value) {
449
- var _this = this;
1248
+ // Get the drawer from collection.
1249
+ var drawer = getDrawer.call(_this2, query); // Open or close the drawer based on its current state.
450
1250
 
451
- if (value === void 0) {
452
- value = this.settings.stateValue;
1251
+ if (drawer.state === 'closed') {
1252
+ return Promise.resolve(open$2.call(_this2, drawer, transition, focus));
1253
+ } else {
1254
+ return Promise.resolve(close$2.call(_this2, drawer, transition, focus));
453
1255
  }
1256
+ } catch (e) {
1257
+ return Promise.reject(e);
1258
+ }
1259
+ };
454
1260
 
455
- el = el.forEach ? el : [el];
456
- el.forEach(function (el) {
457
- el.setAttribute(_this.settings.stateAttr, value);
458
- });
459
- };
1261
+ var toModal = function toModal(entry) {
1262
+ try {
1263
+ var _this4 = this;
460
1264
 
461
- _proto.removeAriaState = function removeAriaState(el) {
462
- var _this2 = this;
1265
+ // Get the drawer configuration.
1266
+ // Add the modal class.
1267
+ entry.el.classList.add(entry.getSetting('classModal')); // Set aria-modal attribute to true.
463
1268
 
464
- el = el.forEach ? el : [el];
465
- el.forEach(function (el) {
466
- el.removeAttribute(_this2.settings.stateAttr);
467
- });
468
- };
1269
+ entry.dialog.setAttribute('aria-modal', 'true'); // If there isn't a stored state but also has the opened state class...
469
1270
 
470
- _proto.setIndeterminate = function setIndeterminate(el) {
471
- var _this3 = this;
1271
+ if (!_this4.store[entry.id] && entry.el.classList.contains(entry.getSetting('stateOpened'))) {
1272
+ // Save the opened state in local store.
1273
+ _this4.store[entry.id] = 'opened';
1274
+ } // Modal drawer defaults to closed state.
472
1275
 
473
- el = el.forEach ? el : [el];
474
- el.forEach(function (el) {
475
- if (el.hasAttribute(_this3.settings.stateAttr)) {
476
- el.indeterminate = true;
477
- } else {
478
- el.indeterminate = false;
479
- }
480
- });
481
- };
482
1276
 
483
- return Checkbox;
484
- }();
1277
+ return Promise.resolve(close$2.call(_this4, entry, false, false)).then(function () {
1278
+ // Dispatch custom switch event.
1279
+ entry.el.dispatchEvent(new CustomEvent(entry.getSetting('customEventPrefix') + 'switchMode', {
1280
+ detail: _this4,
1281
+ bubbles: true
1282
+ })); // Return the entry.
485
1283
 
486
- var defaults$2 = {
487
- autoInit: false,
488
- // Data attributes
489
- dataDrawer: 'drawer',
490
- dataDialog: 'drawer-dialog',
491
- dataToggle: 'drawer-toggle',
492
- dataOpen: 'drawer-open',
493
- dataClose: 'drawer-close',
494
- dataBreakpoint: 'drawer-breakpoint',
495
- dataFocus: 'drawer-focus',
496
- // State classes
497
- stateOpened: 'is-opened',
498
- stateOpening: 'is-opening',
499
- stateClosing: 'is-closing',
500
- stateClosed: 'is-closed',
501
- // Classes
502
- classModal: 'drawer_modal',
503
- // Selectors
504
- selectorInert: null,
505
- selectorOverflow: null,
506
- // Feature toggles
507
- breakpoints: null,
508
- customEventPrefix: 'drawer:',
509
- eventListeners: true,
510
- stateSave: true,
511
- stateKey: 'DrawerState',
512
- setTabindex: true,
513
- transition: true
1284
+ return entry;
1285
+ });
1286
+ } catch (e) {
1287
+ return Promise.reject(e);
1288
+ }
514
1289
  };
515
1290
 
516
- var Breakpoint = /*#__PURE__*/function () {
517
- function Breakpoint(parent) {
518
- this.mediaQueryLists = [];
519
- this.parent = parent;
520
- this.prefix = this.getVariablePrefix();
521
- this.__check = this.check.bind(this);
522
- }
1291
+ var toInline = function toInline(entry) {
1292
+ try {
1293
+ var _this2 = this;
523
1294
 
524
- var _proto = Breakpoint.prototype;
1295
+ // Remove the modal class.
1296
+ entry.el.classList.remove(entry.getSetting('classModal')); // Remove the aria-modal attribute.
525
1297
 
526
- _proto.init = function init() {
527
- var _this = this;
1298
+ entry.dialog.removeAttribute('aria-modal'); // Update the global state.
528
1299
 
529
- var drawers = document.querySelectorAll("[data-" + this.parent.settings.dataBreakpoint + "]");
530
- drawers.forEach(function (drawer) {
531
- // Setup mediaQueryList object
532
- var id = drawer.getAttribute("data-" + _this.parent.settings.dataDrawer);
533
- var key = drawer.getAttribute("data-" + _this.parent.settings.dataBreakpoint);
1300
+ updateGlobalState(false, _extends({}, _this2.settings, entry.settings)); // Remove any focus traps.
534
1301
 
535
- var bp = _this.getBreakpoint(key);
1302
+ _this2.focusTrap.unmount(); // Setup initial state.
536
1303
 
537
- var mql = window.matchMedia('(min-width:' + bp + ')'); // Run match check
538
1304
 
539
- _this.match(mql, drawer); // Conditionally use addListner() for IE11 support
1305
+ return Promise.resolve(initialState.call(_this2, entry)).then(function () {
1306
+ // Dispatch custom switch event.
1307
+ entry.el.dispatchEvent(new CustomEvent(entry.getSetting('customEventPrefix') + 'switchMode', {
1308
+ detail: _this2,
1309
+ bubbles: true
1310
+ })); // Return the entry.
540
1311
 
1312
+ return entry;
1313
+ });
1314
+ } catch (e) {
1315
+ return Promise.reject(e);
1316
+ }
1317
+ };
541
1318
 
542
- if (typeof mql.addEventListener === 'function') {
543
- mql.addEventListener('change', _this.__check);
544
- } else {
545
- mql.addListener(_this.__check);
546
- } // Push to mediaQueryLists array along with drawer ID
1319
+ function switchMode(entry) {
1320
+ switch (entry.mode) {
1321
+ case 'inline':
1322
+ return toInline.call(this, entry);
547
1323
 
1324
+ case 'modal':
1325
+ return toModal.call(this, entry);
548
1326
 
549
- _this.mediaQueryLists.push({
550
- 'mql': mql,
551
- 'drawer': id
552
- });
553
- });
554
- };
1327
+ default:
1328
+ throw new Error("\"" + entry.mode + "\" is not a valid drawer mode.");
1329
+ }
1330
+ }
555
1331
 
556
- _proto.destroy = function destroy() {
1332
+ var register$2 = function register(el, dialog) {
1333
+ try {
557
1334
  var _this2 = this;
558
1335
 
559
- if (this.mediaQueryLists && this.mediaQueryLists.length) {
560
- this.mediaQueryLists.forEach(function (item) {
561
- item.mql.removeListener(_this2.__check);
562
- });
563
- }
1336
+ // Deregister entry incase it has already been registered.
1337
+ return Promise.resolve(deregister$2.call(_this2, el, false)).then(function () {
1338
+ // Save root this for use inside methods API.
1339
+ var root = _this2; // Create an instance of the Breakpoint class.
1340
+
1341
+ var breakpoint = new Breakpoint(); // Setup methods API.
1342
+
1343
+ var methods = {
1344
+ open: function open(transition, focus) {
1345
+ return open$2.call(root, this, transition, focus);
1346
+ },
1347
+ close: function close(transition, focus) {
1348
+ return close$2.call(root, this, transition, focus);
1349
+ },
1350
+ toggle: function toggle$1(transition, focus) {
1351
+ return toggle.call(root, this, transition, focus);
1352
+ },
1353
+ deregister: function deregister() {
1354
+ return deregister$2.call(root, this);
1355
+ },
1356
+ mountBreakpoint: function mountBreakpoint() {
1357
+ var value = this.breakpoint;
1358
+ var handler = this.handleBreakpoint.bind(this);
1359
+ breakpoint.mount(value, handler);
1360
+ return this;
1361
+ },
1362
+ unmountBreakpoint: function unmountBreakpoint() {
1363
+ breakpoint.unmount();
1364
+ return this;
1365
+ },
1366
+ handleBreakpoint: function handleBreakpoint(event) {
1367
+ this.mode = event.matches ? 'inline' : 'modal';
1368
+ return this;
1369
+ },
1370
+ getSetting: function getSetting(key) {
1371
+ return key in this.settings ? this.settings[key] : root.settings[key];
1372
+ }
1373
+ }; // Setup the drawer object.
564
1374
 
565
- this.mediaQueryLists = null;
566
- };
1375
+ var entry = _extends({
1376
+ id: el.id,
1377
+ el: el,
1378
+ dialog: dialog,
1379
+ trigger: null,
1380
+ settings: getConfig$1(el, _this2.settings.dataConfig),
567
1381
 
568
- _proto.check = function check(event) {
569
- var _this3 = this;
1382
+ get breakpoint() {
1383
+ return getBreakpoint.call(root, el);
1384
+ },
570
1385
 
571
- if (event === void 0) {
572
- event = null;
573
- }
1386
+ get state() {
1387
+ return __state;
1388
+ },
574
1389
 
575
- if (this.mediaQueryLists && this.mediaQueryLists.length) {
576
- this.mediaQueryLists.forEach(function (item) {
577
- // If an event is passed, filter out drawers that don't match the query
578
- // If event is null, run all drawers through match
579
- var filter = event ? event.media == item.mql.media : true;
580
- if (!filter) return;
581
- var drawer = document.querySelector("[data-" + _this3.parent.settings.dataDrawer + "=\"" + item.drawer + "\"]");
582
- if (drawer) _this3.match(item.mql, drawer);
583
- });
584
- document.dispatchEvent(new CustomEvent(this.parent.settings.customEventPrefix + 'breakpoint', {
585
- bubbles: true
586
- }));
587
- }
588
- };
1390
+ set state(value) {
1391
+ __state = value; // Save 'opened' and 'closed' states to store if mode is inline.
589
1392
 
590
- _proto.match = function match(mql, drawer) {
591
- if (mql.matches) {
592
- this.parent.switchToDefault(drawer);
593
- } else {
594
- this.parent.switchToModal(drawer);
595
- }
596
- };
1393
+ if (value === 'opened' || value === 'closed') {
1394
+ if (this.mode === 'inline') root.store[this.id] = this.state;
1395
+ }
1396
+ },
597
1397
 
598
- _proto.getBreakpoint = function getBreakpoint(key) {
599
- var breakpoint = key;
1398
+ get mode() {
1399
+ return __mode;
1400
+ },
600
1401
 
601
- if (this.parent.settings.breakpoints && this.parent.settings.breakpoints[key]) {
602
- breakpoint = this.parent.settings.breakpoints[key];
603
- } else if (getComputedStyle(document.body).getPropertyValue(this.prefix + key)) {
604
- breakpoint = getComputedStyle(document.body).getPropertyValue(this.prefix + key);
605
- }
1402
+ set mode(value) {
1403
+ __mode = value;
1404
+ switchMode.call(root, this);
1405
+ }
606
1406
 
607
- return breakpoint;
608
- };
1407
+ }, methods); // Create the state var with the initial state.
609
1408
 
610
- _proto.getVariablePrefix = function getVariablePrefix() {
611
- var prefix = '--';
612
- prefix += getComputedStyle(document.body).getPropertyValue('--vrembem-variable-prefix');
613
- prefix += 'breakpoint-';
614
- return prefix;
615
- };
616
1409
 
617
- return Breakpoint;
618
- }();
1410
+ var __state = el.classList.contains(entry.getSetting('stateOpened')) ? 'opened' : 'closed'; // Create the mode var with the initial mode.
619
1411
 
620
- function getDrawer(drawerKey) {
621
- if (typeof drawerKey !== 'string') return drawerKey;
622
- return document.querySelector("[data-" + this.settings.dataDrawer + "=\"" + drawerKey + "\"]");
623
- }
624
- function drawerNotFound(key) {
625
- return Promise.reject(new Error("Did not find drawer with key: \"" + key + "\""));
626
- }
627
1412
 
628
- var close$2 = function close(drawerKey) {
629
- try {
630
- var _this2 = this;
1413
+ var __mode = el.classList.contains(entry.getSetting('classModal')) ? 'modal' : 'inline'; // Setup mode specific attributes.
1414
+
631
1415
 
632
- var drawer = _this2.getDrawer(drawerKey);
1416
+ if (entry.mode === 'modal') {
1417
+ // Set aria-modal attribute to true.
1418
+ entry.dialog.setAttribute('aria-modal', 'true');
1419
+ } else {
1420
+ // Remove the aria-modal attribute.
1421
+ entry.dialog.removeAttribute('aria-modal');
1422
+ } // Set tabindex="-1" so dialog is focusable via JS or click.
633
1423
 
634
- if (!drawer) return Promise.resolve(drawerNotFound(drawerKey));
635
1424
 
636
- if (hasClass(drawer, _this2.settings.stateOpened)) {
637
- _this2.working = true;
1425
+ if (entry.getSetting('setTabindex')) {
1426
+ entry.dialog.setAttribute('tabindex', '-1');
1427
+ } // Add entry to collection.
638
1428
 
639
- if (hasClass(drawer, _this2.settings.classModal)) {
640
- setInert(false, _this2.settings.selectorInert);
641
- setOverflowHidden(false, _this2.settings.selectorOverflow);
642
- }
643
1429
 
644
- return Promise.resolve(closeTransition(drawer, _this2.settings)).then(function () {
645
- _this2.stateSave(drawer);
1430
+ _this2.collection.push(entry); // If the entry has a breakpoint...
646
1431
 
647
- focusTrigger(_this2);
648
1432
 
649
- _this2.focusTrap.destroy();
1433
+ var _temp = function () {
1434
+ if (entry.breakpoint) {
1435
+ // Mount media query breakpoint functionality.
1436
+ entry.mountBreakpoint();
1437
+ } else {
1438
+ // Else, Setup initial state.
1439
+ return Promise.resolve(initialState.call(_this2, entry)).then(function () {});
1440
+ }
1441
+ }();
650
1442
 
651
- drawer.dispatchEvent(new CustomEvent(_this2.settings.customEventPrefix + 'closed', {
652
- detail: _this2,
653
- bubbles: true
654
- }));
655
- _this2.working = false;
656
- return drawer;
657
- });
658
- } else {
659
- return Promise.resolve(drawer);
660
- }
1443
+ return _temp && _temp.then ? _temp.then(function () {
1444
+ // Return the registered entry.
1445
+ return entry;
1446
+ }) : entry;
1447
+ });
661
1448
  } catch (e) {
662
1449
  return Promise.reject(e);
663
1450
  }
664
1451
  };
665
1452
 
666
- function handlerClick$2(event) {
667
- // Working catch
668
- if (this.working) return; // Toggle data trigger
1453
+ var _handleClick$1 = /*#__PURE__*/_classPrivateFieldLooseKey("handleClick");
669
1454
 
670
- var trigger = event.target.closest("[data-" + this.settings.dataToggle + "]");
1455
+ var _handleKeydown$2 = /*#__PURE__*/_classPrivateFieldLooseKey("handleKeydown");
671
1456
 
672
- if (trigger) {
673
- var selector = trigger.getAttribute("data-" + this.settings.dataToggle);
674
- this.memory.trigger = trigger;
675
- this.toggle(selector);
676
- event.preventDefault();
677
- return;
678
- } // Open data trigger
1457
+ var Drawer = /*#__PURE__*/function (_Collection) {
1458
+ _inheritsLoose(Drawer, _Collection);
679
1459
 
1460
+ function Drawer(options) {
1461
+ var _this;
680
1462
 
681
- trigger = event.target.closest("[data-" + this.settings.dataOpen + "]");
1463
+ _this = _Collection.call(this) || this;
1464
+ Object.defineProperty(_assertThisInitialized(_this), _handleClick$1, {
1465
+ writable: true,
1466
+ value: void 0
1467
+ });
1468
+ Object.defineProperty(_assertThisInitialized(_this), _handleKeydown$2, {
1469
+ writable: true,
1470
+ value: void 0
1471
+ });
1472
+ _this.defaults = defaults$2;
1473
+ _this.settings = _extends({}, _this.defaults, options);
1474
+ _this.focusTrap = new FocusTrap(); // Setup local store for inline drawer state management.
682
1475
 
683
- if (trigger) {
684
- var _selector = trigger.getAttribute("data-" + this.settings.dataOpen);
1476
+ _this.store = localStore(_this.settings.storeKey, _this.settings.store);
1477
+ _classPrivateFieldLooseBase(_assertThisInitialized(_this), _handleClick$1)[_handleClick$1] = handleClick$2.bind(_assertThisInitialized(_this));
1478
+ _classPrivateFieldLooseBase(_assertThisInitialized(_this), _handleKeydown$2)[_handleKeydown$2] = handleKeydown$2.bind(_assertThisInitialized(_this));
1479
+ if (_this.settings.autoInit) _this.init();
1480
+ return _this;
1481
+ }
685
1482
 
686
- this.memory.trigger = trigger;
687
- this.open(_selector);
688
- event.preventDefault();
689
- return;
690
- } // Close data trigger
1483
+ var _proto = Drawer.prototype;
1484
+
1485
+ _proto.init = function init(options) {
1486
+ if (options === void 0) {
1487
+ options = null;
1488
+ }
691
1489
 
1490
+ try {
1491
+ var _this3 = this;
692
1492
 
693
- trigger = event.target.closest("[data-" + this.settings.dataClose + "]");
1493
+ // Update settings with passed options.
1494
+ if (options) _this3.settings = _extends({}, _this3.settings, options); // Get all the modals.
694
1495
 
695
- if (trigger) {
696
- var _selector2 = trigger.getAttribute("data-" + this.settings.dataClose);
1496
+ var drawers = document.querySelectorAll(_this3.settings.selectorDrawer); // Register the collections array with modal instances.
697
1497
 
698
- if (_selector2) {
699
- this.memory.trigger = trigger;
700
- this.close(_selector2);
701
- } else {
702
- var target = event.target.closest("[data-" + this.settings.dataDrawer + "]");
703
- if (target) this.close(target);
1498
+ return Promise.resolve(_this3.registerCollection(drawers)).then(function () {
1499
+ // If eventListeners are enabled, init event listeners.
1500
+ if (_this3.settings.eventListeners) {
1501
+ _this3.initEventListeners();
1502
+ }
1503
+
1504
+ return _this3;
1505
+ });
1506
+ } catch (e) {
1507
+ return Promise.reject(e);
704
1508
  }
1509
+ };
705
1510
 
706
- event.preventDefault();
707
- return;
708
- } // Screen modal trigger
1511
+ _proto.destroy = function destroy() {
1512
+ try {
1513
+ var _this5 = this;
1514
+
1515
+ // Remove all entries from the collection.
1516
+ return Promise.resolve(_this5.deregisterCollection()).then(function () {
1517
+ // If eventListeners are enabled, init event listeners.
1518
+ if (_this5.settings.eventListeners) {
1519
+ _this5.destroyEventListeners();
1520
+ }
709
1521
 
1522
+ return _this5;
1523
+ });
1524
+ } catch (e) {
1525
+ return Promise.reject(e);
1526
+ }
1527
+ };
710
1528
 
711
- if (event.target.hasAttribute("data-" + this.settings.dataDrawer)) {
712
- this.close(event.target);
713
- return;
1529
+ _proto.initEventListeners = function initEventListeners() {
1530
+ document.addEventListener('click', _classPrivateFieldLooseBase(this, _handleClick$1)[_handleClick$1], false);
1531
+ document.addEventListener('touchend', _classPrivateFieldLooseBase(this, _handleClick$1)[_handleClick$1], false);
1532
+ document.addEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown$2)[_handleKeydown$2], false);
1533
+ };
1534
+
1535
+ _proto.destroyEventListeners = function destroyEventListeners() {
1536
+ document.removeEventListener('click', _classPrivateFieldLooseBase(this, _handleClick$1)[_handleClick$1], false);
1537
+ document.removeEventListener('touchend', _classPrivateFieldLooseBase(this, _handleClick$1)[_handleClick$1], false);
1538
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown$2)[_handleKeydown$2], false);
1539
+ };
1540
+
1541
+ _proto.register = function register(query) {
1542
+ var els = getDrawerElements.call(this, query);
1543
+ if (els.error) return Promise.reject(els.error);
1544
+ return register$2.call(this, els.drawer, els.dialog);
1545
+ };
1546
+
1547
+ _proto.deregister = function deregister(query) {
1548
+ var entry = this.get(getDrawerID.call(this, query));
1549
+ return deregister$2.call(this, entry);
1550
+ };
1551
+
1552
+ _proto.open = function open(id, transition, focus) {
1553
+ return open$2.call(this, id, transition, focus);
1554
+ };
1555
+
1556
+ _proto.close = function close(id, transition, focus) {
1557
+ return close$2.call(this, id, transition, focus);
1558
+ };
1559
+
1560
+ _proto.toggle = function toggle$1(id, transition, focus) {
1561
+ return toggle.call(this, id, transition, focus);
1562
+ };
1563
+
1564
+ _createClass(Drawer, [{
1565
+ key: "activeModal",
1566
+ get: function get() {
1567
+ return this.collection.find(function (entry) {
1568
+ return entry.state === 'opened' && entry.mode === 'modal';
1569
+ });
1570
+ }
1571
+ }]);
1572
+
1573
+ return Drawer;
1574
+ }(Collection);
1575
+
1576
+ var defaults$1 = {
1577
+ autoInit: false,
1578
+ // Data attributes
1579
+ dataOpen: 'modal-open',
1580
+ dataClose: 'modal-close',
1581
+ dataReplace: 'modal-replace',
1582
+ dataConfig: 'modal-config',
1583
+ // Selectors
1584
+ selectorModal: '.modal',
1585
+ selectorDialog: '.modal__dialog',
1586
+ selectorRequired: '[role="alertdialog"]',
1587
+ selectorFocus: '[data-focus]',
1588
+ selectorInert: null,
1589
+ selectorOverflow: 'body',
1590
+ // State classes
1591
+ stateOpened: 'is-opened',
1592
+ stateOpening: 'is-opening',
1593
+ stateClosing: 'is-closing',
1594
+ stateClosed: 'is-closed',
1595
+ // Feature settings
1596
+ customEventPrefix: 'modal:',
1597
+ eventListeners: true,
1598
+ teleport: null,
1599
+ teleportMethod: 'append',
1600
+ setTabindex: true,
1601
+ transition: true
1602
+ };
1603
+
1604
+ function getModal(query) {
1605
+ // Get the entry from collection.
1606
+ var entry = typeof query === 'string' ? this.get(query) : this.get(query.id); // Return entry if it was resolved, otherwise throw error.
1607
+
1608
+ if (entry) {
1609
+ return entry;
1610
+ } else {
1611
+ throw new Error("Modal not found in collection with id of \"" + (query.id || query) + "\".");
714
1612
  }
715
1613
  }
716
- function handlerKeydown$2(event) {
717
- // Working catch
718
- if (this.working) return;
719
1614
 
720
- if (event.key === 'Escape') {
721
- var target = document.querySelector("." + this.settings.classModal + "." + this.settings.stateOpened);
1615
+ function getModalID(obj) {
1616
+ // If it's a string, return the string.
1617
+ if (typeof obj === 'string') {
1618
+ return obj;
1619
+ } // If it's an HTML element.
1620
+ else if (typeof obj.hasAttribute === 'function') {
1621
+ // If it's a modal open trigger, return data value.
1622
+ if (obj.hasAttribute("data-" + this.settings.dataOpen)) {
1623
+ return obj.getAttribute("data-" + this.settings.dataOpen);
1624
+ } // If it's a modal close trigger, return data value or false.
1625
+ else if (obj.hasAttribute("data-" + this.settings.dataClose)) {
1626
+ return obj.getAttribute("data-" + this.settings.dataClose) || false;
1627
+ } // If it's a modal replace trigger, return data value.
1628
+ else if (obj.hasAttribute("data-" + this.settings.dataReplace)) {
1629
+ return obj.getAttribute("data-" + this.settings.dataReplace);
1630
+ } // If it's a modal element, return the id.
1631
+ else if (obj.closest(this.settings.selectorModal)) {
1632
+ obj = obj.closest(this.settings.selectorModal);
1633
+ return obj.id || false;
1634
+ } // Return false if no id was found.
1635
+ else return false;
1636
+ } // If it has an id property, return its value.
1637
+ else if (obj.id) {
1638
+ return obj.id;
1639
+ } // Return false if no id was found.
1640
+ else return false;
1641
+ }
722
1642
 
723
- if (target) {
724
- this.close(target);
1643
+ function getModalElements(query) {
1644
+ var id = getModalID.call(this, query);
1645
+
1646
+ if (id) {
1647
+ var modal = document.querySelector("#" + id);
1648
+ var dialog = modal ? modal.querySelector(this.settings.selectorDialog) : null;
1649
+
1650
+ if (!modal && !dialog) {
1651
+ return {
1652
+ error: new Error("No modal elements found using the ID: \"" + id + "\".")
1653
+ };
1654
+ } else if (!dialog) {
1655
+ return {
1656
+ error: new Error('Modal is missing dialog element.')
1657
+ };
1658
+ } else {
1659
+ return {
1660
+ modal: modal,
1661
+ dialog: dialog
1662
+ };
725
1663
  }
1664
+ } else {
1665
+ return {
1666
+ error: new Error('Could not resolve the modal ID.')
1667
+ };
726
1668
  }
727
1669
  }
728
1670
 
729
- var open$2 = function open(drawerKey) {
730
- try {
731
- var _this2 = this;
1671
+ function updateFocusState() {
1672
+ // Check if there's an active modal
1673
+ if (this.active) {
1674
+ // Mount the focus trap on the active modal.
1675
+ this.focusTrap.mount(this.active.dialog, this.settings.selectorFocus);
1676
+ } else {
1677
+ // Set focus to root trigger and unmount the focus trap.
1678
+ if (this.trigger) {
1679
+ this.trigger.focus();
1680
+ this.trigger = null;
1681
+ }
732
1682
 
733
- var drawer = _this2.getDrawer(drawerKey);
1683
+ this.focusTrap.unmount();
1684
+ }
1685
+ }
734
1686
 
735
- if (!drawer) return Promise.resolve(drawerNotFound(drawerKey));
1687
+ function updateStackIndex(stack) {
1688
+ stack.forEach(function (entry, index) {
1689
+ entry.el.style.zIndex = null;
1690
+ var value = getComputedStyle(entry.el)['z-index'];
1691
+ entry.el.style.zIndex = parseInt(value) + index + 1;
1692
+ });
1693
+ }
736
1694
 
737
- if (!hasClass(drawer, _this2.settings.stateOpened)) {
738
- _this2.working = true;
739
- var isModal = hasClass(drawer, _this2.settings.classModal);
1695
+ var handleClick$1 = function handleClick(event) {
1696
+ try {
1697
+ var _this2 = this;
740
1698
 
741
- if (isModal) {
742
- setOverflowHidden(true, _this2.settings.selectorOverflow);
743
- }
1699
+ // If an open or replace button was clicked, open or replace the modal.
1700
+ var trigger = event.target.closest("[data-" + _this2.settings.dataOpen + "], [data-" + _this2.settings.dataReplace + "]");
744
1701
 
745
- return Promise.resolve(openTransition(drawer, _this2.settings)).then(function () {
746
- _this2.stateSave(drawer);
1702
+ if (trigger) {
1703
+ event.preventDefault(); // Save the trigger if it's not coming from inside a modal.
747
1704
 
748
- if (isModal) {
749
- _this2.focusTrap.init(drawer);
1705
+ var fromModal = event.target.closest(_this2.settings.selectorModal);
1706
+ if (!fromModal) _this2.trigger = trigger; // Get the modal.
750
1707
 
751
- setInert(true, _this2.settings.selectorInert);
752
- }
1708
+ var modal = _this2.get(getModalID.call(_this2, trigger)); // Depending on the button type, either open or replace the modal.
753
1709
 
754
- focusTarget(drawer, _this2.settings);
755
- drawer.dispatchEvent(new CustomEvent(_this2.settings.customEventPrefix + 'opened', {
756
- detail: _this2,
757
- bubbles: true
758
- }));
759
- _this2.working = false;
760
- return drawer;
761
- });
762
- } else {
763
- focusTarget(drawer, _this2.settings);
764
- return Promise.resolve(drawer);
765
- }
766
- } catch (e) {
767
- return Promise.reject(e);
768
- }
769
- };
770
1710
 
771
- function stateSet(settings) {
772
- // If save state is disabled
773
- if (!settings.stateSave) return stateClear(settings); // If there isn't an existing state to set
1711
+ return Promise.resolve(trigger.matches("[data-" + _this2.settings.dataOpen + "]") ? modal.open() : modal.replace());
1712
+ } // If a close button was clicked, close the modal.
774
1713
 
775
- var storageCheck = localStorage.getItem(settings.stateKey);
776
1714
 
777
- if (!storageCheck || storageCheck && Object.keys(JSON.parse(storageCheck)).length === 0) {
778
- return stateSave(null, settings);
779
- } // Set the existing state
1715
+ trigger = event.target.closest("[data-" + _this2.settings.dataClose + "]");
780
1716
 
1717
+ if (trigger) {
1718
+ event.preventDefault(); // Get the value of the data attribute.
781
1719
 
782
- var state = JSON.parse(localStorage.getItem(settings.stateKey));
783
- Object.keys(state).forEach(function (key) {
784
- var item = document.querySelector("[data-" + settings.dataDrawer + "=\"" + key + "\"]");
785
- if (!item) return;
786
- state[key] == settings.stateOpened ? addClass(item, settings.stateOpened) : removeClass(item, settings.stateOpened);
787
- });
788
- return state;
789
- }
790
- function stateSave(target, settings) {
791
- // If save state is disabled
792
- if (!settings.stateSave) return stateClear(settings); // Get the currently saved object if it exists
1720
+ var value = trigger.getAttribute("data-" + _this2.settings.dataClose); // Close all if * wildcard is passed, otherwise close a single modal.
793
1721
 
794
- var state = localStorage.getItem(settings.stateKey) ? JSON.parse(localStorage.getItem(settings.stateKey)) : {}; // Are we saving a single target or the entire suite?
1722
+ return Promise.resolve(value === '*' ? _this2.closeAll() : _this2.close(value));
1723
+ } // If the modal screen was clicked, close the modal.
795
1724
 
796
- var drawers = target ? [target] : document.querySelectorAll("[data-" + settings.dataDrawer + "]"); // Loop through drawers and save their states
797
1725
 
798
- drawers.forEach(function (el) {
799
- if (hasClass(el, settings.classModal)) return;
800
- var drawerKey = el.getAttribute("data-" + settings.dataDrawer);
801
- state[drawerKey] = hasClass(el, settings.stateOpened) ? settings.stateOpened : settings.stateClosed;
802
- }); // Save to localStorage and return the state
1726
+ if (event.target.matches(_this2.settings.selectorModal) && !event.target.querySelector(_this2.settings.selectorRequired)) {
1727
+ return Promise.resolve(_this2.close(getModalID.call(_this2, event.target)));
1728
+ }
803
1729
 
804
- localStorage.setItem(settings.stateKey, JSON.stringify(state));
805
- return state;
806
- }
807
- function stateClear(settings) {
808
- if (localStorage.getItem(settings.stateKey)) {
809
- localStorage.removeItem(settings.stateKey);
1730
+ return Promise.resolve();
1731
+ } catch (e) {
1732
+ return Promise.reject(e);
1733
+ }
1734
+ };
1735
+ function handleKeydown$1(event) {
1736
+ // If escape key was pressed.
1737
+ if (event.key === 'Escape') {
1738
+ // If a modal is opened and not required, close the modal.
1739
+ if (this.active && !this.active.dialog.matches(this.settings.selectorRequired)) {
1740
+ return this.close();
1741
+ }
810
1742
  }
811
-
812
- return {};
813
1743
  }
814
1744
 
815
- var switchToDefault = function switchToDefault(drawerKey) {
1745
+ var deregister$1 = function deregister(obj, close) {
1746
+ if (close === void 0) {
1747
+ close = true;
1748
+ }
1749
+
816
1750
  try {
817
- var _this4 = this;
1751
+ var _temp5 = function _temp5() {
1752
+ // Return the modified collection.
1753
+ return _this2.collection;
1754
+ };
818
1755
 
819
- // Initial guards
820
- var drawer = _this4.getDrawer(drawerKey);
1756
+ var _this2 = this;
821
1757
 
822
- if (!drawer) return Promise.resolve(drawerNotFound(drawerKey));
823
- if (!hasClass(drawer, _this4.settings.classModal)) return Promise.resolve(); // Tear down modal state
1758
+ // Return collection if nothing was passed.
1759
+ if (!obj) return Promise.resolve(_this2.collection); // Check if entry has been registered in the collection.
824
1760
 
825
- setInert(false, _this4.settings.selectorInert);
826
- setOverflowHidden(false, _this4.settings.selectorOverflow);
827
- removeClass(drawer, _this4.settings.classModal);
1761
+ var index = _this2.collection.findIndex(function (entry) {
1762
+ return entry.id === obj.id;
1763
+ });
828
1764
 
829
- _this4.focusTrap.destroy(); // Restore drawers saved state
1765
+ var _temp6 = function () {
1766
+ if (index >= 0) {
1767
+ var _temp7 = function _temp7() {
1768
+ // Return teleported modal if a reference has been set.
1769
+ if (_entry.getSetting('teleport')) {
1770
+ _entry.teleportReturn();
1771
+ } // Delete properties from collection entry.
830
1772
 
831
1773
 
832
- drawerKey = drawer.getAttribute("data-" + _this4.settings.dataDrawer);
833
- var drawerState = _this4.state[drawerKey];
1774
+ Object.getOwnPropertyNames(_entry).forEach(function (prop) {
1775
+ delete _entry[prop];
1776
+ }); // Remove entry from collection.
834
1777
 
835
- if (drawerState == _this4.settings.stateOpened) {
836
- addClass(drawer, _this4.settings.stateOpened);
837
- removeClass(drawer, _this4.settings.stateClosed);
838
- } // Dispatch custom event
1778
+ _this2.collection.splice(index, 1);
1779
+ };
839
1780
 
1781
+ // Get the collection entry.
1782
+ var _entry = _this2.collection[index]; // If entry is in the opened state, close it.
840
1783
 
841
- drawer.dispatchEvent(new CustomEvent(_this4.settings.customEventPrefix + 'toDefault', {
842
- bubbles: true
843
- }));
844
- return Promise.resolve(drawer);
845
- } catch (e) {
846
- return Promise.reject(e);
847
- }
848
- };
849
- var switchToModal = function switchToModal(drawerKey) {
850
- try {
851
- var _this2 = this;
1784
+ var _temp8 = function () {
1785
+ if (close && _entry.state === 'opened') {
1786
+ return Promise.resolve(_entry.close(false)).then(function () {});
1787
+ } else {
1788
+ // Get index of modal in stack array.
1789
+ var stackIndex = _this2.stack.findIndex(function (item) {
1790
+ return item.id === _entry.id;
1791
+ }); // Remove modal from stack array.
852
1792
 
853
- // Initial guards
854
- var drawer = _this2.getDrawer(drawerKey);
855
1793
 
856
- if (!drawer) return Promise.resolve(drawerNotFound(drawerKey));
857
- if (hasClass(drawer, _this2.settings.classModal)) return Promise.resolve(); // Enable modal state
1794
+ if (stackIndex >= 0) {
1795
+ _this2.stack.splice(stackIndex, 1);
1796
+ }
1797
+ }
1798
+ }();
858
1799
 
859
- addClass(drawer, _this2.settings.classModal);
860
- addClass(drawer, _this2.settings.stateClosed);
861
- removeClass(drawer, _this2.settings.stateOpened); // Dispatch custom event
1800
+ return _temp8 && _temp8.then ? _temp8.then(_temp7) : _temp7(_temp8);
1801
+ }
1802
+ }();
862
1803
 
863
- drawer.dispatchEvent(new CustomEvent(_this2.settings.customEventPrefix + 'toModal', {
864
- bubbles: true
865
- }));
866
- return Promise.resolve(drawer);
1804
+ return Promise.resolve(_temp6 && _temp6.then ? _temp6.then(_temp5) : _temp5(_temp6));
867
1805
  } catch (e) {
868
1806
  return Promise.reject(e);
869
1807
  }
870
1808
  };
871
1809
 
872
- var toggle = function toggle(drawerKey) {
1810
+ var open$1 = function open(query, transition, focus) {
1811
+ if (focus === void 0) {
1812
+ focus = true;
1813
+ }
1814
+
873
1815
  try {
874
- var _this2 = this;
1816
+ var _temp3 = function _temp3() {
1817
+ // Update focus if the focus param is true.
1818
+ if (focus) {
1819
+ updateFocusState.call(_this2);
1820
+ } // Dispatch custom opened event.
875
1821
 
876
- var drawer = _this2.getDrawer(drawerKey);
877
1822
 
878
- if (!drawer) return Promise.resolve(drawerNotFound(drawerKey));
879
- var isClosed = !hasClass(drawer, _this2.settings.stateOpened);
1823
+ modal.el.dispatchEvent(new CustomEvent(config.customEventPrefix + 'opened', {
1824
+ detail: _this2,
1825
+ bubbles: true
1826
+ })); // Return the modal.
880
1827
 
881
- if (isClosed) {
882
- return Promise.resolve(_this2.open(drawer));
883
- } else {
884
- return Promise.resolve(_this2.close(drawer));
885
- }
886
- } catch (e) {
887
- return Promise.reject(e);
888
- }
889
- };
1828
+ return modal;
1829
+ };
890
1830
 
891
- var Drawer = /*#__PURE__*/function () {
892
- function Drawer(options) {
893
- this.defaults = defaults$2;
894
- this.settings = _extends({}, this.defaults, options);
895
- this.working = false;
896
- this.memory = {};
897
- this.state = {};
898
- this.focusTrap = new FocusTrap();
899
- this.breakpoint = new Breakpoint(this);
900
- this.__handlerClick = handlerClick$2.bind(this);
901
- this.__handlerKeydown = handlerKeydown$2.bind(this);
902
- if (this.settings.autoInit) this.init();
903
- }
1831
+ var _this2 = this;
904
1832
 
905
- var _proto = Drawer.prototype;
1833
+ // Get the modal from collection.
1834
+ var modal = getModal.call(_this2, query); // Get the modal configuration.
906
1835
 
907
- _proto.init = function init(options) {
908
- if (options === void 0) {
909
- options = null;
910
- }
1836
+ var config = _extends({}, _this2.settings, modal.settings); // Add transition parameter to configuration.
911
1837
 
912
- if (options) this.settings = _extends({}, this.settings, options);
913
- this.stateSet();
914
1838
 
915
- if (this.settings.setTabindex) {
916
- this.setTabindex();
917
- }
1839
+ if (transition !== undefined) config.transition = transition; // Check if modal is already in the stack.
918
1840
 
919
- this.breakpoint.init();
1841
+ var index = _this2.stack.findIndex(function (entry) {
1842
+ return entry.id === modal.id;
1843
+ }); // If modal is already open.
920
1844
 
921
- if (this.settings.eventListeners) {
922
- this.initEventListeners();
923
- }
924
- };
925
1845
 
926
- _proto.destroy = function destroy() {
927
- this.breakpoint.destroy();
928
- this.memory = {};
929
- this.state = {};
930
- localStorage.removeItem(this.settings.stateKey);
1846
+ if (index >= 0) {
1847
+ // Remove modal from stack array.
1848
+ _this2.stack.splice(index, 1); // Move back to end of stack.
931
1849
 
932
- if (this.settings.eventListeners) {
933
- this.destroyEventListeners();
934
- }
935
- }
936
- /**
937
- * Event listeners
938
- */
939
- ;
940
1850
 
941
- _proto.initEventListeners = function initEventListeners() {
942
- document.addEventListener('click', this.__handlerClick, false);
943
- document.addEventListener('touchend', this.__handlerClick, false);
944
- document.addEventListener('keydown', this.__handlerKeydown, false);
945
- };
1851
+ _this2.stack.push(modal);
1852
+ } // If modal is closed.
946
1853
 
947
- _proto.destroyEventListeners = function destroyEventListeners() {
948
- document.removeEventListener('click', this.__handlerClick, false);
949
- document.removeEventListener('touchend', this.__handlerClick, false);
950
- document.removeEventListener('keydown', this.__handlerKeydown, false);
951
- }
952
- /**
953
- * Helpers
954
- */
955
- ;
956
1854
 
957
- _proto.getDrawer = function getDrawer$1(drawerKey) {
958
- return getDrawer.call(this, drawerKey);
959
- };
1855
+ var _temp4 = function () {
1856
+ if (modal.state === 'closed') {
1857
+ // Update modal state.
1858
+ modal.state = 'opening'; // Apply z-index styles based on stack length.
960
1859
 
961
- _proto.setTabindex = function setTabindex$1() {
962
- return setTabindex("\n [data-" + this.settings.dataDrawer + "]\n [data-" + this.settings.dataDialog + "]\n ");
963
- }
964
- /**
965
- * Save state functionality
966
- */
967
- ;
1860
+ modal.el.style.zIndex = null;
1861
+ var value = getComputedStyle(modal.el)['z-index'];
1862
+ modal.el.style.zIndex = parseInt(value) + _this2.stack.length + 1; // Store modal in stack array.
968
1863
 
969
- _proto.stateSet = function stateSet$1() {
970
- this.state = stateSet(this.settings);
971
- };
1864
+ _this2.stack.push(modal); // Run the open transition.
972
1865
 
973
- _proto.stateSave = function stateSave$1(target) {
974
- if (target === void 0) {
975
- target = null;
976
- }
977
1866
 
978
- this.state = stateSave(target, this.settings);
979
- };
1867
+ return Promise.resolve(openTransition(modal.el, config)).then(function () {
1868
+ // Update modal state.
1869
+ modal.state = 'opened';
1870
+ });
1871
+ }
1872
+ }();
980
1873
 
981
- _proto.stateClear = function stateClear$1() {
982
- this.state = stateClear(this.settings);
1874
+ return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(_temp3) : _temp3(_temp4));
1875
+ } catch (e) {
1876
+ return Promise.reject(e);
983
1877
  }
984
- /**
985
- * SwitchTo functionality
986
- */
987
- ;
988
-
989
- _proto.switchToDefault = function switchToDefault$1(drawerKey) {
990
- return switchToDefault.call(this, drawerKey);
991
- };
1878
+ };
992
1879
 
993
- _proto.switchToModal = function switchToModal$1(drawerKey) {
994
- return switchToModal.call(this, drawerKey);
1880
+ var close$1 = function close(query, transition, focus) {
1881
+ if (focus === void 0) {
1882
+ focus = true;
995
1883
  }
996
- /**
997
- * Change state functionality
998
- */
999
- ;
1000
1884
 
1001
- _proto.toggle = function toggle$1(drawerKey) {
1002
- return toggle.call(this, drawerKey);
1003
- };
1885
+ try {
1886
+ var _this2 = this;
1004
1887
 
1005
- _proto.open = function open(drawerKey) {
1006
- return open$2.call(this, drawerKey);
1007
- };
1888
+ // Get the modal from collection, or top modal in stack if no query is provided.
1889
+ var modal = query ? getModal.call(_this2, query) : _this2.active; // If a modal exists and its state is opened.
1008
1890
 
1009
- _proto.close = function close(drawerKey) {
1010
- return close$2.call(this, drawerKey);
1011
- };
1891
+ var _temp2 = function () {
1892
+ if (modal && modal.state === 'opened') {
1893
+ // Update modal state.
1894
+ modal.state = 'closing'; // Get the modal configuration.
1012
1895
 
1013
- return Drawer;
1014
- }();
1896
+ var config = _extends({}, _this2.settings, modal.settings); // Add transition parameter to configuration.
1015
1897
 
1016
- var defaults$1 = {
1017
- autoInit: false,
1018
- // Data attributes
1019
- dataModal: 'modal',
1020
- dataDialog: 'modal-dialog',
1021
- dataOpen: 'modal-open',
1022
- dataClose: 'modal-close',
1023
- dataFocus: 'modal-focus',
1024
- dataRequired: 'modal-required',
1025
- dataConfig: 'modal-config',
1026
- // State classes
1027
- stateOpened: 'is-opened',
1028
- stateOpening: 'is-opening',
1029
- stateClosing: 'is-closing',
1030
- stateClosed: 'is-closed',
1031
- // Selector
1032
- selectorInert: null,
1033
- selectorOverflow: 'body',
1034
- // Feature toggles
1035
- customEventPrefix: 'modal:',
1036
- eventListeners: true,
1037
- moveModals: {
1038
- ref: null,
1039
- type: null
1040
- },
1041
- setTabindex: true,
1042
- transition: true
1043
- };
1044
1898
 
1045
- function getModalConfig(modal) {
1046
- var json = modal.getAttribute("data-" + this.settings.dataConfig);
1899
+ if (transition !== undefined) config.transition = transition; // Remove focus from active element.
1047
1900
 
1048
- if (json) {
1049
- var config = JSON.parse(json);
1050
- return _extends({}, this.settings, config);
1051
- } else {
1052
- return this.settings;
1053
- }
1054
- }
1055
- function getModal(modalKey) {
1056
- if (typeof modalKey !== 'string') return modalKey;
1057
- return document.querySelector("[data-" + this.settings.dataModal + "=\"" + modalKey + "\"]");
1058
- }
1059
- function modalNotFound(key) {
1060
- return Promise.reject(new Error("Did not find modal with key: \"" + key + "\""));
1061
- }
1062
- function moveModals(type, ref) {
1063
- if (type === void 0) {
1064
- type = this.settings.moveModals.type;
1065
- }
1901
+ document.activeElement.blur(); // Run the close transition.
1066
1902
 
1067
- if (ref === void 0) {
1068
- ref = this.settings.moveModals.ref;
1069
- }
1903
+ return Promise.resolve(closeTransition(modal.el, config)).then(function () {
1904
+ // Remove z-index styles.
1905
+ modal.el.style.zIndex = null; // Get index of modal in stack array.
1070
1906
 
1071
- var modals = document.querySelectorAll("[data-" + this.settings.dataModal + "]");
1072
- if (modals.length) moveElement(modals, type, ref);
1073
- }
1907
+ var index = _this2.stack.findIndex(function (entry) {
1908
+ return entry.id === modal.id;
1909
+ }); // Remove modal from stack array.
1074
1910
 
1075
- var close$1 = function close(returnFocus) {
1076
- if (returnFocus === void 0) {
1077
- returnFocus = true;
1078
- }
1079
1911
 
1080
- try {
1081
- var _this2 = this;
1912
+ _this2.stack.splice(index, 1); // Update focus if the focus param is true.
1082
1913
 
1083
- var modal = document.querySelector("[data-" + _this2.settings.dataModal + "]." + _this2.settings.stateOpened);
1084
1914
 
1085
- if (modal) {
1086
- _this2.working = true;
1087
- var config = getModalConfig.call(_this2, modal);
1088
- setInert(false, config.selectorInert);
1089
- setOverflowHidden(false, config.selectorOverflow);
1090
- return Promise.resolve(closeTransition(modal, config)).then(function () {
1091
- if (returnFocus) focusTrigger(_this2);
1915
+ if (focus) {
1916
+ updateFocusState.call(_this2);
1917
+ } // Update modal state.
1092
1918
 
1093
- _this2.focusTrap.destroy();
1094
1919
 
1095
- modal.dispatchEvent(new CustomEvent(config.customEventPrefix + 'closed', {
1096
- detail: _this2,
1097
- bubbles: true
1098
- }));
1099
- _this2.working = false;
1100
- return modal;
1101
- });
1102
- } else {
1103
- return Promise.resolve(modal);
1104
- }
1920
+ modal.state = 'closed'; // Dispatch custom closed event.
1921
+
1922
+ modal.el.dispatchEvent(new CustomEvent(config.customEventPrefix + 'closed', {
1923
+ detail: _this2,
1924
+ bubbles: true
1925
+ }));
1926
+ });
1927
+ }
1928
+ }();
1929
+
1930
+ return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {
1931
+ // Return the modal.
1932
+ return modal;
1933
+ }) : modal);
1105
1934
  } catch (e) {
1106
1935
  return Promise.reject(e);
1107
1936
  }
1108
1937
  };
1109
1938
 
1110
- var handlerClick$1 = function handlerClick(event) {
1939
+ var closeAll$1 = function closeAll(exclude, transition) {
1111
1940
  try {
1112
- var _temp3 = function _temp3(_result) {
1113
- if (_exit2) return _result;
1941
+ var _this2 = this;
1942
+
1943
+ var result = [];
1944
+ return Promise.resolve(Promise.all(_this2.stack.map(function (modal) {
1945
+ try {
1946
+ var _temp3 = function _temp3() {
1947
+ modal.trigger = null;
1948
+ };
1949
+
1950
+ var _temp4 = function () {
1951
+ if (exclude && exclude === modal.id) {
1952
+ Promise.resolve();
1953
+ } else {
1954
+ var _push2 = result.push;
1955
+ return Promise.resolve(close$1.call(_this2, modal, transition, false)).then(function (_close$call) {
1956
+ _push2.call(result, _close$call);
1957
+ });
1958
+ }
1959
+ }();
1114
1960
 
1115
- // Close click
1116
- if (event.target.closest("[data-" + _this2.settings.dataClose + "]")) {
1117
- event.preventDefault();
1961
+ return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(_temp3) : _temp3(_temp4));
1962
+ } catch (e) {
1963
+ return Promise.reject(e);
1964
+ }
1965
+ }))).then(function () {
1966
+ return result;
1967
+ });
1968
+ } catch (e) {
1969
+ return Promise.reject(e);
1970
+ }
1971
+ };
1118
1972
 
1119
- _this2.close();
1973
+ var replace = function replace(query, transition, focus) {
1974
+ if (focus === void 0) {
1975
+ focus = true;
1976
+ }
1120
1977
 
1121
- return;
1122
- } // Root click
1978
+ try {
1979
+ var _temp3 = function _temp3() {
1980
+ // Update focus if the focus param is true.
1981
+ if (focus) {
1982
+ updateFocusState.call(_this2);
1983
+ } // Return the modals there were opened and closed.
1123
1984
 
1124
1985
 
1125
- if (event.target.hasAttribute("data-" + _this2.settings.dataModal) && !event.target.hasAttribute("data-" + _this2.settings.dataRequired)) {
1126
- _this2.close();
1127
- }
1986
+ return {
1987
+ opened: resultOpened,
1988
+ closed: resultClosed
1989
+ };
1128
1990
  };
1129
1991
 
1130
- var _exit2;
1131
-
1132
1992
  var _this2 = this;
1133
1993
 
1134
- // Working catch
1135
- if (_this2.working) return Promise.resolve(); // Trigger click
1994
+ // Get the modal from collection.
1995
+ var modal = getModal.call(_this2, query); // Setup results for return.
1136
1996
 
1137
- var trigger = event.target.closest("[data-" + _this2.settings.dataOpen + "]");
1997
+ var resultOpened, resultClosed;
1138
1998
 
1139
1999
  var _temp4 = function () {
1140
- if (trigger) {
1141
- event.preventDefault();
1142
- var modalKey = trigger.getAttribute("data-" + _this2.settings.dataOpen);
1143
- var fromModal = event.target.closest("[data-" + _this2.settings.dataModal + "]");
1144
- if (!fromModal) _this2.memory.trigger = trigger;
1145
- return Promise.resolve(_this2.close(!fromModal)).then(function () {
1146
- _this2.open(modalKey);
1147
-
1148
- _exit2 = 1;
2000
+ if (modal.state === 'opened') {
2001
+ // If modal is open, close all modals except for replacement.
2002
+ resultOpened = modal;
2003
+ return Promise.resolve(closeAll$1.call(_this2, modal.id, transition)).then(function (_closeAll$call) {
2004
+ resultClosed = _closeAll$call;
1149
2005
  });
2006
+ } else {
2007
+ // If modal is closed, close all and open replacement at the same time.
2008
+ resultOpened = open$1.call(_this2, modal, transition, false);
2009
+ resultClosed = closeAll$1.call(_this2, false, transition);
2010
+ return Promise.resolve(Promise.all([resultOpened, resultClosed])).then(function () {});
1150
2011
  }
1151
2012
  }();
1152
2013
 
@@ -1155,343 +2016,285 @@ var handlerClick$1 = function handlerClick(event) {
1155
2016
  return Promise.reject(e);
1156
2017
  }
1157
2018
  };
1158
- function handlerKeydown$1(event) {
1159
- // Working catch
1160
- if (this.working) return;
1161
-
1162
- if (event.key === 'Escape') {
1163
- var target = document.querySelector("[data-" + this.settings.dataModal + "]." + this.settings.stateOpened);
1164
2019
 
1165
- if (target && !target.hasAttribute("data-" + this.settings.dataRequired)) {
1166
- this.close();
1167
- }
1168
- }
1169
- }
2020
+ var register$1 = function register(el, dialog) {
2021
+ try {
2022
+ var _this2 = this;
1170
2023
 
1171
- function setInitialState() {
1172
- var _this = this;
2024
+ // Deregister entry incase it has already been registered.
2025
+ return Promise.resolve(deregister$1.call(_this2, el, false)).then(function () {
2026
+ // Save root this for use inside methods API.
2027
+ var root = _this2; // Setup methods API.
2028
+
2029
+ var methods = {
2030
+ open: function open(transition, focus) {
2031
+ return open$1.call(root, this, transition, focus);
2032
+ },
2033
+ close: function close(transition, focus) {
2034
+ return close$1.call(root, this, transition, focus);
2035
+ },
2036
+ replace: function replace$1(transition, focus) {
2037
+ return replace.call(root, this, transition, focus);
2038
+ },
2039
+ deregister: function deregister() {
2040
+ return deregister$1.call(root, this);
2041
+ },
2042
+ teleport: function teleport$1(ref, method) {
2043
+ if (ref === void 0) {
2044
+ ref = this.getSetting('teleport');
2045
+ }
1173
2046
 
1174
- var modals = document.querySelectorAll("[data-" + this.settings.dataModal + "]");
1175
- modals.forEach(function (el) {
1176
- // Remove opened state setup
1177
- if (el.classList.contains(_this.settings.stateOpened)) {
1178
- setInert(false, _this.settings.selectorInert);
1179
- setOverflowHidden(false, _this.settings.selectorOverflow);
1180
- focusTrigger(_this);
2047
+ if (method === void 0) {
2048
+ method = this.getSetting('teleportMethod');
2049
+ }
1181
2050
 
1182
- _this.focusTrap.destroy();
1183
- } // Remove all state classes and add the default state (closed)
2051
+ if (!this.returnRef) {
2052
+ this.returnRef = teleport(this.el, ref, method);
2053
+ return this.el;
2054
+ } else {
2055
+ console.error('Element has already been teleported:', this.el);
2056
+ return false;
2057
+ }
2058
+ },
2059
+ teleportReturn: function teleportReturn() {
2060
+ if (this.returnRef) {
2061
+ this.returnRef = teleport(this.el, this.returnRef);
2062
+ return this.el;
2063
+ } else {
2064
+ console.error('No return reference found:', this.el);
2065
+ return false;
2066
+ }
2067
+ },
2068
+ getSetting: function getSetting(key) {
2069
+ return key in this.settings ? this.settings[key] : root.settings[key];
2070
+ }
2071
+ }; // Setup the modal object.
1184
2072
 
2073
+ var entry = _extends({
2074
+ id: el.id,
2075
+ state: 'closed',
2076
+ el: el,
2077
+ dialog: dialog,
2078
+ returnRef: null,
2079
+ settings: getConfig$1(el, _this2.settings.dataConfig)
2080
+ }, methods); // Set aria-modal attribute to true.
1185
2081
 
1186
- removeClass(el, _this.settings.stateOpened, _this.settings.stateOpening, _this.settings.stateClosing);
1187
- addClass(el, _this.settings.stateClosed);
1188
- });
1189
- }
1190
2082
 
1191
- var open$1 = function open(modalKey) {
1192
- try {
1193
- var _this2 = this;
2083
+ entry.dialog.setAttribute('aria-modal', 'true'); // If a role attribute is not set, set it to "dialog" as the default.
1194
2084
 
1195
- var modal = getModal.call(_this2, modalKey);
1196
- if (!modal) return Promise.resolve(modalNotFound(modalKey));
1197
- var config = getModalConfig.call(_this2, modal);
1198
-
1199
- if (hasClass(modal, config.stateClosed)) {
1200
- _this2.working = true;
1201
- setOverflowHidden(true, config.selectorOverflow);
1202
- return Promise.resolve(openTransition(modal, config)).then(function () {
1203
- _this2.focusTrap.init(modal);
1204
-
1205
- focusTarget(modal, config);
1206
- setInert(true, config.selectorInert);
1207
- modal.dispatchEvent(new CustomEvent(config.customEventPrefix + 'opened', {
1208
- detail: _this2,
1209
- bubbles: true
1210
- }));
1211
- _this2.working = false;
1212
- return modal;
1213
- });
1214
- } else {
1215
- return Promise.resolve(modal);
1216
- }
1217
- } catch (e) {
1218
- return Promise.reject(e);
1219
- }
1220
- };
2085
+ if (!entry.dialog.hasAttribute('role')) {
2086
+ entry.dialog.setAttribute('role', 'dialog');
2087
+ } // Set tabindex="-1" so dialog is focusable via JS or click.
1221
2088
 
1222
- var Modal = /*#__PURE__*/function () {
1223
- function Modal(options) {
1224
- this.defaults = defaults$1;
1225
- this.settings = _extends({}, this.defaults, options);
1226
- this.working = false;
1227
- this.memory = {};
1228
- this.focusTrap = new FocusTrap();
1229
- this.__handlerClick = handlerClick$1.bind(this);
1230
- this.__handlerKeydown = handlerKeydown$1.bind(this);
1231
- if (this.settings.autoInit) this.init();
1232
- }
1233
2089
 
1234
- var _proto = Modal.prototype;
2090
+ if (entry.getSetting('setTabindex')) {
2091
+ entry.dialog.setAttribute('tabindex', '-1');
2092
+ } // Teleport modal if a reference has been set.
1235
2093
 
1236
- _proto.init = function init(options) {
1237
- if (options === void 0) {
1238
- options = null;
1239
- }
1240
2094
 
1241
- if (options) this.settings = _extends({}, this.settings, options);
1242
- this.moveModals();
1243
- this.setInitialState();
2095
+ if (entry.getSetting('teleport')) {
2096
+ entry.teleport();
2097
+ } // Add entry to collection.
1244
2098
 
1245
- if (this.settings.setTabindex) {
1246
- this.setTabindex();
1247
- }
1248
2099
 
1249
- if (this.settings.eventListeners) {
1250
- this.initEventListeners();
1251
- }
1252
- };
2100
+ _this2.collection.push(entry); // Setup initial state.
1253
2101
 
1254
- _proto.destroy = function destroy() {
1255
- this.memory = {};
1256
2102
 
1257
- if (this.settings.eventListeners) {
1258
- this.destroyEventListeners();
1259
- }
1260
- }
1261
- /**
1262
- * Event listeners
1263
- */
1264
- ;
2103
+ var _temp = function () {
2104
+ if (entry.el.classList.contains(_this2.settings.stateOpened)) {
2105
+ // Open entry with transitions disabled.
2106
+ return Promise.resolve(entry.open(false)).then(function () {});
2107
+ } else {
2108
+ // Remove transition state classes.
2109
+ entry.el.classList.remove(_this2.settings.stateOpening);
2110
+ entry.el.classList.remove(_this2.settings.stateClosing); // Add closed state class.
1265
2111
 
1266
- _proto.initEventListeners = function initEventListeners() {
1267
- document.addEventListener('click', this.__handlerClick, false);
1268
- document.addEventListener('touchend', this.__handlerClick, false);
1269
- document.addEventListener('keydown', this.__handlerKeydown, false);
1270
- };
2112
+ entry.el.classList.add(_this2.settings.stateClosed);
2113
+ }
2114
+ }();
1271
2115
 
1272
- _proto.destroyEventListeners = function destroyEventListeners() {
1273
- document.removeEventListener('click', this.__handlerClick, false);
1274
- document.removeEventListener('touchend', this.__handlerClick, false);
1275
- document.removeEventListener('keydown', this.__handlerKeydown, false);
2116
+ return _temp && _temp.then ? _temp.then(function () {
2117
+ // Return the registered entry.
2118
+ return entry;
2119
+ }) : entry;
2120
+ });
2121
+ } catch (e) {
2122
+ return Promise.reject(e);
1276
2123
  }
1277
- /**
1278
- * Helpers
1279
- */
1280
- ;
2124
+ };
1281
2125
 
1282
- _proto.getModal = function getModal$1(modalKey) {
1283
- return getModal.call(this, modalKey);
1284
- };
2126
+ var _handleClick = /*#__PURE__*/_classPrivateFieldLooseKey("handleClick");
1285
2127
 
1286
- _proto.setTabindex = function setTabindex$1() {
1287
- return setTabindex("\n [data-" + this.settings.dataModal + "]\n [data-" + this.settings.dataDialog + "]\n ");
1288
- };
2128
+ var _handleKeydown$1 = /*#__PURE__*/_classPrivateFieldLooseKey("handleKeydown");
1289
2129
 
1290
- _proto.setInitialState = function setInitialState$1() {
1291
- return setInitialState.call(this);
1292
- };
2130
+ var Modal = /*#__PURE__*/function (_Collection) {
2131
+ _inheritsLoose(Modal, _Collection);
1293
2132
 
1294
- _proto.moveModals = function moveModals$1(type, ref) {
1295
- return moveModals.call(this, type, ref);
1296
- }
1297
- /**
1298
- * Change state functionality
1299
- */
1300
- ;
2133
+ function Modal(options) {
2134
+ var _this;
1301
2135
 
1302
- _proto.open = function open(modalKey) {
1303
- return open$1.call(this, modalKey);
1304
- };
2136
+ _this = _Collection.call(this) || this;
2137
+ Object.defineProperty(_assertThisInitialized(_this), _handleClick, {
2138
+ writable: true,
2139
+ value: void 0
2140
+ });
2141
+ Object.defineProperty(_assertThisInitialized(_this), _handleKeydown$1, {
2142
+ writable: true,
2143
+ value: void 0
2144
+ });
2145
+ _this.defaults = defaults$1;
2146
+ _this.settings = _extends({}, _this.defaults, options);
2147
+ _this.trigger = null;
2148
+ _this.focusTrap = new FocusTrap(); // Setup a proxy for stack array.
2149
+
2150
+ _this.stack = new Proxy([], {
2151
+ set: function set(target, property, value) {
2152
+ target[property] = value; // Update global state if stack length changed.
2153
+
2154
+ if (property === 'length') {
2155
+ updateGlobalState(_this.active, _this.settings);
2156
+ updateStackIndex(_this.stack);
2157
+ }
1305
2158
 
1306
- _proto.close = function close(returnFocus) {
1307
- return close$1.call(this, returnFocus);
1308
- };
2159
+ return true;
2160
+ }
2161
+ });
2162
+ _classPrivateFieldLooseBase(_assertThisInitialized(_this), _handleClick)[_handleClick] = handleClick$1.bind(_assertThisInitialized(_this));
2163
+ _classPrivateFieldLooseBase(_assertThisInitialized(_this), _handleKeydown$1)[_handleKeydown$1] = handleKeydown$1.bind(_assertThisInitialized(_this));
2164
+ if (_this.settings.autoInit) _this.init();
2165
+ return _this;
2166
+ }
1309
2167
 
1310
- return Modal;
1311
- }();
2168
+ var _proto = Modal.prototype;
1312
2169
 
1313
- var Collection = /*#__PURE__*/function () {
1314
- function Collection() {
1315
- this.collection = [];
1316
- }
2170
+ _proto.init = function init(options) {
2171
+ try {
2172
+ var _this3 = this;
1317
2173
 
1318
- var _proto = Collection.prototype;
2174
+ // Update settings with passed options.
2175
+ if (options) _this3.settings = _extends({}, _this3.settings, options); // Get all the modals.
1319
2176
 
1320
- _proto.register = function register(item) {
1321
- this.deregister(item);
1322
- this.collection.push(item);
1323
- return this.collection;
1324
- };
2177
+ var modals = document.querySelectorAll(_this3.settings.selectorModal); // Register the collections array with modal instances.
1325
2178
 
1326
- _proto.deregister = function deregister(ref) {
1327
- var index = this.collection.findIndex(function (entry) {
1328
- return entry === ref;
1329
- });
2179
+ return Promise.resolve(_this3.registerCollection(modals)).then(function () {
2180
+ // If eventListeners are enabled, init event listeners.
2181
+ if (_this3.settings.eventListeners) {
2182
+ _this3.initEventListeners();
2183
+ }
1330
2184
 
1331
- if (index >= 0) {
1332
- var entry = this.collection[index];
1333
- Object.getOwnPropertyNames(entry).forEach(function (prop) {
1334
- delete entry[prop];
2185
+ return _this3;
1335
2186
  });
1336
- this.collection.splice(index, 1);
2187
+ } catch (e) {
2188
+ return Promise.reject(e);
1337
2189
  }
1338
-
1339
- return this.collection;
1340
2190
  };
1341
2191
 
1342
- _proto.registerCollection = function registerCollection(items) {
1343
- var _this = this;
1344
-
1345
- items.forEach(function (item) {
1346
- _this.register(item);
1347
- });
1348
- return this.collection;
1349
- };
2192
+ _proto.destroy = function destroy() {
2193
+ try {
2194
+ var _this5 = this;
1350
2195
 
1351
- _proto.deregisterCollection = function deregisterCollection() {
1352
- while (this.collection.length > 0) {
1353
- this.deregister(this.collection[0]);
1354
- }
2196
+ // Clear stored trigger.
2197
+ _this5.trigger = null; // Remove all entries from the collection.
1355
2198
 
1356
- return this.collection;
1357
- };
2199
+ return Promise.resolve(_this5.deregisterCollection()).then(function () {
2200
+ // If eventListeners are enabled, destroy event listeners.
2201
+ if (_this5.settings.eventListeners) {
2202
+ _this5.destroyEventListeners();
2203
+ }
1358
2204
 
1359
- _proto.get = function get(query, key) {
1360
- if (key === void 0) {
1361
- key = 'id';
2205
+ return _this5;
2206
+ });
2207
+ } catch (e) {
2208
+ return Promise.reject(e);
1362
2209
  }
1363
-
1364
- var result = this.collection.find(function (item) {
1365
- return item[key] === query;
1366
- });
1367
- return result || null;
1368
2210
  };
1369
2211
 
1370
- return Collection;
1371
- }();
1372
-
1373
- var defaults = {
1374
- autoInit: false,
1375
- // Selectors
1376
- selectorPopover: '.popover',
1377
- selectorArrow: '.popover__arrow',
1378
- // State classes
1379
- stateActive: 'is-active',
1380
- // Feature toggles
1381
- eventListeners: true,
1382
- eventType: 'click',
1383
- placement: 'bottom'
1384
- };
1385
-
1386
- function close(popover) {
1387
- // Update state class
1388
- popover.target.classList.remove(this.settings.stateActive); // Update a11y attributes
1389
-
1390
- if (popover.trigger.hasAttribute('aria-controls')) {
1391
- popover.trigger.setAttribute('aria-expanded', 'false');
1392
- } // Disable popper event listeners
1393
-
1394
-
1395
- popover.popper.setOptions({
1396
- modifiers: [{
1397
- name: 'eventListeners',
1398
- enabled: false
1399
- }]
1400
- }); // Update popover state
1401
-
1402
- popover.state = 'closed'; // Clear memory if popover trigger matches the one saved in memory
1403
-
1404
- if (popover.trigger === this.memory.trigger) {
1405
- this.memory.trigger = null;
1406
- } // Return the popover
1407
-
1408
-
1409
- return popover;
1410
- }
1411
- function closeAll() {
1412
- this.collection.forEach(function (popover) {
1413
- if (popover.state === 'opened') {
1414
- popover.close();
1415
- }
1416
- }); // Return the collection
2212
+ _proto.initEventListeners = function initEventListeners() {
2213
+ document.addEventListener('click', _classPrivateFieldLooseBase(this, _handleClick)[_handleClick], false);
2214
+ document.addEventListener('touchend', _classPrivateFieldLooseBase(this, _handleClick)[_handleClick], false);
2215
+ document.addEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown$1)[_handleKeydown$1], false);
2216
+ };
1417
2217
 
1418
- return this.collection;
1419
- }
1420
- function closeCheck(popover) {
1421
- // Only run closeCheck if provided popover is currently open
1422
- if (popover.state != 'opened') return; // Needed to correctly check which element is currently being focused
2218
+ _proto.destroyEventListeners = function destroyEventListeners() {
2219
+ document.removeEventListener('click', _classPrivateFieldLooseBase(this, _handleClick)[_handleClick], false);
2220
+ document.removeEventListener('touchend', _classPrivateFieldLooseBase(this, _handleClick)[_handleClick], false);
2221
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown$1)[_handleKeydown$1], false);
2222
+ };
1423
2223
 
1424
- setTimeout(function () {
1425
- // Check if trigger or target are being hovered
1426
- var isHovered = popover.target.closest(':hover') === popover.target || popover.trigger.closest(':hover') === popover.trigger; // Check if trigger or target are being focused
2224
+ _proto.register = function register(query) {
2225
+ var els = getModalElements.call(this, query);
2226
+ if (els.error) return Promise.reject(els.error);
2227
+ return register$1.call(this, els.modal, els.dialog);
2228
+ };
1427
2229
 
1428
- var isFocused = document.activeElement.closest("#" + popover.id + ", [aria-controls=\"" + popover.id + "\"]"); // Close if the trigger and target are not currently hovered or focused
2230
+ _proto.deregister = function deregister(query) {
2231
+ var modal = this.get(getModalID.call(this, query));
2232
+ return deregister$1.call(this, modal);
2233
+ };
1429
2234
 
1430
- if (!isHovered && !isFocused) {
1431
- popover.close();
1432
- } // Return the popover
2235
+ _proto.open = function open(id, transition, focus) {
2236
+ return open$1.call(this, id, transition, focus);
2237
+ };
1433
2238
 
2239
+ _proto.close = function close(id, transition, focus) {
2240
+ return close$1.call(this, id, transition, focus);
2241
+ };
1434
2242
 
1435
- return popover;
1436
- }, 1);
1437
- }
2243
+ _proto.replace = function replace$1(id, transition, focus) {
2244
+ return replace.call(this, id, transition, focus);
2245
+ };
1438
2246
 
1439
- function handlerClick(popover) {
1440
- if (popover.target.classList.contains(this.settings.stateActive)) {
1441
- popover.close();
1442
- } else {
1443
- this.memory.trigger = popover.trigger;
1444
- popover.open();
1445
- documentClick.call(this, popover);
1446
- }
1447
- }
1448
- function handlerKeydown(event) {
1449
- var _this = this;
2247
+ _proto.closeAll = function closeAll(exclude, transition, focus) {
2248
+ if (exclude === void 0) {
2249
+ exclude = false;
2250
+ }
1450
2251
 
1451
- switch (event.key) {
1452
- case 'Escape':
1453
- if (this.memory.trigger) {
1454
- this.memory.trigger.focus();
1455
- }
2252
+ if (focus === void 0) {
2253
+ focus = true;
2254
+ }
1456
2255
 
1457
- closeAll.call(this);
1458
- return;
2256
+ try {
2257
+ var _this7 = this;
1459
2258
 
1460
- case 'Tab':
1461
- this.collection.forEach(function (popover) {
1462
- closeCheck.call(_this, popover);
2259
+ return Promise.resolve(closeAll$1.call(_this7, exclude, transition)).then(function (result) {
2260
+ // Update focus if the focus param is true.
2261
+ if (focus) {
2262
+ updateFocusState.call(_this7);
2263
+ }
2264
+
2265
+ return result;
1463
2266
  });
1464
- return;
2267
+ } catch (e) {
2268
+ return Promise.reject(e);
2269
+ }
2270
+ };
1465
2271
 
1466
- default:
1467
- return;
1468
- }
1469
- }
1470
- function documentClick(popover) {
1471
- var root = this;
1472
- document.addEventListener('click', function _f(event) {
1473
- // Check if a popover was clicked
1474
- var result = event.target.closest("#" + popover.id + ", [aria-controls=\"" + popover.id + "\"]");
2272
+ _createClass(Modal, [{
2273
+ key: "active",
2274
+ get: function get() {
2275
+ return this.stack[this.stack.length - 1];
2276
+ }
2277
+ }]);
1475
2278
 
1476
- if (!result) {
1477
- // If it doesn't match and popover is open, close it and remove event listener
1478
- if (popover.target && popover.target.classList.contains(root.settings.stateActive)) {
1479
- popover.close();
1480
- }
2279
+ return Modal;
2280
+ }(Collection);
1481
2281
 
1482
- this.removeEventListener('click', _f);
1483
- } else {
1484
- // If it does match and popover isn't currently active, remove event listener
1485
- if (popover.target && !popover.target.classList.contains(root.settings.stateActive)) {
1486
- this.removeEventListener('click', _f);
1487
- }
1488
- }
1489
- });
1490
- }
2282
+ var defaults = {
2283
+ autoInit: false,
2284
+ // Selectors
2285
+ selectorPopover: '.popover',
2286
+ selectorArrow: '.popover__arrow',
2287
+ // State classes
2288
+ stateActive: 'is-active',
2289
+ // Feature settings
2290
+ eventListeners: true,
2291
+ eventType: 'click',
2292
+ placement: 'bottom'
2293
+ };
1491
2294
 
1492
2295
  function getConfig(el, settings) {
1493
- // Get the computed styles of the popover
1494
- var styles = getComputedStyle(el); // Setup the config obj with default values
2296
+ // Get the computed styles of the element.
2297
+ var styles = getComputedStyle(el); // Setup the config obj with default values.
1495
2298
 
1496
2299
  var config = {
1497
2300
  'placement': settings.placement,
@@ -1501,29 +2304,30 @@ function getConfig(el, settings) {
1501
2304
  'flip-padding': 0,
1502
2305
  'arrow-element': settings.selectorArrow,
1503
2306
  'arrow-padding': 0
1504
- }; // Loop through config obj
2307
+ }; // Loop through config obj.
1505
2308
 
1506
2309
  for (var prop in config) {
1507
- // Get the CSS variable property values
1508
- var prefix = getComputedStyle(document.body).getPropertyValue('--vrembem-variable-prefix');
1509
- var value = styles.getPropertyValue("--" + prefix + "popover-" + prop).trim(); // If a value was found, replace the default in config obj
2310
+ // Get the CSS variable property values.
2311
+ var prefix = L();
2312
+ var value = styles.getPropertyValue("--" + prefix + "popover-" + prop).trim(); // If a value was found, replace the default in config obj.
1510
2313
 
1511
2314
  if (value) {
1512
2315
  config[prop] = value;
1513
2316
  }
1514
- } // Return the config obj
2317
+ } // Return the config obj.
1515
2318
 
1516
2319
 
1517
2320
  return config;
1518
2321
  }
2322
+
1519
2323
  function getPadding(value) {
1520
- var padding; // Split the value by spaces if it's a string
2324
+ var padding; // Split the value by spaces if it's a string.
1521
2325
 
1522
- var array = typeof value === 'string' ? value.trim().split(' ') : [value]; // Convert individual values to integers
2326
+ var array = typeof value === 'string' ? value.trim().split(' ') : [value]; // Convert individual values to integers.
1523
2327
 
1524
2328
  array.forEach(function (item, index) {
1525
2329
  array[index] = parseInt(item, 10);
1526
- }); // Build the padding object based on the number of values passed
2330
+ }); // Build the padding object based on the number of values passed.
1527
2331
 
1528
2332
  switch (array.length) {
1529
2333
  case 1:
@@ -1560,11 +2364,12 @@ function getPadding(value) {
1560
2364
  default:
1561
2365
  padding = false;
1562
2366
  break;
1563
- } // Return the padding object
2367
+ } // Return the padding object.
1564
2368
 
1565
2369
 
1566
2370
  return padding;
1567
2371
  }
2372
+
1568
2373
  function getModifiers(options) {
1569
2374
  return [{
1570
2375
  name: 'offset',
@@ -1589,57 +2394,212 @@ function getModifiers(options) {
1589
2394
  }
1590
2395
  }];
1591
2396
  }
2397
+
2398
+ function getPopover(query) {
2399
+ // Get the entry from collection.
2400
+ var entry = typeof query === 'string' ? this.get(query) : this.get(query.id); // Return entry if it was resolved, otherwise throw error.
2401
+
2402
+ if (entry) {
2403
+ return entry;
2404
+ } else {
2405
+ throw new Error("Popover not found in collection with id of \"" + query + "\".");
2406
+ }
2407
+ }
2408
+
1592
2409
  function getPopoverID(obj) {
1593
- // If it's a string
2410
+ // If it's a string, return the string.
1594
2411
  if (typeof obj === 'string') {
1595
2412
  return obj;
1596
- } // If it's an HTML element
2413
+ } // If it's an HTML element.
1597
2414
  else if (typeof obj.hasAttribute === 'function') {
1598
- // If it's a popover trigger
1599
- if (obj.hasAttribute('aria-controls')) {
2415
+ // If it's a popover element, return the id.
2416
+ if (obj.closest(this.settings.selectorPopover)) {
2417
+ obj = obj.closest(this.settings.selectorPopover);
2418
+ return obj.id;
2419
+ } // If it's a popover trigger, return value of aria-controls.
2420
+ else if (obj.hasAttribute('aria-controls')) {
1600
2421
  return obj.getAttribute('aria-controls');
1601
- } // If it's a popover tooltip trigger
2422
+ } // If it's a popover tooltip trigger, return the value of aria-describedby.
1602
2423
  else if (obj.hasAttribute('aria-describedby')) {
1603
2424
  return obj.getAttribute('aria-describedby');
1604
- } // If it's a popover target
1605
- else if (obj.closest(this.settings.selectorPopover)) {
1606
- return obj.id;
1607
- } // Return false if no id was found
2425
+ } // Return false if no id was found.
1608
2426
  else return false;
1609
- } // If it has an ID property
2427
+ } // If it has an id property, return its value.
1610
2428
  else if (obj.id) {
1611
2429
  return obj.id;
1612
- } // Return false if no id was found
2430
+ } // Return false if no id was found.
1613
2431
  else return false;
1614
2432
  }
2433
+
1615
2434
  function getPopoverElements(query) {
1616
2435
  var id = getPopoverID.call(this, query);
1617
2436
 
1618
2437
  if (id) {
2438
+ var popover = document.querySelector("#" + id);
1619
2439
  var trigger = document.querySelector("[aria-controls=\"" + id + "\"]") || document.querySelector("[aria-describedby=\"" + id + "\"]");
1620
- var target = document.querySelector("#" + id);
1621
2440
 
1622
- if (!trigger && !target) {
1623
- console.error('No popover elements found using the provided ID:', id);
2441
+ if (!trigger && !popover) {
2442
+ return {
2443
+ error: new Error("No popover elements found using the ID: \"" + id + "\".")
2444
+ };
1624
2445
  } else if (!trigger) {
1625
- console.error('No popover trigger associated with the provided popover:', target);
1626
- } else if (!target) {
1627
- console.error('No popover associated with the provided popover trigger:', trigger);
1628
- }
1629
-
1630
- if (!trigger || !target) {
1631
- return false;
2446
+ return {
2447
+ error: new Error('No popover trigger associated with the provided popover.')
2448
+ };
2449
+ } else if (!popover) {
2450
+ return {
2451
+ error: new Error('No popover associated with the provided popover trigger.')
2452
+ };
1632
2453
  } else {
1633
2454
  return {
1634
- trigger: trigger,
1635
- target: target
2455
+ popover: popover,
2456
+ trigger: trigger
1636
2457
  };
1637
2458
  }
1638
2459
  } else {
1639
- console.error('Could not resolve the popover ID:', query);
1640
- return false;
2460
+ return {
2461
+ error: new Error('Could not resolve the popover ID.')
2462
+ };
2463
+ }
2464
+ }
2465
+
2466
+ var closeAll = function closeAll() {
2467
+ try {
2468
+ var _this4 = this;
2469
+
2470
+ var result = [];
2471
+ return Promise.resolve(Promise.all(_this4.collection.map(function (popover) {
2472
+ try {
2473
+ var _temp4 = function () {
2474
+ if (popover.state === 'opened') {
2475
+ var _push2 = result.push;
2476
+ return Promise.resolve(close.call(_this4, popover)).then(function (_close$call) {
2477
+ _push2.call(result, _close$call);
2478
+ });
2479
+ }
2480
+ }();
2481
+
2482
+ return Promise.resolve(_temp4 && _temp4.then ? _temp4.then(function () {}) : void 0);
2483
+ } catch (e) {
2484
+ return Promise.reject(e);
2485
+ }
2486
+ }))).then(function () {
2487
+ return result;
2488
+ });
2489
+ } catch (e) {
2490
+ return Promise.reject(e);
2491
+ }
2492
+ };
2493
+ var close = function close(query) {
2494
+ try {
2495
+ var _temp2 = function _temp2(popover) {
2496
+ // If a modal exists and its state is opened.
2497
+ if (popover && popover.state === 'opened') {
2498
+ // Update state class.
2499
+ popover.el.classList.remove(_this2.settings.stateActive); // Update accessibility attribute(s).
2500
+
2501
+ if (popover.trigger.hasAttribute('aria-controls')) {
2502
+ popover.trigger.setAttribute('aria-expanded', 'false');
2503
+ } // Disable popper event listeners.
2504
+
2505
+
2506
+ popover.popper.setOptions({
2507
+ modifiers: [{
2508
+ name: 'eventListeners',
2509
+ enabled: false
2510
+ }]
2511
+ }); // Update popover state.
2512
+
2513
+ popover.state = 'closed'; // Clear root trigger if popover trigger matches.
2514
+
2515
+ if (popover.trigger === _this2.trigger) {
2516
+ _this2.trigger = null;
2517
+ }
2518
+ } // Return the popover.
2519
+
2520
+
2521
+ return popover;
2522
+ };
2523
+
2524
+ var _this2 = this;
2525
+
2526
+ // Get the popover from collection.
2527
+ return Promise.resolve(query ? _temp2(getPopover.call(_this2, query)) : Promise.resolve(closeAll.call(_this2)).then(_temp2));
2528
+ } catch (e) {
2529
+ return Promise.reject(e);
2530
+ }
2531
+ };
2532
+ function closeCheck(popover) {
2533
+ // Only run closeCheck if provided popover is currently open.
2534
+ if (popover.state != 'opened') return; // Needed to correctly check which element is currently being focused.
2535
+
2536
+ setTimeout(function () {
2537
+ // Check if trigger or element are being hovered.
2538
+ var isHovered = popover.el.closest(':hover') === popover.el || popover.trigger.closest(':hover') === popover.trigger; // Check if trigger or element are being focused.
2539
+
2540
+ var isFocused = document.activeElement.closest("#" + popover.id + ", [aria-controls=\"" + popover.id + "\"]"); // Close if the trigger and element are not currently hovered or focused.
2541
+
2542
+ if (!isHovered && !isFocused) {
2543
+ popover.close();
2544
+ } // Return the popover.
2545
+
2546
+
2547
+ return popover;
2548
+ }, 1);
2549
+ }
2550
+
2551
+ function handleClick(popover) {
2552
+ if (popover.state === 'opened') {
2553
+ popover.close();
2554
+ } else {
2555
+ this.trigger = popover.trigger;
2556
+ popover.open();
2557
+ handleDocumentClick.call(this, popover);
2558
+ }
2559
+ }
2560
+ function handleKeydown(event) {
2561
+ var _this = this;
2562
+
2563
+ switch (event.key) {
2564
+ case 'Escape':
2565
+ if (this.trigger) {
2566
+ this.trigger.focus();
2567
+ }
2568
+
2569
+ closeAll.call(this);
2570
+ return;
2571
+
2572
+ case 'Tab':
2573
+ this.collection.forEach(function (popover) {
2574
+ closeCheck.call(_this, popover);
2575
+ });
2576
+ return;
2577
+
2578
+ default:
2579
+ return;
1641
2580
  }
1642
2581
  }
2582
+ function handleDocumentClick(popover) {
2583
+ var root = this;
2584
+ document.addEventListener('click', function _f(event) {
2585
+ // Check if a popover was clicked.
2586
+ var result = event.target.closest("#" + popover.id + ", [aria-controls=\"" + popover.id + "\"]");
2587
+
2588
+ if (!result) {
2589
+ // If it doesn't match and popover is open, close it and remove event listener.
2590
+ if (popover.el && popover.el.classList.contains(root.settings.stateActive)) {
2591
+ popover.close();
2592
+ }
2593
+
2594
+ this.removeEventListener('click', _f);
2595
+ } else {
2596
+ // If it does match and popover isn't currently active, remove event listener.
2597
+ if (popover.el && !popover.el.classList.contains(root.settings.stateActive)) {
2598
+ this.removeEventListener('click', _f);
2599
+ }
2600
+ }
2601
+ });
2602
+ }
1643
2603
 
1644
2604
  var top = 'top';
1645
2605
  var bottom = 'bottom';
@@ -1941,6 +2901,10 @@ function getContainingBlock(element) {
1941
2901
 
1942
2902
  var currentNode = getParentNode(element);
1943
2903
 
2904
+ if (isShadowRoot(currentNode)) {
2905
+ currentNode = currentNode.host;
2906
+ }
2907
+
1944
2908
  while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
1945
2909
  var css = getComputedStyle$1(currentNode); // This is non-exhaustive but covers the most common CSS properties that
1946
2910
  // create a containing block.
@@ -2164,7 +3128,7 @@ function mapToStyles(_ref2) {
2164
3128
 
2165
3129
  if (placement === top || (placement === left || placement === right) && variation === end) {
2166
3130
  sideY = bottom;
2167
- var offsetY = isFixed && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]
3131
+ var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]
2168
3132
  offsetParent[heightProp];
2169
3133
  y -= offsetY - popperRect.height;
2170
3134
  y *= gpuAcceleration ? 1 : -1;
@@ -2172,7 +3136,7 @@ function mapToStyles(_ref2) {
2172
3136
 
2173
3137
  if (placement === left || (placement === top || placement === bottom) && variation === end) {
2174
3138
  sideX = right;
2175
- var offsetX = isFixed && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]
3139
+ var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]
2176
3140
  offsetParent[widthProp];
2177
3141
  x -= offsetX - popperRect.width;
2178
3142
  x *= gpuAcceleration ? 1 : -1;
@@ -3424,170 +4388,204 @@ var createPopper = /*#__PURE__*/popperGenerator({
3424
4388
  defaultModifiers: defaultModifiers
3425
4389
  }); // eslint-disable-next-line import/no-unused-modules
3426
4390
 
3427
- function open(popover) {
3428
- // Update state class
3429
- popover.target.classList.add(this.settings.stateActive); // Update a11y attribute
4391
+ var deregister = function deregister(obj) {
4392
+ try {
4393
+ var _this2 = this;
4394
+
4395
+ // Return collection if nothing was passed.
4396
+ if (!obj) return Promise.resolve(_this2.collection); // Check if entry has been registered in the collection.
4397
+
4398
+ var index = _this2.collection.findIndex(function (entry) {
4399
+ return entry.id === obj.id;
4400
+ });
4401
+
4402
+ if (index >= 0) {
4403
+ // Get the collection entry.
4404
+ var entry = _this2.collection[index]; // If entry is in the opened state, close it.
4405
+
4406
+ if (entry.state === 'opened') {
4407
+ entry.close();
4408
+ } // Clean up the popper instance.
4409
+
4410
+
4411
+ entry.popper.destroy(); // Remove event listeners.
4412
+
4413
+ deregisterEventListeners(entry); // Delete properties from collection entry.
4414
+
4415
+ Object.getOwnPropertyNames(entry).forEach(function (prop) {
4416
+ delete entry[prop];
4417
+ }); // Remove entry from collection.
3430
4418
 
3431
- if (popover.trigger.hasAttribute('aria-controls')) {
3432
- popover.trigger.setAttribute('aria-expanded', 'true');
3433
- } // Update popover config
4419
+ _this2.collection.splice(index, 1);
4420
+ } // Return the modified collection.
3434
4421
 
3435
4422
 
3436
- popover.config = getConfig(popover.target, this.settings); // Enable popper event listeners and set placement/modifiers
4423
+ return Promise.resolve(_this2.collection);
4424
+ } catch (e) {
4425
+ return Promise.reject(e);
4426
+ }
4427
+ };
4428
+ function deregisterEventListeners(entry) {
4429
+ // If event listeners have been setup.
4430
+ if (entry.__eventListeners) {
4431
+ // Loop through listeners and remove from the appropriate elements.
4432
+ entry.__eventListeners.forEach(function (evObj) {
4433
+ evObj.el.forEach(function (el) {
4434
+ evObj.type.forEach(function (type) {
4435
+ entry[el].removeEventListener(type, evObj.listener, false);
4436
+ });
4437
+ });
4438
+ }); // Remove eventListeners object from collection.
3437
4439
 
3438
- popover.popper.setOptions({
3439
- placement: popover.config['placement'],
3440
- modifiers: [{
3441
- name: 'eventListeners',
3442
- enabled: true
3443
- }].concat(getModifiers(popover.config))
3444
- }); // Update popover position
3445
4440
 
3446
- popover.popper.update(); // Update popover state
4441
+ delete entry.__eventListeners;
4442
+ } // Return the entry object.
3447
4443
 
3448
- popover.state = 'opened'; // Return the popover
3449
4444
 
3450
- return popover;
4445
+ return entry;
3451
4446
  }
3452
4447
 
3453
- function register(trigger, target) {
3454
- // Deregister popover if it already exists in the collection
3455
- this.deregister(target.id); // Create popper instance
4448
+ var open = function open(query) {
4449
+ try {
4450
+ var _this2 = this;
3456
4451
 
3457
- var popperInstance = createPopper(trigger, target); // Save root this for use inside object & create methods API
4452
+ // Get the popover from collection.
4453
+ var popover = getPopover.call(_this2, query); // Update state class.
3458
4454
 
3459
- var root = this;
3460
- var methods = {
3461
- open: function open$1() {
3462
- open.call(root, this);
3463
- },
3464
- close: function close$1() {
3465
- close.call(root, this);
3466
- },
3467
- deregister: function deregister() {
3468
- _deregister.call(root, this);
3469
- }
3470
- }; // Build popover object and push to collection array
4455
+ popover.el.classList.add(_this2.settings.stateActive); // Update accessibility attribute(s).
3471
4456
 
3472
- var popover = _extends({
3473
- id: target.id,
3474
- state: 'closed',
3475
- trigger: trigger,
3476
- target: target,
3477
- popper: popperInstance,
3478
- config: getConfig(target, this.settings)
3479
- }, methods); // Setup event listeners
4457
+ if (popover.trigger.hasAttribute('aria-controls')) {
4458
+ popover.trigger.setAttribute('aria-expanded', 'true');
4459
+ } // Update popover config.
3480
4460
 
3481
4461
 
3482
- registerEventListeners.call(this, popover); // Set initial state of popover
4462
+ popover.config = getConfig(popover.el, _this2.settings); // Enable popper event listeners and set placement/modifiers.
3483
4463
 
3484
- if (popover.target.classList.contains(this.settings.stateActive)) {
3485
- popover.open();
3486
- documentClick.call(this, popover);
3487
- } else {
3488
- popover.close();
3489
- } // Add item to collection
4464
+ popover.popper.setOptions({
4465
+ placement: popover.config['placement'],
4466
+ modifiers: [{
4467
+ name: 'eventListeners',
4468
+ enabled: true
4469
+ }].concat(getModifiers(popover.config))
4470
+ }); // Update popover position.
3490
4471
 
4472
+ popover.popper.update(); // Update popover state.
3491
4473
 
3492
- this.collection.push(popover); // Return the popover object
4474
+ popover.state = 'opened'; // Return the popover.
3493
4475
 
3494
- return popover;
3495
- }
4476
+ return Promise.resolve(popover);
4477
+ } catch (e) {
4478
+ return Promise.reject(e);
4479
+ }
4480
+ };
4481
+
4482
+ var register = function register(el, trigger) {
4483
+ try {
4484
+ var _this2 = this;
4485
+
4486
+ // Deregister entry incase it has already been registered.
4487
+ deregister.call(_this2, el); // Save root this for use inside methods API.
3496
4488
 
3497
- function _deregister(popover) {
3498
- // Check if this item has been registered in the collection
3499
- var index = this.collection.findIndex(function (entry) {
3500
- return entry.id === popover.id;
3501
- }); // If the entry exists in the collection
3502
4489
 
3503
- if (index >= 0) {
3504
- // Get the collection entry
3505
- var entry = this.collection[index]; // Close the collection entry if it's open
4490
+ var root = _this2; // Setup methods API.
3506
4491
 
3507
- if (entry.state === 'opened') {
3508
- entry.close();
3509
- } // Clean up the popper instance
4492
+ var methods = {
4493
+ open: function open$1() {
4494
+ return open.call(root, this);
4495
+ },
4496
+ close: function close$1() {
4497
+ return close.call(root, this);
4498
+ },
4499
+ deregister: function deregister$1() {
4500
+ return deregister.call(root, this);
4501
+ }
4502
+ }; // Setup the popover object.
3510
4503
 
4504
+ var entry = _extends({
4505
+ id: el.id,
4506
+ state: 'closed',
4507
+ el: el,
4508
+ trigger: trigger,
4509
+ popper: createPopper(trigger, el),
4510
+ config: getConfig(el, _this2.settings)
4511
+ }, methods); // Set aria-expanded to false if trigger has aria-controls attribute.
3511
4512
 
3512
- entry.popper.destroy(); // Remove event listeners
3513
4513
 
3514
- deregisterEventListeners(entry); // Delete properties from collection entry
4514
+ if (entry.trigger.hasAttribute('aria-controls')) {
4515
+ entry.trigger.setAttribute('aria-expanded', 'false');
4516
+ } // Setup event listeners.
3515
4517
 
3516
- Object.getOwnPropertyNames(entry).forEach(function (prop) {
3517
- delete entry[prop];
3518
- }); // Remove entry from collection
3519
4518
 
3520
- this.collection.splice(index, 1);
3521
- } // Return the new collection
4519
+ registerEventListeners.call(_this2, entry); // Add entry to collection.
3522
4520
 
4521
+ _this2.collection.push(entry); // Set initial state.
3523
4522
 
3524
- return this.collection;
3525
- }
3526
- function registerEventListeners(popover) {
3527
- // If event listeners aren't already setup
3528
- if (!popover.__eventListeners) {
3529
- // Add event listeners based on event type
3530
- var eventType = popover.config['event'];
4523
+
4524
+ var _temp2 = function () {
4525
+ if (entry.el.classList.contains(_this2.settings.stateActive)) {
4526
+ return Promise.resolve(entry.open()).then(function () {
4527
+ handleDocumentClick.call(_this2, entry);
4528
+ });
4529
+ }
4530
+ }();
4531
+
4532
+ return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {
4533
+ // Return the registered entry.
4534
+ return entry;
4535
+ }) : entry);
4536
+ } catch (e) {
4537
+ return Promise.reject(e);
4538
+ }
4539
+ };
4540
+ function registerEventListeners(entry) {
4541
+ // If event listeners aren't already setup.
4542
+ if (!entry.__eventListeners) {
4543
+ // Add event listeners based on event type.
4544
+ var eventType = entry.config['event']; // If the event type is hover.
3531
4545
 
3532
4546
  if (eventType === 'hover') {
3533
- // Setup event listeners object for hover
3534
- popover.__eventListeners = [{
4547
+ // Setup event listeners object for hover.
4548
+ entry.__eventListeners = [{
3535
4549
  el: ['trigger'],
3536
4550
  type: ['mouseenter', 'focus'],
3537
- listener: open.bind(this, popover)
4551
+ listener: open.bind(this, entry)
3538
4552
  }, {
3539
- el: ['trigger', 'target'],
4553
+ el: ['el', 'trigger'],
3540
4554
  type: ['mouseleave', 'focusout'],
3541
- listener: closeCheck.bind(this, popover)
3542
- }]; // Loop through listeners and apply to appropriate elements
4555
+ listener: closeCheck.bind(this, entry)
4556
+ }]; // Loop through listeners and apply to the appropriate elements.
3543
4557
 
3544
- popover.__eventListeners.forEach(function (evObj) {
4558
+ entry.__eventListeners.forEach(function (evObj) {
3545
4559
  evObj.el.forEach(function (el) {
3546
4560
  evObj.type.forEach(function (type) {
3547
- popover[el].addEventListener(type, evObj.listener, false);
4561
+ entry[el].addEventListener(type, evObj.listener, false);
3548
4562
  });
3549
4563
  });
3550
4564
  });
3551
- } else {
3552
- // Setup event listeners object for click
3553
- popover.__eventListeners = [{
4565
+ } // Else the event type is click.
4566
+ else {
4567
+ // Setup event listeners object for click.
4568
+ entry.__eventListeners = [{
3554
4569
  el: ['trigger'],
3555
4570
  type: ['click'],
3556
- listener: handlerClick.bind(this, popover)
3557
- }]; // Loop through listeners and apply to appropriate elements
4571
+ listener: handleClick.bind(this, entry)
4572
+ }]; // Loop through listeners and apply to the appropriate elements.
3558
4573
 
3559
- popover.__eventListeners.forEach(function (evObj) {
4574
+ entry.__eventListeners.forEach(function (evObj) {
3560
4575
  evObj.el.forEach(function (el) {
3561
4576
  evObj.type.forEach(function (type) {
3562
- popover[el].addEventListener(type, evObj.listener, false);
4577
+ entry[el].addEventListener(type, evObj.listener, false);
3563
4578
  });
3564
4579
  });
3565
4580
  });
3566
4581
  }
3567
- } // Return the popover object
4582
+ } // Return the entry object.
3568
4583
 
3569
4584
 
3570
- return popover;
4585
+ return entry;
3571
4586
  }
3572
- function deregisterEventListeners(popover) {
3573
- // If event listeners have been setup
3574
- if (popover.__eventListeners) {
3575
- // Loop through listeners and remove from appropriate elements
3576
- popover.__eventListeners.forEach(function (evObj) {
3577
- evObj.el.forEach(function (el) {
3578
- evObj.type.forEach(function (type) {
3579
- popover[el].removeEventListener(type, evObj.listener, false);
3580
- });
3581
- });
3582
- }); // Remove eventListeners object from collection
3583
-
3584
-
3585
- delete popover.__eventListeners;
3586
- } // Return the popover object
3587
4587
 
3588
-
3589
- return popover;
3590
- }
4588
+ var _handleKeydown = /*#__PURE__*/_classPrivateFieldLooseKey("handleKeydown");
3591
4589
 
3592
4590
  var Popover = /*#__PURE__*/function (_Collection) {
3593
4591
  _inheritsLoose(Popover, _Collection);
@@ -3596,13 +4594,14 @@ var Popover = /*#__PURE__*/function (_Collection) {
3596
4594
  var _this;
3597
4595
 
3598
4596
  _this = _Collection.call(this) || this;
4597
+ Object.defineProperty(_assertThisInitialized(_this), _handleKeydown, {
4598
+ writable: true,
4599
+ value: void 0
4600
+ });
3599
4601
  _this.defaults = defaults;
3600
- _this.settings = _extends({}, _this.defaults, options); // this.collection = [];
3601
-
3602
- _this.memory = {
3603
- trigger: null
3604
- };
3605
- _this.__handlerKeydown = handlerKeydown.bind(_assertThisInitialized(_this));
4602
+ _this.settings = _extends({}, _this.defaults, options);
4603
+ _this.trigger = null;
4604
+ _classPrivateFieldLooseBase(_assertThisInitialized(_this), _handleKeydown)[_handleKeydown] = handleKeydown.bind(_assertThisInitialized(_this));
3606
4605
  if (_this.settings.autoInit) _this.init();
3607
4606
  return _this;
3608
4607
  }
@@ -3610,55 +4609,67 @@ var Popover = /*#__PURE__*/function (_Collection) {
3610
4609
  var _proto = Popover.prototype;
3611
4610
 
3612
4611
  _proto.init = function init(options) {
3613
- if (options === void 0) {
3614
- options = null;
3615
- }
4612
+ try {
4613
+ var _this3 = this;
3616
4614
 
3617
- // Update settings with passed options
3618
- if (options) this.settings = _extends({}, this.settings, options); // Get all the popovers
4615
+ // Update settings with passed options.
4616
+ if (options) _this3.settings = _extends({}, _this3.settings, options); // Get all the popovers.
3619
4617
 
3620
- var popovers = document.querySelectorAll(this.settings.selectorPopover); // Build the collections array with popover instances
4618
+ var popovers = document.querySelectorAll(_this3.settings.selectorPopover); // Register the collections array with popover instances.
3621
4619
 
3622
- this.registerCollection(popovers); // If eventListeners is enabled
4620
+ return Promise.resolve(_this3.registerCollection(popovers)).then(function () {
4621
+ // If eventListeners are enabled, init event listeners.
4622
+ if (_this3.settings.eventListeners) {
4623
+ // Pass false to initEventListeners() since registerCollection()
4624
+ // already adds event listeners to popovers.
4625
+ _this3.initEventListeners(false);
4626
+ }
3623
4627
 
3624
- if (this.settings.eventListeners) {
3625
- // Pass false to initEventListeners() since registerCollection()
3626
- // already adds event listeners to popovers
3627
- this.initEventListeners(false);
4628
+ return _this3;
4629
+ });
4630
+ } catch (e) {
4631
+ return Promise.reject(e);
3628
4632
  }
3629
4633
  };
3630
4634
 
3631
4635
  _proto.destroy = function destroy() {
3632
- // Deregister all popovers from collection
3633
- this.deregisterCollection(); // If eventListeners is enabled
4636
+ try {
4637
+ var _this5 = this;
4638
+
4639
+ // Clear stored trigger.
4640
+ _this5.trigger = null; // Remove all entries from the collection.
4641
+
4642
+ return Promise.resolve(_this5.deregisterCollection()).then(function () {
4643
+ // If eventListeners are enabled, destroy event listeners.
4644
+ if (_this5.settings.eventListeners) {
4645
+ // Pass false to destroyEventListeners() since deregisterCollection()
4646
+ // already removes event listeners from popovers.
4647
+ _this5.destroyEventListeners(false);
4648
+ }
3634
4649
 
3635
- if (this.settings.eventListeners) {
3636
- // Pass false to destroyEventListeners() since deregisterCollection()
3637
- // already removes event listeners from popovers
3638
- this.destroyEventListeners(false);
4650
+ return _this5;
4651
+ });
4652
+ } catch (e) {
4653
+ return Promise.reject(e);
3639
4654
  }
3640
- }
3641
- /**
3642
- * Event listeners
3643
- */
3644
- ;
4655
+ };
3645
4656
 
3646
4657
  _proto.initEventListeners = function initEventListeners(processCollection) {
3647
- var _this2 = this;
4658
+ var _this6 = this;
3648
4659
 
3649
4660
  if (processCollection === void 0) {
3650
4661
  processCollection = true;
3651
4662
  }
3652
4663
 
3653
4664
  if (processCollection) {
3654
- // Loop through collection and setup event listeners
4665
+ // Loop through collection and setup event listeners.
3655
4666
  this.collection.forEach(function (popover) {
3656
- registerEventListeners.call(_this2, popover);
4667
+ registerEventListeners.call(_this6, popover);
3657
4668
  });
3658
- } // Add keydown global event listener
4669
+ } // Add keydown global event listener.
3659
4670
 
3660
4671
 
3661
- document.addEventListener('keydown', this.__handlerKeydown, false);
4672
+ document.addEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown)[_handleKeydown], false);
3662
4673
  };
3663
4674
 
3664
4675
  _proto.destroyEventListeners = function destroyEventListeners(processCollection) {
@@ -3667,50 +4678,33 @@ var Popover = /*#__PURE__*/function (_Collection) {
3667
4678
  }
3668
4679
 
3669
4680
  if (processCollection) {
3670
- // Loop through collection and remove event listeners
4681
+ // Loop through collection and remove event listeners.
3671
4682
  this.collection.forEach(function (popover) {
3672
4683
  deregisterEventListeners(popover);
3673
4684
  });
3674
- } // Remove keydown global event listener
4685
+ } // Remove keydown global event listener.
3675
4686
 
3676
4687
 
3677
- document.removeEventListener('keydown', this.__handlerKeydown, false);
3678
- }
3679
- /**
3680
- * Register popover functionality
3681
- */
3682
- ;
4688
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown)[_handleKeydown], false);
4689
+ };
3683
4690
 
3684
4691
  _proto.register = function register$1(query) {
3685
4692
  var els = getPopoverElements.call(this, query);
3686
- if (!els) return false;
3687
- return register.call(this, els.trigger, els.target);
4693
+ if (els.error) return Promise.reject(els.error);
4694
+ return register.call(this, els.popover, els.trigger);
3688
4695
  };
3689
4696
 
3690
- _proto.deregister = function deregister(query) {
3691
- var popover = this.get(getPopoverID(query));
3692
- if (!popover) return false;
3693
- return _deregister.call(this, popover);
3694
- }
3695
- /**
3696
- * Change state functionality
3697
- */
3698
- ;
3699
-
3700
- _proto.open = function open(id) {
3701
- var popover = this.get(id);
3702
- if (!popover) return false;
3703
- return popover.open();
3704
- };
3705
-
3706
- _proto.close = function close(id) {
3707
- if (id) {
3708
- var popover = this.get(id);
3709
- if (!popover) return false;
3710
- return popover.close();
3711
- } else {
3712
- return closeAll.call(this);
3713
- }
4697
+ _proto.deregister = function deregister$1(query) {
4698
+ var popover = this.get(getPopoverID.call(this, query));
4699
+ return deregister.call(this, popover);
4700
+ };
4701
+
4702
+ _proto.open = function open$1(id) {
4703
+ return open.call(this, id);
4704
+ };
4705
+
4706
+ _proto.close = function close$1(id) {
4707
+ return close.call(this, id);
3714
4708
  };
3715
4709
 
3716
4710
  return Popover;