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