@graupl/core 1.0.0-beta.22 → 1.0.0-beta.24
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/dist/css/base/button.css +2 -2
- package/dist/css/base/button.css.map +1 -1
- package/dist/css/base/form.css +2 -2
- package/dist/css/base/form.css.map +1 -1
- package/dist/css/base/link.css +2 -2
- package/dist/css/base/link.css.map +1 -1
- package/dist/css/base/table.css +2 -2
- package/dist/css/base/table.css.map +1 -1
- package/dist/css/base.css +2 -2
- package/dist/css/base.css.map +1 -1
- package/dist/css/component/accordion.css +2 -5
- package/dist/css/component/accordion.css.map +1 -1
- package/dist/css/component/alert.css +2 -2
- package/dist/css/component/alert.css.map +1 -1
- package/dist/css/component/badge.css +2 -2
- package/dist/css/component/badge.css.map +1 -1
- package/dist/css/component/card.css +2 -2
- package/dist/css/component/card.css.map +1 -1
- package/dist/css/component/carousel.css +2 -2
- package/dist/css/component/carousel.css.map +1 -1
- package/dist/css/component/disclosure.css +2 -2
- package/dist/css/component/disclosure.css.map +1 -1
- package/dist/css/component/input-group.css +2 -2
- package/dist/css/component/input-group.css.map +1 -1
- package/dist/css/component/list.css +2 -2
- package/dist/css/component/list.css.map +1 -1
- package/dist/css/component/menu.css +2 -2
- package/dist/css/component/menu.css.map +1 -1
- package/dist/css/component/navigation.css +2 -2
- package/dist/css/component/navigation.css.map +1 -1
- package/dist/css/component.css +2 -5
- package/dist/css/component.css.map +1 -1
- package/dist/css/graupl.css +2 -5
- package/dist/css/graupl.css.map +1 -1
- package/dist/css/init.css +2 -2
- package/dist/css/init.css.map +1 -1
- package/dist/css/layout/columns.css +2 -2
- package/dist/css/layout/columns.css.map +1 -1
- package/dist/css/layout/container.css +2 -2
- package/dist/css/layout/container.css.map +1 -1
- package/dist/css/layout/flex-columns.css +2 -2
- package/dist/css/layout/flex-columns.css.map +1 -1
- package/dist/css/layout.css +2 -5
- package/dist/css/layout.css.map +1 -1
- package/dist/css/normalize.css +2 -2
- package/dist/css/normalize.css.map +1 -1
- package/dist/css/state/focus.css +2 -2
- package/dist/css/state/focus.css.map +1 -1
- package/dist/css/state.css +2 -2
- package/dist/css/state.css.map +1 -1
- package/dist/css/theme/color.css +2 -2
- package/dist/css/theme/color.css.map +1 -1
- package/dist/css/theme/typography.css +2 -2
- package/dist/css/theme/typography.css.map +1 -1
- package/dist/css/theme.css +2 -2
- package/dist/css/theme.css.map +1 -1
- package/dist/css/utilities/alignment.css +1 -1
- package/dist/css/utilities/alignment.css.map +1 -1
- package/dist/css/utilities/background.css +2 -2
- package/dist/css/utilities/background.css.map +1 -1
- package/dist/css/utilities/border.css +2 -2
- package/dist/css/utilities/border.css.map +1 -1
- package/dist/css/utilities/color.css +2 -2
- package/dist/css/utilities/color.css.map +1 -1
- package/dist/css/utilities/container.css +1 -1
- package/dist/css/utilities/container.css.map +1 -1
- package/dist/css/utilities/display.css +2 -2
- package/dist/css/utilities/display.css.map +1 -1
- package/dist/css/utilities/flex.css +2 -2
- package/dist/css/utilities/flex.css.map +1 -1
- package/dist/css/utilities/gradient.css +2 -2
- package/dist/css/utilities/gradient.css.map +1 -1
- package/dist/css/utilities/height.css +2 -2
- package/dist/css/utilities/height.css.map +1 -1
- package/dist/css/utilities/inset.css +2 -2
- package/dist/css/utilities/inset.css.map +1 -1
- package/dist/css/utilities/justification.css +1 -1
- package/dist/css/utilities/justification.css.map +1 -1
- package/dist/css/utilities/list.css +1 -1
- package/dist/css/utilities/list.css.map +1 -1
- package/dist/css/utilities/order.css +2 -2
- package/dist/css/utilities/order.css.map +1 -1
- package/dist/css/utilities/position.css +2 -2
- package/dist/css/utilities/position.css.map +1 -1
- package/dist/css/utilities/ratio.css +2 -2
- package/dist/css/utilities/ratio.css.map +1 -1
- package/dist/css/utilities/spacing.css +2 -2
- package/dist/css/utilities/spacing.css.map +1 -1
- package/dist/css/utilities/typography.css +2 -2
- package/dist/css/utilities/typography.css.map +1 -1
- package/dist/css/utilities/visibility.css +2 -2
- package/dist/css/utilities/visibility.css.map +1 -1
- package/dist/css/utilities/visually-hidden.css +2 -2
- package/dist/css/utilities/visually-hidden.css.map +1 -1
- package/dist/css/utilities/width.css +2 -2
- package/dist/css/utilities/width.css.map +1 -1
- package/dist/css/utilities/z-index.css +1 -1
- package/dist/css/utilities/z-index.css.map +1 -1
- package/dist/css/utilities.css +2 -2
- package/dist/css/utilities.css.map +1 -1
- package/dist/js/accordion.js.map +1 -1
- package/dist/js/alert.js.map +1 -1
- package/dist/js/carousel.js.map +1 -1
- package/dist/js/component/accordion.cjs.js.map +1 -1
- package/dist/js/component/accordion.es.js.map +1 -1
- package/dist/js/component/accordion.iife.js.map +1 -1
- package/dist/js/component/alert.cjs.js.map +1 -1
- package/dist/js/component/alert.es.js.map +1 -1
- package/dist/js/component/alert.iife.js.map +1 -1
- package/dist/js/component/carousel.cjs.js.map +1 -1
- package/dist/js/component/carousel.es.js.map +1 -1
- package/dist/js/component/carousel.iife.js.map +1 -1
- package/dist/js/component/disclosure.cjs.js +2 -2
- package/dist/js/component/disclosure.cjs.js.map +1 -1
- package/dist/js/component/disclosure.es.js +2 -2
- package/dist/js/component/disclosure.es.js.map +1 -1
- package/dist/js/component/disclosure.iife.js +2 -2
- package/dist/js/component/disclosure.iife.js.map +1 -1
- package/dist/js/component/tabs.cjs.js +5 -0
- package/dist/js/component/tabs.cjs.js.map +1 -0
- package/dist/js/component/tabs.es.js +5 -0
- package/dist/js/component/tabs.es.js.map +1 -0
- package/dist/js/component/tabs.iife.js +5 -0
- package/dist/js/component/tabs.iife.js.map +1 -0
- package/dist/js/disclosure.js +2 -2
- package/dist/js/disclosure.js.map +1 -1
- package/dist/js/generator/accordion.cjs.js.map +1 -1
- package/dist/js/generator/accordion.es.js.map +1 -1
- package/dist/js/generator/accordion.iife.js.map +1 -1
- package/dist/js/generator/alert.cjs.js.map +1 -1
- package/dist/js/generator/alert.es.js.map +1 -1
- package/dist/js/generator/alert.iife.js.map +1 -1
- package/dist/js/generator/carousel.cjs.js.map +1 -1
- package/dist/js/generator/carousel.es.js.map +1 -1
- package/dist/js/generator/carousel.iife.js.map +1 -1
- package/dist/js/generator/disclosure.cjs.js +2 -2
- package/dist/js/generator/disclosure.cjs.js.map +1 -1
- package/dist/js/generator/disclosure.es.js +2 -2
- package/dist/js/generator/disclosure.es.js.map +1 -1
- package/dist/js/generator/disclosure.iife.js +2 -2
- package/dist/js/generator/disclosure.iife.js.map +1 -1
- package/dist/js/generator/navigation.cjs.js.map +1 -1
- package/dist/js/generator/navigation.es.js.map +1 -1
- package/dist/js/generator/navigation.iife.js.map +1 -1
- package/dist/js/generator/tabs.cjs.js +5 -0
- package/dist/js/generator/tabs.cjs.js.map +1 -0
- package/dist/js/generator/tabs.es.js +5 -0
- package/dist/js/generator/tabs.es.js.map +1 -0
- package/dist/js/generator/tabs.iife.js +5 -0
- package/dist/js/generator/tabs.iife.js.map +1 -0
- package/dist/js/graupl.js +5 -5
- package/dist/js/graupl.js.map +1 -1
- package/dist/js/navigation.js.map +1 -1
- package/dist/js/tabs.js +5 -0
- package/dist/js/tabs.js.map +1 -0
- package/package.json +4 -3
- package/src/js/disclosure/Disclosure.js +25 -45
- package/src/js/domHelpers.js +39 -22
- package/src/js/tabs/TabToggle.js +378 -0
- package/src/js/tabs/Tabs.js +1091 -0
- package/src/js/tabs/generator.js +32 -0
- package/src/js/tabs/index.js +5 -0
- package/src/scss/_defaults.scss +21 -88
- package/src/scss/_variables.scss +70 -0
- package/src/scss/base/button/_defaults.scss +2 -24
- package/src/scss/base/button/_index.scss +53 -52
- package/src/scss/base/button/_mixins.scss +24 -58
- package/src/scss/base/button/_variables.scss +139 -0
- package/src/scss/base/form/_defaults.scss +72 -2
- package/src/scss/base/form/_index.scss +196 -70
- package/src/scss/base/form/_variables.scss +166 -0
- package/src/scss/base/link/_defaults.scss +31 -0
- package/src/scss/base/link/_index.scss +177 -172
- package/src/scss/base/link/_variables.scss +215 -0
- package/src/scss/base/table/_defaults.scss +1 -11
- package/src/scss/base/table/_index.scss +126 -117
- package/src/scss/base/table/_variables.scss +214 -3
- package/src/scss/component/_index.scss +1 -0
- package/src/scss/component/accordion/_defaults.scss +73 -22
- package/src/scss/component/accordion/_index.scss +437 -62
- package/src/scss/component/accordion/_variables.scss +527 -101
- package/src/scss/component/alert/_defaults.scss +23 -32
- package/src/scss/component/alert/_index.scss +236 -30
- package/src/scss/component/alert/_variables.scss +155 -6
- package/src/scss/component/badge/_defaults.scss +1 -0
- package/src/scss/component/badge/_index.scss +25 -28
- package/src/scss/component/badge/_variables.scss +66 -2
- package/src/scss/component/card/_defaults.scss +64 -13
- package/src/scss/component/card/_index.scss +276 -30
- package/src/scss/component/card/_variables.scss +132 -0
- package/src/scss/component/carousel/_defaults.scss +73 -15
- package/src/scss/component/carousel/_index.scss +357 -41
- package/src/scss/component/carousel/_variables.scss +391 -0
- package/src/scss/component/disclosure/_index.scss +4 -4
- package/src/scss/component/disclosure/_variables.scss +127 -2
- package/src/scss/component/input-group/_defaults.scss +10 -3
- package/src/scss/component/input-group/_index.scss +72 -4
- package/src/scss/component/input-group/_variables.scss +37 -0
- package/src/scss/component/list/_defaults.scss +35 -2
- package/src/scss/component/list/_index.scss +159 -5
- package/src/scss/component/list/_variables.scss +152 -0
- package/src/scss/component/menu/_defaults.scss +49 -7
- package/src/scss/component/menu/_index.scss +325 -99
- package/src/scss/component/menu/_variables.scss +484 -1
- package/src/scss/component/navigation/_defaults.scss +45 -3
- package/src/scss/component/navigation/_index.scss +249 -98
- package/src/scss/component/navigation/_variables.scss +334 -5
- package/src/scss/component/tabs/_defaults.scss +82 -0
- package/src/scss/component/tabs/_index.scss +497 -0
- package/src/scss/component/tabs/_variables.scss +974 -0
- package/src/scss/layout/columns/_defaults.scss +5 -3
- package/src/scss/layout/columns/_index.scss +27 -21
- package/src/scss/layout/columns/_variables.scss +13 -0
- package/src/scss/layout/container/_defaults.scss +28 -11
- package/src/scss/layout/container/_index.scss +305 -161
- package/src/scss/layout/container/_variables.scss +148 -15
- package/src/scss/layout/flex-columns/_defaults.scss +5 -3
- package/src/scss/layout/flex-columns/_index.scss +28 -20
- package/src/scss/layout/flex-columns/_variables.scss +9 -0
- package/src/scss/mixins/_state.scss +37 -0
- package/src/scss/mixins/_theme.scss +36 -1
- package/src/scss/state/focus/_index.scss +17 -12
- package/src/scss/state/focus/_variables.scss +30 -4
- package/src/scss/theme/color/_defaults.scss +6 -35
- package/src/scss/theme/color/_index.scss +167 -1
- package/src/scss/theme/color/_variables.scss +155 -0
- package/src/scss/theme/typography/_defaults.scss +26 -19
- package/src/scss/theme/typography/_index.scss +176 -20
- package/src/scss/theme/typography/_variables.scss +186 -0
- package/src/scss/utilities/_template/_index.scss +0 -1
- package/src/scss/utilities/alignment/_defaults.scss +0 -33
- package/src/scss/utilities/alignment/_index.scss +24 -25
- package/src/scss/utilities/background/_defaults.scss +0 -77
- package/src/scss/utilities/background/_index.scss +32 -37
- package/src/scss/utilities/border/_defaults.scss +0 -33
- package/src/scss/utilities/border/_index.scss +25 -26
- package/src/scss/utilities/color/_defaults.scss +0 -19
- package/src/scss/utilities/color/_index.scss +22 -22
- package/src/scss/utilities/container/_defaults.scss +0 -11
- package/src/scss/utilities/container/_index.scss +20 -19
- package/src/scss/utilities/display/_defaults.scss +0 -11
- package/src/scss/utilities/display/_index.scss +20 -19
- package/src/scss/utilities/flex/_defaults.scss +0 -55
- package/src/scss/utilities/flex/_index.scss +28 -31
- package/src/scss/utilities/gradient/_defaults.scss +0 -28
- package/src/scss/utilities/gradient/_index.scss +27 -28
- package/src/scss/utilities/gradient/_variables.scss +15 -0
- package/src/scss/utilities/height/_defaults.scss +0 -8
- package/src/scss/utilities/height/_index.scss +22 -21
- package/src/scss/utilities/inset/_defaults.scss +0 -16
- package/src/scss/utilities/inset/_index.scss +20 -20
- package/src/scss/utilities/justification/_defaults.scss +0 -33
- package/src/scss/utilities/justification/_index.scss +24 -25
- package/src/scss/utilities/list/_defaults.scss +0 -22
- package/src/scss/utilities/list/_index.scss +22 -22
- package/src/scss/utilities/order/_defaults.scss +0 -8
- package/src/scss/utilities/order/_index.scss +20 -19
- package/src/scss/utilities/position/_defaults.scss +0 -11
- package/src/scss/utilities/position/_index.scss +20 -19
- package/src/scss/utilities/ratio/_defaults.scss +0 -8
- package/src/scss/utilities/ratio/_index.scss +22 -21
- package/src/scss/utilities/ratio/_variables.scss +6 -0
- package/src/scss/utilities/spacing/_defaults.scss +0 -11
- package/src/scss/utilities/spacing/_index.scss +18 -17
- package/src/scss/utilities/typography/_defaults.scss +0 -22
- package/src/scss/utilities/typography/_index.scss +27 -26
- package/src/scss/utilities/visibility/_defaults.scss +0 -11
- package/src/scss/utilities/visibility/_index.scss +19 -18
- package/src/scss/utilities/visually-hidden/_index.scss +19 -17
- package/src/scss/utilities/width/_defaults.scss +0 -8
- package/src/scss/utilities/width/_index.scss +21 -20
- package/src/scss/utilities/z-index/_defaults.scss +0 -11
- package/src/scss/utilities/z-index/_index.scss +19 -18
|
@@ -139,22 +139,22 @@ class Disclosure {
|
|
|
139
139
|
_closeOnBlur = false;
|
|
140
140
|
|
|
141
141
|
/**
|
|
142
|
-
* The width of the screen
|
|
142
|
+
* The width of the screen that the disclosure will automatically open/close itself.
|
|
143
143
|
*
|
|
144
144
|
* @protected
|
|
145
145
|
*
|
|
146
|
-
* @type {
|
|
146
|
+
* @type {string}
|
|
147
147
|
*/
|
|
148
|
-
_breakpointWidth =
|
|
148
|
+
_breakpointWidth = "";
|
|
149
149
|
|
|
150
150
|
/**
|
|
151
|
-
* This
|
|
151
|
+
* This MediaQueryList for the disclosure.
|
|
152
152
|
*
|
|
153
153
|
* @protected
|
|
154
154
|
*
|
|
155
|
-
* @type {
|
|
155
|
+
* @type {MediaQueryList|null}
|
|
156
156
|
*/
|
|
157
|
-
|
|
157
|
+
_mediaQueryList = null;
|
|
158
158
|
|
|
159
159
|
/**
|
|
160
160
|
* The event that is triggered when the disclosure expands.
|
|
@@ -231,7 +231,7 @@ class Disclosure {
|
|
|
231
231
|
* @param {boolean} [options.openDuration = -1] - The duration of the transition from "closed" to "open" states (in milliseconds).
|
|
232
232
|
* @param {boolean} [options.closeDuration = -1] - The duration of the transition from "open" to "closed" states (in milliseconds).
|
|
233
233
|
* @param {boolean} [options.closeOnBlur = false] - Whether to close the disclosure when it loses focus in the dom.
|
|
234
|
-
* @param {
|
|
234
|
+
* @param {?string} [options.minWidth = ""] - The width of the screen that the disclosure will automatically open/close itself.
|
|
235
235
|
* @param {boolean} [options.autoOpen = false] - Whether to automatically open when above the minWidth.
|
|
236
236
|
* @param {?string} [options.prefix = graupl-] - The prefix to use for CSS custom properties.
|
|
237
237
|
* @param {?(string|string[])} [options.initializeClass = initializing] - The class to apply when a disclosure is initialzing.
|
|
@@ -248,7 +248,7 @@ class Disclosure {
|
|
|
248
248
|
openDuration = -1,
|
|
249
249
|
closeDuration = -1,
|
|
250
250
|
closeOnBlur = false,
|
|
251
|
-
minWidth =
|
|
251
|
+
minWidth = "",
|
|
252
252
|
autoOpen = false,
|
|
253
253
|
prefix = "graupl-",
|
|
254
254
|
initializeClass = "initializing",
|
|
@@ -276,7 +276,7 @@ class Disclosure {
|
|
|
276
276
|
this._closeOnBlur = closeOnBlur;
|
|
277
277
|
|
|
278
278
|
// Set collapse width and auto open functionality.
|
|
279
|
-
this._breakpointWidth = minWidth;
|
|
279
|
+
this._breakpointWidth = minWidth || "";
|
|
280
280
|
this._shouldOpen = autoOpen;
|
|
281
281
|
|
|
282
282
|
// Set the prefix.
|
|
@@ -516,7 +516,7 @@ class Disclosure {
|
|
|
516
516
|
}
|
|
517
517
|
|
|
518
518
|
/**
|
|
519
|
-
* The width of the screen
|
|
519
|
+
* The width of the screen that the disclosure will automatically open/close itself.
|
|
520
520
|
*
|
|
521
521
|
* @type {number}
|
|
522
522
|
*
|
|
@@ -527,7 +527,7 @@ class Disclosure {
|
|
|
527
527
|
}
|
|
528
528
|
|
|
529
529
|
set minWidth(value) {
|
|
530
|
-
isValidType("
|
|
530
|
+
isValidType("string", { value });
|
|
531
531
|
|
|
532
532
|
if (this._breakpointWidth !== value) {
|
|
533
533
|
this._breakpointWidth = value;
|
|
@@ -1105,45 +1105,25 @@ class Disclosure {
|
|
|
1105
1105
|
}
|
|
1106
1106
|
|
|
1107
1107
|
_handleResize() {
|
|
1108
|
-
if (this._breakpointWidth
|
|
1108
|
+
if (this._breakpointWidth === "") {
|
|
1109
1109
|
return;
|
|
1110
1110
|
}
|
|
1111
1111
|
|
|
1112
|
-
|
|
1112
|
+
this._mediaQueryList = window.matchMedia(
|
|
1113
|
+
`(width <= ${this._breakpointWidth})`
|
|
1114
|
+
);
|
|
1113
1115
|
|
|
1114
|
-
this.
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
if (typeof inlineSize !== "number") continue;
|
|
1126
|
-
|
|
1127
|
-
if (width === inlineSize) continue;
|
|
1128
|
-
|
|
1129
|
-
const belowBreakpoint = inlineSize <= this.minWidth;
|
|
1130
|
-
const aboveBreakpoint = inlineSize > this.minWidth;
|
|
1131
|
-
|
|
1132
|
-
if (belowBreakpoint && this.isOpen) {
|
|
1133
|
-
this.close({ preserveState: true });
|
|
1134
|
-
} else if (
|
|
1135
|
-
aboveBreakpoint &&
|
|
1136
|
-
!this.isOpen &&
|
|
1137
|
-
(this.hasOpened || this.shouldOpen)
|
|
1138
|
-
) {
|
|
1139
|
-
this.open();
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
|
-
width = inlineSize;
|
|
1143
|
-
}
|
|
1144
|
-
});
|
|
1116
|
+
this._mediaQueryList.addEventListener("change", (event) => {
|
|
1117
|
+
if (event.matches && this.isOpen) {
|
|
1118
|
+
this.close({ preserveState: true });
|
|
1119
|
+
} else if (
|
|
1120
|
+
!event.matches &&
|
|
1121
|
+
!this.isOpen &&
|
|
1122
|
+
(this.hasOpened || this.shouldOpen)
|
|
1123
|
+
) {
|
|
1124
|
+
this.open();
|
|
1125
|
+
}
|
|
1145
1126
|
});
|
|
1146
|
-
this._observer.observe(document.body);
|
|
1147
1127
|
}
|
|
1148
1128
|
|
|
1149
1129
|
/**
|
package/src/js/domHelpers.js
CHANGED
|
@@ -39,10 +39,11 @@ export function removeClass(className, element) {
|
|
|
39
39
|
/**
|
|
40
40
|
* Select all focusable elements within a given context.
|
|
41
41
|
*
|
|
42
|
-
* @param
|
|
43
|
-
* @
|
|
42
|
+
* @param {HTMLElement} [context = document] - The context in which to search for focusable elements.
|
|
43
|
+
* @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.
|
|
44
|
+
* @return {HTMLElement[]} - An array of focusable elements.
|
|
44
45
|
*/
|
|
45
|
-
export function selectAllFocusableElements(context = document) {
|
|
46
|
+
export function selectAllFocusableElements(context = document, fn = null) {
|
|
46
47
|
const querySelector =
|
|
47
48
|
"a[href],area[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),button:not([disabled]),[tabindex]";
|
|
48
49
|
const elements = Array.from(context.querySelectorAll(querySelector));
|
|
@@ -55,17 +56,22 @@ export function selectAllFocusableElements(context = document) {
|
|
|
55
56
|
return check;
|
|
56
57
|
});
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
if (fn !== null) {
|
|
60
|
+
return tabbableElements.filter(fn);
|
|
61
|
+
} else {
|
|
62
|
+
return tabbableElements;
|
|
63
|
+
}
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
/**
|
|
62
67
|
* Select the first focusable element within a given context.
|
|
63
68
|
*
|
|
64
|
-
* @param
|
|
65
|
-
* @
|
|
69
|
+
* @param {HTMLElement} [context = document] - The context in which to search for focusable elements.
|
|
70
|
+
* @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.
|
|
71
|
+
* @return {HTMLElement|boolean} - The first focusable element or false if none found.
|
|
66
72
|
*/
|
|
67
|
-
export function selectFirstFocusableElement(context = document) {
|
|
68
|
-
const tabbableElements = selectAllFocusableElements(context);
|
|
73
|
+
export function selectFirstFocusableElement(context = document, fn = null) {
|
|
74
|
+
const tabbableElements = selectAllFocusableElements(context, fn);
|
|
69
75
|
|
|
70
76
|
return tabbableElements[0] || false;
|
|
71
77
|
}
|
|
@@ -73,11 +79,12 @@ export function selectFirstFocusableElement(context = document) {
|
|
|
73
79
|
/**
|
|
74
80
|
* Select the last focusable element within a given context.
|
|
75
81
|
*
|
|
76
|
-
* @param
|
|
77
|
-
* @
|
|
82
|
+
* @param {HTMLElement} [context = document] - The context in which to search for focusable elements.
|
|
83
|
+
* @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.
|
|
84
|
+
* @return {HTMLElement|boolean} - The last focusable element or false if none found.
|
|
78
85
|
*/
|
|
79
|
-
export function selectLastFocusableElement(context = document) {
|
|
80
|
-
const tabbableElements = selectAllFocusableElements(context);
|
|
86
|
+
export function selectLastFocusableElement(context = document, fn = null) {
|
|
87
|
+
const tabbableElements = selectAllFocusableElements(context, fn);
|
|
81
88
|
|
|
82
89
|
return tabbableElements[tabbableElements.length - 1] || false;
|
|
83
90
|
}
|
|
@@ -85,12 +92,17 @@ export function selectLastFocusableElement(context = document) {
|
|
|
85
92
|
/**
|
|
86
93
|
* Select the next focusable element relative to the given element within a context.
|
|
87
94
|
*
|
|
88
|
-
* @param
|
|
89
|
-
* @param
|
|
90
|
-
* @
|
|
95
|
+
* @param {HTMLElement} element - The reference element.
|
|
96
|
+
* @param {HTMLElement} [context = document] - The context in which to search for focusable elements.
|
|
97
|
+
* @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.
|
|
98
|
+
* @return {HTMLElement|boolean} - The next focusable element or false if none found.
|
|
91
99
|
*/
|
|
92
|
-
export function selectNextFocusableElement(
|
|
93
|
-
|
|
100
|
+
export function selectNextFocusableElement(
|
|
101
|
+
element,
|
|
102
|
+
context = document,
|
|
103
|
+
fn = null
|
|
104
|
+
) {
|
|
105
|
+
const tabbableElements = selectAllFocusableElements(context, fn);
|
|
94
106
|
const index = tabbableElements.indexOf(element);
|
|
95
107
|
|
|
96
108
|
return index === tabbableElements.length - 1
|
|
@@ -101,12 +113,17 @@ export function selectNextFocusableElement(element, context = document) {
|
|
|
101
113
|
/**
|
|
102
114
|
* Select the previous focusable element relative to the given element within a context.
|
|
103
115
|
*
|
|
104
|
-
* @param
|
|
105
|
-
* @param
|
|
106
|
-
* @
|
|
116
|
+
* @param {HTMLElement} element - The reference element.
|
|
117
|
+
* @param {HTMLElement} [context = document] - The context in which to search for focusable elements.
|
|
118
|
+
* @param {?function(HTMLElement): boolean} [fn = null] - An optional addition filter function to process out focusable elements.
|
|
119
|
+
* @return {HTMLElement|boolean} - The previous focusable element or false if none found.
|
|
107
120
|
*/
|
|
108
|
-
export function selectPreviousFocusableElement(
|
|
109
|
-
|
|
121
|
+
export function selectPreviousFocusableElement(
|
|
122
|
+
element,
|
|
123
|
+
context = document,
|
|
124
|
+
fn = null
|
|
125
|
+
) {
|
|
126
|
+
const tabbableElements = selectAllFocusableElements(context, fn);
|
|
110
127
|
const index = tabbableElements.indexOf(element);
|
|
111
128
|
|
|
112
129
|
return index === 0 ? false : tabbableElements[index - 1];
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/* global Tabs */
|
|
2
|
+
|
|
3
|
+
import { addClass, removeClass } from "@graupl/core/src/domHelpers.js";
|
|
4
|
+
import { TransactionalValue } from "../TransactionalValue.js";
|
|
5
|
+
|
|
6
|
+
class TabToggle {
|
|
7
|
+
/**
|
|
8
|
+
* The DOM elements within the tab toggle.
|
|
9
|
+
*
|
|
10
|
+
* @protected
|
|
11
|
+
*
|
|
12
|
+
* @type {Object<HTMLElement>}
|
|
13
|
+
*
|
|
14
|
+
* @property {HTMLElement} toggle - The toggle element.
|
|
15
|
+
* @property {HTMLElement} content - The content element.
|
|
16
|
+
*/
|
|
17
|
+
_dom = {
|
|
18
|
+
toggle: null,
|
|
19
|
+
content: null,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The declared elements within the tab toggle.
|
|
24
|
+
*
|
|
25
|
+
* @protected
|
|
26
|
+
*
|
|
27
|
+
* @type {Object<Tabs>}
|
|
28
|
+
*
|
|
29
|
+
* @property {Tabs} parent - The parent tabs element.
|
|
30
|
+
*/
|
|
31
|
+
_elements = {
|
|
32
|
+
parent: null,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The active state of the tab toggle.
|
|
37
|
+
*
|
|
38
|
+
* @protected
|
|
39
|
+
*
|
|
40
|
+
* @type {TransactionalValue}
|
|
41
|
+
*/
|
|
42
|
+
_active = new TransactionalValue(false);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The event that is triggered when the tab toggle is shown.
|
|
46
|
+
*
|
|
47
|
+
* @protected
|
|
48
|
+
*
|
|
49
|
+
* @event grauplTabToggleActivate
|
|
50
|
+
*
|
|
51
|
+
* @type {CustomEvent}
|
|
52
|
+
*
|
|
53
|
+
* @property {boolean} bubbles - A flag to bubble the event.
|
|
54
|
+
* @property {Object<TabToggle>} detail - The details object containing the Accordion item itself.
|
|
55
|
+
*/
|
|
56
|
+
_activateEvent = new CustomEvent("grauplTabToggleActivate", {
|
|
57
|
+
bubbles: true,
|
|
58
|
+
detail: { item: this },
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The event that is triggered when the tab toggle is hidden.
|
|
63
|
+
*
|
|
64
|
+
* @protected
|
|
65
|
+
*
|
|
66
|
+
* @event grauplTabToggleDeactivate
|
|
67
|
+
*
|
|
68
|
+
* @type {CustomEvent}
|
|
69
|
+
*
|
|
70
|
+
* @property {boolean} bubbles - A flag to bubble the event.
|
|
71
|
+
* @property {Object<TabToggle>} detail - The details object containing the Accordion item itself.
|
|
72
|
+
*/
|
|
73
|
+
_deactivateEvent = new CustomEvent("grauplTabToggleDeactivate", {
|
|
74
|
+
bubbles: true,
|
|
75
|
+
detail: { item: this },
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
constructor({ toggleElement, contentElement, parentTab }) {
|
|
79
|
+
// Set DOM elements.
|
|
80
|
+
this._dom.toggle = toggleElement;
|
|
81
|
+
this._dom.content = contentElement;
|
|
82
|
+
|
|
83
|
+
// Set the parent tab instance.
|
|
84
|
+
this._elements.parent = parentTab;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Initializes the tab toggle.
|
|
89
|
+
*/
|
|
90
|
+
initialize() {
|
|
91
|
+
// Set up the DOM.
|
|
92
|
+
this._setIds();
|
|
93
|
+
this._setAriaAttributes();
|
|
94
|
+
|
|
95
|
+
if (this.dom.toggle.getAttribute("aria-selected") === "true") {
|
|
96
|
+
this.show();
|
|
97
|
+
} else {
|
|
98
|
+
this._deactivate({ emit: false, transition: false });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The DOM elements of the tab toggle.
|
|
104
|
+
*
|
|
105
|
+
* @readonly
|
|
106
|
+
*
|
|
107
|
+
* @type {Object<HTMLElement>}
|
|
108
|
+
*
|
|
109
|
+
* @see _dom
|
|
110
|
+
*/
|
|
111
|
+
get dom() {
|
|
112
|
+
return this._dom;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The declared elements in the tab toggle.
|
|
117
|
+
*
|
|
118
|
+
* @protected
|
|
119
|
+
*
|
|
120
|
+
* @type {Object<Tabs>}
|
|
121
|
+
*
|
|
122
|
+
* @see _elements
|
|
123
|
+
*/
|
|
124
|
+
get elements() {
|
|
125
|
+
return this._elements;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The active state of the tab toggle.
|
|
130
|
+
*
|
|
131
|
+
* @readonly
|
|
132
|
+
*
|
|
133
|
+
* @type {TransactionalValue}
|
|
134
|
+
*
|
|
135
|
+
* @see _active
|
|
136
|
+
*/
|
|
137
|
+
get isActive() {
|
|
138
|
+
return this._active.value;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Sets the IDs of the tab toggle and it's content if they do not already exist.
|
|
143
|
+
*
|
|
144
|
+
* The generated IDs use the following format:
|
|
145
|
+
* - toggle: `tab-toggle-${key}-${index}`
|
|
146
|
+
* - content: `tab-content-${key}-${index}`
|
|
147
|
+
*
|
|
148
|
+
* Where `${key}` is the parent's key and `${index}` is the toggles index in the list of the parent's toggles.
|
|
149
|
+
*
|
|
150
|
+
* @protected
|
|
151
|
+
*/
|
|
152
|
+
_setIds() {
|
|
153
|
+
// Get the required information for IDs.
|
|
154
|
+
const { key } = this.elements.parent;
|
|
155
|
+
const index = this.elements.parent.dom.tabToggle.indexOf(this.dom.toggle);
|
|
156
|
+
|
|
157
|
+
this.dom.toggle.id = this.dom.toggle.id || `tab-toggle-${key}-${index}`;
|
|
158
|
+
this.dom.content.id = this.dom.content.id || `tab-content-${key}-${index}`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Sets the ARIA attributes on the disclosure and it's content.
|
|
163
|
+
*/
|
|
164
|
+
_setAriaAttributes() {
|
|
165
|
+
// Set the ARIA attributes for the tab item toggle.
|
|
166
|
+
this.dom.toggle.setAttribute("role", "tab");
|
|
167
|
+
|
|
168
|
+
// If aria-selected is not explicitly set to "true", then set it to "false".
|
|
169
|
+
if (this.dom.toggle.getAttribute("aria-selected") !== "true") {
|
|
170
|
+
this.dom.toggle.setAttribute("aria-selected", "false");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Set the aria-controls attribute for the toggle.
|
|
174
|
+
this.dom.toggle.setAttribute("aria-controls", this.dom.content.id);
|
|
175
|
+
|
|
176
|
+
// Set the role for the content.
|
|
177
|
+
this.dom.content.setAttribute("role", "tabpanel");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Activate the toggle.
|
|
182
|
+
*
|
|
183
|
+
* Sets the toggles's `aria-selected` to "true", adds the
|
|
184
|
+
* open class to the content, and removes the closed class from the content.
|
|
185
|
+
*
|
|
186
|
+
* @protected
|
|
187
|
+
*
|
|
188
|
+
* @fires grauplTabToggleActivate
|
|
189
|
+
*
|
|
190
|
+
* @param {Object<boolean>} [options = {}] - Options for activating the toggle.
|
|
191
|
+
* @param {boolean} [options.emit = true] - Emit the activat event once activated.
|
|
192
|
+
* @param {boolean} [options.transition = true] - Respect the transition class.
|
|
193
|
+
*/
|
|
194
|
+
_activate({ emit = true, transition = true } = {}) {
|
|
195
|
+
const { closeClass, openClass, transitionClass, openDuration } =
|
|
196
|
+
this.elements.parent;
|
|
197
|
+
|
|
198
|
+
// Set aria-selected to true when hiding accordion item.
|
|
199
|
+
this.dom.toggle.setAttribute("aria-selected", "true");
|
|
200
|
+
|
|
201
|
+
// If we're dealing with transition classes, then we need to utilize
|
|
202
|
+
// requestAnimationFrame to add the transition class, remove the hide class,
|
|
203
|
+
// add the show class, and finally remove the transition class.
|
|
204
|
+
//
|
|
205
|
+
// If `transition` is false, then it doesn't matter if the transition class
|
|
206
|
+
// is set. Do not use the transition.
|
|
207
|
+
if (transition && transitionClass !== "") {
|
|
208
|
+
addClass(transitionClass, this.dom.content);
|
|
209
|
+
|
|
210
|
+
requestAnimationFrame(() => {
|
|
211
|
+
removeClass(closeClass, this.dom.content);
|
|
212
|
+
|
|
213
|
+
requestAnimationFrame(() => {
|
|
214
|
+
addClass(openClass, this.dom.content);
|
|
215
|
+
|
|
216
|
+
requestAnimationFrame(() => {
|
|
217
|
+
setTimeout(() => {
|
|
218
|
+
removeClass(transitionClass, this.dom.content);
|
|
219
|
+
}, openDuration);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
} else {
|
|
224
|
+
// Add the show class
|
|
225
|
+
addClass(openClass, this.dom.content);
|
|
226
|
+
|
|
227
|
+
// Remove the hide class.
|
|
228
|
+
removeClass(closeClass, this.dom.content);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (emit) {
|
|
232
|
+
this.dom.toggle.dispatchEvent(this._activateEvent);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Deactivates the disclosure.
|
|
238
|
+
*
|
|
239
|
+
* Sets the toggles's `aria-expanded` to "false", adds the
|
|
240
|
+
* close class to the content, and removes the open class from the content.
|
|
241
|
+
*
|
|
242
|
+
* @protected
|
|
243
|
+
*
|
|
244
|
+
* @fires grauplTabToggleDeactivate
|
|
245
|
+
*
|
|
246
|
+
* @param {Object<boolean>} [options = {}] - Options for collapsing the toggle.
|
|
247
|
+
* @param {boolean} [options.emit = true] - Emit the deactivate event once deactivated.
|
|
248
|
+
* @param {boolean} [options.transition = true] - Respect the transition class.
|
|
249
|
+
*/
|
|
250
|
+
_deactivate({ emit = true, transition = true } = {}) {
|
|
251
|
+
const { closeClass, openClass, transitionClass, closeDuration } =
|
|
252
|
+
this.elements.parent;
|
|
253
|
+
|
|
254
|
+
// Set aria-selected to false when hiding accordion item.
|
|
255
|
+
this.dom.toggle.setAttribute("aria-selected", "false");
|
|
256
|
+
|
|
257
|
+
// If we're dealing with transition classes, then we need to utilize
|
|
258
|
+
// requestAnimationFrame to add the transition class, remove the show class,
|
|
259
|
+
// add the hide class, and finally remove the transition class.
|
|
260
|
+
//
|
|
261
|
+
// If `transition` is false, then it doesn't matter if the transition class
|
|
262
|
+
// is set. Do not use the transition.
|
|
263
|
+
if (transition && transitionClass !== "") {
|
|
264
|
+
addClass(transitionClass, this.dom.content);
|
|
265
|
+
|
|
266
|
+
requestAnimationFrame(() => {
|
|
267
|
+
removeClass(openClass, this.dom.content);
|
|
268
|
+
|
|
269
|
+
requestAnimationFrame(() => {
|
|
270
|
+
addClass(closeClass, this.dom.content);
|
|
271
|
+
|
|
272
|
+
requestAnimationFrame(() => {
|
|
273
|
+
setTimeout(() => {
|
|
274
|
+
removeClass(transitionClass, this.dom.content);
|
|
275
|
+
}, closeDuration);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
} else {
|
|
280
|
+
// Add the hide class
|
|
281
|
+
addClass(closeClass, this.dom.content);
|
|
282
|
+
|
|
283
|
+
// Remove the show class.
|
|
284
|
+
removeClass(openClass, this.dom.content);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (emit) {
|
|
288
|
+
this.dom.toggle.dispatchEvent(this._deactivateEvent);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Shows the tab toggle's content.
|
|
294
|
+
*
|
|
295
|
+
* @param {Object<boolean>} [options = {}] - Options for showing the toggle.
|
|
296
|
+
* @param {boolean} [options.force = false] - Whether to force the show action.
|
|
297
|
+
* @param {boolean} [options.preserveState = false] - Whether to preserve the active state.
|
|
298
|
+
*/
|
|
299
|
+
show({ force = false, preserveState = false } = {}) {
|
|
300
|
+
if (this.isActive && !force) return;
|
|
301
|
+
|
|
302
|
+
// Set the focus state of the parent tabs element.
|
|
303
|
+
this.elements.parent.focusState = "self";
|
|
304
|
+
|
|
305
|
+
// Activate the toggle.
|
|
306
|
+
this._activate();
|
|
307
|
+
|
|
308
|
+
// Set the active state
|
|
309
|
+
this._active.value = true;
|
|
310
|
+
|
|
311
|
+
if (!preserveState) {
|
|
312
|
+
this._active.commit();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Set the tabindex to 0 so it can be focused.
|
|
316
|
+
this.dom.toggle.setAttribute("tabindex", "0");
|
|
317
|
+
|
|
318
|
+
// Deactivate all sibling tab toggles.
|
|
319
|
+
this.deactivateSiblings();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Hides the tab toggle's content.
|
|
324
|
+
*
|
|
325
|
+
* @param {Object<boolean>} [options = {}] - Options for hiding the toggle.
|
|
326
|
+
* @param {boolean} [options.force = false] - Whether to force the show action.
|
|
327
|
+
* @param {boolean} [options.preserveState = false] - Whether to preserve the active state.
|
|
328
|
+
*/
|
|
329
|
+
hide({ force = false, preserveState = false } = {}) {
|
|
330
|
+
if (!this.isActive && !force) return;
|
|
331
|
+
|
|
332
|
+
// Set the focus state of the parent tabs element.
|
|
333
|
+
this.elements.parent.focusState = "none";
|
|
334
|
+
|
|
335
|
+
// Deactivate the toggle.
|
|
336
|
+
this._deactivate();
|
|
337
|
+
|
|
338
|
+
// Set the active state
|
|
339
|
+
this._active.value = false;
|
|
340
|
+
|
|
341
|
+
if (!preserveState) {
|
|
342
|
+
this._active.commit();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Set the tabindex to -1.
|
|
346
|
+
this.dom.toggle.setAttribute("tabindex", "-1");
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Focuses the accordion item.
|
|
351
|
+
*
|
|
352
|
+
* @public
|
|
353
|
+
*/
|
|
354
|
+
focus() {
|
|
355
|
+
this.dom.toggle.focus();
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Blurs the accordion item.
|
|
360
|
+
*
|
|
361
|
+
* @public
|
|
362
|
+
*/
|
|
363
|
+
blur() {
|
|
364
|
+
this.dom.toggle.blur();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
deactivateSiblings() {
|
|
368
|
+
if (this.elements.parent) {
|
|
369
|
+
this.elements.parent.elements.tabToggle.forEach((toggle) => {
|
|
370
|
+
if (toggle !== this) {
|
|
371
|
+
toggle.hide();
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export default TabToggle;
|