@graupl/core 1.0.0-beta.43 → 1.0.0-beta.44

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.
Files changed (41) hide show
  1. package/dist/js/accordion.js.map +1 -1
  2. package/dist/js/alert.js +1 -1
  3. package/dist/js/alert.js.map +1 -1
  4. package/dist/js/component/accordion.cjs.js.map +1 -1
  5. package/dist/js/component/accordion.es.js.map +1 -1
  6. package/dist/js/component/accordion.iife.js.map +1 -1
  7. package/dist/js/component/alert.cjs.js +1 -1
  8. package/dist/js/component/alert.cjs.js.map +1 -1
  9. package/dist/js/component/alert.es.js +1 -1
  10. package/dist/js/component/alert.es.js.map +1 -1
  11. package/dist/js/component/alert.iife.js +1 -1
  12. package/dist/js/component/alert.iife.js.map +1 -1
  13. package/dist/js/component/disclosure.cjs.js +2 -2
  14. package/dist/js/component/disclosure.cjs.js.map +1 -1
  15. package/dist/js/component/disclosure.es.js +2 -2
  16. package/dist/js/component/disclosure.es.js.map +1 -1
  17. package/dist/js/component/disclosure.iife.js +2 -2
  18. package/dist/js/component/disclosure.iife.js.map +1 -1
  19. package/dist/js/disclosure.js +2 -2
  20. package/dist/js/disclosure.js.map +1 -1
  21. package/dist/js/generator/accordion.cjs.js.map +1 -1
  22. package/dist/js/generator/accordion.es.js.map +1 -1
  23. package/dist/js/generator/accordion.iife.js.map +1 -1
  24. package/dist/js/generator/alert.cjs.js +1 -1
  25. package/dist/js/generator/alert.cjs.js.map +1 -1
  26. package/dist/js/generator/alert.es.js +1 -1
  27. package/dist/js/generator/alert.es.js.map +1 -1
  28. package/dist/js/generator/alert.iife.js +1 -1
  29. package/dist/js/generator/alert.iife.js.map +1 -1
  30. package/dist/js/generator/disclosure.cjs.js +2 -2
  31. package/dist/js/generator/disclosure.cjs.js.map +1 -1
  32. package/dist/js/generator/disclosure.es.js +2 -2
  33. package/dist/js/generator/disclosure.es.js.map +1 -1
  34. package/dist/js/generator/disclosure.iife.js +2 -2
  35. package/dist/js/generator/disclosure.iife.js.map +1 -1
  36. package/dist/js/graupl.js +2 -2
  37. package/dist/js/graupl.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/js/accordion/AccordionItem.js +2 -2
  40. package/src/js/alert/Alert.js +3 -3
  41. package/src/js/disclosure/Disclosure.js +497 -42
@@ -49,6 +49,8 @@ import Component from "../Component.js";
49
49
  * @property {Object<string>} _selectors - The query selectors used by the disclosure.
50
50
  * @property {string} _selectors.content - The query selector for the disclosure content.
51
51
  * @property {Object<string, string[]>} _classes - The CSS classes to apply when the disclosure is in various states.
52
+ * @property {string|string[]} _classes.locked - The class(es) to apply when the disclosure is locked.
53
+ * @property {string|string[]} _classes.unlocked - The class(es) to apply when the disclosure is unlocked.
52
54
  * @property {string|string[]} _classes.open - The class(es) to apply when the disclosure is open.
53
55
  * @property {string|string[]} _classes.close - The class(es) to apply when the disclosure is closed.
54
56
  * @property {string|string[]} _classes.transition - The class(es) to apply when the disclosure is transitioning between states.
@@ -59,6 +61,15 @@ import Component from "../Component.js";
59
61
  * @property {number} _durations.close - The duration time (in milliseconds) for the transition from open to closed states.
60
62
  * @property {TransactionalValue<boolean>} _open - The open state of the disclosure.
61
63
  * @property {boolean} _shouldOpen - A value to force the disclosure open when the breakpoint width is passed.
64
+ * @property {boolean} _openInsideBreakpoint - A flag to open the disclosure when inside the breakpoint.
65
+ * @property {boolean} _openOutsideBreakpoint - A flag to open the disclosure when outside the breakpoint.
66
+ * @property {boolean} _closeInsideBreakpoint - A flag to close the disclosure when inside the breakpoint.
67
+ * @property {boolean} _closeOutsideBreakpoint - A flag to close the disclosure when outside the breakpoint.
68
+ * @property {boolean} _lockInsideBreakpoint - A flag to lock the disclosure in its current state when inside the breakpoint.
69
+ * @property {boolean} _lockOutsideBreakpoint - A flag to lock the disclosure in its current state when outside the breakpoint.
70
+ * @property {boolean} _unlockInsideBreakpoint - A flag to unlock the disclosure when inside the breakpoint.
71
+ * @property {boolean} _unlockOutsideBreakpoint - A flag to unlock the disclosure when outside the breakpoint.
72
+ * @property {TransactionalValue<boolean>} _locked - The locked state of the disclosure.
62
73
  * @property {boolean} _closeOnBlur - Whether to close the disclosure when it loses focus in the DOM.
63
74
  * @property {Function} _mediaQueryListEventCallback - The callback for media query list events.
64
75
  * @property {string} _storageKey - The key used for storage.
@@ -88,19 +99,60 @@ class Disclosure extends Component {
88
99
  _rootDOMElement = "disclosure";
89
100
  _protectedDOMElements = ["controller"];
90
101
  _open = new TransactionalValue(false);
102
+ _openInsideBreakpoint = false;
103
+ _openOutsideBreakpoint = false;
104
+ _closeInsideBreakpoint = false;
105
+ _closeOutsideBreakpoint = false;
106
+ _lockInsideBreakpoint = false;
107
+ _lockOutsideBreakpoint = false;
108
+ _unlockInsideBreakpoint = false;
109
+ _unlockOutsideBreakpoint = false;
110
+ _locked = new TransactionalValue(false);
91
111
  _shouldOpen = false;
92
112
  _closeOnBlur = false;
93
113
  _storageKey = "disclosures";
94
114
  _name = "Disclosure";
95
115
  _mediaQueryListEventCallback = (event) => {
96
- if (event.matches && this.isOpen) {
97
- this.close({ preserveState: true });
98
- } else if (
99
- !event.matches &&
100
- !this.isOpen &&
101
- (this.hasOpened || this.shouldOpen)
102
- ) {
103
- this.open();
116
+ if (event.matches) {
117
+ if (this.unlockInsideBreakpoint) {
118
+ this.unlock();
119
+ }
120
+
121
+ if (this.isOpen && this.closeInsideBreakpoint) {
122
+ if (this.isLocked) {
123
+ this.unlock();
124
+ }
125
+ this.close({ preserveState: true });
126
+ } else if (!this.isOpen && this.openInsideBreakpoint) {
127
+ if (this.isLocked) {
128
+ this.unlock();
129
+ }
130
+ this.open();
131
+ }
132
+
133
+ if (this.lockInsideBreakpoint) {
134
+ this.lock();
135
+ }
136
+ } else {
137
+ if (this.unlockOutsideBreakpoint) {
138
+ this.unlock();
139
+ }
140
+
141
+ if (this.isOpen && this.closeOutsideBreakpoint) {
142
+ if (this.isLocked) {
143
+ this.unlock();
144
+ }
145
+ this.close({ preserveState: true });
146
+ } else if (!this.isOpen && this.openOutsideBreakpoint) {
147
+ if (this.isLocked) {
148
+ this.unlock();
149
+ }
150
+ this.open();
151
+ }
152
+
153
+ if (this.lockOutsideBreakpoint) {
154
+ this.lock();
155
+ }
104
156
  }
105
157
  };
106
158
 
@@ -111,6 +163,8 @@ class Disclosure extends Component {
111
163
  * @param {HTMLElement} options.disclosureElement - The disclosure element in the DOM.
112
164
  * @param {HTMLElement} options.controllerElement - The disclosure toggle element in the DOM.
113
165
  * @param {string} [options.disclosureContentSelector = .disclosure-content] - The query selector string for the disclosure content.
166
+ * @param {?(string|string[])} [options.lockedClass = locked] - The class(es) to apply when the disclosure is locked.
167
+ * @param {?(string|string[])} [options.unlockedClass = unlocked] - The class(es) to apply when the disclosure is unlocked.
114
168
  * @param {?(string|string[])} [options.openClass = show] - The class to apply when a disclosure is "open".
115
169
  * @param {?(string|string[])} [options.closeClass = hide] - The class to apply when a disclosure is "closed".
116
170
  * @param {?(string|string[])} [options.transitionClass = transitioning] - The class to apply when a disclosure is transitioning between "open" and "closed" states.
@@ -120,6 +174,16 @@ class Disclosure extends Component {
120
174
  * @param {boolean} [options.closeOnBlur = false] - Whether to close the disclosure when it loses focus in the dom.
121
175
  * @param {?string} [options.minWidth = ""] - The width of the screen that the disclosure will automatically open/close itself.
122
176
  * @param {boolean} [options.autoOpen = false] - Whether to automatically open when above the minWidth.
177
+ * @param {?string} [options.breakpoint = ""] - The breakpoint that the disclosure will automatically open/close itself.
178
+ * @param {boolean} [options.openInsideBreakpoint = false] - A flag to open the disclosure when inside the breakpoint.
179
+ * @param {boolean} [options.openOutsideBreakpoint = false] - A flag to open the disclosure when outside the breakpoint.
180
+ * @param {boolean} [options.closeInsideBreakpoint = false] - A flag to close the disclosure when inside the breakpoint.
181
+ * @param {boolean} [options.closeOutsideBreakpoint = false] - A flag to close the disclosure when outside the breakpoint.
182
+ * @param {boolean} [options.lockInsideBreakpoint = false] - A flag to lock the disclosure when inside the breakpoint.
183
+ * @param {boolean} [options.lockOutsideBreakpoint = false] - A flag to lock the disclosure when outside the breakpoint.
184
+ * @param {boolean} [options.unlockInsideBreakpoint = false] - A flag to unlock the disclosure when inside the breakpoint.
185
+ * @param {boolean} [options.unlockOutsideBreakpoint = false] - A flag to unlock the disclosure when outside the breakpoint.
186
+ * @param {boolean} [options.locked = false] - A flag to lock the disclosure in its current state.
123
187
  * @param {?string} [options.mediaQuery = ""] - The media query to use when automatically opening/closing the disclosure.
124
188
  * @param {?string} [options.prefix = graupl-] - The prefix used for CSS custom properties and attributes.
125
189
  * @param {?string} [options.key = null] - The key used to generate IDs throughout the disclosure.
@@ -130,6 +194,8 @@ class Disclosure extends Component {
130
194
  disclosureElement,
131
195
  controllerElement,
132
196
  disclosureContentSelector = ".disclosure-content",
197
+ lockedClass = "locked",
198
+ unlockedClass = "unlocked",
133
199
  openClass = "show",
134
200
  closeClass = "hide",
135
201
  transitionClass = "transitioning",
@@ -138,7 +204,17 @@ class Disclosure extends Component {
138
204
  closeDuration = -1,
139
205
  closeOnBlur = false,
140
206
  minWidth = "",
207
+ breakpoint = "",
141
208
  autoOpen = false,
209
+ openInsideBreakpoint = false,
210
+ openOutsideBreakpoint = false,
211
+ closeInsideBreakpoint = false,
212
+ closeOutsideBreakpoint = false,
213
+ lockInsideBreakpoint = false,
214
+ lockOutsideBreakpoint = false,
215
+ unlockInsideBreakpoint = false,
216
+ unlockOutsideBreakpoint = false,
217
+ locked = false,
142
218
  mediaQuery = "",
143
219
  prefix = "graupl-",
144
220
  key = null,
@@ -159,6 +235,8 @@ class Disclosure extends Component {
159
235
  this._selectors.content = disclosureContentSelector;
160
236
 
161
237
  // Set the classes.
238
+ this._classes.locked = lockedClass || "";
239
+ this._classes.unlocked = unlockedClass || "";
162
240
  this._classes.open = openClass || "";
163
241
  this._classes.close = closeClass || "";
164
242
  this._classes.transition = transitionClass || "";
@@ -171,14 +249,47 @@ class Disclosure extends Component {
171
249
  // Set close on blur.
172
250
  this._closeOnBlur = closeOnBlur;
173
251
 
252
+ // @todo Remove minWidth and autoOpen options in favor of breakpoint, openInsideBreakpoint, openOutsideBreakpoint, closeInsideBreakpoint, and closeOutsideBreakpoint options.
253
+ if (minWidth !== "") {
254
+ console.warn(
255
+ "`minWidth` is deprecated and will be removed in a future release. Please set `breakpoint` instead."
256
+ );
257
+
258
+ if (breakpoint === "") {
259
+ breakpoint = minWidth;
260
+ }
261
+ }
262
+
263
+ if (autoOpen && breakpoint !== "") {
264
+ console.warn(
265
+ "`autoOpen` is deprecated and will be removed in a future release. Please set `openOutsideBreakpoint` and `closeInsideBreakpoint` to `true` instead."
266
+ );
267
+
268
+ openOutsideBreakpoint = autoOpen;
269
+ closeInsideBreakpoint = autoOpen;
270
+ }
271
+
174
272
  // Set collapse width and auto open functionality.
175
- this._breakpoint = minWidth || "";
273
+ this._breakpoint = breakpoint || "";
176
274
  this._shouldOpen = autoOpen;
275
+ this._openInsideBreakpoint = openInsideBreakpoint;
276
+ this._openOutsideBreakpoint = openOutsideBreakpoint;
277
+ this._closeInsideBreakpoint = closeInsideBreakpoint;
278
+ this._closeOutsideBreakpoint = closeOutsideBreakpoint;
279
+ this._lockInsideBreakpoint = lockInsideBreakpoint;
280
+ this._lockOutsideBreakpoint = lockOutsideBreakpoint;
281
+ this._unlockInsideBreakpoint = unlockInsideBreakpoint;
282
+ this._unlockOutsideBreakpoint = unlockOutsideBreakpoint;
177
283
  this._mediaQueryString = mediaQuery || "";
178
284
 
285
+ // Set the lock state.
286
+ this._locked = new TransactionalValue(locked);
287
+
179
288
  // Register custom events.
180
289
  this._registerEvent("expand", { detail: { disclosure: this } });
181
290
  this._registerEvent("collapse", { detail: { disclosure: this } });
291
+ this._registerEvent("lock", { detail: { disclosure: this } });
292
+ this._registerEvent("unlock", { detail: { disclosure: this } });
182
293
 
183
294
  // Set up custom initialization.
184
295
  this._addEventListener(
@@ -189,11 +300,25 @@ class Disclosure extends Component {
189
300
  // those that _should_ open.
190
301
  if (
191
302
  this.dom.controller.getAttribute("aria-expanded") === "true" ||
192
- (this.shouldOpen && !window.matchMedia(this.mediaQuery).matches)
303
+ (this.openOutsideBreakpoint &&
304
+ !window.matchMedia(this.mediaQuery).matches) ||
305
+ (this.openInsideBreakpoint &&
306
+ window.matchMedia(this.mediaQuery).matches)
193
307
  ) {
194
- this._expand({ emit: false, transition: false });
308
+ this.open();
195
309
  } else {
196
- this._collapse({ emit: false, transition: false });
310
+ this.close();
311
+ }
312
+
313
+ // Handle auto-locking disclosures that should be locked.
314
+ if (
315
+ this.isLocked ||
316
+ (this.lockInsideBreakpoint &&
317
+ window.matchMedia(this.mediaQuery).matches) ||
318
+ (this.lockOutsideBreakpoint &&
319
+ !window.matchMedia(this.mediaQuery).matches)
320
+ ) {
321
+ this.lock();
197
322
  }
198
323
  }
199
324
  );
@@ -206,7 +331,15 @@ class Disclosure extends Component {
206
331
  // Boolean checks.
207
332
  const booleans = {
208
333
  closeOnBlur: this._closeOnBlur,
209
- autoOpen: this._shouldOpen,
334
+ openInsideBreakpoint: this._openInsideBreakpoint,
335
+ openOutsideBreakpoint: this._openOutsideBreakpoint,
336
+ closeInsideBreakpoint: this._closeInsideBreakpoint,
337
+ closeOutsideBreakpoint: this._closeOutsideBreakpoint,
338
+ lockInsideBreakpoint: this._lockInsideBreakpoint,
339
+ lockOutsideBreakpoint: this._lockOutsideBreakpoint,
340
+ unlockInsideBreakpoint: this._unlockInsideBreakpoint,
341
+ unlockOutsideBreakpoint: this._unlockOutsideBreakpoint,
342
+ locked: this._locked.value,
210
343
  };
211
344
 
212
345
  // Check the booleans.
@@ -227,6 +360,44 @@ class Disclosure extends Component {
227
360
  }
228
361
  }
229
362
 
363
+ /**
364
+ * The class(es) to apply to the disclosure.
365
+ *
366
+ * @type {string|string[]}
367
+ *
368
+ * @see _classes.locked
369
+ */
370
+ get lockedClass() {
371
+ return this._classes.locked;
372
+ }
373
+
374
+ set lockedClass(value) {
375
+ isValidClassList({ lockedClass: value });
376
+
377
+ if (this._classes.locked !== value) {
378
+ this._classes.locked = value;
379
+ }
380
+ }
381
+
382
+ /**
383
+ * The class(es) to apply to the disclosure.
384
+ *
385
+ * @type {string|string[]}
386
+ *
387
+ * @see _classes.unlocked
388
+ */
389
+ get unlockedClass() {
390
+ return this._classes.unlocked;
391
+ }
392
+
393
+ set unlockedClass(value) {
394
+ isValidClassList({ unlockedClass: value });
395
+
396
+ if (this._classes.unlocked !== value) {
397
+ this._classes.unlocked = value;
398
+ }
399
+ }
400
+
230
401
  /**
231
402
  * The class(es) to apply when the disclosure is open.
232
403
  *
@@ -368,10 +539,18 @@ class Disclosure extends Component {
368
539
  * @see breakpoint
369
540
  */
370
541
  get minWidth() {
542
+ console.warn(
543
+ "`minWidth` is deprecated and will be removed in a future release. Please use `breakpoint` instead."
544
+ );
545
+
371
546
  return this.breakpoint;
372
547
  }
373
548
 
374
549
  set minWidth(value) {
550
+ console.warn(
551
+ "`minWidth` is deprecated and will be removed in a future release. Please use `breakpoint` instead."
552
+ );
553
+
375
554
  this.breakpoint = value;
376
555
  }
377
556
 
@@ -428,10 +607,18 @@ class Disclosure extends Component {
428
607
  * @see _shouldOpen
429
608
  */
430
609
  get shouldOpen() {
610
+ console.warn(
611
+ "`shouldOpen` is deprecated and will be removed in a future release. Please use `openOutsideBreakpoint` and `closeInsideBreakpoint` instead."
612
+ );
613
+
431
614
  return this._shouldOpen;
432
615
  }
433
616
 
434
617
  set shouldOpen(value) {
618
+ console.warn(
619
+ "`shouldOpen` is deprecated and will be removed in a future release. Please use `openOutsideBreakpoint` and `closeInsideBreakpoint` instead."
620
+ );
621
+
435
622
  isValidType("boolean", { shouldOpen: value });
436
623
 
437
624
  if (this._shouldOpen !== value) {
@@ -439,6 +626,146 @@ class Disclosure extends Component {
439
626
  }
440
627
  }
441
628
 
629
+ /**
630
+ * A flag to open the disclosure when inside the breakpoint.
631
+ *
632
+ * @type {boolean}
633
+ *
634
+ * @see _openInsideBreakpoint
635
+ */
636
+ get openInsideBreakpoint() {
637
+ return this._openInsideBreakpoint;
638
+ }
639
+
640
+ set openInsideBreakpoint(value) {
641
+ isValidType("boolean", { openInsideBreakpoint: value });
642
+
643
+ if (this._openInsideBreakpoint !== value) {
644
+ this._openInsideBreakpoint = value;
645
+ }
646
+ }
647
+
648
+ /**
649
+ * A flag to open the disclosure when outside the breakpoint.
650
+ *
651
+ * @type {boolean}
652
+ *
653
+ * @see _openOutsideBreakpoint
654
+ */
655
+ get openOutsideBreakpoint() {
656
+ return this._openOutsideBreakpoint;
657
+ }
658
+
659
+ set openOutsideBreakpoint(value) {
660
+ isValidType("boolean", { openOutsideBreakpoint: value });
661
+
662
+ if (this._openOutsideBreakpoint !== value) {
663
+ this._openOutsideBreakpoint = value;
664
+ }
665
+ }
666
+
667
+ /**
668
+ * A flag to close the disclosure when inside the breakpoint.
669
+ *
670
+ * @type {boolean}
671
+ *
672
+ * @see _closeInsideBreakpoint
673
+ */
674
+ get closeInsideBreakpoint() {
675
+ return this._closeInsideBreakpoint;
676
+ }
677
+
678
+ set closeInsideBreakpoint(value) {
679
+ isValidType("boolean", { closeInsideBreakpoint: value });
680
+
681
+ if (this._closeInsideBreakpoint !== value) {
682
+ this._closeInsideBreakpoint = value;
683
+ }
684
+ }
685
+
686
+ /**
687
+ * A flag to close the disclosure when outside the breakpoint.
688
+ *
689
+ * @type {boolean}
690
+ *
691
+ * @see _closeOutsideBreakpoint
692
+ */
693
+ get closeOutsideBreakpoint() {
694
+ return this._closeOutsideBreakpoint;
695
+ }
696
+
697
+ set closeOutsideBreakpoint(value) {
698
+ isValidType("boolean", { closeOutsideBreakpoint: value });
699
+
700
+ if (this._closeOutsideBreakpoint !== value) {
701
+ this._closeOutsideBreakpoint = value;
702
+ }
703
+ }
704
+
705
+ /**
706
+ * A flag to lock the disclosure in its current state when inside the breakpoint.
707
+ *
708
+ * @type {boolean}
709
+ *
710
+ * @see _lockInsideBreakpoint
711
+ */
712
+ get lockInsideBreakpoint() {
713
+ return this._lockInsideBreakpoint;
714
+ }
715
+
716
+ set lockInsideBreakpoint(value) {
717
+ isValidType("boolean", { lockInsideBreakpoint: value });
718
+
719
+ if (this._lockInsideBreakpoint !== value) {
720
+ this._lockInsideBreakpoint = value;
721
+ }
722
+ }
723
+
724
+ /**
725
+ * A flag to lock the disclosure in its current state when outside the breakpoint.
726
+ *
727
+ * @type {boolean}
728
+ *
729
+ * @see _lockOutsideBreakpoint
730
+ */
731
+ get lockOutsideBreakpoint() {
732
+ return this._lockOutsideBreakpoint;
733
+ }
734
+
735
+ set lockOutsideBreakpoint(value) {
736
+ isValidType("boolean", { lockOutsideBreakpoint: value });
737
+
738
+ if (this._lockOutsideBreakpoint !== value) {
739
+ this._lockOutsideBreakpoint = value;
740
+ }
741
+ }
742
+
743
+ /**
744
+ * A flag to indicate if the disclosure is locked.
745
+ *
746
+ * @readonly
747
+ *
748
+ * @type {boolean}
749
+ *
750
+ * @see _locked
751
+ */
752
+ get isLocked() {
753
+ return this._locked.value;
754
+ }
755
+
756
+ /**
757
+ * The committed lock preference for the disclosure.
758
+ *
759
+ * @readonly
760
+ *
761
+ * @type {boolean}
762
+ *
763
+ * @see _locked
764
+ */
765
+ get shouldBeLocked() {
766
+ return this._locked.committed;
767
+ }
768
+
442
769
  /**
443
770
  * Sets the IDs throughout the disclosure.
444
771
  *
@@ -541,11 +868,11 @@ class Disclosure extends Component {
541
868
  *
542
869
  * @fires grauplDisclosureExpand
543
870
  *
544
- * @param {Object<boolean>} [options = {}] - Options for expanding the disclosure.
545
- * @param {boolean} [options.emit = true] - Emit the expand event once expanded.
546
- * @param {boolean} [options.transition = true] - Respect the transition class.
871
+ * @param {Object<boolean>} [options = {}] - Options for expanding the disclosure.
872
+ * @param {boolean} [options.emit = this.isInitialized] - Emit the expand event once expanded.
873
+ * @param {boolean} [options.transition = this.isInitialized] - Respect the transition class.
547
874
  */
548
- _expand({ emit = true, transition = true } = {}) {
875
+ _reveal({ emit = this.isInitialized, transition = this.isInitialized } = {}) {
549
876
  this.dom.controller.setAttribute("aria-expanded", "true");
550
877
 
551
878
  // If we're dealing with transition classes, then we need to utilize
@@ -592,11 +919,14 @@ class Disclosure extends Component {
592
919
  *
593
920
  * @fires grauplDisclosureCollapse
594
921
  *
595
- * @param {Object<boolean>} [options = {}] - Options for collapsing the disclosure.
596
- * @param {boolean} [options.emit = true] - Emit the collapse event once collapsed.
597
- * @param {boolean} [options.transition = true] - Respect the transition class.
922
+ * @param {Object<boolean>} [options = {}] - Options for collapsing the disclosure.
923
+ * @param {boolean} [options.emit = this.isInitialized] - Emit the collapse event once collapsed.
924
+ * @param {boolean} [options.transition = this.isInitialized] - Respect the transition class.
598
925
  */
599
- _collapse({ emit = true, transition = true } = {}) {
926
+ _conceal({
927
+ emit = this.isInitialized,
928
+ transition = this.isInitialized,
929
+ } = {}) {
600
930
  this.dom.controller.setAttribute("aria-expanded", "false");
601
931
 
602
932
  // If we're dealing with transition classes, then we need to utilize
@@ -635,6 +965,50 @@ class Disclosure extends Component {
635
965
  }
636
966
  }
637
967
 
968
+ /**
969
+ * Applies the locked state styling and dispatches the lock event.
970
+ *
971
+ * @protected
972
+ *
973
+ * @param {Object<boolean>} [options = {}] - Options for the lock side effects.
974
+ * @param {boolean} [options.emit = this.isInitialized] - Whether to emit the lock event.
975
+ */
976
+ _lock({ emit = this.isInitialized } = {}) {
977
+ // Add the locked class
978
+ addClass(this.lockedClass, this.dom.disclosure);
979
+
980
+ // Remove the unlocked class.
981
+ removeClass(this.unlockedClass, this.dom.disclosure);
982
+
983
+ this.dom.controller.setAttribute("disabled", "true");
984
+
985
+ if (emit) {
986
+ this._dispatchEvent("lock", this.dom.disclosure);
987
+ }
988
+ }
989
+
990
+ /**
991
+ * Applies the unlocked state styling and dispatches the unlock event.
992
+ *
993
+ * @protected
994
+ *
995
+ * @param {Object<boolean>} [options = {}] - Options for the unlock side effects.
996
+ * @param {boolean} [options.emit = this.isInitialized] - Whether to emit the unlock event.
997
+ */
998
+ _unlock({ emit = this.isInitialized } = {}) {
999
+ // Add the unlocked class
1000
+ addClass(this.unlockedClass, this.dom.disclosure);
1001
+
1002
+ // Remove the locked class.
1003
+ removeClass(this.lockedClass, this.dom.disclosure);
1004
+
1005
+ this.dom.controller.removeAttribute("disabled");
1006
+
1007
+ if (emit) {
1008
+ this._dispatchEvent("unlock", this.dom.disclosure);
1009
+ }
1010
+ }
1011
+
638
1012
  /**
639
1013
  * Handles focus events throughout the disclosure.
640
1014
  *
@@ -771,18 +1145,26 @@ class Disclosure extends Component {
771
1145
  *
772
1146
  * Sets the disclosure's focus state to "self", calls expand, and sets isOpen to `true`.
773
1147
  *
774
- * @param {Object<boolean>} [options = {}] - Options for opening the disclosure.
775
- * @param {boolean} [options.force = false] - Whether to force the open action.
776
- * @param {boolean} [options.preserveState = false] - Whether to preserve the open state.
1148
+ * @param {Object<boolean>} [options = {}] - Options for opening the disclosure.
1149
+ * @param {boolean} [options.force = false] - Whether to force the open action.
1150
+ * @param {boolean} [options.emit = this.isInitialized] - Whether to emit the expand event once opened.
1151
+ * @param {boolean} [options.transition = this.isInitialized] - Respect the transition class.
1152
+ * @param {boolean} [options.preserveState = false] - Whether to preserve the open state.
777
1153
  */
778
- open({ force = false, preserveState = false } = {}) {
1154
+ open({
1155
+ force = false,
1156
+ emit = this.isInitialized,
1157
+ transition = this.isInitialized,
1158
+ preserveState = false,
1159
+ } = {}) {
779
1160
  if (this.isOpen && !force) return;
1161
+ if (this.isLocked) return;
780
1162
 
781
1163
  // Set the focus state.
782
1164
  this.focusState = "self";
783
1165
 
784
1166
  // Expand the disclosure.
785
- this._expand();
1167
+ this._reveal({ emit, transition });
786
1168
 
787
1169
  // Set the open state.
788
1170
  this._open.value = true;
@@ -797,18 +1179,26 @@ class Disclosure extends Component {
797
1179
  *
798
1180
  * Sets the disclosure's focus state to "none", calls expand, and sets isOpen to `true`.
799
1181
  *
800
- * @param {Object<boolean>} [options = {}] - Options for previewing the disclosure.
801
- * @param {boolean} [options.force = false] - Whether to force the preview action.
802
- * @param {boolean} [options.preserveState = false] - Whether to preserve the open state.
1182
+ * @param {Object<boolean>} [options = {}] - Options for previewing the disclosure.
1183
+ * @param {boolean} [options.force = false] - Whether to force the preview action.
1184
+ * @param {boolean} [options.emit = this.isInitialized] - Whether to emit the expand event once previewed.
1185
+ * @param {boolean} [options.transition = this.isInitialized] - Respect the transition class.
1186
+ * @param {boolean} [options.preserveState = false] - Whether to preserve the open state.
803
1187
  */
804
- preview({ force = false, preserveState = false } = {}) {
1188
+ preview({
1189
+ force = false,
1190
+ emit = this.isInitialized,
1191
+ transition = this.isInitialized,
1192
+ preserveState = false,
1193
+ } = {}) {
805
1194
  if (this.isOpen && !force) return;
1195
+ if (this.isLocked) return;
806
1196
 
807
1197
  // Set the focus state.
808
1198
  this.focusState = "none";
809
1199
 
810
1200
  // Expand the disclosure.
811
- this._expand();
1201
+ this._reveal({ emit, transition });
812
1202
 
813
1203
  // Set the open state.
814
1204
  this._open.value = true;
@@ -823,18 +1213,26 @@ class Disclosure extends Component {
823
1213
  *
824
1214
  * Sets the disclosure's focus state to "none", calls collapse, and sets isOpen to `false`.
825
1215
  *
826
- * @param {Object<boolean>} [options = {}] - Options for closing the disclosure.
827
- * @param {boolean} [options.force = false] - Whether to force the close action.
828
- * @param {boolean} [options.preserveState = false] - Whether to preserve the open state.
1216
+ * @param {Object<boolean>} [options = {}] - Options for closing the disclosure.
1217
+ * @param {boolean} [options.force = false] - Whether to force the close action.
1218
+ * @param {boolean} [options.emit = this.isInitialized] - Whether to emit the collapse event once closed.
1219
+ * @param {boolean} [options.transition = this.isInitialized] - Respect the transition class.
1220
+ * @param {boolean} [options.preserveState = false] - Whether to preserve the open state.
829
1221
  */
830
- close({ force = false, preserveState = false } = {}) {
1222
+ close({
1223
+ force = false,
1224
+ emit = this.isInitialized,
1225
+ transition = this.isInitialized,
1226
+ preserveState = false,
1227
+ } = {}) {
831
1228
  if (!this.isOpen && !force) return;
1229
+ if (this.isLocked) return;
832
1230
 
833
1231
  // Set the focus state.
834
1232
  this.focusState = "none";
835
1233
 
836
1234
  // Collapse the disclosure.
837
- this._collapse();
1235
+ this._conceal({ emit, transition });
838
1236
 
839
1237
  // Set the open state.
840
1238
  this._open.value = false;
@@ -847,15 +1245,72 @@ class Disclosure extends Component {
847
1245
  /**
848
1246
  * Toggles the open state of the disclosure.
849
1247
  *
850
- * @param {Object<boolean>} [options = {}] - Options for toggling the disclosure.
851
- * @param {boolean} [options.force = false] - Whether to force the open or close action.
852
- * @param {boolean} [options.preserveState = false] - Whether to preserve the open state.
1248
+ * @param {Object<boolean>} [options = {}] - Options for toggling the disclosure.
1249
+ * @param {boolean} [options.force = false] - Whether to force the open or close action.
1250
+ * @param {boolean} [options.emit = this.isInitialized] - Whether to emit the expand/collapse event once toggled.
1251
+ * @param {boolean} [options.transition = this.isInitialized] - Respect the transition class.
1252
+ * @param {boolean} [options.preserveState = false] - Whether to preserve the open state.
853
1253
  */
854
- toggle({ force = false, preserveState = false } = {}) {
1254
+ toggle({
1255
+ force = false,
1256
+ emit = this.isInitialized,
1257
+ transition = this.isInitialized,
1258
+ preserveState = false,
1259
+ } = {}) {
855
1260
  if (this.isOpen) {
856
- this.close({ force, preserveState });
1261
+ this.close({ force, emit, transition, preserveState });
1262
+ } else {
1263
+ this.open({ force, emit, transition, preserveState });
1264
+ }
1265
+ }
1266
+
1267
+ /**
1268
+ * Locks the disclosure.
1269
+ *
1270
+ * @param {Object<boolean>} [options = {}] - Options for locking the disclosure.
1271
+ * @param {boolean} [options.force = false] - Whether to force the lock action.
1272
+ * @param {boolean} [options.emit = this.isInitialized] - Whether to emit the lock event.
1273
+ */
1274
+ lock({ force = false, emit = this.isInitialized } = {}) {
1275
+ // Only lock if the disclosure is unlocked.
1276
+ if (this.isLocked && !force) return;
1277
+
1278
+ this._locked.value = true;
1279
+ this._lock({ emit });
1280
+
1281
+ // Commit the locked preference.
1282
+ this._locked.commit();
1283
+ }
1284
+
1285
+ /**
1286
+ * Unlocks the disclosure.
1287
+ *
1288
+ * @param {Object<boolean>} [options = {}] - Options for unlocking the disclosure.
1289
+ * @param {boolean} [options.force = true] - Whether to force the unlock action.
1290
+ * @param {boolean} [options.emit = this.isInitialized] - Whether to emit the unlock event.
1291
+ */
1292
+ unlock({ force = false, emit = this.isInitialized } = {}) {
1293
+ // Only unlock if the disclosure is locked.
1294
+ if (!this.isLocked && !force) return;
1295
+
1296
+ this._locked.value = false;
1297
+ this._unlock({ emit });
1298
+
1299
+ this._locked.commit();
1300
+ }
1301
+
1302
+ /**
1303
+ * Toggles the locked state of the disclosure.
1304
+ *
1305
+ * @param {Object<boolean>} [options = {}] - Options for toggling the lock state.
1306
+ * @param {boolean} [options.force = false] - Whether to force the toggle action.
1307
+ * @param {boolean} [options.emit = this.isInitialized] - Whether to emit the lock/unlock event.
1308
+ */
1309
+ toggleLock({ force = false, emit = this.isInitialized } = {}) {
1310
+ if (this.isLocked) {
1311
+ this.unlock({ force, emit });
857
1312
  } else {
858
- this.open({ force, preserveState });
1313
+ this.lock({ force, emit });
859
1314
  }
860
1315
  }
861
1316
  }