@graupl/graupl 1.0.0-alpha.14 → 1.0.0-alpha.16
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.
- package/CHANGELOG.md +24 -0
- package/build.js +7 -0
- package/dist/css/base/button.css +2 -0
- package/dist/css/base/button.css.map +1 -0
- package/dist/css/base/form.css.map +1 -0
- package/dist/css/base/link.css.map +1 -0
- package/dist/css/base/table.css.map +1 -0
- package/dist/css/base.css +2 -0
- package/dist/css/base.css.map +1 -0
- package/dist/css/component/accordion.css +2 -0
- package/dist/css/component/accordion.css.map +1 -0
- package/dist/css/component/alert.css +2 -0
- package/dist/css/component/alert.css.map +1 -0
- package/dist/css/component/card.css.map +1 -0
- package/dist/css/component/carousel.css +2 -0
- package/dist/css/component/carousel.css.map +1 -0
- package/dist/css/component/input-group.css.map +1 -0
- package/dist/css/component/menu.css.map +1 -0
- package/dist/css/component/navigation.css.map +1 -0
- package/dist/css/component.css +2 -0
- package/dist/css/component.css.map +1 -0
- package/dist/css/graupl.css +2 -0
- package/dist/css/graupl.css.map +1 -0
- package/dist/css/init.css.map +1 -0
- package/dist/css/layout/columns.css.map +1 -0
- package/dist/css/layout/container.css.map +1 -0
- package/dist/css/layout/flex-columns.css.map +1 -0
- package/dist/css/layout.css +2 -0
- package/dist/css/layout.css.map +1 -0
- package/dist/css/normalize.css.map +1 -0
- package/dist/css/state/focus.css +2 -0
- package/dist/css/state/focus.css.map +1 -0
- package/dist/css/state.css +2 -0
- package/dist/css/state.css.map +1 -0
- package/dist/css/theme/color.css.map +1 -0
- package/dist/css/theme/typography.css.map +1 -0
- package/dist/css/theme.css.map +1 -0
- package/dist/css/utilities/alignment.css.map +1 -0
- package/dist/css/utilities/color.css.map +1 -0
- package/dist/css/utilities/display.css.map +1 -0
- package/dist/css/utilities/flex.css.map +1 -0
- package/dist/css/utilities/height.css.map +1 -0
- package/dist/css/utilities/inset.css.map +1 -0
- package/dist/css/utilities/justification.css.map +1 -0
- package/dist/css/utilities/list.css.map +1 -0
- package/dist/css/utilities/order.css.map +1 -0
- package/dist/css/utilities/postion.css.map +1 -0
- package/dist/css/utilities/spacing.css.map +1 -0
- package/dist/css/utilities/typography.css.map +1 -0
- package/dist/css/utilities/visibility.css.map +1 -0
- package/dist/css/utilities/width.css.map +1 -0
- package/dist/css/utilities.css.map +1 -0
- package/dist/js/component/accordion.cjs.js +3 -0
- package/dist/js/component/accordion.esm.js +1289 -0
- package/dist/js/component/accordion.iife.js +3 -0
- package/dist/js/component/alert.cjs.js +3 -0
- package/dist/js/component/alert.esm.js +529 -0
- package/dist/js/component/alert.iife.js +3 -0
- package/dist/js/component/carousel.cjs.js +3 -0
- package/dist/js/component/carousel.esm.js +1110 -0
- package/dist/js/component/carousel.iife.js +3 -0
- package/dist/js/graupl.cjs.js +5 -0
- package/dist/js/graupl.esm.js +1462 -0
- package/dist/js/graupl.iife.js +5 -0
- package/index.html +56 -2
- package/index.js +12 -0
- package/package.json +26 -5
- package/scss/component/accordion.scss +3 -0
- package/src/js/accordion/Accordion.js +1163 -0
- package/src/js/accordion/AccordionItem.js +496 -0
- package/src/js/accordion/index.js +10 -0
- package/src/js/alert/Alert.js +71 -1
- package/src/js/alert/index.js +1 -11
- package/src/js/carousel/Carousel.js +67 -16
- package/src/js/carousel/index.js +1 -11
- package/src/js/eventHandlers.js +7 -0
- package/src/js/storage.js +106 -0
- package/src/scss/_defaults.scss +29 -0
- package/src/scss/base/button/_mixins.scss +64 -62
- package/src/scss/component/_index.scss +1 -0
- package/src/scss/component/accordion/_defaults.scss +40 -0
- package/src/scss/component/accordion/_index.scss +180 -0
- package/src/scss/component/accordion/_variables.scss +304 -0
- package/src/scss/component/carousel/_index.scss +6 -0
- package/src/scss/layout/columns/_index.scss +1 -1
- package/src/scss/layout/flex-columns/_index.scss +1 -1
- package/src/scss/state/focus/_index.scss +6 -6
- package/src/scss/state/focus/_mixins.scss +15 -0
- package/stylelint.config.js +4 -0
- package/vite.config.js +57 -0
- package/dist/base/button.css +0 -2
- package/dist/base/button.css.map +0 -1
- package/dist/base/form.css.map +0 -1
- package/dist/base/link.css.map +0 -1
- package/dist/base/table.css.map +0 -1
- package/dist/base.css +0 -2
- package/dist/base.css.map +0 -1
- package/dist/component/alert.css +0 -2
- package/dist/component/alert.css.map +0 -1
- package/dist/component/card.css.map +0 -1
- package/dist/component/carousel.css +0 -2
- package/dist/component/carousel.css.map +0 -1
- package/dist/component/input-group.css.map +0 -1
- package/dist/component/menu.css.map +0 -1
- package/dist/component/navigation.css.map +0 -1
- package/dist/component.css +0 -2
- package/dist/component.css.map +0 -1
- package/dist/graupl.css +0 -2
- package/dist/graupl.css.map +0 -1
- package/dist/init.css.map +0 -1
- package/dist/layout/columns.css.map +0 -1
- package/dist/layout/container.css.map +0 -1
- package/dist/layout/flex-columns.css.map +0 -1
- package/dist/layout.css +0 -2
- package/dist/layout.css.map +0 -1
- package/dist/normalize.css.map +0 -1
- package/dist/state/focus.css +0 -2
- package/dist/state/focus.css.map +0 -1
- package/dist/state.css +0 -2
- package/dist/state.css.map +0 -1
- package/dist/theme/color.css.map +0 -1
- package/dist/theme/typography.css.map +0 -1
- package/dist/theme.css.map +0 -1
- package/dist/utilities/alignment.css.map +0 -1
- package/dist/utilities/color.css.map +0 -1
- package/dist/utilities/display.css.map +0 -1
- package/dist/utilities/flex.css.map +0 -1
- package/dist/utilities/height.css.map +0 -1
- package/dist/utilities/inset.css.map +0 -1
- package/dist/utilities/justification.css.map +0 -1
- package/dist/utilities/list.css.map +0 -1
- package/dist/utilities/order.css.map +0 -1
- package/dist/utilities/postion.css.map +0 -1
- package/dist/utilities/spacing.css.map +0 -1
- package/dist/utilities/typography.css.map +0 -1
- package/dist/utilities/visibility.css.map +0 -1
- package/dist/utilities/width.css.map +0 -1
- package/dist/utilities.css.map +0 -1
- /package/dist/{base → css/base}/form.css +0 -0
- /package/dist/{base → css/base}/link.css +0 -0
- /package/dist/{base → css/base}/table.css +0 -0
- /package/dist/{component → css/component}/card.css +0 -0
- /package/dist/{component → css/component}/input-group.css +0 -0
- /package/dist/{component → css/component}/menu.css +0 -0
- /package/dist/{component → css/component}/navigation.css +0 -0
- /package/dist/{init.css → css/init.css} +0 -0
- /package/dist/{layout → css/layout}/columns.css +0 -0
- /package/dist/{layout → css/layout}/container.css +0 -0
- /package/dist/{layout → css/layout}/flex-columns.css +0 -0
- /package/dist/{normalize.css → css/normalize.css} +0 -0
- /package/dist/{theme → css/theme}/color.css +0 -0
- /package/dist/{theme → css/theme}/typography.css +0 -0
- /package/dist/{theme.css → css/theme.css} +0 -0
- /package/dist/{utilities → css/utilities}/alignment.css +0 -0
- /package/dist/{utilities → css/utilities}/color.css +0 -0
- /package/dist/{utilities → css/utilities}/display.css +0 -0
- /package/dist/{utilities → css/utilities}/flex.css +0 -0
- /package/dist/{utilities → css/utilities}/height.css +0 -0
- /package/dist/{utilities → css/utilities}/inset.css +0 -0
- /package/dist/{utilities → css/utilities}/justification.css +0 -0
- /package/dist/{utilities → css/utilities}/list.css +0 -0
- /package/dist/{utilities → css/utilities}/order.css +0 -0
- /package/dist/{utilities → css/utilities}/postion.css +0 -0
- /package/dist/{utilities → css/utilities}/spacing.css +0 -0
- /package/dist/{utilities → css/utilities}/typography.css +0 -0
- /package/dist/{utilities → css/utilities}/visibility.css +0 -0
- /package/dist/{utilities → css/utilities}/width.css +0 -0
- /package/dist/{utilities.css → css/utilities.css} +0 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
* The Accordion Item class.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* global Accordion */
|
|
7
|
+
|
|
8
|
+
import { isTag, isValidType } from "../validate.js";
|
|
9
|
+
import { addClass, removeClass } from "../domHelpers.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new accordion item.
|
|
13
|
+
*
|
|
14
|
+
* @class
|
|
15
|
+
*/
|
|
16
|
+
class AccordionItem {
|
|
17
|
+
/**
|
|
18
|
+
* The HTML elements for the accordion item in the DOM.
|
|
19
|
+
*
|
|
20
|
+
* @protected
|
|
21
|
+
*
|
|
22
|
+
* @type {Object<HTMLElement>}
|
|
23
|
+
*
|
|
24
|
+
* @property {HTMLElement} item - The accordion item element.
|
|
25
|
+
* @property {HTMLElement} toggle - The controller element.
|
|
26
|
+
* @property {HTMLElement} header - The header element.
|
|
27
|
+
* @property {HTMLElement} content - The content element.
|
|
28
|
+
*/
|
|
29
|
+
_dom = {
|
|
30
|
+
item: null,
|
|
31
|
+
toggle: null,
|
|
32
|
+
header: null,
|
|
33
|
+
content: null,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The declared graupl accordion elements within the accordion item.
|
|
38
|
+
*
|
|
39
|
+
* @protected
|
|
40
|
+
*
|
|
41
|
+
* @type {Object<Accordion>}
|
|
42
|
+
*
|
|
43
|
+
* @property {Accordion} parentAccordion - The parent accordion containing this item.
|
|
44
|
+
*/
|
|
45
|
+
_elements = {
|
|
46
|
+
parentAccordion: null,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The open state of the accordion.
|
|
51
|
+
*
|
|
52
|
+
* @protected
|
|
53
|
+
*
|
|
54
|
+
* @type {boolean}
|
|
55
|
+
*/
|
|
56
|
+
_open = false;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The locked state of the accordions item.
|
|
60
|
+
*
|
|
61
|
+
* If locked, the accordion item cannot be closed.
|
|
62
|
+
*
|
|
63
|
+
* @protected
|
|
64
|
+
*
|
|
65
|
+
* @type {boolean}
|
|
66
|
+
*/
|
|
67
|
+
_locked = false;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The event that is triggered when the accordion item is shown.
|
|
71
|
+
*
|
|
72
|
+
* @protected
|
|
73
|
+
*
|
|
74
|
+
* @event grauplAccordionItemExpand
|
|
75
|
+
*
|
|
76
|
+
* @type {CustomEvent}
|
|
77
|
+
*
|
|
78
|
+
* @property {boolean} bubbles - A flag to bubble the event.
|
|
79
|
+
* @property {Object<AccordionItem>} detail - The details object containing the Accordion item itself.
|
|
80
|
+
*/
|
|
81
|
+
_expandEvent = new CustomEvent("grauplAccordionItemExpand", {
|
|
82
|
+
bubbles: true,
|
|
83
|
+
detail: { item: this },
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The event that is triggered when the accordion item is hidden.
|
|
88
|
+
*
|
|
89
|
+
* @protected
|
|
90
|
+
*
|
|
91
|
+
* @event grauplAccordionItemCollapse
|
|
92
|
+
*
|
|
93
|
+
* @type {CustomEvent}
|
|
94
|
+
*
|
|
95
|
+
* @property {boolean} bubbles - A flag to bubble the event.
|
|
96
|
+
* @property {Object<AccordionItem>} detail - The details object containing the Accordion item itself.
|
|
97
|
+
*/
|
|
98
|
+
_collapseEvent = new CustomEvent("grauplAccordionItemCollapse", {
|
|
99
|
+
bubbles: true,
|
|
100
|
+
detail: { item: this },
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Constructs a new Accordion item object.
|
|
105
|
+
*
|
|
106
|
+
* @class
|
|
107
|
+
*
|
|
108
|
+
* @param {object} options - The options object.
|
|
109
|
+
* @param {HTMLElement} options.accordionItemElement - The accordion item element.
|
|
110
|
+
* @param {HTMLElement} options.accordionItemToggleElement - The toggle element.
|
|
111
|
+
* @param {HTMLElement} options.accordionItemHeaderElement - The header element.
|
|
112
|
+
* @param {HTMLElement} options.accordionItemContentElement - The content element.
|
|
113
|
+
* @param {Accordion} [options.parentAccordion = null] - The accordion containing this item.
|
|
114
|
+
*/
|
|
115
|
+
constructor({
|
|
116
|
+
accordionItemElement,
|
|
117
|
+
accordionItemToggleElement,
|
|
118
|
+
accordionItemHeaderElement,
|
|
119
|
+
accordionItemContentElement,
|
|
120
|
+
parentAccordion = null,
|
|
121
|
+
}) {
|
|
122
|
+
// Set DOM elements.
|
|
123
|
+
this._dom.item = accordionItemElement;
|
|
124
|
+
this._dom.toggle = accordionItemToggleElement;
|
|
125
|
+
this._dom.header = accordionItemHeaderElement;
|
|
126
|
+
this._dom.content = accordionItemContentElement;
|
|
127
|
+
|
|
128
|
+
// Set the accordion elements.
|
|
129
|
+
this._elements.parentAccordion = parentAccordion;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Initializes the accordion item.
|
|
134
|
+
*/
|
|
135
|
+
initialize() {
|
|
136
|
+
// Set the IDs for the accordion item and it's elements if they don't exist.
|
|
137
|
+
this._setIds();
|
|
138
|
+
|
|
139
|
+
// Set the ARIA attributes for the accordion item and it's elements.
|
|
140
|
+
this._setAriaAttributes();
|
|
141
|
+
|
|
142
|
+
// Set the initial state of the accordion item.
|
|
143
|
+
if (this.dom.toggle.getAttribute("aria-expanded") === "true") {
|
|
144
|
+
this.show(false, false);
|
|
145
|
+
} else {
|
|
146
|
+
this.hide(false, false);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The HTML elements for the accordion item in the DOM.
|
|
152
|
+
*
|
|
153
|
+
* @readonly
|
|
154
|
+
*
|
|
155
|
+
* @type {object}
|
|
156
|
+
*
|
|
157
|
+
* @see _dom
|
|
158
|
+
*/
|
|
159
|
+
get dom() {
|
|
160
|
+
return this._dom;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* The declared graupl accordion elements within the accordion item.
|
|
165
|
+
*
|
|
166
|
+
* @readonly
|
|
167
|
+
*
|
|
168
|
+
* @type {Object<Accordion>}
|
|
169
|
+
*
|
|
170
|
+
* @see _elements
|
|
171
|
+
*/
|
|
172
|
+
get elements() {
|
|
173
|
+
return this._elements;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* The open state of the accordion.
|
|
178
|
+
*
|
|
179
|
+
* @readonly
|
|
180
|
+
*
|
|
181
|
+
* @type {object}
|
|
182
|
+
*
|
|
183
|
+
* @see _open
|
|
184
|
+
*/
|
|
185
|
+
get isOpen() {
|
|
186
|
+
return this._open;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The locked state of the accordions item.
|
|
191
|
+
*
|
|
192
|
+
* If locked, the accordion item cannot be closed.
|
|
193
|
+
*
|
|
194
|
+
* @readonly
|
|
195
|
+
*
|
|
196
|
+
* @type {boolean}
|
|
197
|
+
*
|
|
198
|
+
* @see _locked
|
|
199
|
+
*/
|
|
200
|
+
get isLocked() {
|
|
201
|
+
return this._locked;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
set isOpen(value) {
|
|
205
|
+
isValidType("boolean", { value });
|
|
206
|
+
|
|
207
|
+
if (this._open !== value) {
|
|
208
|
+
this._open = value;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Sets the IDs for the accordion item and it's elements if they don't exist.
|
|
214
|
+
*
|
|
215
|
+
* The generated IDs use the parent accordion's key and follows the pattern:
|
|
216
|
+
* - Accordion item: `accordion-item-{key}-{index}`
|
|
217
|
+
* - Accordion item toggle: `accordion-item-toggle-{key}-{index}`
|
|
218
|
+
* - Accordion item content: `accordion-item-content-{key}-{index}`
|
|
219
|
+
*/
|
|
220
|
+
_setIds() {
|
|
221
|
+
// Get the required information for IDs.
|
|
222
|
+
const { key } = this.elements.parentAccordion;
|
|
223
|
+
const index = this.elements.parentAccordion.dom.accordionItems.indexOf(
|
|
224
|
+
this.dom.item
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
this.dom.item.id = this.dom.item.id || `accordion-item-${key}-${index}`;
|
|
228
|
+
this.dom.toggle.id =
|
|
229
|
+
this.dom.toggle.id || `accordion-item-toggle-${key}-${index}`;
|
|
230
|
+
this.dom.header.id =
|
|
231
|
+
this.dom.header.id || `accordion-item-header-${key}-${index}`;
|
|
232
|
+
this.dom.content.id =
|
|
233
|
+
this.dom.content.id || `accordion-item-content-${key}-${index}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Sets the ARIA attributes for the accordion item and it's elements.
|
|
238
|
+
*/
|
|
239
|
+
_setAriaAttributes() {
|
|
240
|
+
// Set the ARIA attributes for the accordion item toggle.
|
|
241
|
+
// If the toggle is not a button, then set the role to "button".
|
|
242
|
+
if (!isTag("button", { toggle: this.dom.toggle })) {
|
|
243
|
+
this.dom.toggle.setAttribute("role", "button");
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// If aria-expanded is not explicitly set to "true", then set it to "false".
|
|
247
|
+
if (this.dom.toggle.getAttribute("aria-expanded") !== "true") {
|
|
248
|
+
this.dom.toggle.setAttribute("aria-expanded", "false");
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Set the aria-controls attribute for the toggle.
|
|
252
|
+
this.dom.toggle.setAttribute("aria-controls", this.dom.content.id);
|
|
253
|
+
|
|
254
|
+
// Set the ARIA attributes for the accordion item content.
|
|
255
|
+
// If the content is not a section, then set the role to "region".
|
|
256
|
+
if (!isTag("section", { content: this.dom.content })) {
|
|
257
|
+
this.dom.content.setAttribute("role", "region");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Set the aria-labelledby attribute for the content.
|
|
261
|
+
this.dom.content.setAttribute("aria-labelledby", this.dom.toggle.id);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Shows the accordion item.
|
|
266
|
+
*
|
|
267
|
+
* @public
|
|
268
|
+
*
|
|
269
|
+
* @fires grauplAccordionItemExpand
|
|
270
|
+
*
|
|
271
|
+
* @param {boolean} [emit = true] - Emit the show event once shown.
|
|
272
|
+
* @param {boolean} [transition = true] - Respect the transition class.
|
|
273
|
+
*/
|
|
274
|
+
show(emit = true, transition = true) {
|
|
275
|
+
if (this._open) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const { closeClass, openClass, transitionClass, openDuration } =
|
|
280
|
+
this.elements.parentAccordion;
|
|
281
|
+
|
|
282
|
+
// Set aria-expanded to true when hiding accordion item.
|
|
283
|
+
this.dom.toggle.setAttribute("aria-expanded", "true");
|
|
284
|
+
|
|
285
|
+
// If we're dealing with transition classes, then we need to utilize
|
|
286
|
+
// requestAnimationFrame to add the transition class, remove the hide class,
|
|
287
|
+
// add the show class, and finally remove the transition class.
|
|
288
|
+
//
|
|
289
|
+
// If `transition` is false, then it doesn't matter if the transition class
|
|
290
|
+
// is set. Do not use the transition.
|
|
291
|
+
if (transition && transitionClass !== "") {
|
|
292
|
+
addClass(transitionClass, this.dom.item);
|
|
293
|
+
|
|
294
|
+
requestAnimationFrame(() => {
|
|
295
|
+
removeClass(closeClass, this.dom.item);
|
|
296
|
+
|
|
297
|
+
this.dom.item.style.height = `${this.dom.header.getBoundingClientRect().height}px`;
|
|
298
|
+
|
|
299
|
+
requestAnimationFrame(() => {
|
|
300
|
+
addClass(openClass, this.dom.item);
|
|
301
|
+
|
|
302
|
+
this.dom.item.style.height = `${this.dom.header.getBoundingClientRect().height + this.dom.content.getBoundingClientRect().height}px`;
|
|
303
|
+
|
|
304
|
+
requestAnimationFrame(() => {
|
|
305
|
+
setTimeout(() => {
|
|
306
|
+
removeClass(transitionClass, this.dom.item);
|
|
307
|
+
|
|
308
|
+
this.dom.item.style.height = "";
|
|
309
|
+
}, openDuration);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
} else {
|
|
314
|
+
// Add the show class
|
|
315
|
+
addClass(openClass, this.dom.item);
|
|
316
|
+
|
|
317
|
+
// Remove the hide class.
|
|
318
|
+
removeClass(closeClass, this.dom.item);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
this._open = true;
|
|
322
|
+
|
|
323
|
+
// If the parent accordion only allows a single item to be open at a time,
|
|
324
|
+
// then close all other items.
|
|
325
|
+
if (!this.elements.parentAccordion.allowMultipleExpand) {
|
|
326
|
+
this.unlockSiblings();
|
|
327
|
+
this.closeSiblings();
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// If the parent accordion requires at least one item to be open, and this
|
|
331
|
+
// is the only open item, then lock it. Otherwise, unlock all siblings.
|
|
332
|
+
if (!this.elements.parentAccordion.allowNoExpand) {
|
|
333
|
+
if (this.elements.parentAccordion.openAccordionItems.length <= 1) {
|
|
334
|
+
this.lock();
|
|
335
|
+
} else {
|
|
336
|
+
this.unlockSiblings();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (emit) {
|
|
341
|
+
this.dom.item.dispatchEvent(this._expandEvent);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Hides the accordion item.
|
|
347
|
+
*
|
|
348
|
+
* @public
|
|
349
|
+
*
|
|
350
|
+
* @fires grauplAccordionItemCollapse
|
|
351
|
+
*
|
|
352
|
+
* @param {boolean} [emit = true] - Emit the show event once shown.
|
|
353
|
+
* @param {boolean} [transition = true] - Respect the transition class.
|
|
354
|
+
*/
|
|
355
|
+
hide(emit = true, transition = true) {
|
|
356
|
+
if (!this._open) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (
|
|
361
|
+
!this.elements.parentAccordion.allowNoExpand &&
|
|
362
|
+
this.elements.parentAccordion.openAccordionItems.length <= 1
|
|
363
|
+
) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const { closeClass, openClass, transitionClass, closeDuration } =
|
|
368
|
+
this.elements.parentAccordion;
|
|
369
|
+
|
|
370
|
+
// Set aria-expanded to false when hiding accordion item.
|
|
371
|
+
this.dom.toggle.setAttribute("aria-expanded", "false");
|
|
372
|
+
|
|
373
|
+
// If we're dealing with transition classes, then we need to utilize
|
|
374
|
+
// requestAnimationFrame to add the transition class, remove the show class,
|
|
375
|
+
// add the hide class, and finally remove the transition class.
|
|
376
|
+
//
|
|
377
|
+
// If `transition` is false, then it doesn't matter if the transition class
|
|
378
|
+
// is set. Do not use the transition.
|
|
379
|
+
if (transition && transitionClass !== "") {
|
|
380
|
+
addClass(transitionClass, this.dom.item);
|
|
381
|
+
this.dom.item.style.height = `${this.dom.item.getBoundingClientRect().height}px`;
|
|
382
|
+
|
|
383
|
+
requestAnimationFrame(() => {
|
|
384
|
+
removeClass(openClass, this.dom.item);
|
|
385
|
+
this.dom.item.style.height = `${this.dom.header.getBoundingClientRect().height}px`;
|
|
386
|
+
|
|
387
|
+
requestAnimationFrame(() => {
|
|
388
|
+
addClass(closeClass, this.dom.item);
|
|
389
|
+
|
|
390
|
+
requestAnimationFrame(() => {
|
|
391
|
+
setTimeout(() => {
|
|
392
|
+
removeClass(transitionClass, this.dom.item);
|
|
393
|
+
|
|
394
|
+
this.dom.item.style.height = "";
|
|
395
|
+
}, closeDuration);
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
} else {
|
|
400
|
+
// Add the hide class
|
|
401
|
+
addClass(closeClass, this.dom.item);
|
|
402
|
+
|
|
403
|
+
// Remove the show class.
|
|
404
|
+
removeClass(openClass, this.dom.item);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
this._open = false;
|
|
408
|
+
|
|
409
|
+
// If the parent accordion requires at least one item to be open, and this was
|
|
410
|
+
// the second to last open item, then lock to last open item.
|
|
411
|
+
if (
|
|
412
|
+
!this.elements.parentAccordion.allowNoExpand &&
|
|
413
|
+
this.elements.parentAccordion.openAccordionItems.length === 1
|
|
414
|
+
) {
|
|
415
|
+
this.elements.parentAccordion.openAccordionItems[0].lock();
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (emit) {
|
|
419
|
+
this.dom.item.dispatchEvent(this._collapseEvent);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Toggle the accordion item.
|
|
425
|
+
*
|
|
426
|
+
* @public
|
|
427
|
+
*/
|
|
428
|
+
toggle() {
|
|
429
|
+
this.isOpen ? this.hide() : this.show();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Focuses the accordion item.
|
|
434
|
+
*
|
|
435
|
+
* @public
|
|
436
|
+
*/
|
|
437
|
+
focus() {
|
|
438
|
+
this.dom.toggle.focus();
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Blurs the accordion item.
|
|
443
|
+
*
|
|
444
|
+
* @public
|
|
445
|
+
*/
|
|
446
|
+
blur() {
|
|
447
|
+
this.dom.toggle.blur();
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Locks the accordion item.
|
|
452
|
+
*
|
|
453
|
+
* @public
|
|
454
|
+
*/
|
|
455
|
+
lock() {
|
|
456
|
+
this._locked = true;
|
|
457
|
+
this.dom.toggle.setAttribute("disabled", "true");
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Unlocks the accordion item.
|
|
462
|
+
*
|
|
463
|
+
* @public
|
|
464
|
+
*/
|
|
465
|
+
unlock() {
|
|
466
|
+
this._locked = false;
|
|
467
|
+
this.dom.toggle.removeAttribute("disabled");
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
closeSiblings() {
|
|
471
|
+
if (this.elements.parentAccordion) {
|
|
472
|
+
this.elements.parentAccordion.elements.accordionItems.forEach((item) => {
|
|
473
|
+
if (item !== this) {
|
|
474
|
+
item.hide();
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Unlocks the siblings of the accordion item.
|
|
482
|
+
*
|
|
483
|
+
* @public
|
|
484
|
+
*/
|
|
485
|
+
unlockSiblings() {
|
|
486
|
+
if (this.elements.parentAccordion) {
|
|
487
|
+
this.elements.parentAccordion.elements.accordionItems.forEach((item) => {
|
|
488
|
+
if (item !== this) {
|
|
489
|
+
item.unlock();
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
export default AccordionItem;
|
package/src/js/alert/Alert.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { isValidClassList, isValidInstance, isValidType } from "../validate.js";
|
|
7
7
|
import { addClass, removeClass } from "../domHelpers.js";
|
|
8
8
|
import { keyPress, preventEvent } from "../eventHandlers.js";
|
|
9
|
+
import storage from "../storage.js";
|
|
9
10
|
|
|
10
11
|
class Alert {
|
|
11
12
|
/**
|
|
@@ -65,6 +66,15 @@ class Alert {
|
|
|
65
66
|
*/
|
|
66
67
|
_transitionTimer = 150;
|
|
67
68
|
|
|
69
|
+
/**
|
|
70
|
+
* The key used to generate IDs throughout the carousel.
|
|
71
|
+
*
|
|
72
|
+
* @protected
|
|
73
|
+
*
|
|
74
|
+
* @type {string}
|
|
75
|
+
*/
|
|
76
|
+
_key = "";
|
|
77
|
+
|
|
68
78
|
/**
|
|
69
79
|
* An array of error messages generated by the alert.
|
|
70
80
|
*
|
|
@@ -83,7 +93,7 @@ class Alert {
|
|
|
83
93
|
*
|
|
84
94
|
* @type {CustomEvent}
|
|
85
95
|
*
|
|
86
|
-
* @property {boolean} bubbles - A flag to
|
|
96
|
+
* @property {boolean} bubbles - A flag to bubble the event.
|
|
87
97
|
* @property {Object<Alert>} detail - The details object container the Alert itself.
|
|
88
98
|
*/
|
|
89
99
|
_showEvent = new CustomEvent("grauplAlertShow", {
|
|
@@ -119,6 +129,7 @@ class Alert {
|
|
|
119
129
|
* @param {string|string[]|null} [options.transitionClass = transitioning] - The class to add when the alert is transitioning between shown and hidden.
|
|
120
130
|
* @param {number} [options.transitionTimer = 150] - The time in milliseconds the transition will take.
|
|
121
131
|
* @param {boolean} [options.isHidden = false] - A flag to determine the initial state of the alert.
|
|
132
|
+
* @param {?string} [options.key = null] - The key used to generate IDs throughout the alert.
|
|
122
133
|
* @param {boolean} [options.initialize = false] - AA flag to initialize the alert immediately upon creation.
|
|
123
134
|
*/
|
|
124
135
|
constructor({
|
|
@@ -129,6 +140,7 @@ class Alert {
|
|
|
129
140
|
transitionClass = "transitioning",
|
|
130
141
|
transitionTimer = 150,
|
|
131
142
|
isHidden = false,
|
|
143
|
+
key = null,
|
|
132
144
|
initialize = false,
|
|
133
145
|
}) {
|
|
134
146
|
this._dom.alert = alertElement;
|
|
@@ -139,6 +151,9 @@ class Alert {
|
|
|
139
151
|
this._transitionTimer = transitionTimer;
|
|
140
152
|
this._hidden = isHidden;
|
|
141
153
|
|
|
154
|
+
// Set the key.
|
|
155
|
+
this._key = key || "";
|
|
156
|
+
|
|
142
157
|
if (initialize) {
|
|
143
158
|
this.initialize();
|
|
144
159
|
}
|
|
@@ -157,9 +172,18 @@ class Alert {
|
|
|
157
172
|
);
|
|
158
173
|
}
|
|
159
174
|
|
|
175
|
+
// Set up the DOM.
|
|
176
|
+
this._generateKey();
|
|
177
|
+
this._setIds();
|
|
178
|
+
|
|
179
|
+
// Handle events.
|
|
160
180
|
this._handleClick();
|
|
161
181
|
this._handleKeydown();
|
|
162
182
|
this._handleKeyup();
|
|
183
|
+
|
|
184
|
+
// Set up the storage.
|
|
185
|
+
storage.initializeStorage("alerts");
|
|
186
|
+
storage.pushToStorage("alerts", this.dom.alert.id, this);
|
|
163
187
|
} catch (error) {
|
|
164
188
|
console.error(error);
|
|
165
189
|
}
|
|
@@ -222,6 +246,17 @@ class Alert {
|
|
|
222
246
|
return this._transitionTimer;
|
|
223
247
|
}
|
|
224
248
|
|
|
249
|
+
/**
|
|
250
|
+
* The key used to generate IDs throughout the accordion.
|
|
251
|
+
*
|
|
252
|
+
* @type {string}
|
|
253
|
+
*
|
|
254
|
+
* @see _key
|
|
255
|
+
*/
|
|
256
|
+
get key() {
|
|
257
|
+
return this._key;
|
|
258
|
+
}
|
|
259
|
+
|
|
225
260
|
set showClass(value) {
|
|
226
261
|
isValidClassList({ showClass: value });
|
|
227
262
|
|
|
@@ -254,6 +289,14 @@ class Alert {
|
|
|
254
289
|
}
|
|
255
290
|
}
|
|
256
291
|
|
|
292
|
+
set key(value) {
|
|
293
|
+
isValidType("string", { value });
|
|
294
|
+
|
|
295
|
+
if (this._key !== value) {
|
|
296
|
+
this._key = value;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
257
300
|
/**
|
|
258
301
|
* Validates all aspects of the alert to ensure proper functionality.
|
|
259
302
|
*
|
|
@@ -334,6 +377,33 @@ class Alert {
|
|
|
334
377
|
return check;
|
|
335
378
|
}
|
|
336
379
|
|
|
380
|
+
/**
|
|
381
|
+
* Generates a key for the alert.
|
|
382
|
+
*
|
|
383
|
+
* @param {boolean} [regenerate = false] - A flag to determine if the key should be regenerated.
|
|
384
|
+
*/
|
|
385
|
+
_generateKey(regenerate = false) {
|
|
386
|
+
if (this.key === "" || regenerate) {
|
|
387
|
+
this.key = Math.random()
|
|
388
|
+
.toString(36)
|
|
389
|
+
.replace(/[^a-z]+/g, "")
|
|
390
|
+
.substring(0, 10);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Sets the IDs of the alert and it's children if they do not already exist.
|
|
396
|
+
*
|
|
397
|
+
* The generated IDs use the key and follow the format:
|
|
398
|
+
* - alert: `alert-${key}`
|
|
399
|
+
* - controller: `alert-controller-${key}`
|
|
400
|
+
*/
|
|
401
|
+
_setIds() {
|
|
402
|
+
this.dom.alert.id = this.dom.alert.id || `alert-${this.key}`;
|
|
403
|
+
this.dom.controller.id =
|
|
404
|
+
this.dom.controller.id || `alert-controller-${this.key}`;
|
|
405
|
+
}
|
|
406
|
+
|
|
337
407
|
/**
|
|
338
408
|
* Shows the alert.
|
|
339
409
|
*
|
package/src/js/alert/index.js
CHANGED
|
@@ -1,21 +1,11 @@
|
|
|
1
1
|
import Alert from "./Alert.js";
|
|
2
2
|
|
|
3
3
|
document.addEventListener("DOMContentLoaded", () => {
|
|
4
|
-
const alerts = [];
|
|
5
|
-
|
|
6
4
|
document.querySelectorAll(".alert").forEach((alertElement) => {
|
|
7
|
-
|
|
5
|
+
new Alert({
|
|
8
6
|
alertElement,
|
|
9
7
|
controllerElement: alertElement.querySelector(".alert-dismisser") || null,
|
|
10
8
|
initialize: true,
|
|
11
9
|
});
|
|
12
|
-
|
|
13
|
-
alerts.push(alert);
|
|
14
10
|
});
|
|
15
|
-
|
|
16
|
-
const graupl = window.Graupl || {};
|
|
17
|
-
|
|
18
|
-
graupl.alerts = alerts;
|
|
19
|
-
|
|
20
|
-
window.Graupl = graupl;
|
|
21
11
|
});
|