vrembem 2.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,60 +1,105 @@
1
- const setInert = (state, selector) => {
2
- if (selector) {
3
- const els = document.querySelectorAll(selector);
4
- els.forEach(el => {
5
- if (state) {
6
- el.inert = true;
7
- el.setAttribute('aria-hidden', true);
8
- } else {
9
- el.inert = null;
10
- el.removeAttribute('aria-hidden');
1
+ function _extends() {
2
+ _extends = Object.assign || function (target) {
3
+ for (var i = 1; i < arguments.length; i++) {
4
+ var source = arguments[i];
5
+
6
+ for (var key in source) {
7
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
8
+ target[key] = source[key];
9
+ }
11
10
  }
11
+ }
12
+
13
+ return target;
14
+ };
15
+
16
+ return _extends.apply(this, arguments);
17
+ }
18
+
19
+ var id = 0;
20
+
21
+ function _classPrivateFieldLooseKey(name) {
22
+ return "__private_" + id++ + "_" + name;
23
+ }
24
+
25
+ function _classPrivateFieldLooseBase(receiver, privateKey) {
26
+ if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
27
+ throw new TypeError("attempted to use private field on non-instance");
28
+ }
29
+
30
+ return receiver;
31
+ }
32
+
33
+ var _handler = /*#__PURE__*/_classPrivateFieldLooseKey("handler");
34
+
35
+ class Breakpoint {
36
+ constructor(value, handler) {
37
+ Object.defineProperty(this, _handler, {
38
+ writable: true,
39
+ value: void 0
12
40
  });
41
+ this.value = value;
42
+ _classPrivateFieldLooseBase(this, _handler)[_handler] = handler;
43
+ this.mql = null;
13
44
  }
14
- };
15
- const setOverflowHidden = (state, selector) => {
16
- if (selector) {
17
- const els = document.querySelectorAll(selector);
18
- els.forEach(el => {
19
- if (state) {
20
- el.style.overflow = 'hidden';
45
+
46
+ get handler() {
47
+ return _classPrivateFieldLooseBase(this, _handler)[_handler];
48
+ } // Unmount existing handler before setting a new one.
49
+
50
+
51
+ set handler(func) {
52
+ if (this.mql) {
53
+ // Conditionally use removeListener() for IE11 support.
54
+ if (typeof this.mql.removeEventListener === 'function') {
55
+ this.mql.removeEventListener('change', _classPrivateFieldLooseBase(this, _handler)[_handler]);
21
56
  } else {
22
- el.style.removeProperty('overflow');
57
+ this.mql.removeListener(_classPrivateFieldLooseBase(this, _handler)[_handler]);
23
58
  }
24
- });
59
+ }
60
+
61
+ _classPrivateFieldLooseBase(this, _handler)[_handler] = func;
25
62
  }
26
- };
27
- const setTabindex = selector => {
28
- if (selector) {
29
- const els = document.querySelectorAll(selector);
30
- els.forEach(el => {
31
- el.setAttribute('tabindex', '-1');
32
- });
63
+
64
+ mount(value, handler) {
65
+ // Update passed params.
66
+ if (value) this.value = value;
67
+ if (handler) _classPrivateFieldLooseBase(this, _handler)[_handler] = handler; // Guard if no breakpoint was set.
68
+
69
+ if (!this.value) return this; // Setup and store the MediaQueryList instance.
70
+
71
+ this.mql = window.matchMedia(`(min-width: ${this.value})`); // Conditionally use addListener() for IE11 support.
72
+
73
+ if (typeof this.mql.addEventListener === 'function') {
74
+ this.mql.addEventListener('change', _classPrivateFieldLooseBase(this, _handler)[_handler]);
75
+ } else {
76
+ this.mql.addListener(_classPrivateFieldLooseBase(this, _handler)[_handler]);
77
+ } // Run the handler.
78
+
79
+
80
+ _classPrivateFieldLooseBase(this, _handler)[_handler](this.mql);
81
+
82
+ return this;
33
83
  }
34
- };
35
84
 
36
- /**
37
- * Adds a class or classes to a Node or NodeList.
38
- * @param {Node || NodeList} el - Element(s) to add class(es) to.
39
- * @param {String || Array} cl - Class(es) to add.
40
- */
41
- const addClass = (el, ...cl) => {
42
- el = el.forEach ? el : [el];
43
- el.forEach(el => {
44
- el.classList.add(...cl);
45
- });
46
- };
85
+ unmount() {
86
+ // Guard if no MediaQueryList instance exists.
87
+ if (!this.mql) return this; // Conditionally use removeListener() for IE11 support.
88
+
89
+ if (typeof this.mql.removeEventListener === 'function') {
90
+ this.mql.removeEventListener('change', _classPrivateFieldLooseBase(this, _handler)[_handler]);
91
+ } else {
92
+ this.mql.removeListener(_classPrivateFieldLooseBase(this, _handler)[_handler]);
93
+ } // Set value, handler and MediaQueryList to null.
47
94
 
48
- /**
49
- * Takes a hyphen cased string and converts it to camel case.
50
- * @param {String } str - the string to convert to camel case.
51
- * @returns {Boolean} - returns a camel cased string.
52
- */
53
- const camelCase = str => {
54
- return str.replace(/-([a-z])/g, function (g) {
55
- return g[1].toUpperCase();
56
- });
57
- };
95
+
96
+ this.value = null;
97
+ _classPrivateFieldLooseBase(this, _handler)[_handler] = null;
98
+ this.mql = null;
99
+ return this;
100
+ }
101
+
102
+ }
58
103
 
59
104
  class Collection {
60
105
  constructor() {
@@ -108,154 +153,172 @@ class Collection {
108
153
 
109
154
  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^="-"])'];
110
155
 
111
- const focusTarget = (target, settings) => {
112
- const innerFocus = target.querySelector(settings.selectorFocus);
156
+ var _focusable = /*#__PURE__*/_classPrivateFieldLooseKey("focusable");
157
+
158
+ var _handleFocusTrap = /*#__PURE__*/_classPrivateFieldLooseKey("handleFocusTrap");
159
+
160
+ var _handleFocusLock = /*#__PURE__*/_classPrivateFieldLooseKey("handleFocusLock");
113
161
 
114
- if (innerFocus) {
115
- innerFocus.focus();
116
- } else {
117
- const innerElement = target.querySelector('[tabindex="-1"]');
118
- if (innerElement) innerElement.focus();
119
- }
120
- };
121
- const focusTrigger = obj => {
122
- if (!obj || !obj.memory || !obj.memory.trigger) return;
123
- obj.memory.trigger.focus();
124
- obj.memory.trigger = null;
125
- };
126
162
  class FocusTrap {
127
- constructor() {
128
- this.target = null;
129
- this.__handlerFocusTrap = this.handlerFocusTrap.bind(this);
163
+ constructor(el = null, selectorFocus = '[data-focus]') {
164
+ Object.defineProperty(this, _focusable, {
165
+ writable: true,
166
+ value: void 0
167
+ });
168
+ Object.defineProperty(this, _handleFocusTrap, {
169
+ writable: true,
170
+ value: void 0
171
+ });
172
+ Object.defineProperty(this, _handleFocusLock, {
173
+ writable: true,
174
+ value: void 0
175
+ });
176
+ this.el = el;
177
+ this.selectorFocus = selectorFocus;
178
+ _classPrivateFieldLooseBase(this, _handleFocusTrap)[_handleFocusTrap] = handleFocusTrap.bind(this);
179
+ _classPrivateFieldLooseBase(this, _handleFocusLock)[_handleFocusLock] = handleFocusLock.bind(this);
180
+ }
181
+
182
+ get focusable() {
183
+ return _classPrivateFieldLooseBase(this, _focusable)[_focusable];
130
184
  }
131
185
 
132
- init(target) {
133
- this.destroy();
134
- this.target = target;
135
- this.inner = this.target.querySelector('[tabindex="-1"]');
136
- this.focusable = this.getFocusable();
186
+ set focusable(value) {
187
+ // Update the focusable value.
188
+ _classPrivateFieldLooseBase(this, _focusable)[_focusable] = value; // Apply event listeners based on new focusable array length.
137
189
 
138
- if (this.focusable.length) {
139
- this.focusableFirst = this.focusable[0];
140
- this.focusableLast = this.focusable[this.focusable.length - 1];
141
- this.target.addEventListener('keydown', this.__handlerFocusTrap);
190
+ if (_classPrivateFieldLooseBase(this, _focusable)[_focusable].length) {
191
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusLock)[_handleFocusLock]);
192
+ document.addEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusTrap)[_handleFocusTrap]);
142
193
  } else {
143
- this.target.addEventListener('keydown', this.handlerFocusLock);
194
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusTrap)[_handleFocusTrap]);
195
+ document.addEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusLock)[_handleFocusLock]);
144
196
  }
145
197
  }
146
198
 
147
- destroy() {
148
- if (!this.target) return;
149
- this.inner = null;
150
- this.focusable = null;
151
- this.focusableFirst = null;
152
- this.focusableLast = null;
153
- this.target.removeEventListener('keydown', this.__handlerFocusTrap);
154
- this.target.removeEventListener('keydown', this.handlerFocusLock);
155
- this.target = null;
156
- }
157
-
158
- refresh() {
159
- // Check if a target has been set
160
- if (!this.target) return; // Remove existing events
161
-
162
- this.target.removeEventListener('keydown', this.__handlerFocusTrap);
163
- this.target.removeEventListener('keydown', this.handlerFocusLock); // Get the focusable elements
164
-
165
- this.focusable = this.getFocusable(); // Setup the focus handlers based on focusable length
166
-
167
- if (this.focusable.length) {
168
- // If there are focusable elements, setup focus trap
169
- this.focusableFirst = this.focusable[0];
170
- this.focusableLast = this.focusable[this.focusable.length - 1];
171
- this.target.addEventListener('keydown', this.__handlerFocusTrap);
172
- } else {
173
- // If there are no focusable elements, setup focus lock
174
- this.focusableFirst = null;
175
- this.focusableLast = null;
176
- this.target.addEventListener('keydown', this.handlerFocusLock);
177
- }
199
+ get focusableFirst() {
200
+ return this.focusable[0];
178
201
  }
179
202
 
180
- handlerFocusTrap(event) {
181
- const isTab = event.key === 'Tab' || event.keyCode === 9;
182
- if (!isTab) return;
203
+ get focusableLast() {
204
+ return this.focusable[this.focusable.length - 1];
205
+ }
183
206
 
184
- if (event.shiftKey) {
185
- if (document.activeElement === this.focusableFirst || document.activeElement === this.inner) {
186
- this.focusableLast.focus();
187
- event.preventDefault();
188
- }
189
- } else {
190
- if (document.activeElement === this.focusableLast || document.activeElement === this.inner) {
191
- this.focusableFirst.focus();
192
- event.preventDefault();
193
- }
194
- }
207
+ mount(el, selectorFocus) {
208
+ // Update passed params.
209
+ if (el) this.el = el;
210
+ if (selectorFocus) this.selectorFocus = selectorFocus; // Get the focusable elements.
211
+
212
+ this.focusable = this.getFocusable(); // Set the focus on the element.
213
+
214
+ this.focus();
215
+ }
216
+
217
+ unmount() {
218
+ // Set element to null.
219
+ this.el = null; // Apply empty array to focusable.
220
+
221
+ this.focusable = []; // Remove event listeners
222
+
223
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusTrap)[_handleFocusTrap]);
224
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleFocusLock)[_handleFocusLock]);
195
225
  }
196
226
 
197
- handlerFocusLock(event) {
198
- const isTab = event.key === 'Tab' || event.keyCode === 9;
199
- if (isTab) event.preventDefault();
227
+ focus(el = this.el, selectorFocus = this.selectorFocus) {
228
+ // Query for the focus selector, otherwise return this element.
229
+ const result = el.querySelector(selectorFocus) || el; // Give the returned element focus.
230
+
231
+ result.focus();
200
232
  }
201
233
 
202
- getFocusable() {
203
- const focusable = [];
234
+ getFocusable(el = this.el) {
235
+ // Initialize the focusable array.
236
+ const focusable = []; // Store the initial focus and scroll position.
237
+
204
238
  const initFocus = document.activeElement;
205
- const initScrollTop = this.inner ? this.inner.scrollTop : 0;
206
- this.target.querySelectorAll(focusableSelectors.join(',')).forEach(el => {
207
- el.focus();
239
+ const initScrollTop = el.scrollTop; // Query for all the focusable elements.
240
+
241
+ const els = el.querySelectorAll(focusableSelectors.join(',')); // Loop through all focusable elements.
208
242
 
209
- if (el === document.activeElement) {
243
+ els.forEach(el => {
244
+ // Set them to focus and check
245
+ el.focus(); // Test that the element took focus.
246
+
247
+ if (document.activeElement === el) {
248
+ // Add element to the focusable array.
210
249
  focusable.push(el);
211
250
  }
212
- });
213
- if (this.inner) this.inner.scrollTop = initScrollTop;
214
- initFocus.focus();
251
+ }); // Restore the initial scroll position and focus.
252
+
253
+ el.scrollTop = initScrollTop;
254
+ initFocus.focus(); // Return the focusable array.
255
+
215
256
  return focusable;
216
257
  }
217
258
 
218
259
  }
219
260
 
220
- /**
221
- * Checks an element or NodeList whether they contain a class or classes.
222
- * Ref: https://davidwalsh.name/nodelist-array
223
- * @param {Node} el - Element(s) to check class(es) on.
224
- * @param {String || Array} c - Class(es) to check.
225
- * @returns {Boolean} - Returns true if class exists, otherwise false.
226
- */
227
- const hasClass = (el, ...cl) => {
228
- el = el.forEach ? el : [el];
229
- el = [].slice.call(el);
230
- return cl.some(cl => {
231
- return el.some(el => {
232
- if (el.classList.contains(cl)) return true;
233
- });
234
- });
235
- };
261
+ function handleFocusTrap(event) {
262
+ // Check if the click was a tab and return if not.
263
+ const isTab = event.key === 'Tab' || event.keyCode === 9;
264
+ if (!isTab) return; // If the shift key is pressed.
236
265
 
237
- /**
238
- * Takes a camel cased string and converts it to hyphen case.
239
- * @param {String } str - the string to convert to hyphen case.
240
- * @returns {Boolean} - returns a hyphen cased string.
241
- */
242
- const hyphenCase = str => {
243
- return str.replace(/([a-z][A-Z])/g, function (g) {
244
- return g[0] + '-' + g[1].toLowerCase();
245
- });
246
- };
266
+ if (event.shiftKey) {
267
+ // If the active element is either the root el or first focusable.
268
+ if (document.activeElement === this.focusableFirst || document.activeElement === this.el) {
269
+ // Prevent default and focus the last focusable element instead.
270
+ event.preventDefault();
271
+ this.focusableLast.focus();
272
+ }
273
+ } else {
274
+ // If the active element is either the root el or last focusable.
275
+ if (document.activeElement === this.focusableLast || document.activeElement === this.el) {
276
+ // Prevent default and focus the first focusable element instead.
277
+ event.preventDefault();
278
+ this.focusableFirst.focus();
279
+ }
280
+ }
281
+ }
247
282
 
248
- /**
249
- * Remove a class or classes from an element or NodeList.
250
- * @param {Node || NodeList} el - Element(s) to remove class(es) from.
251
- * @param {String || Array} cl - Class(es) to remove.
252
- */
253
- const removeClass = (el, ...cl) => {
254
- el = el.forEach ? el : [el];
255
- el.forEach(el => {
256
- el.classList.remove(...cl);
283
+ function handleFocusLock(event) {
284
+ // Ignore the tab key by preventing default.
285
+ const isTab = event.key === 'Tab' || event.keyCode === 9;
286
+ if (isTab) event.preventDefault();
287
+ }
288
+
289
+ function getConfig$1(el, dataConfig) {
290
+ const string = el.getAttribute(`data-${dataConfig}`) || '';
291
+ const json = string.replace(/'/g, '"');
292
+ return json ? JSON.parse(json) : {};
293
+ }
294
+
295
+ function getPrefix() {
296
+ return getComputedStyle(document.body).getPropertyValue('--vrembem-variable-prefix').trim();
297
+ }
298
+
299
+ function localStore(key, enable = true) {
300
+ function getStore() {
301
+ const value = localStorage.getItem(key);
302
+ return value ? JSON.parse(value) : {};
303
+ }
304
+
305
+ function setStore(obj) {
306
+ localStorage.setItem(key, JSON.stringify(obj));
307
+ }
308
+
309
+ return new Proxy(getStore(), {
310
+ set: (target, property, value) => {
311
+ target[property] = value;
312
+ if (enable) setStore(target);
313
+ return true;
314
+ },
315
+ deleteProperty: (target, property) => {
316
+ delete target[property];
317
+ if (enable) setStore(target);
318
+ return true;
319
+ }
257
320
  });
258
- };
321
+ }
259
322
 
260
323
  /**
261
324
  * Teleports an element in the DOM based on a reference and teleport method.
@@ -299,20 +362,6 @@ function teleport(what, where, how) {
299
362
  return returnRef;
300
363
  }
301
364
 
302
- /**
303
- * Toggle a class or classes on an element or NodeList.
304
- * @param {Node || NodeList} el - Element(s) to toggle class(es) on.
305
- * @param {String || Array} cl - Class(es) to toggle.
306
- */
307
- const toggleClass = (el, ...cl) => {
308
- el = el.forEach ? el : [el];
309
- el.forEach(el => {
310
- cl.forEach(cl => {
311
- el.classList.toggle(cl);
312
- });
313
- });
314
- };
315
-
316
365
  const openTransition = (el, settings) => {
317
366
  return new Promise(resolve => {
318
367
  if (settings.transition) {
@@ -350,44 +399,55 @@ const closeTransition = (el, settings) => {
350
399
  });
351
400
  };
352
401
 
402
+ function setOverflowHidden(state, selector) {
403
+ if (selector) {
404
+ const els = document.querySelectorAll(selector);
405
+ els.forEach(el => {
406
+ if (state) {
407
+ el.style.overflow = 'hidden';
408
+ } else {
409
+ el.style.removeProperty('overflow');
410
+ }
411
+ });
412
+ }
413
+ }
414
+
415
+ function setInert(state, selector) {
416
+ if (selector) {
417
+ const els = document.querySelectorAll(selector);
418
+ els.forEach(el => {
419
+ if (state) {
420
+ el.inert = true;
421
+ el.setAttribute('aria-hidden', true);
422
+ } else {
423
+ el.inert = null;
424
+ el.removeAttribute('aria-hidden');
425
+ }
426
+ });
427
+ }
428
+ }
429
+
430
+ function updateGlobalState(param, config) {
431
+ // Set inert state based on if a modal is active.
432
+ setInert(!!param, config.selectorInert); // Set overflow state based on if a modal is active.
433
+
434
+ setOverflowHidden(!!param, config.selectorOverflow);
435
+ }
436
+
353
437
  var index = {
354
438
  __proto__: null,
355
- setInert: setInert,
356
- setOverflowHidden: setOverflowHidden,
357
- setTabindex: setTabindex,
358
- addClass: addClass,
359
- camelCase: camelCase,
439
+ Breakpoint: Breakpoint,
360
440
  Collection: Collection,
361
- focusTarget: focusTarget,
362
- focusTrigger: focusTrigger,
363
441
  FocusTrap: FocusTrap,
364
- hasClass: hasClass,
365
- hyphenCase: hyphenCase,
366
- removeClass: removeClass,
442
+ getConfig: getConfig$1,
443
+ getPrefix: getPrefix,
444
+ localStore: localStore,
367
445
  teleport: teleport,
368
- toggleClass: toggleClass,
369
446
  openTransition: openTransition,
370
- closeTransition: closeTransition
447
+ closeTransition: closeTransition,
448
+ updateGlobalState: updateGlobalState
371
449
  };
372
450
 
373
- function _extends() {
374
- _extends = Object.assign || function (target) {
375
- for (var i = 1; i < arguments.length; i++) {
376
- var source = arguments[i];
377
-
378
- for (var key in source) {
379
- if (Object.prototype.hasOwnProperty.call(source, key)) {
380
- target[key] = source[key];
381
- }
382
- }
383
- }
384
-
385
- return target;
386
- };
387
-
388
- return _extends.apply(this, arguments);
389
- }
390
-
391
451
  var defaults$3 = {
392
452
  autoInit: false,
393
453
  stateAttr: 'aria-checked',
@@ -452,16 +512,17 @@ class Checkbox {
452
512
  var defaults$2 = {
453
513
  autoInit: false,
454
514
  // Data attributes
455
- dataDrawer: 'drawer',
456
- dataDialog: 'drawer-dialog',
457
- dataToggle: 'drawer-toggle',
458
515
  dataOpen: 'drawer-open',
459
516
  dataClose: 'drawer-close',
517
+ dataToggle: 'drawer-toggle',
460
518
  dataBreakpoint: 'drawer-breakpoint',
519
+ dataConfig: 'drawer-config',
461
520
  // Selectors
521
+ selectorDrawer: '.drawer',
522
+ selectorDialog: '.drawer__dialog',
462
523
  selectorFocus: '[data-focus]',
463
524
  selectorInert: null,
464
- selectorOverflow: null,
525
+ selectorOverflow: 'body',
465
526
  // State classes
466
527
  stateOpened: 'is-opened',
467
528
  stateOpening: 'is-opening',
@@ -473,440 +534,590 @@ var defaults$2 = {
473
534
  breakpoints: null,
474
535
  customEventPrefix: 'drawer:',
475
536
  eventListeners: true,
476
- stateSave: true,
477
- stateKey: 'DrawerState',
537
+ store: true,
538
+ storeKey: 'VB:DrawerState',
478
539
  setTabindex: true,
479
540
  transition: true
480
541
  };
481
542
 
482
- class Breakpoint {
483
- constructor(parent) {
484
- this.mediaQueryLists = [];
485
- this.parent = parent;
486
- this.prefix = this.getVariablePrefix();
487
- this.__check = this.check.bind(this);
488
- }
489
-
490
- init() {
491
- const drawers = document.querySelectorAll(`[data-${this.parent.settings.dataBreakpoint}]`);
492
- drawers.forEach(drawer => {
493
- // Setup mediaQueryList object
494
- const id = drawer.getAttribute(`data-${this.parent.settings.dataDrawer}`);
495
- const key = drawer.getAttribute(`data-${this.parent.settings.dataBreakpoint}`);
496
- const bp = this.getBreakpoint(key);
497
- const mql = window.matchMedia('(min-width:' + bp + ')'); // Run match check
498
-
499
- this.match(mql, drawer); // Conditionally use addListner() for IE11 support
500
-
501
- if (typeof mql.addEventListener === 'function') {
502
- mql.addEventListener('change', this.__check);
503
- } else {
504
- mql.addListener(this.__check);
505
- } // Push to mediaQueryLists array along with drawer ID
543
+ function handleClick$2(event) {
544
+ // If an open, close or toggle button was clicked, handle the click event.
545
+ const trigger = event.target.closest(`
546
+ [data-${this.settings.dataOpen}],
547
+ [data-${this.settings.dataToggle}],
548
+ [data-${this.settings.dataClose}]
549
+ `);
550
+
551
+ if (trigger) {
552
+ // Prevent the default behavior of the trigger.
553
+ event.preventDefault(); // If it's a toggle trigger...
554
+
555
+ if (trigger.matches(`[data-${this.settings.dataToggle}]`)) {
556
+ const selectors = trigger.getAttribute(`data-${this.settings.dataToggle}`).trim().split(' ');
557
+ selectors.forEach(selector => {
558
+ // Get the entry from collection using the attribute value.
559
+ const entry = this.get(selector); // Store the trigger on the entry.
560
+
561
+ entry.trigger = trigger; // Toggle the drawer
562
+
563
+ entry.toggle();
564
+ });
565
+ } // If it's a open trigger...
566
+
567
+
568
+ if (trigger.matches(`[data-${this.settings.dataOpen}]`)) {
569
+ const selectors = trigger.getAttribute(`data-${this.settings.dataOpen}`).trim().split(' ');
570
+ selectors.forEach(selector => {
571
+ // Get the entry from collection using the attribute value.
572
+ const entry = this.get(selector); // Store the trigger on the entry.
573
+
574
+ entry.trigger = trigger; // Open the drawer.
575
+
576
+ entry.open();
577
+ });
578
+ } // If it's a close trigger...
579
+
580
+
581
+ if (trigger.matches(`[data-${this.settings.dataClose}]`)) {
582
+ const selectors = trigger.getAttribute(`data-${this.settings.dataClose}`).trim().split(' ');
583
+ selectors.forEach(selector => {
584
+ if (selector) {
585
+ // Get the entry from collection using the attribute value.
586
+ const entry = this.get(selector); // Store the trigger on the entry.
587
+
588
+ entry.trigger = trigger; // Close the drawer.
589
+
590
+ entry.close();
591
+ } else {
592
+ // If no value is set on close trigger, get the parent drawer.
593
+ const parent = event.target.closest(this.settings.selectorDrawer); // If a parent drawer was found, close it.
594
+
595
+ if (parent) this.close(parent);
596
+ }
597
+ });
598
+ }
599
+
600
+ return;
601
+ } // If the modal drawer screen was clicked...
602
+
603
+
604
+ if (event.target.matches(this.settings.selectorDrawer)) {
605
+ // Close the modal drawer.
606
+ this.close(event.target.id);
607
+ }
608
+ }
609
+ function handleKeydown$2(event) {
610
+ if (event.key === 'Escape') {
611
+ const modal = this.activeModal;
612
+ if (modal) this.close(modal);
613
+ }
614
+ }
615
+
616
+ async function deregister$2(obj, close = true) {
617
+ // Return collection if nothing was passed.
618
+ if (!obj) return this.collection; // Check if entry has been registered in the collection.
619
+
620
+ const index = this.collection.findIndex(entry => {
621
+ return entry.id === obj.id;
622
+ });
623
+
624
+ if (index >= 0) {
625
+ // Get the collection entry.
626
+ const entry = this.collection[index]; // If entry is in the opened state.
627
+
628
+ if (close && entry.state === 'opened') {
629
+ // Close the drawer.
630
+ await entry.close(false);
631
+ } // Remove entry from local store.
632
+
633
+
634
+ delete this.store[entry.id]; // Unmount the MatchMedia functionality.
635
+
636
+ entry.unmountBreakpoint(); // Delete properties from collection entry.
637
+
638
+ Object.getOwnPropertyNames(entry).forEach(prop => {
639
+ delete entry[prop];
640
+ }); // Remove entry from collection.
641
+
642
+ this.collection.splice(index, 1);
643
+ } // Return the modified collection.
644
+
645
+
646
+ return this.collection;
647
+ }
648
+
649
+ function L() {
650
+ return getComputedStyle(document.body).getPropertyValue("--vrembem-variable-prefix").trim();
651
+ }
652
+
653
+ function getBreakpoint(drawer) {
654
+ const prefix = L();
655
+ const bp = drawer.getAttribute(`data-${this.settings.dataBreakpoint}`);
656
+
657
+ if (this.settings.breakpoints && this.settings.breakpoints[bp]) {
658
+ return this.settings.breakpoints[bp];
659
+ } else if (getComputedStyle(document.body).getPropertyValue(`--${prefix}breakpoint-${bp}`).trim()) {
660
+ return getComputedStyle(document.body).getPropertyValue(`--${prefix}breakpoint-${bp}`).trim();
661
+ } else {
662
+ return bp;
663
+ }
664
+ }
665
+
666
+ function getDrawer(query) {
667
+ // Get the entry from collection.
668
+ const entry = typeof query === 'string' ? this.get(query) : this.get(query.id); // Return entry if it was resolved, otherwise throw error.
669
+
670
+ if (entry) {
671
+ return entry;
672
+ } else {
673
+ throw new Error(`Drawer not found in collection with id of "${query.id || query}".`);
674
+ }
675
+ }
676
+
677
+ function getDrawerID(obj) {
678
+ // If it's a string, return the string.
679
+ if (typeof obj === 'string') {
680
+ return obj;
681
+ } // If it's an HTML element.
682
+ else if (typeof obj.hasAttribute === 'function') {
683
+ // If it's a drawer open trigger, return data value.
684
+ if (obj.hasAttribute(`data-${this.settings.dataOpen}`)) {
685
+ return obj.getAttribute(`data-${this.settings.dataOpen}`);
686
+ } // If it's a drawer close trigger, return data value or false.
687
+ else if (obj.hasAttribute(`data-${this.settings.dataClose}`)) {
688
+ return obj.getAttribute(`data-${this.settings.dataClose}`) || false;
689
+ } // If it's a drawer toggle trigger, return data value.
690
+ else if (obj.hasAttribute(`data-${this.settings.dataToggle}`)) {
691
+ return obj.getAttribute(`data-${this.settings.dataToggle}`);
692
+ } // If it's a drawer element, return the id.
693
+ else if (obj.closest(this.settings.selectorDrawer)) {
694
+ obj = obj.closest(this.settings.selectorDrawer);
695
+ return obj.id || false;
696
+ } // Return false if no id was found.
697
+ else return false;
698
+ } // If it has an id property, return its value.
699
+ else if (obj.id) {
700
+ return obj.id;
701
+ } // Return false if no id was found.
702
+ else return false;
703
+ }
506
704
 
705
+ function getDrawerElements(query) {
706
+ const id = getDrawerID.call(this, query);
507
707
 
508
- this.mediaQueryLists.push({
509
- 'mql': mql,
510
- 'drawer': id
511
- });
512
- });
513
- }
708
+ if (id) {
709
+ const drawer = document.querySelector(`#${id}`);
710
+ const dialog = drawer ? drawer.querySelector(this.settings.selectorDialog) : null;
514
711
 
515
- destroy() {
516
- if (this.mediaQueryLists && this.mediaQueryLists.length) {
517
- this.mediaQueryLists.forEach(item => {
518
- item.mql.removeListener(this.__check);
519
- });
712
+ if (!drawer && !dialog) {
713
+ return {
714
+ error: new Error(`No drawer elements found using the ID: "${id}".`)
715
+ };
716
+ } else if (!dialog) {
717
+ return {
718
+ error: new Error('Drawer is missing dialog element.')
719
+ };
720
+ } else {
721
+ return {
722
+ drawer,
723
+ dialog
724
+ };
520
725
  }
521
-
522
- this.mediaQueryLists = null;
726
+ } else {
727
+ return {
728
+ error: new Error('Could not resolve the drawer ID.')
729
+ };
523
730
  }
731
+ }
524
732
 
525
- check(event = null) {
526
- if (this.mediaQueryLists && this.mediaQueryLists.length) {
527
- this.mediaQueryLists.forEach(item => {
528
- // If an event is passed, filter out drawers that don't match the query
529
- // If event is null, run all drawers through match
530
- let filter = event ? event.media == item.mql.media : true;
531
- if (!filter) return;
532
- const drawer = document.querySelector(`[data-${this.parent.settings.dataDrawer}="${item.drawer}"]`);
533
- if (drawer) this.match(item.mql, drawer);
534
- });
535
- document.dispatchEvent(new CustomEvent(this.parent.settings.customEventPrefix + 'breakpoint', {
536
- bubbles: true
537
- }));
733
+ async function initialState(entry) {
734
+ // Setup initial state using the following priority:
735
+ // 1. If a store state is available, restore from local store.
736
+ // 2. If opened state class is set, set state to opened.
737
+ // 3. Else, initialize default state.
738
+ if (this.store[entry.id]) {
739
+ // Restore drawers to saved inline state.
740
+ if (this.store[entry.id] === 'opened') {
741
+ await entry.open(false, false);
742
+ } else {
743
+ await entry.close(false, false);
538
744
  }
745
+ } else if (entry.el.classList.contains(this.settings.stateOpened)) {
746
+ // Update drawer state.
747
+ entry.state = 'opened';
748
+ } else {
749
+ // Remove transition state classes.
750
+ entry.el.classList.remove(this.settings.stateOpening);
751
+ entry.el.classList.remove(this.settings.stateClosing); // Add closed state class.
752
+
753
+ entry.el.classList.add(this.settings.stateClosed);
539
754
  }
755
+ }
540
756
 
541
- match(mql, drawer) {
542
- if (mql.matches) {
543
- this.parent.switchToDefault(drawer);
757
+ function updateFocusState$1(entry) {
758
+ // Check if there's an active modal
759
+ if (entry.state === 'opened') {
760
+ // Mount the focus trap on the opened drawer.
761
+ if (entry.mode === 'modal') {
762
+ this.focusTrap.mount(entry.dialog, this.settings.selectorFocus);
544
763
  } else {
545
- this.parent.switchToModal(drawer);
764
+ this.focusTrap.focus(entry.dialog, this.settings.selectorFocus);
765
+ }
766
+ } else {
767
+ // Set focus to root trigger and unmount the focus trap.
768
+ if (entry.trigger) {
769
+ entry.trigger.focus();
770
+ entry.trigger = null;
546
771
  }
772
+
773
+ this.focusTrap.unmount();
547
774
  }
775
+ }
548
776
 
549
- getBreakpoint(key) {
550
- let breakpoint = key;
777
+ async function open$2(query, transition, focus = true) {
778
+ // Get the drawer from collection.
779
+ const drawer = getDrawer.call(this, query); // Get the modal configuration.
551
780
 
552
- if (this.parent.settings.breakpoints && this.parent.settings.breakpoints[key]) {
553
- breakpoint = this.parent.settings.breakpoints[key];
554
- } else if (getComputedStyle(document.body).getPropertyValue(this.prefix + key)) {
555
- breakpoint = getComputedStyle(document.body).getPropertyValue(this.prefix + key);
556
- }
781
+ const config = _extends({}, this.settings, drawer.settings); // Add transition parameter to configuration.
557
782
 
558
- return breakpoint;
559
- }
560
783
 
561
- getVariablePrefix() {
562
- let prefix = '--';
563
- prefix += getComputedStyle(document.body).getPropertyValue('--vrembem-variable-prefix');
564
- prefix += 'breakpoint-';
565
- return prefix;
566
- }
784
+ if (transition !== undefined) config.transition = transition; // If drawer is closed.
567
785
 
568
- }
786
+ if (drawer.state === 'closed') {
787
+ // Update drawer state.
788
+ drawer.state = 'opening'; // Run the open transition.
569
789
 
570
- function getDrawer(drawerKey) {
571
- if (typeof drawerKey !== 'string') return drawerKey;
572
- return document.querySelector(`[data-${this.settings.dataDrawer}="${drawerKey}"]`);
573
- }
574
- function drawerNotFound(key) {
575
- return Promise.reject(new Error(`Did not find drawer with key: "${key}"`));
790
+ await openTransition(drawer.el, config); // Update the global state if mode is modal.
791
+
792
+ if (drawer.mode === 'modal') updateGlobalState(true, config); // Update drawer state.
793
+
794
+ drawer.state = 'opened';
795
+ } // Set focus to the drawer element if the focus param is true.
796
+
797
+
798
+ if (focus) {
799
+ updateFocusState$1.call(this, drawer);
800
+ } // Dispatch custom opened event.
801
+
802
+
803
+ drawer.el.dispatchEvent(new CustomEvent(config.customEventPrefix + 'opened', {
804
+ detail: this,
805
+ bubbles: true
806
+ })); // Return the drawer.
807
+
808
+ return drawer;
576
809
  }
577
810
 
578
- async function close$2(drawerKey) {
579
- const drawer = this.getDrawer(drawerKey);
580
- if (!drawer) return drawerNotFound(drawerKey);
811
+ async function close$2(query, transition, focus = true) {
812
+ // Get the drawer from collection.
813
+ const drawer = getDrawer.call(this, query); // Get the modal configuration.
581
814
 
582
- if (hasClass(drawer, this.settings.stateOpened)) {
583
- this.working = true;
815
+ const config = _extends({}, this.settings, drawer.settings); // Add transition parameter to configuration.
584
816
 
585
- if (hasClass(drawer, this.settings.classModal)) {
586
- setInert(false, this.settings.selectorInert);
587
- setOverflowHidden(false, this.settings.selectorOverflow);
588
- }
589
817
 
590
- await closeTransition(drawer, this.settings);
591
- this.stateSave(drawer);
592
- focusTrigger(this);
593
- this.focusTrap.destroy();
594
- drawer.dispatchEvent(new CustomEvent(this.settings.customEventPrefix + 'closed', {
818
+ if (transition !== undefined) config.transition = transition; // If drawer is opened.
819
+
820
+ if (drawer.state === 'opened') {
821
+ // Update drawer state.
822
+ drawer.state = 'closing'; // Remove focus from active element.
823
+
824
+ document.activeElement.blur(); // Run the close transition.
825
+
826
+ await closeTransition(drawer.el, config); // Update the global state if mode is modal.
827
+
828
+ if (drawer.mode === 'modal') updateGlobalState(false, config); // Set focus to the trigger element if the focus param is true.
829
+
830
+ if (focus) {
831
+ updateFocusState$1.call(this, drawer);
832
+ } // Update drawer state.
833
+
834
+
835
+ drawer.state = 'closed'; // Dispatch custom closed event.
836
+
837
+ drawer.el.dispatchEvent(new CustomEvent(config.customEventPrefix + 'closed', {
595
838
  detail: this,
596
839
  bubbles: true
597
840
  }));
598
- this.working = false;
599
- return drawer;
841
+ } // Return the drawer.
842
+
843
+
844
+ return drawer;
845
+ }
846
+
847
+ async function toggle(query, transition, focus) {
848
+ // Get the drawer from collection.
849
+ const drawer = getDrawer.call(this, query); // Open or close the drawer based on its current state.
850
+
851
+ if (drawer.state === 'closed') {
852
+ return open$2.call(this, drawer, transition, focus);
600
853
  } else {
601
- return drawer;
854
+ return close$2.call(this, drawer, transition, focus);
602
855
  }
603
856
  }
604
857
 
605
- function handlerClick$1(event) {
606
- // Working catch
607
- if (this.working) return; // Toggle data trigger
858
+ function switchMode(entry) {
859
+ switch (entry.mode) {
860
+ case 'inline':
861
+ return toInline.call(this, entry);
608
862
 
609
- let trigger = event.target.closest(`[data-${this.settings.dataToggle}]`);
863
+ case 'modal':
864
+ return toModal.call(this, entry);
610
865
 
611
- if (trigger) {
612
- const selector = trigger.getAttribute(`data-${this.settings.dataToggle}`);
613
- this.memory.trigger = trigger;
614
- this.toggle(selector);
615
- event.preventDefault();
616
- return;
617
- } // Open data trigger
866
+ default:
867
+ throw new Error(`"${entry.mode}" is not a valid drawer mode.`);
868
+ }
869
+ }
618
870
 
871
+ async function toInline(entry) {
872
+ // Remove the modal class.
873
+ entry.el.classList.remove(entry.getSetting('classModal')); // Remove the aria-modal attribute.
619
874
 
620
- trigger = event.target.closest(`[data-${this.settings.dataOpen}]`);
875
+ entry.dialog.removeAttribute('aria-modal'); // Update the global state.
621
876
 
622
- if (trigger) {
623
- const selector = trigger.getAttribute(`data-${this.settings.dataOpen}`);
624
- this.memory.trigger = trigger;
625
- this.open(selector);
626
- event.preventDefault();
627
- return;
628
- } // Close data trigger
877
+ updateGlobalState(false, _extends({}, this.settings, entry.settings)); // Remove any focus traps.
629
878
 
879
+ this.focusTrap.unmount(); // Setup initial state.
630
880
 
631
- trigger = event.target.closest(`[data-${this.settings.dataClose}]`);
881
+ await initialState.call(this, entry); // Dispatch custom switch event.
632
882
 
633
- if (trigger) {
634
- const selector = trigger.getAttribute(`data-${this.settings.dataClose}`);
883
+ entry.el.dispatchEvent(new CustomEvent(entry.getSetting('customEventPrefix') + 'switchMode', {
884
+ detail: this,
885
+ bubbles: true
886
+ })); // Return the entry.
635
887
 
636
- if (selector) {
637
- this.memory.trigger = trigger;
638
- this.close(selector);
639
- } else {
640
- const target = event.target.closest(`[data-${this.settings.dataDrawer}]`);
641
- if (target) this.close(target);
642
- }
888
+ return entry;
889
+ }
643
890
 
644
- event.preventDefault();
645
- return;
646
- } // Screen modal trigger
891
+ async function toModal(entry) {
892
+ // Get the drawer configuration.
893
+ // Add the modal class.
894
+ entry.el.classList.add(entry.getSetting('classModal')); // Set aria-modal attribute to true.
647
895
 
896
+ entry.dialog.setAttribute('aria-modal', 'true'); // If there isn't a stored state but also has the opened state class...
648
897
 
649
- if (event.target.hasAttribute(`data-${this.settings.dataDrawer}`)) {
650
- this.close(event.target);
651
- return;
652
- }
653
- }
654
- function handlerKeydown$1(event) {
655
- // Working catch
656
- if (this.working) return;
898
+ if (!this.store[entry.id] && entry.el.classList.contains(entry.getSetting('stateOpened'))) {
899
+ // Save the opened state in local store.
900
+ this.store[entry.id] = 'opened';
901
+ } // Modal drawer defaults to closed state.
657
902
 
658
- if (event.key === 'Escape') {
659
- const target = document.querySelector(`.${this.settings.classModal}.${this.settings.stateOpened}`);
660
903
 
661
- if (target) {
662
- this.close(target);
663
- }
664
- }
904
+ await close$2.call(this, entry, false, false); // Dispatch custom switch event.
905
+
906
+ entry.el.dispatchEvent(new CustomEvent(entry.getSetting('customEventPrefix') + 'switchMode', {
907
+ detail: this,
908
+ bubbles: true
909
+ })); // Return the entry.
910
+
911
+ return entry;
665
912
  }
666
913
 
667
- async function open$2(drawerKey) {
668
- const drawer = this.getDrawer(drawerKey);
669
- if (!drawer) return drawerNotFound(drawerKey);
914
+ async function register$2(el, dialog) {
915
+ // Deregister entry incase it has already been registered.
916
+ await deregister$2.call(this, el, false); // Save root this for use inside methods API.
670
917
 
671
- if (!hasClass(drawer, this.settings.stateOpened)) {
672
- this.working = true;
673
- const isModal = hasClass(drawer, this.settings.classModal);
918
+ const root = this; // Create an instance of the Breakpoint class.
674
919
 
675
- if (isModal) {
676
- setOverflowHidden(true, this.settings.selectorOverflow);
677
- }
920
+ const breakpoint = new Breakpoint(); // Setup methods API.
678
921
 
679
- await openTransition(drawer, this.settings);
680
- this.stateSave(drawer);
922
+ const methods = {
923
+ open(transition, focus) {
924
+ return open$2.call(root, this, transition, focus);
925
+ },
681
926
 
682
- if (isModal) {
683
- this.focusTrap.init(drawer);
684
- setInert(true, this.settings.selectorInert);
685
- }
927
+ close(transition, focus) {
928
+ return close$2.call(root, this, transition, focus);
929
+ },
686
930
 
687
- focusTarget(drawer, this.settings);
688
- drawer.dispatchEvent(new CustomEvent(this.settings.customEventPrefix + 'opened', {
689
- detail: this,
690
- bubbles: true
691
- }));
692
- this.working = false;
693
- return drawer;
694
- } else {
695
- focusTarget(drawer, this.settings);
696
- return drawer;
697
- }
698
- }
931
+ toggle(transition, focus) {
932
+ return toggle.call(root, this, transition, focus);
933
+ },
934
+
935
+ deregister() {
936
+ return deregister$2.call(root, this);
937
+ },
699
938
 
700
- function stateSet(settings) {
701
- // If save state is disabled
702
- if (!settings.stateSave) return stateClear(settings); // If there isn't an existing state to set
939
+ mountBreakpoint() {
940
+ const value = this.breakpoint;
941
+ const handler = this.handleBreakpoint.bind(this);
942
+ breakpoint.mount(value, handler);
943
+ return this;
944
+ },
703
945
 
704
- const storageCheck = localStorage.getItem(settings.stateKey);
946
+ unmountBreakpoint() {
947
+ breakpoint.unmount();
948
+ return this;
949
+ },
705
950
 
706
- if (!storageCheck || storageCheck && Object.keys(JSON.parse(storageCheck)).length === 0) {
707
- return stateSave(null, settings);
708
- } // Set the existing state
951
+ handleBreakpoint(event) {
952
+ this.mode = event.matches ? 'inline' : 'modal';
953
+ return this;
954
+ },
709
955
 
956
+ getSetting(key) {
957
+ return key in this.settings ? this.settings[key] : root.settings[key];
958
+ }
710
959
 
711
- const state = JSON.parse(localStorage.getItem(settings.stateKey));
712
- Object.keys(state).forEach(key => {
713
- const item = document.querySelector(`[data-${settings.dataDrawer}="${key}"]`);
714
- if (!item) return;
715
- state[key] == settings.stateOpened ? addClass(item, settings.stateOpened) : removeClass(item, settings.stateOpened);
716
- });
717
- return state;
718
- }
719
- function stateSave(target, settings) {
720
- // If save state is disabled
721
- if (!settings.stateSave) return stateClear(settings); // Get the currently saved object if it exists
960
+ }; // Setup the drawer object.
722
961
 
723
- const state = localStorage.getItem(settings.stateKey) ? JSON.parse(localStorage.getItem(settings.stateKey)) : {}; // Are we saving a single target or the entire suite?
962
+ const entry = _extends({
963
+ id: el.id,
964
+ el: el,
965
+ dialog: dialog,
966
+ trigger: null,
967
+ settings: getConfig$1(el, this.settings.dataConfig),
724
968
 
725
- const drawers = target ? [target] : document.querySelectorAll(`[data-${settings.dataDrawer}]`); // Loop through drawers and save their states
969
+ get breakpoint() {
970
+ return getBreakpoint.call(root, el);
971
+ },
726
972
 
727
- drawers.forEach(el => {
728
- if (hasClass(el, settings.classModal)) return;
729
- const drawerKey = el.getAttribute(`data-${settings.dataDrawer}`);
730
- state[drawerKey] = hasClass(el, settings.stateOpened) ? settings.stateOpened : settings.stateClosed;
731
- }); // Save to localStorage and return the state
973
+ get state() {
974
+ return __state;
975
+ },
732
976
 
733
- localStorage.setItem(settings.stateKey, JSON.stringify(state));
734
- return state;
735
- }
736
- function stateClear(settings) {
737
- if (localStorage.getItem(settings.stateKey)) {
738
- localStorage.removeItem(settings.stateKey);
739
- }
977
+ set state(value) {
978
+ __state = value; // Save 'opened' and 'closed' states to store if mode is inline.
740
979
 
741
- return {};
742
- }
980
+ if (value === 'opened' || value === 'closed') {
981
+ if (this.mode === 'inline') root.store[this.id] = this.state;
982
+ }
983
+ },
743
984
 
744
- async function switchToModal(drawerKey) {
745
- // Initial guards
746
- const drawer = this.getDrawer(drawerKey);
747
- if (!drawer) return drawerNotFound(drawerKey);
748
- if (hasClass(drawer, this.settings.classModal)) return; // Enable modal state
985
+ get mode() {
986
+ return __mode;
987
+ },
749
988
 
750
- addClass(drawer, this.settings.classModal);
751
- addClass(drawer, this.settings.stateClosed);
752
- removeClass(drawer, this.settings.stateOpened); // Dispatch custom event
989
+ set mode(value) {
990
+ __mode = value;
991
+ switchMode.call(root, this);
992
+ }
753
993
 
754
- drawer.dispatchEvent(new CustomEvent(this.settings.customEventPrefix + 'toModal', {
755
- bubbles: true
756
- }));
757
- return drawer;
758
- }
759
- async function switchToDefault(drawerKey) {
760
- // Initial guards
761
- const drawer = this.getDrawer(drawerKey);
762
- if (!drawer) return drawerNotFound(drawerKey);
763
- if (!hasClass(drawer, this.settings.classModal)) return; // Tear down modal state
994
+ }, methods); // Create the state var with the initial state.
764
995
 
765
- setInert(false, this.settings.selectorInert);
766
- setOverflowHidden(false, this.settings.selectorOverflow);
767
- removeClass(drawer, this.settings.classModal);
768
- this.focusTrap.destroy(); // Restore drawers saved state
769
996
 
770
- drawerKey = drawer.getAttribute(`data-${this.settings.dataDrawer}`);
771
- const drawerState = this.state[drawerKey];
997
+ let __state = el.classList.contains(entry.getSetting('stateOpened')) ? 'opened' : 'closed'; // Create the mode var with the initial mode.
772
998
 
773
- if (drawerState == this.settings.stateOpened) {
774
- addClass(drawer, this.settings.stateOpened);
775
- removeClass(drawer, this.settings.stateClosed);
776
- } // Dispatch custom event
777
999
 
1000
+ let __mode = el.classList.contains(entry.getSetting('classModal')) ? 'modal' : 'inline'; // Setup mode specific attributes.
1001
+
1002
+
1003
+ if (entry.mode === 'modal') {
1004
+ // Set aria-modal attribute to true.
1005
+ entry.dialog.setAttribute('aria-modal', 'true');
1006
+ } else {
1007
+ // Remove the aria-modal attribute.
1008
+ entry.dialog.removeAttribute('aria-modal');
1009
+ } // Set tabindex="-1" so dialog is focusable via JS or click.
1010
+
1011
+
1012
+ if (entry.getSetting('setTabindex')) {
1013
+ entry.dialog.setAttribute('tabindex', '-1');
1014
+ } // Add entry to collection.
778
1015
 
779
- drawer.dispatchEvent(new CustomEvent(this.settings.customEventPrefix + 'toDefault', {
780
- bubbles: true
781
- }));
782
- return drawer;
783
- }
784
1016
 
785
- async function toggle(drawerKey) {
786
- const drawer = this.getDrawer(drawerKey);
787
- if (!drawer) return drawerNotFound(drawerKey);
788
- const isClosed = !hasClass(drawer, this.settings.stateOpened);
1017
+ this.collection.push(entry); // If the entry has a breakpoint...
789
1018
 
790
- if (isClosed) {
791
- return this.open(drawer);
1019
+ if (entry.breakpoint) {
1020
+ // Mount media query breakpoint functionality.
1021
+ entry.mountBreakpoint();
792
1022
  } else {
793
- return this.close(drawer);
794
- }
1023
+ // Else, Setup initial state.
1024
+ await initialState.call(this, entry);
1025
+ } // Return the registered entry.
1026
+
1027
+
1028
+ return entry;
795
1029
  }
796
1030
 
797
- class Drawer {
1031
+ var _handleClick$1 = /*#__PURE__*/_classPrivateFieldLooseKey("handleClick");
1032
+
1033
+ var _handleKeydown$2 = /*#__PURE__*/_classPrivateFieldLooseKey("handleKeydown");
1034
+
1035
+ class Drawer extends Collection {
798
1036
  constructor(options) {
1037
+ super();
1038
+ Object.defineProperty(this, _handleClick$1, {
1039
+ writable: true,
1040
+ value: void 0
1041
+ });
1042
+ Object.defineProperty(this, _handleKeydown$2, {
1043
+ writable: true,
1044
+ value: void 0
1045
+ });
799
1046
  this.defaults = defaults$2;
800
1047
  this.settings = _extends({}, this.defaults, options);
801
- this.working = false;
802
- this.memory = {};
803
- this.state = {};
804
- this.focusTrap = new FocusTrap();
805
- this.breakpoint = new Breakpoint(this);
806
- this.__handlerClick = handlerClick$1.bind(this);
807
- this.__handlerKeydown = handlerKeydown$1.bind(this);
1048
+ this.focusTrap = new FocusTrap(); // Setup local store for inline drawer state management.
1049
+
1050
+ this.store = localStore(this.settings.storeKey, this.settings.store);
1051
+ _classPrivateFieldLooseBase(this, _handleClick$1)[_handleClick$1] = handleClick$2.bind(this);
1052
+ _classPrivateFieldLooseBase(this, _handleKeydown$2)[_handleKeydown$2] = handleKeydown$2.bind(this);
808
1053
  if (this.settings.autoInit) this.init();
809
1054
  }
810
1055
 
811
- init(options = null) {
812
- if (options) this.settings = _extends({}, this.settings, options);
813
- this.stateSet();
1056
+ get activeModal() {
1057
+ return this.collection.find(entry => {
1058
+ return entry.state === 'opened' && entry.mode === 'modal';
1059
+ });
1060
+ }
814
1061
 
815
- if (this.settings.setTabindex) {
816
- this.setTabindex();
817
- }
1062
+ async init(options = null) {
1063
+ // Update settings with passed options.
1064
+ if (options) this.settings = _extends({}, this.settings, options); // Get all the modals.
818
1065
 
819
- this.breakpoint.init();
1066
+ const drawers = document.querySelectorAll(this.settings.selectorDrawer); // Register the collections array with modal instances.
1067
+
1068
+ await this.registerCollection(drawers); // If eventListeners are enabled, init event listeners.
820
1069
 
821
1070
  if (this.settings.eventListeners) {
822
1071
  this.initEventListeners();
823
1072
  }
1073
+
1074
+ return this;
824
1075
  }
825
1076
 
826
- destroy() {
827
- this.breakpoint.destroy();
828
- this.memory = {};
829
- this.state = {};
830
- localStorage.removeItem(this.settings.stateKey);
1077
+ async destroy() {
1078
+ // Remove all entries from the collection.
1079
+ await this.deregisterCollection(); // If eventListeners are enabled, init event listeners.
831
1080
 
832
1081
  if (this.settings.eventListeners) {
833
1082
  this.destroyEventListeners();
834
1083
  }
835
- }
836
- /**
837
- * Event listeners
838
- */
839
1084
 
1085
+ return this;
1086
+ }
840
1087
 
841
1088
  initEventListeners() {
842
- document.addEventListener('click', this.__handlerClick, false);
843
- document.addEventListener('touchend', this.__handlerClick, false);
844
- document.addEventListener('keydown', this.__handlerKeydown, false);
1089
+ document.addEventListener('click', _classPrivateFieldLooseBase(this, _handleClick$1)[_handleClick$1], false);
1090
+ document.addEventListener('touchend', _classPrivateFieldLooseBase(this, _handleClick$1)[_handleClick$1], false);
1091
+ document.addEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown$2)[_handleKeydown$2], false);
845
1092
  }
846
1093
 
847
1094
  destroyEventListeners() {
848
- document.removeEventListener('click', this.__handlerClick, false);
849
- document.removeEventListener('touchend', this.__handlerClick, false);
850
- document.removeEventListener('keydown', this.__handlerKeydown, false);
851
- }
852
- /**
853
- * Helpers
854
- */
855
-
856
-
857
- getDrawer(drawerKey) {
858
- return getDrawer.call(this, drawerKey);
859
- }
860
-
861
- setTabindex() {
862
- return setTabindex(`
863
- [data-${this.settings.dataDrawer}]
864
- [data-${this.settings.dataDialog}]
865
- `);
866
- }
867
- /**
868
- * Save state functionality
869
- */
870
-
871
-
872
- stateSet() {
873
- this.state = stateSet(this.settings);
874
- }
875
-
876
- stateSave(target = null) {
877
- this.state = stateSave(target, this.settings);
1095
+ document.removeEventListener('click', _classPrivateFieldLooseBase(this, _handleClick$1)[_handleClick$1], false);
1096
+ document.removeEventListener('touchend', _classPrivateFieldLooseBase(this, _handleClick$1)[_handleClick$1], false);
1097
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown$2)[_handleKeydown$2], false);
878
1098
  }
879
1099
 
880
- stateClear() {
881
- this.state = stateClear(this.settings);
882
- }
883
- /**
884
- * SwitchTo functionality
885
- */
886
-
887
-
888
- switchToDefault(drawerKey) {
889
- return switchToDefault.call(this, drawerKey);
1100
+ register(query) {
1101
+ const els = getDrawerElements.call(this, query);
1102
+ if (els.error) return Promise.reject(els.error);
1103
+ return register$2.call(this, els.drawer, els.dialog);
890
1104
  }
891
1105
 
892
- switchToModal(drawerKey) {
893
- return switchToModal.call(this, drawerKey);
1106
+ deregister(query) {
1107
+ const entry = this.get(getDrawerID.call(this, query));
1108
+ return deregister$2.call(this, entry);
894
1109
  }
895
- /**
896
- * Change state functionality
897
- */
898
1110
 
899
-
900
- toggle(drawerKey) {
901
- return toggle.call(this, drawerKey);
1111
+ open(id, transition, focus) {
1112
+ return open$2.call(this, id, transition, focus);
902
1113
  }
903
1114
 
904
- open(drawerKey) {
905
- return open$2.call(this, drawerKey);
1115
+ close(id, transition, focus) {
1116
+ return close$2.call(this, id, transition, focus);
906
1117
  }
907
1118
 
908
- close(drawerKey) {
909
- return close$2.call(this, drawerKey);
1119
+ toggle(id, transition, focus) {
1120
+ return toggle.call(this, id, transition, focus);
910
1121
  }
911
1122
 
912
1123
  }
@@ -939,38 +1150,6 @@ var defaults$1 = {
939
1150
  transition: true
940
1151
  };
941
1152
 
942
- function updateGlobalState() {
943
- // Set inert state based on if a modal is active.
944
- setInert(!!this.active, this.settings.selectorInert); // Set overflow state based on if a modal is active.
945
-
946
- setOverflowHidden(!!this.active, this.settings.selectorOverflow); // Update the z-index of the stack.
947
-
948
- updateStackIndex(this.stack);
949
- }
950
- function updateFocusState() {
951
- // Check if there's an active modal
952
- if (this.active) {
953
- // Set focus and init focus trap on active modal.
954
- focusTarget(this.active.target, this.settings);
955
- this.focusTrap.init(this.active.target);
956
- } else {
957
- // Set focus to root trigger and destroy focus trap.
958
- focusTrigger(this);
959
- this.focusTrap.destroy();
960
- }
961
- }
962
- function updateStackIndex(stack) {
963
- stack.forEach((entry, index) => {
964
- entry.target.style.zIndex = null;
965
- const value = getComputedStyle(entry.target)['z-index'];
966
- entry.target.style.zIndex = parseInt(value) + index + 1;
967
- });
968
- }
969
- function getConfig$1(el) {
970
- const string = el.getAttribute(`data-${this.settings.dataConfig}`) || '';
971
- const json = string.replace(/'/g, '"');
972
- return json ? JSON.parse(json) : {};
973
- }
974
1153
  function getModal(query) {
975
1154
  // Get the entry from collection.
976
1155
  const entry = typeof query === 'string' ? this.get(query) : this.get(query.id); // Return entry if it was resolved, otherwise throw error.
@@ -978,9 +1157,10 @@ function getModal(query) {
978
1157
  if (entry) {
979
1158
  return entry;
980
1159
  } else {
981
- throw new Error(`Modal not found in collection with id of "${query}".`);
1160
+ throw new Error(`Modal not found in collection with id of "${query.id || query}".`);
982
1161
  }
983
1162
  }
1163
+
984
1164
  function getModalID(obj) {
985
1165
  // If it's a string, return the string.
986
1166
  if (typeof obj === 'string') {
@@ -996,7 +1176,7 @@ function getModalID(obj) {
996
1176
  } // If it's a modal replace trigger, return data value.
997
1177
  else if (obj.hasAttribute(`data-${this.settings.dataReplace}`)) {
998
1178
  return obj.getAttribute(`data-${this.settings.dataReplace}`);
999
- } // If it's a modal target, return the id.
1179
+ } // If it's a modal element, return the id.
1000
1180
  else if (obj.closest(this.settings.selectorModal)) {
1001
1181
  obj = obj.closest(this.settings.selectorModal);
1002
1182
  return obj.id || false;
@@ -1008,14 +1188,15 @@ function getModalID(obj) {
1008
1188
  } // Return false if no id was found.
1009
1189
  else return false;
1010
1190
  }
1191
+
1011
1192
  function getModalElements(query) {
1012
1193
  const id = getModalID.call(this, query);
1013
1194
 
1014
1195
  if (id) {
1015
- const target = document.querySelector(`#${id}`);
1016
- const dialog = target ? target.querySelector(this.settings.selectorDialog) : null;
1196
+ const modal = document.querySelector(`#${id}`);
1197
+ const dialog = modal ? modal.querySelector(this.settings.selectorDialog) : null;
1017
1198
 
1018
- if (!target && !dialog) {
1199
+ if (!modal && !dialog) {
1019
1200
  return {
1020
1201
  error: new Error(`No modal elements found using the ID: "${id}".`)
1021
1202
  };
@@ -1025,7 +1206,7 @@ function getModalElements(query) {
1025
1206
  };
1026
1207
  } else {
1027
1208
  return {
1028
- target,
1209
+ modal,
1029
1210
  dialog
1030
1211
  };
1031
1212
  }
@@ -1036,7 +1217,31 @@ function getModalElements(query) {
1036
1217
  }
1037
1218
  }
1038
1219
 
1039
- async function handleClick(event) {
1220
+ function updateFocusState() {
1221
+ // Check if there's an active modal
1222
+ if (this.active) {
1223
+ // Mount the focus trap on the active modal.
1224
+ this.focusTrap.mount(this.active.dialog, this.settings.selectorFocus);
1225
+ } else {
1226
+ // Set focus to root trigger and unmount the focus trap.
1227
+ if (this.trigger) {
1228
+ this.trigger.focus();
1229
+ this.trigger = null;
1230
+ }
1231
+
1232
+ this.focusTrap.unmount();
1233
+ }
1234
+ }
1235
+
1236
+ function updateStackIndex(stack) {
1237
+ stack.forEach((entry, index) => {
1238
+ entry.el.style.zIndex = null;
1239
+ const value = getComputedStyle(entry.el)['z-index'];
1240
+ entry.el.style.zIndex = parseInt(value) + index + 1;
1241
+ });
1242
+ }
1243
+
1244
+ async function handleClick$1(event) {
1040
1245
  // If an open or replace button was clicked, open or replace the modal.
1041
1246
  let trigger = event.target.closest(`[data-${this.settings.dataOpen}], [data-${this.settings.dataReplace}]`);
1042
1247
 
@@ -1044,7 +1249,7 @@ async function handleClick(event) {
1044
1249
  event.preventDefault(); // Save the trigger if it's not coming from inside a modal.
1045
1250
 
1046
1251
  const fromModal = event.target.closest(this.settings.selectorModal);
1047
- if (!fromModal) this.memory.trigger = trigger; // Get the modal.
1252
+ if (!fromModal) this.trigger = trigger; // Get the modal.
1048
1253
 
1049
1254
  const modal = this.get(getModalID.call(this, trigger)); // Depending on the button type, either open or replace the modal.
1050
1255
 
@@ -1067,7 +1272,7 @@ async function handleClick(event) {
1067
1272
  return this.close(getModalID.call(this, event.target));
1068
1273
  }
1069
1274
  }
1070
- function handleKeydown(event) {
1275
+ function handleKeydown$1(event) {
1071
1276
  // If escape key was pressed.
1072
1277
  if (event.key === 'Escape') {
1073
1278
  // If a modal is opened and not required, close the modal.
@@ -1119,7 +1324,7 @@ async function deregister$1(obj, close = true) {
1119
1324
  return this.collection;
1120
1325
  }
1121
1326
 
1122
- async function open$1(query, transition, bulk = false) {
1327
+ async function open$1(query, transition, focus = true) {
1123
1328
  // Get the modal from collection.
1124
1329
  const modal = getModal.call(this, query); // Get the modal configuration.
1125
1330
 
@@ -1144,24 +1349,24 @@ async function open$1(query, transition, bulk = false) {
1144
1349
  // Update modal state.
1145
1350
  modal.state = 'opening'; // Apply z-index styles based on stack length.
1146
1351
 
1147
- modal.target.style.zIndex = null;
1148
- const value = getComputedStyle(modal.target)['z-index'];
1149
- modal.target.style.zIndex = parseInt(value) + this.stack.length + 1; // Store modal in stack array.
1352
+ modal.el.style.zIndex = null;
1353
+ const value = getComputedStyle(modal.el)['z-index'];
1354
+ modal.el.style.zIndex = parseInt(value) + this.stack.length + 1; // Store modal in stack array.
1150
1355
 
1151
1356
  this.stack.push(modal); // Run the open transition.
1152
1357
 
1153
- await openTransition(modal.target, config); // Update modal state.
1358
+ await openTransition(modal.el, config); // Update modal state.
1154
1359
 
1155
1360
  modal.state = 'opened';
1156
- } // Update the focus state if this is not a bulk action.
1361
+ } // Update focus if the focus param is true.
1157
1362
 
1158
1363
 
1159
- if (!bulk) {
1364
+ if (focus) {
1160
1365
  updateFocusState.call(this);
1161
1366
  } // Dispatch custom opened event.
1162
1367
 
1163
1368
 
1164
- modal.target.dispatchEvent(new CustomEvent(config.customEventPrefix + 'opened', {
1369
+ modal.el.dispatchEvent(new CustomEvent(config.customEventPrefix + 'opened', {
1165
1370
  detail: this,
1166
1371
  bubbles: true
1167
1372
  })); // Return the modal.
@@ -1169,7 +1374,7 @@ async function open$1(query, transition, bulk = false) {
1169
1374
  return modal;
1170
1375
  }
1171
1376
 
1172
- async function close$1(query, transition, bulk = false) {
1377
+ async function close$1(query, transition, focus = true) {
1173
1378
  // Get the modal from collection, or top modal in stack if no query is provided.
1174
1379
  const modal = query ? getModal.call(this, query) : this.active; // If a modal exists and its state is opened.
1175
1380
 
@@ -1184,24 +1389,24 @@ async function close$1(query, transition, bulk = false) {
1184
1389
 
1185
1390
  document.activeElement.blur(); // Run the close transition.
1186
1391
 
1187
- await closeTransition(modal.target, config); // Remove z-index styles.
1392
+ await closeTransition(modal.el, config); // Remove z-index styles.
1188
1393
 
1189
- modal.target.style.zIndex = null; // Get index of modal in stack array.
1394
+ modal.el.style.zIndex = null; // Get index of modal in stack array.
1190
1395
 
1191
1396
  const index = this.stack.findIndex(entry => {
1192
1397
  return entry.id === modal.id;
1193
1398
  }); // Remove modal from stack array.
1194
1399
 
1195
- this.stack.splice(index, 1); // Update the focus state if this is not a bulk action.
1400
+ this.stack.splice(index, 1); // Update focus if the focus param is true.
1196
1401
 
1197
- if (!bulk) {
1402
+ if (focus) {
1198
1403
  updateFocusState.call(this);
1199
1404
  } // Update modal state.
1200
1405
 
1201
1406
 
1202
1407
  modal.state = 'closed'; // Dispatch custom closed event.
1203
1408
 
1204
- modal.target.dispatchEvent(new CustomEvent(config.customEventPrefix + 'closed', {
1409
+ modal.el.dispatchEvent(new CustomEvent(config.customEventPrefix + 'closed', {
1205
1410
  detail: this,
1206
1411
  bubbles: true
1207
1412
  }));
@@ -1217,7 +1422,7 @@ async function closeAll$1(exclude, transition) {
1217
1422
  if (exclude && exclude === modal.id) {
1218
1423
  Promise.resolve();
1219
1424
  } else {
1220
- result.push(await close$1.call(this, modal, transition, true));
1425
+ result.push(await close$1.call(this, modal, transition, false));
1221
1426
  }
1222
1427
 
1223
1428
  modal.trigger = null;
@@ -1225,7 +1430,7 @@ async function closeAll$1(exclude, transition) {
1225
1430
  return result;
1226
1431
  }
1227
1432
 
1228
- async function replace(query, transition) {
1433
+ async function replace(query, transition, focus = true) {
1229
1434
  // Get the modal from collection.
1230
1435
  const modal = getModal.call(this, query); // Setup results for return.
1231
1436
 
@@ -1237,13 +1442,16 @@ async function replace(query, transition) {
1237
1442
  resultClosed = await closeAll$1.call(this, modal.id, transition);
1238
1443
  } else {
1239
1444
  // If modal is closed, close all and open replacement at the same time.
1240
- resultOpened = open$1.call(this, modal, transition, true);
1445
+ resultOpened = open$1.call(this, modal, transition, false);
1241
1446
  resultClosed = closeAll$1.call(this, false, transition);
1242
1447
  await Promise.all([resultOpened, resultClosed]);
1243
- } // Update the focus state.
1448
+ } // Update focus if the focus param is true.
1449
+
1244
1450
 
1451
+ if (focus) {
1452
+ updateFocusState.call(this);
1453
+ } // Return the modals there were opened and closed.
1245
1454
 
1246
- updateFocusState.call(this); // Return the modals there were opened and closed.
1247
1455
 
1248
1456
  return {
1249
1457
  opened: resultOpened,
@@ -1251,23 +1459,23 @@ async function replace(query, transition) {
1251
1459
  };
1252
1460
  }
1253
1461
 
1254
- async function register$1(target, dialog) {
1462
+ async function register$1(el, dialog) {
1255
1463
  // Deregister entry incase it has already been registered.
1256
- await deregister$1.call(this, target, false); // Save root this for use inside methods API.
1464
+ await deregister$1.call(this, el, false); // Save root this for use inside methods API.
1257
1465
 
1258
1466
  const root = this; // Setup methods API.
1259
1467
 
1260
1468
  const methods = {
1261
- open(transition) {
1262
- return open$1.call(root, this, transition);
1469
+ open(transition, focus) {
1470
+ return open$1.call(root, this, transition, focus);
1263
1471
  },
1264
1472
 
1265
- close(transition) {
1266
- return close$1.call(root, this, transition);
1473
+ close(transition, focus) {
1474
+ return close$1.call(root, this, transition, focus);
1267
1475
  },
1268
1476
 
1269
- replace(transition) {
1270
- return replace.call(root, this, transition);
1477
+ replace(transition, focus) {
1478
+ return replace.call(root, this, transition, focus);
1271
1479
  },
1272
1480
 
1273
1481
  deregister() {
@@ -1276,20 +1484,20 @@ async function register$1(target, dialog) {
1276
1484
 
1277
1485
  teleport(ref = this.getSetting('teleport'), method = this.getSetting('teleportMethod')) {
1278
1486
  if (!this.returnRef) {
1279
- this.returnRef = teleport(this.target, ref, method);
1280
- return this.target;
1487
+ this.returnRef = teleport(this.el, ref, method);
1488
+ return this.el;
1281
1489
  } else {
1282
- console.error('Element has already been teleported:', this.target);
1490
+ console.error('Element has already been teleported:', this.el);
1283
1491
  return false;
1284
1492
  }
1285
1493
  },
1286
1494
 
1287
1495
  teleportReturn() {
1288
1496
  if (this.returnRef) {
1289
- this.returnRef = teleport(this.target, this.returnRef);
1290
- return this.target;
1497
+ this.returnRef = teleport(this.el, this.returnRef);
1498
+ return this.el;
1291
1499
  } else {
1292
- console.error('No return reference found:', this.target);
1500
+ console.error('No return reference found:', this.el);
1293
1501
  return false;
1294
1502
  }
1295
1503
  },
@@ -1301,12 +1509,12 @@ async function register$1(target, dialog) {
1301
1509
  }; // Setup the modal object.
1302
1510
 
1303
1511
  const entry = _extends({
1304
- id: target.id,
1512
+ id: el.id,
1305
1513
  state: 'closed',
1306
- settings: getConfig$1.call(this, target),
1307
- target: target,
1514
+ el: el,
1308
1515
  dialog: dialog,
1309
- returnRef: null
1516
+ returnRef: null,
1517
+ settings: getConfig$1(el, this.settings.dataConfig)
1310
1518
  }, methods); // Set aria-modal attribute to true.
1311
1519
 
1312
1520
 
@@ -1329,42 +1537,55 @@ async function register$1(target, dialog) {
1329
1537
 
1330
1538
  this.collection.push(entry); // Setup initial state.
1331
1539
 
1332
- if (entry.target.classList.contains(this.settings.stateOpened)) {
1333
- // Open modal with transitions disabled.
1334
- entry.open(false);
1540
+ if (entry.el.classList.contains(this.settings.stateOpened)) {
1541
+ // Open entry with transitions disabled.
1542
+ await entry.open(false);
1335
1543
  } else {
1336
1544
  // Remove transition state classes.
1337
- entry.target.classList.remove(this.settings.stateOpening);
1338
- entry.target.classList.remove(this.settings.stateClosing); // Add closed state class.
1545
+ entry.el.classList.remove(this.settings.stateOpening);
1546
+ entry.el.classList.remove(this.settings.stateClosing); // Add closed state class.
1339
1547
 
1340
- entry.target.classList.add(this.settings.stateClosed);
1548
+ entry.el.classList.add(this.settings.stateClosed);
1341
1549
  } // Return the registered entry.
1342
1550
 
1343
1551
 
1344
1552
  return entry;
1345
1553
  }
1346
1554
 
1555
+ var _handleClick = /*#__PURE__*/_classPrivateFieldLooseKey("handleClick");
1556
+
1557
+ var _handleKeydown$1 = /*#__PURE__*/_classPrivateFieldLooseKey("handleKeydown");
1558
+
1347
1559
  class Modal extends Collection {
1348
1560
  constructor(options) {
1349
1561
  super();
1562
+ Object.defineProperty(this, _handleClick, {
1563
+ writable: true,
1564
+ value: void 0
1565
+ });
1566
+ Object.defineProperty(this, _handleKeydown$1, {
1567
+ writable: true,
1568
+ value: void 0
1569
+ });
1350
1570
  this.defaults = defaults$1;
1351
1571
  this.settings = _extends({}, this.defaults, options);
1352
- this.memory = {};
1572
+ this.trigger = null;
1353
1573
  this.focusTrap = new FocusTrap(); // Setup a proxy for stack array.
1354
1574
 
1355
1575
  this.stack = new Proxy([], {
1356
1576
  set: (target, property, value) => {
1357
- target[property] = value; // Update global state whenever the length property of stack changes.
1577
+ target[property] = value; // Update global state if stack length changed.
1358
1578
 
1359
1579
  if (property === 'length') {
1360
- updateGlobalState.call(this);
1580
+ updateGlobalState(this.active, this.settings);
1581
+ updateStackIndex(this.stack);
1361
1582
  }
1362
1583
 
1363
1584
  return true;
1364
1585
  }
1365
1586
  });
1366
- this.__handleClick = handleClick.bind(this);
1367
- this.__handleKeydown = handleKeydown.bind(this);
1587
+ _classPrivateFieldLooseBase(this, _handleClick)[_handleClick] = handleClick$1.bind(this);
1588
+ _classPrivateFieldLooseBase(this, _handleKeydown$1)[_handleKeydown$1] = handleKeydown$1.bind(this);
1368
1589
  if (this.settings.autoInit) this.init();
1369
1590
  }
1370
1591
 
@@ -1383,35 +1604,39 @@ class Modal extends Collection {
1383
1604
  if (this.settings.eventListeners) {
1384
1605
  this.initEventListeners();
1385
1606
  }
1607
+
1608
+ return this;
1386
1609
  }
1387
1610
 
1388
1611
  async destroy() {
1389
- // Clear any stored memory.
1390
- this.memory = {}; // Remove all entries from the collection.
1612
+ // Clear stored trigger.
1613
+ this.trigger = null; // Remove all entries from the collection.
1391
1614
 
1392
1615
  await this.deregisterCollection(); // If eventListeners are enabled, destroy event listeners.
1393
1616
 
1394
1617
  if (this.settings.eventListeners) {
1395
1618
  this.destroyEventListeners();
1396
1619
  }
1620
+
1621
+ return this;
1397
1622
  }
1398
1623
 
1399
1624
  initEventListeners() {
1400
- document.addEventListener('click', this.__handleClick, false);
1401
- document.addEventListener('touchend', this.__handleClick, false);
1402
- document.addEventListener('keydown', this.__handleKeydown, false);
1625
+ document.addEventListener('click', _classPrivateFieldLooseBase(this, _handleClick)[_handleClick], false);
1626
+ document.addEventListener('touchend', _classPrivateFieldLooseBase(this, _handleClick)[_handleClick], false);
1627
+ document.addEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown$1)[_handleKeydown$1], false);
1403
1628
  }
1404
1629
 
1405
1630
  destroyEventListeners() {
1406
- document.removeEventListener('click', this.__handleClick, false);
1407
- document.removeEventListener('touchend', this.__handleClick, false);
1408
- document.removeEventListener('keydown', this.__handleKeydown, false);
1631
+ document.removeEventListener('click', _classPrivateFieldLooseBase(this, _handleClick)[_handleClick], false);
1632
+ document.removeEventListener('touchend', _classPrivateFieldLooseBase(this, _handleClick)[_handleClick], false);
1633
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown$1)[_handleKeydown$1], false);
1409
1634
  }
1410
1635
 
1411
1636
  register(query) {
1412
1637
  const els = getModalElements.call(this, query);
1413
1638
  if (els.error) return Promise.reject(els.error);
1414
- return register$1.call(this, els.target, els.dialog);
1639
+ return register$1.call(this, els.modal, els.dialog);
1415
1640
  }
1416
1641
 
1417
1642
  deregister(query) {
@@ -1419,21 +1644,25 @@ class Modal extends Collection {
1419
1644
  return deregister$1.call(this, modal);
1420
1645
  }
1421
1646
 
1422
- open(id, transition) {
1423
- return open$1.call(this, id, transition);
1647
+ open(id, transition, focus) {
1648
+ return open$1.call(this, id, transition, focus);
1424
1649
  }
1425
1650
 
1426
- close(id, transition) {
1427
- return close$1.call(this, id, transition);
1651
+ close(id, transition, focus) {
1652
+ return close$1.call(this, id, transition, focus);
1428
1653
  }
1429
1654
 
1430
- replace(id, transition) {
1431
- return replace.call(this, id, transition);
1655
+ replace(id, transition, focus) {
1656
+ return replace.call(this, id, transition, focus);
1432
1657
  }
1433
1658
 
1434
- async closeAll(exclude = false, transition) {
1435
- const result = await closeAll$1.call(this, exclude, transition);
1436
- updateFocusState.call(this);
1659
+ async closeAll(exclude = false, transition, focus = true) {
1660
+ const result = await closeAll$1.call(this, exclude, transition); // Update focus if the focus param is true.
1661
+
1662
+ if (focus) {
1663
+ updateFocusState.call(this);
1664
+ }
1665
+
1437
1666
  return result;
1438
1667
  }
1439
1668
 
@@ -1468,7 +1697,7 @@ function getConfig(el, settings) {
1468
1697
 
1469
1698
  for (const prop in config) {
1470
1699
  // Get the CSS variable property values.
1471
- const prefix = getComputedStyle(document.body).getPropertyValue('--vrembem-variable-prefix');
1700
+ const prefix = L();
1472
1701
  const value = styles.getPropertyValue(`--${prefix}popover-${prop}`).trim(); // If a value was found, replace the default in config obj.
1473
1702
 
1474
1703
  if (value) {
@@ -1479,6 +1708,7 @@ function getConfig(el, settings) {
1479
1708
 
1480
1709
  return config;
1481
1710
  }
1711
+
1482
1712
  function getPadding(value) {
1483
1713
  let padding; // Split the value by spaces if it's a string.
1484
1714
 
@@ -1528,6 +1758,7 @@ function getPadding(value) {
1528
1758
 
1529
1759
  return padding;
1530
1760
  }
1761
+
1531
1762
  function getModifiers(options) {
1532
1763
  return [{
1533
1764
  name: 'offset',
@@ -1552,6 +1783,7 @@ function getModifiers(options) {
1552
1783
  }
1553
1784
  }];
1554
1785
  }
1786
+
1555
1787
  function getPopover(query) {
1556
1788
  // Get the entry from collection.
1557
1789
  const entry = typeof query === 'string' ? this.get(query) : this.get(query.id); // Return entry if it was resolved, otherwise throw error.
@@ -1562,13 +1794,14 @@ function getPopover(query) {
1562
1794
  throw new Error(`Popover not found in collection with id of "${query}".`);
1563
1795
  }
1564
1796
  }
1797
+
1565
1798
  function getPopoverID(obj) {
1566
1799
  // If it's a string, return the string.
1567
1800
  if (typeof obj === 'string') {
1568
1801
  return obj;
1569
1802
  } // If it's an HTML element.
1570
1803
  else if (typeof obj.hasAttribute === 'function') {
1571
- // If it's a popover target, return the id.
1804
+ // If it's a popover element, return the id.
1572
1805
  if (obj.closest(this.settings.selectorPopover)) {
1573
1806
  obj = obj.closest(this.settings.selectorPopover);
1574
1807
  return obj.id;
@@ -1586,14 +1819,15 @@ function getPopoverID(obj) {
1586
1819
  } // Return false if no id was found.
1587
1820
  else return false;
1588
1821
  }
1822
+
1589
1823
  function getPopoverElements(query) {
1590
1824
  const id = getPopoverID.call(this, query);
1591
1825
 
1592
1826
  if (id) {
1827
+ const popover = document.querySelector(`#${id}`);
1593
1828
  const trigger = document.querySelector(`[aria-controls="${id}"]`) || document.querySelector(`[aria-describedby="${id}"]`);
1594
- const target = document.querySelector(`#${id}`);
1595
1829
 
1596
- if (!trigger && !target) {
1830
+ if (!trigger && !popover) {
1597
1831
  return {
1598
1832
  error: new Error(`No popover elements found using the ID: "${id}".`)
1599
1833
  };
@@ -1601,14 +1835,14 @@ function getPopoverElements(query) {
1601
1835
  return {
1602
1836
  error: new Error('No popover trigger associated with the provided popover.')
1603
1837
  };
1604
- } else if (!target) {
1838
+ } else if (!popover) {
1605
1839
  return {
1606
1840
  error: new Error('No popover associated with the provided popover trigger.')
1607
1841
  };
1608
1842
  } else {
1609
1843
  return {
1610
- trigger,
1611
- target
1844
+ popover,
1845
+ trigger
1612
1846
  };
1613
1847
  }
1614
1848
  } else {
@@ -1624,7 +1858,7 @@ async function close(query) {
1624
1858
 
1625
1859
  if (popover && popover.state === 'opened') {
1626
1860
  // Update state class.
1627
- popover.target.classList.remove(this.settings.stateActive); // Update accessibility attribute(s).
1861
+ popover.el.classList.remove(this.settings.stateActive); // Update accessibility attribute(s).
1628
1862
 
1629
1863
  if (popover.trigger.hasAttribute('aria-controls')) {
1630
1864
  popover.trigger.setAttribute('aria-expanded', 'false');
@@ -1638,10 +1872,10 @@ async function close(query) {
1638
1872
  }]
1639
1873
  }); // Update popover state.
1640
1874
 
1641
- popover.state = 'closed'; // Clear memory if popover trigger matches the one saved in memory.
1875
+ popover.state = 'closed'; // Clear root trigger if popover trigger matches.
1642
1876
 
1643
- if (popover.trigger === this.memory.trigger) {
1644
- this.memory.trigger = null;
1877
+ if (popover.trigger === this.trigger) {
1878
+ this.trigger = null;
1645
1879
  }
1646
1880
  } // Return the popover.
1647
1881
 
@@ -1662,10 +1896,10 @@ function closeCheck(popover) {
1662
1896
  if (popover.state != 'opened') return; // Needed to correctly check which element is currently being focused.
1663
1897
 
1664
1898
  setTimeout(() => {
1665
- // Check if trigger or target are being hovered.
1666
- const isHovered = popover.target.closest(':hover') === popover.target || popover.trigger.closest(':hover') === popover.trigger; // Check if trigger or target are being focused.
1899
+ // Check if trigger or element are being hovered.
1900
+ const isHovered = popover.el.closest(':hover') === popover.el || popover.trigger.closest(':hover') === popover.trigger; // Check if trigger or element are being focused.
1667
1901
 
1668
- const isFocused = document.activeElement.closest(`#${popover.id}, [aria-controls="${popover.id}"]`); // Close if the trigger and target are not currently hovered or focused.
1902
+ const isFocused = document.activeElement.closest(`#${popover.id}, [aria-controls="${popover.id}"]`); // Close if the trigger and element are not currently hovered or focused.
1669
1903
 
1670
1904
  if (!isHovered && !isFocused) {
1671
1905
  popover.close();
@@ -1676,20 +1910,20 @@ function closeCheck(popover) {
1676
1910
  }, 1);
1677
1911
  }
1678
1912
 
1679
- function handlerClick(popover) {
1913
+ function handleClick(popover) {
1680
1914
  if (popover.state === 'opened') {
1681
1915
  popover.close();
1682
1916
  } else {
1683
- this.memory.trigger = popover.trigger;
1917
+ this.trigger = popover.trigger;
1684
1918
  popover.open();
1685
- documentClick.call(this, popover);
1919
+ handleDocumentClick.call(this, popover);
1686
1920
  }
1687
1921
  }
1688
- function handlerKeydown(event) {
1922
+ function handleKeydown(event) {
1689
1923
  switch (event.key) {
1690
1924
  case 'Escape':
1691
- if (this.memory.trigger) {
1692
- this.memory.trigger.focus();
1925
+ if (this.trigger) {
1926
+ this.trigger.focus();
1693
1927
  }
1694
1928
 
1695
1929
  closeAll.call(this);
@@ -1705,7 +1939,7 @@ function handlerKeydown(event) {
1705
1939
  return;
1706
1940
  }
1707
1941
  }
1708
- function documentClick(popover) {
1942
+ function handleDocumentClick(popover) {
1709
1943
  const root = this;
1710
1944
  document.addEventListener('click', function _f(event) {
1711
1945
  // Check if a popover was clicked.
@@ -1713,14 +1947,14 @@ function documentClick(popover) {
1713
1947
 
1714
1948
  if (!result) {
1715
1949
  // If it doesn't match and popover is open, close it and remove event listener.
1716
- if (popover.target && popover.target.classList.contains(root.settings.stateActive)) {
1950
+ if (popover.el && popover.el.classList.contains(root.settings.stateActive)) {
1717
1951
  popover.close();
1718
1952
  }
1719
1953
 
1720
1954
  this.removeEventListener('click', _f);
1721
1955
  } else {
1722
1956
  // If it does match and popover isn't currently active, remove event listener.
1723
- if (popover.target && !popover.target.classList.contains(root.settings.stateActive)) {
1957
+ if (popover.el && !popover.el.classList.contains(root.settings.stateActive)) {
1724
1958
  this.removeEventListener('click', _f);
1725
1959
  }
1726
1960
  }
@@ -3569,14 +3803,14 @@ async function open(query) {
3569
3803
  // Get the popover from collection.
3570
3804
  const popover = getPopover.call(this, query); // Update state class.
3571
3805
 
3572
- popover.target.classList.add(this.settings.stateActive); // Update accessibility attribute(s).
3806
+ popover.el.classList.add(this.settings.stateActive); // Update accessibility attribute(s).
3573
3807
 
3574
3808
  if (popover.trigger.hasAttribute('aria-controls')) {
3575
3809
  popover.trigger.setAttribute('aria-expanded', 'true');
3576
3810
  } // Update popover config.
3577
3811
 
3578
3812
 
3579
- popover.config = getConfig(popover.target, this.settings); // Enable popper event listeners and set placement/modifiers.
3813
+ popover.config = getConfig(popover.el, this.settings); // Enable popper event listeners and set placement/modifiers.
3580
3814
 
3581
3815
  popover.popper.setOptions({
3582
3816
  placement: popover.config['placement'],
@@ -3593,9 +3827,9 @@ async function open(query) {
3593
3827
  return popover;
3594
3828
  }
3595
3829
 
3596
- async function register(trigger, target) {
3830
+ async function register(el, trigger) {
3597
3831
  // Deregister entry incase it has already been registered.
3598
- deregister.call(this, target); // Save root this for use inside methods API.
3832
+ deregister.call(this, el); // Save root this for use inside methods API.
3599
3833
 
3600
3834
  const root = this; // Setup methods API.
3601
3835
 
@@ -3615,12 +3849,12 @@ async function register(trigger, target) {
3615
3849
  }; // Setup the popover object.
3616
3850
 
3617
3851
  const entry = _extends({
3618
- id: target.id,
3852
+ id: el.id,
3619
3853
  state: 'closed',
3854
+ el: el,
3620
3855
  trigger: trigger,
3621
- target: target,
3622
- popper: createPopper(trigger, target),
3623
- config: getConfig(target, this.settings)
3856
+ popper: createPopper(trigger, el),
3857
+ config: getConfig(el, this.settings)
3624
3858
  }, methods); // Set aria-expanded to false if trigger has aria-controls attribute.
3625
3859
 
3626
3860
 
@@ -3633,9 +3867,9 @@ async function register(trigger, target) {
3633
3867
 
3634
3868
  this.collection.push(entry); // Set initial state.
3635
3869
 
3636
- if (entry.target.classList.contains(this.settings.stateActive)) {
3870
+ if (entry.el.classList.contains(this.settings.stateActive)) {
3637
3871
  await entry.open();
3638
- documentClick.call(this, entry);
3872
+ handleDocumentClick.call(this, entry);
3639
3873
  } // Return the registered entry.
3640
3874
 
3641
3875
 
@@ -3654,7 +3888,7 @@ function registerEventListeners(entry) {
3654
3888
  type: ['mouseenter', 'focus'],
3655
3889
  listener: open.bind(this, entry)
3656
3890
  }, {
3657
- el: ['trigger', 'target'],
3891
+ el: ['el', 'trigger'],
3658
3892
  type: ['mouseleave', 'focusout'],
3659
3893
  listener: closeCheck.bind(this, entry)
3660
3894
  }]; // Loop through listeners and apply to the appropriate elements.
@@ -3672,7 +3906,7 @@ function registerEventListeners(entry) {
3672
3906
  entry.__eventListeners = [{
3673
3907
  el: ['trigger'],
3674
3908
  type: ['click'],
3675
- listener: handlerClick.bind(this, entry)
3909
+ listener: handleClick.bind(this, entry)
3676
3910
  }]; // Loop through listeners and apply to the appropriate elements.
3677
3911
 
3678
3912
  entry.__eventListeners.forEach(evObj => {
@@ -3689,13 +3923,19 @@ function registerEventListeners(entry) {
3689
3923
  return entry;
3690
3924
  }
3691
3925
 
3926
+ var _handleKeydown = /*#__PURE__*/_classPrivateFieldLooseKey("handleKeydown");
3927
+
3692
3928
  class Popover extends Collection {
3693
3929
  constructor(options) {
3694
3930
  super();
3931
+ Object.defineProperty(this, _handleKeydown, {
3932
+ writable: true,
3933
+ value: void 0
3934
+ });
3695
3935
  this.defaults = defaults;
3696
3936
  this.settings = _extends({}, this.defaults, options);
3697
- this.memory = {};
3698
- this.__handlerKeydown = handlerKeydown.bind(this);
3937
+ this.trigger = null;
3938
+ _classPrivateFieldLooseBase(this, _handleKeydown)[_handleKeydown] = handleKeydown.bind(this);
3699
3939
  if (this.settings.autoInit) this.init();
3700
3940
  }
3701
3941
 
@@ -3712,11 +3952,13 @@ class Popover extends Collection {
3712
3952
  // already adds event listeners to popovers.
3713
3953
  this.initEventListeners(false);
3714
3954
  }
3955
+
3956
+ return this;
3715
3957
  }
3716
3958
 
3717
3959
  async destroy() {
3718
- // Clear any stored memory.
3719
- this.memory = {}; // Remove all entries from the collection.
3960
+ // Clear stored trigger.
3961
+ this.trigger = null; // Remove all entries from the collection.
3720
3962
 
3721
3963
  await this.deregisterCollection(); // If eventListeners are enabled, destroy event listeners.
3722
3964
 
@@ -3725,6 +3967,8 @@ class Popover extends Collection {
3725
3967
  // already removes event listeners from popovers.
3726
3968
  this.destroyEventListeners(false);
3727
3969
  }
3970
+
3971
+ return this;
3728
3972
  }
3729
3973
 
3730
3974
  initEventListeners(processCollection = true) {
@@ -3736,7 +3980,7 @@ class Popover extends Collection {
3736
3980
  } // Add keydown global event listener.
3737
3981
 
3738
3982
 
3739
- document.addEventListener('keydown', this.__handlerKeydown, false);
3983
+ document.addEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown)[_handleKeydown], false);
3740
3984
  }
3741
3985
 
3742
3986
  destroyEventListeners(processCollection = true) {
@@ -3748,13 +3992,13 @@ class Popover extends Collection {
3748
3992
  } // Remove keydown global event listener.
3749
3993
 
3750
3994
 
3751
- document.removeEventListener('keydown', this.__handlerKeydown, false);
3995
+ document.removeEventListener('keydown', _classPrivateFieldLooseBase(this, _handleKeydown)[_handleKeydown], false);
3752
3996
  }
3753
3997
 
3754
3998
  register(query) {
3755
3999
  const els = getPopoverElements.call(this, query);
3756
4000
  if (els.error) return Promise.reject(els.error);
3757
- return register.call(this, els.trigger, els.target);
4001
+ return register.call(this, els.popover, els.trigger);
3758
4002
  }
3759
4003
 
3760
4004
  deregister(query) {