@ulu/frontend 0.0.23 → 0.1.0-beta.0
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/deprecated/js/drupal-programmatic-modal.js +91 -0
- package/{js/ui/modals.js → deprecated/js/micromodal-modals.js} +41 -67
- package/dist/ulu-frontend.min.css +1 -1
- package/dist/ulu-frontend.min.js +70 -1
- package/index.js +6 -1
- package/js/events/index.js +58 -7
- package/js/index.js +3 -7
- package/js/{helpers/css-breakpoint.js → ui/breakpoints.js} +9 -11
- package/js/ui/collapsible.js +195 -0
- package/js/ui/dialog.js +157 -0
- package/js/ui/dialog.todo +37 -0
- package/js/ui/flipcard.js +55 -11
- package/js/ui/grid.js +2 -47
- package/js/ui/index.js +21 -0
- package/js/ui/modal-builder.js +197 -0
- package/js/ui/overflow-scroller-pager.js +1 -1
- package/js/ui/overflow-scroller.js +8 -5
- package/js/ui/page.js +14 -0
- package/js/ui/popover.js +135 -0
- package/js/ui/print-details.js +44 -0
- package/js/ui/print.js +67 -0
- package/js/ui/programmatic-modal.js +79 -81
- package/js/ui/proxy-click.js +80 -0
- package/js/ui/resizer.js +3 -3
- package/js/ui/scroll-slider.js +56 -0
- package/js/ui/scrollpoint.js +300 -0
- package/js/ui/slider.js +72 -10
- package/js/ui/tabs.js +85 -58
- package/js/ui/theme-toggle.js +129 -0
- package/js/ui/tooltip.js +268 -67
- package/js/utils/{logger.js → class-logger.js} +6 -5
- package/js/utils/dom.js +122 -0
- package/js/utils/file-save.js +67 -0
- package/js/utils/floating-ui.js +83 -0
- package/js/utils/id.js +22 -0
- package/js/utils/index.js +7 -0
- package/js/{helpers → utils}/pause-youtube-video.js +1 -1
- package/package.json +32 -11
- package/resources/drupal/twig-macros/accordion.twig +99 -0
- package/resources/drupal/twig-macros/dropdown.twig +44 -0
- package/resources/drupal/twig-macros/flipcard.twig +69 -0
- package/resources/drupal/twig-macros/image.twig +30 -0
- package/resources/drupal/twig-macros/layout.twig +338 -0
- package/resources/drupal/twig-macros/slider.twig +214 -0
- package/resources/drupal/twig-macros/tabs.twig +84 -0
- package/scss/README.md +13 -1
- package/scss/_breakpoint.scss +69 -26
- package/scss/_button.scss +148 -57
- package/scss/_color.scss +46 -28
- package/scss/_cssvar.scss +103 -12
- package/scss/_element.scss +84 -67
- package/scss/_index.scss +0 -3
- package/scss/_layout.scss +57 -26
- package/scss/_path.scss +2 -2
- package/scss/_selector.scss +20 -11
- package/scss/_typography.scss +115 -82
- package/scss/_units.scss +14 -13
- package/scss/_utils.scss +280 -18
- package/scss/base/_color.scss +2 -1
- package/scss/base/_elements.scss +61 -35
- package/scss/base/_index.scss +60 -23
- package/scss/base/_keyframes.scss +115 -16
- package/scss/base/_layout.scss +10 -6
- package/scss/base/_normalize.scss +6 -122
- package/scss/base/_print.scss +49 -0
- package/scss/base/_root.scss +28 -0
- package/scss/base/_typography.scss +4 -1
- package/scss/components/_accordion.scss +217 -0
- package/scss/components/_adaptive-spacing.scss +148 -0
- package/scss/components/_badge.scss +17 -14
- package/scss/components/_button-verbose.scss +138 -0
- package/scss/components/_button.scss +9 -4
- package/scss/components/_callout.scss +175 -0
- package/scss/components/_captioned-figure.scss +173 -0
- package/scss/components/_card-grid.scss +75 -0
- package/scss/components/_card.scss +420 -0
- package/scss/components/_css-icon.scss +433 -0
- package/scss/{_grid.scss → components/_data-grid.scss} +100 -68
- package/scss/components/_data-table.scss +180 -0
- package/scss/components/_fill-context.scss +20 -22
- package/scss/components/_flipcard-grid.scss +66 -0
- package/scss/components/_flipcard.scss +304 -0
- package/scss/components/_form-theme.scss +633 -0
- package/scss/components/_hero.scss +183 -0
- package/scss/components/_horizontal-rule.scss +51 -0
- package/scss/components/_image-grid.scss +71 -0
- package/scss/components/_index.scss +276 -38
- package/scss/components/_links.scss +1 -1
- package/scss/components/_list-lines.scss +14 -3
- package/scss/components/_list-ordered.scss +3 -1
- package/scss/components/_list-unordered.scss +3 -1
- package/scss/components/_menu-stack.scss +245 -0
- package/scss/components/_modal.scss +495 -0
- package/scss/components/_nav-strip.scss +148 -0
- package/scss/components/_overlay-section.scss +122 -0
- package/scss/components/_pager.scss +168 -0
- package/scss/components/_placeholder-block.scss +121 -0
- package/scss/components/_popover.scss +263 -0
- package/scss/components/_pull-quote.scss +111 -0
- package/scss/components/_ratio-box.scss +64 -0
- package/scss/components/_rule.scss +12 -9
- package/scss/components/_scroll-slider.scss +204 -0
- package/scss/components/_skip-link.scss +92 -0
- package/scss/components/_slider.scss +241 -0
- package/scss/components/_spoke-spinner.scss +193 -0
- package/scss/components/_tabs.scss +179 -0
- package/scss/components/_tag.scss +142 -0
- package/scss/components/_tile-button.scss +131 -0
- package/scss/components/_tile-grid-overlay.scss +132 -0
- package/scss/components/_tile-grid.scss +172 -0
- package/scss/components/_vignette.scss +65 -0
- package/scss/components/_wysiwyg.scss +94 -0
- package/scss/helpers/_color.scss +1 -0
- package/scss/helpers/_display.scss +2 -1
- package/scss/helpers/_index.scss +45 -22
- package/scss/helpers/_print.scss +20 -43
- package/scss/helpers/_typography.scss +3 -0
- package/scss/helpers/_units.scss +10 -13
- package/scss/helpers/_utilities.scss +5 -1
- package/scss/stylesheets/base-styles.scss +7 -0
- package/scss/stylesheets/component-styles.scss +7 -0
- package/scss/stylesheets/helper-styles.scss +7 -0
- package/types/events/index.d.ts +1 -1
- package/types/events/index.d.ts.map +1 -1
- package/types/index.d.ts +2 -2
- package/types/{helpers/css-breakpoint.d.ts → ui/breakpoints.d.ts} +3 -3
- package/types/ui/breakpoints.d.ts.map +1 -0
- package/types/ui/collapsible.d.ts +67 -0
- package/types/ui/collapsible.d.ts.map +1 -0
- package/types/ui/dialog.d.ts +42 -0
- package/types/ui/dialog.d.ts.map +1 -0
- package/types/ui/flipcard.d.ts +8 -1
- package/types/ui/flipcard.d.ts.map +1 -1
- package/types/ui/grid.d.ts +0 -11
- package/types/ui/grid.d.ts.map +1 -1
- package/types/ui/index.d.ts +23 -0
- package/types/ui/index.d.ts.map +1 -0
- package/types/ui/modal-builder.d.ts +54 -0
- package/types/ui/modal-builder.d.ts.map +1 -0
- package/types/ui/overflow-scroller-pager.d.ts +1 -1
- package/types/ui/overflow-scroller-pager.d.ts.map +1 -1
- package/types/ui/overflow-scroller.d.ts +3 -1
- package/types/ui/overflow-scroller.d.ts.map +1 -1
- package/types/ui/page.d.ts +5 -0
- package/types/ui/page.d.ts.map +1 -0
- package/types/ui/popover.d.ts +40 -0
- package/types/ui/popover.d.ts.map +1 -0
- package/types/ui/print-details.d.ts +10 -0
- package/types/ui/print-details.d.ts.map +1 -0
- package/types/ui/print.d.ts +10 -0
- package/types/ui/print.d.ts.map +1 -0
- package/types/ui/programmatic-modal.d.ts +19 -1
- package/types/ui/programmatic-modal.d.ts.map +1 -1
- package/types/ui/proxy-click.d.ts +18 -0
- package/types/ui/proxy-click.d.ts.map +1 -0
- package/types/ui/resizer.d.ts +1 -1
- package/types/ui/resizer.d.ts.map +1 -1
- package/types/ui/scroll-slider.d.ts +13 -0
- package/types/ui/scroll-slider.d.ts.map +1 -0
- package/types/ui/scrollpoint.d.ts +133 -0
- package/types/ui/scrollpoint.d.ts.map +1 -0
- package/types/ui/slider.d.ts +14 -2
- package/types/ui/slider.d.ts.map +1 -1
- package/types/ui/tabs.d.ts +22 -0
- package/types/ui/tabs.d.ts.map +1 -1
- package/types/ui/theme-toggle.d.ts +14 -0
- package/types/ui/theme-toggle.d.ts.map +1 -0
- package/types/ui/tooltip.d.ts +92 -10
- package/types/ui/tooltip.d.ts.map +1 -1
- package/types/utils/{logger.d.ts → class-logger.d.ts} +1 -1
- package/types/utils/class-logger.d.ts.map +1 -0
- package/types/utils/dom.d.ts +48 -0
- package/types/utils/dom.d.ts.map +1 -0
- package/types/utils/file-save.d.ts +64 -0
- package/types/utils/file-save.d.ts.map +1 -0
- package/types/utils/floating-ui.d.ts +19 -0
- package/types/utils/floating-ui.d.ts.map +1 -0
- package/types/utils/id.d.ts +10 -0
- package/types/utils/id.d.ts.map +1 -0
- package/types/utils/index.d.ts +9 -0
- package/types/utils/index.d.ts.map +1 -0
- package/types/utils/pause-youtube-video.d.ts.map +1 -0
- package/js/helpers/file-save.js +0 -52
- package/js/helpers/scrollbar-width-property.js +0 -14
- package/project.todo +0 -22
- package/scss/_calculate.scss +0 -64
- package/scss/_utility.scss +0 -12
- package/types/helpers/css-breakpoint.d.ts.map +0 -1
- package/types/helpers/file-save.d.ts +0 -17
- package/types/helpers/file-save.d.ts.map +0 -1
- package/types/helpers/node-data-manager.d.ts +0 -45
- package/types/helpers/node-data-manager.d.ts.map +0 -1
- package/types/helpers/pause-youtube-video.d.ts.map +0 -1
- package/types/helpers/scrollbar-width-property.d.ts +0 -11
- package/types/helpers/scrollbar-width-property.d.ts.map +0 -1
- package/types/ui/modals.d.ts +0 -27
- package/types/ui/modals.d.ts.map +0 -1
- package/types/utils/logger.d.ts.map +0 -1
- package/vite.config.js +0 -36
- /package/{js/deprecated → deprecated/js}/doc-ready.js +0 -0
- /package/{js/deprecated → deprecated/js}/jquery-prototypes.js +0 -0
- /package/{js/deprecated → deprecated/js}/mini-collapsible-popper-positioning.js +0 -0
- /package/{js/deprecated → deprecated/js}/mini-collapsible.js +0 -0
- /package/{js/helpers → deprecated/js}/node-data-manager.js +0 -0
- /package/{js/deprecated → deprecated/js}/script-loader.js +0 -0
- /package/{js/deprecated → deprecated/js}/waypoints/README.md +0 -0
- /package/{js/deprecated → deprecated/js}/waypoints/anchor-menu.js +0 -0
- /package/{js/deprecated → deprecated/js}/waypoints/element-waypoint.js +0 -0
- /package/{js/deprecated → deprecated/js}/waypoints/examples/page-link-menu.md +0 -0
- /package/{js/deprecated → deprecated/js}/waypoints/state-in-attribute.js +0 -0
- /package/types/{helpers → utils}/pause-youtube-video.d.ts +0 -0
package/js/ui/slider.js
CHANGED
|
@@ -28,10 +28,14 @@
|
|
|
28
28
|
// * Will Change use
|
|
29
29
|
|
|
30
30
|
import maintain from 'ally.js/maintain/_maintain';
|
|
31
|
-
import { log, logError, logWarning } from "../utils/logger.js";
|
|
32
31
|
import { hasRequiredProps } from '@ulu/utils/object.js';
|
|
33
32
|
import { trimWhitespace } from "@ulu/utils/string.js";
|
|
34
33
|
import { debounce } from "@ulu/utils/performance.js";
|
|
34
|
+
import { log, logError, logWarning } from "../utils/class-logger.js";
|
|
35
|
+
import { getDatasetOptionalJson } from "../utils/dom.js";
|
|
36
|
+
import { createPager } from "./overflow-scroller-pager.js";
|
|
37
|
+
import { getName } from "../events/index.js";
|
|
38
|
+
|
|
35
39
|
const debugMode = false; // Global dev debug
|
|
36
40
|
const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
37
41
|
const eventOnce = { once: true };
|
|
@@ -50,6 +54,61 @@ const requiredElements = [
|
|
|
50
54
|
"track",
|
|
51
55
|
"slides"
|
|
52
56
|
];
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Default data attributes
|
|
60
|
+
*/
|
|
61
|
+
export const attrs = {
|
|
62
|
+
init: "data-ulu-slider-init",
|
|
63
|
+
slider: "data-ulu-slider",
|
|
64
|
+
track: "data-ulu-slider-track",
|
|
65
|
+
trackContainer: "data-ulu-slider-track-container",
|
|
66
|
+
controls: "data-ulu-slider-control-context"
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Utils for selecting things based on attributes
|
|
70
|
+
const attrSelector = key => `[${ attrs[key] }]`;
|
|
71
|
+
const attrSelectorInitial = key => `${ attrSelector(key) }:not([${ attrs.init }])`;
|
|
72
|
+
|
|
73
|
+
const defaults = {
|
|
74
|
+
amount: createPager()
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const instances = [];
|
|
78
|
+
|
|
79
|
+
export function init() {
|
|
80
|
+
document.addEventListener(getName("pageModified"), setup);
|
|
81
|
+
setup();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function setup() {
|
|
85
|
+
const builders = document.querySelectorAll(attrSelectorInitial("slider"));
|
|
86
|
+
builders.forEach(setupSlider);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function setupSlider(container) {
|
|
90
|
+
container.setAttribute(attrs.init, "");
|
|
91
|
+
const options = getDatasetOptionalJson(container, "uluScrollSlider");
|
|
92
|
+
const config = Object.assign({}, defaults, options);
|
|
93
|
+
const elements = {
|
|
94
|
+
container,
|
|
95
|
+
track: container.querySelector("[data-ulu-slider-track]"),
|
|
96
|
+
trackContainer: container.querySelector("[data-ulu-slider-track-container]"),
|
|
97
|
+
controlContext: container.querySelector("[data-ulu-slider-control-context]"),
|
|
98
|
+
slides: container.querySelectorAll("[data-ulu-slider-slide]")
|
|
99
|
+
};
|
|
100
|
+
// Add in any global settings
|
|
101
|
+
// Object.assign(config, {
|
|
102
|
+
// callbacks: {}
|
|
103
|
+
// });
|
|
104
|
+
// /
|
|
105
|
+
// This was added because there was an issue on the new windows, need to test this
|
|
106
|
+
// config.transitionFade = true;
|
|
107
|
+
if (elements.slides.length) {
|
|
108
|
+
instances.push(new Slider(elements, config, false));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
53
112
|
export class Slider {
|
|
54
113
|
static instances = [];
|
|
55
114
|
static defaults = {
|
|
@@ -61,7 +120,9 @@ export class Slider {
|
|
|
61
120
|
transitionDuration: 700,
|
|
62
121
|
transitionDurationExit: 400,
|
|
63
122
|
transitionTimingFunction: "ease-in-out",
|
|
64
|
-
|
|
123
|
+
buttonClasses: ["Slider__control-icon", "button", "button--icon"],
|
|
124
|
+
iconClassesPrevious: ["css-icon", "css-icon--angle-left"],
|
|
125
|
+
iconClassesNext: ["css-icon", "css-icon--angle-right"]
|
|
65
126
|
// transition: true
|
|
66
127
|
}
|
|
67
128
|
// constructor(container, title, trackContainer, track, slides, config, debug = false) {
|
|
@@ -136,7 +197,7 @@ export class Slider {
|
|
|
136
197
|
* @param {number} duration Duration to wait for complete
|
|
137
198
|
* @param {Function} beginTransition Css changes to begin/start transtion
|
|
138
199
|
*/
|
|
139
|
-
|
|
200
|
+
ensureTransitionEnds(element, duration, beginTransition) {
|
|
140
201
|
return new Promise(resolve => {
|
|
141
202
|
const tid = {};
|
|
142
203
|
// If the transition has started remove the fallback for start
|
|
@@ -179,7 +240,7 @@ export class Slider {
|
|
|
179
240
|
const set = () => track.style.transform = `translateX(-${ x }px)`;
|
|
180
241
|
// tell brwoser we're about to animate
|
|
181
242
|
track.style.willChange = "transform";
|
|
182
|
-
return this.
|
|
243
|
+
return this.ensureTransitionEnds(track, duration, set).then(() => {
|
|
183
244
|
// Remove to avoid any issues with optimization
|
|
184
245
|
track.style.willChange = "auto";
|
|
185
246
|
});
|
|
@@ -205,7 +266,7 @@ export class Slider {
|
|
|
205
266
|
const { options } = this;
|
|
206
267
|
const { element } = slide;
|
|
207
268
|
const duration = visible ? options.transitionDuration : options.transitionDurationExit;
|
|
208
|
-
return this.
|
|
269
|
+
return this.ensureTransitionEnds(element, duration, () => {
|
|
209
270
|
element.style.opacity = visible ? "1" : "0";
|
|
210
271
|
});
|
|
211
272
|
}
|
|
@@ -393,6 +454,7 @@ export class Slider {
|
|
|
393
454
|
const button = document.createElement("button");
|
|
394
455
|
button.classList.add(this.getClass("control-button"));
|
|
395
456
|
button.classList.add(this.getClass(`control-button--${ action }`));
|
|
457
|
+
button.classList.add(...this.options.buttonClasses);
|
|
396
458
|
button.setAttribute("data-slider-control", action);
|
|
397
459
|
button.setAttribute("type", "button");
|
|
398
460
|
button.innerHTML = this.getControlContent(action);
|
|
@@ -452,20 +514,20 @@ export class Slider {
|
|
|
452
514
|
button.addEventListener("click", this.goto.bind(this, index));
|
|
453
515
|
return button;
|
|
454
516
|
}
|
|
517
|
+
// change to css-icon
|
|
455
518
|
getControlContent(action) {
|
|
519
|
+
const classes = this.options[action === "next" ? "iconClassesNext" : "iconClassesPrevious"];
|
|
456
520
|
return `
|
|
457
521
|
<span class="hidden-visually">${ action }</span>
|
|
458
|
-
<span
|
|
522
|
+
<span class="${ classes.join(' ') }" aria-hidden="true"></span>
|
|
459
523
|
`;
|
|
460
524
|
}
|
|
461
525
|
getNavContent(number) {
|
|
462
|
-
return `<span class="hidden-visually">Item
|
|
526
|
+
return `<span class="hidden-visually">Item ${ number }</span>`;
|
|
463
527
|
}
|
|
464
528
|
emit(name, args) {
|
|
465
529
|
if (this.options.events[name]) {
|
|
466
530
|
this.options.events[name].apply(this, args);
|
|
467
531
|
}
|
|
468
532
|
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
export default Slider;
|
|
533
|
+
}
|
package/js/ui/tabs.js
CHANGED
|
@@ -2,91 +2,124 @@
|
|
|
2
2
|
* @module ui/tabs
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
// * - Attribute to enable behavior 'data-site-tablist'
|
|
6
|
-
// * - Options can be passed via JSON in data attribute
|
|
7
|
-
// * - openByUrlHash | Optionally add "openByUrlHash" to have the
|
|
8
|
-
// * script open a tab and focus it on page load (and set it in history
|
|
9
|
-
// * as they navigate)
|
|
10
|
-
|
|
11
|
-
|
|
12
5
|
import AriaTablist from "aria-tablist";
|
|
13
6
|
|
|
14
|
-
const
|
|
7
|
+
const initAttr = "data-ulu-tablist-init";
|
|
8
|
+
const errorHeader = "[data-ulu-tablist] error:";
|
|
15
9
|
|
|
16
10
|
/**
|
|
17
11
|
* Array of current tab instances (exported if you need to interact with them)
|
|
18
12
|
* @type {Array}
|
|
19
13
|
*/
|
|
20
|
-
const instances = [];
|
|
21
|
-
|
|
22
|
-
// Init all instances currently in page
|
|
23
|
-
window.addEventListener("load", () => {
|
|
24
|
-
initWithin(document);
|
|
25
|
-
// Run this on page load, optionally exported for use when page is running
|
|
26
|
-
instances.forEach(openByCurrentHash);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
// Initialize when page updates/changes
|
|
30
|
-
document.addEventListener("pageModified", e => initWithin(e.target));
|
|
14
|
+
export const instances = [];
|
|
31
15
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Init all instances currently in document
|
|
18
|
+
* @param {Object} options Options to serve as defaults
|
|
19
|
+
*/
|
|
20
|
+
export function init(options = {}) {
|
|
21
|
+
const initial = () => {
|
|
22
|
+
initWithin(document, options);
|
|
23
|
+
// Run this on page load, optionally exported for use when page is running
|
|
24
|
+
instances.forEach(openByCurrentHash);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
if (document.readyState === "complete") {
|
|
28
|
+
initial();
|
|
29
|
+
} else {
|
|
30
|
+
window.addEventListener("load", initial);
|
|
31
|
+
}
|
|
32
|
+
// Initialize when page updates/changes
|
|
33
|
+
document.addEventListener("pageModified", e => initWithin(e.target, options));
|
|
36
34
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Init all tabs within a certain context
|
|
38
|
+
* @param {Node} context Element to init within
|
|
39
|
+
* @param {Object} options Options to serve as defaults
|
|
40
|
+
*/
|
|
41
|
+
export function initWithin(context, options = {}) {
|
|
42
|
+
if (!context) {
|
|
43
|
+
console.warn("Missing context to initWithin, skipping init of tabs");
|
|
44
|
+
return;
|
|
48
45
|
}
|
|
46
|
+
const tablists = context.querySelectorAll(`[data-ulu-tablist]:not([${ initAttr }])`);
|
|
47
|
+
tablists.forEach(element => setup(element, options));
|
|
49
48
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
* @param {Node} element Tablist Element
|
|
53
|
+
* @param {Node} options Options to set as defaults (can be overridden by element dataset options)
|
|
54
|
+
* @return {Object} Instance object
|
|
55
|
+
*/
|
|
56
|
+
export function setup(element, options = {}) {
|
|
57
|
+
let elementOptions = {};
|
|
53
58
|
|
|
54
|
-
if (element.dataset.
|
|
59
|
+
if (element.dataset.uluTablist) {
|
|
55
60
|
try {
|
|
56
|
-
|
|
61
|
+
elementOptions = JSON.parse(element.dataset.uluTablist);
|
|
57
62
|
} catch(e) {
|
|
58
63
|
console.error(errorHeader, "(JSON Parse for options)", element);
|
|
59
64
|
}
|
|
60
65
|
}
|
|
61
|
-
|
|
66
|
+
|
|
67
|
+
const config = Object.assign({}, options, elementOptions);
|
|
68
|
+
|
|
69
|
+
if (config.vertical) {
|
|
62
70
|
config.allArrows = true;
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
// Need to render the markup before checking height
|
|
66
74
|
// - used to wait until images had loaded
|
|
67
|
-
|
|
75
|
+
const instance = { element, options };
|
|
76
|
+
instance.ariaTablist = AriaTablist(element, {
|
|
77
|
+
onOpen(...args) {
|
|
78
|
+
args.unshift(instance);
|
|
79
|
+
handleOpen.apply(null, args);
|
|
80
|
+
},
|
|
81
|
+
...config
|
|
82
|
+
});
|
|
83
|
+
instances.push(instance);
|
|
68
84
|
|
|
69
|
-
if (
|
|
85
|
+
if (config.equalHeights) {
|
|
70
86
|
setHeights(element);
|
|
71
87
|
}
|
|
88
|
+
|
|
89
|
+
element.setAttribute(initAttr, "");
|
|
72
90
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
91
|
+
return instance;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Opens the a tabpanel if it matches current hash (used in initial init)
|
|
96
|
+
*/
|
|
97
|
+
function openByCurrentHash({ options, ariaTablist }) {
|
|
98
|
+
if (options.openByUrlHash) {
|
|
99
|
+
const { hash } = window.location;
|
|
100
|
+
if (hash && hash.length > 1) {
|
|
101
|
+
const possibleId = hash.substring(1);
|
|
102
|
+
ariaTablist.tabs.forEach(tab => {
|
|
103
|
+
if (possibleId === tab.id) {
|
|
104
|
+
ariaTablist.open(tab);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
83
108
|
}
|
|
84
109
|
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Responsible for setting hash on open if option is set
|
|
113
|
+
*/
|
|
85
114
|
function handleOpen({ options }, panel, tab) {
|
|
86
115
|
if (options.openByUrlHash && window.history) {
|
|
87
116
|
window.history.replaceState(null, "", `#${ tab.id }`);
|
|
88
117
|
}
|
|
89
118
|
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Responsible for creating equal height tab panels
|
|
122
|
+
*/
|
|
90
123
|
function setHeights(element) {
|
|
91
124
|
const tabs = [ ...element.children];
|
|
92
125
|
const panels = tabs.map(n => document.querySelector(`[aria-labelledby="${ n.id }"]`));
|
|
@@ -105,9 +138,3 @@ function setHeights(element) {
|
|
|
105
138
|
panels.forEach(panel => panel.style.minHeight = `${ max }px`);
|
|
106
139
|
});
|
|
107
140
|
}
|
|
108
|
-
|
|
109
|
-
export { instances };
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// Progressive Enhancement turns select elements into accessible autocomplete fields
|
|
2
|
+
|
|
3
|
+
// import { getName } from "@ulu/frontend/js/events/index.js";
|
|
4
|
+
import { getName } from "../events/index.js";
|
|
5
|
+
|
|
6
|
+
const attrs = {
|
|
7
|
+
trigger: "data-site-theme-toggle",
|
|
8
|
+
icon: "data-site-theme-toggle-icon",
|
|
9
|
+
init: "data-site-theme-toggle-init",
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const attrSelector = key => `[${ attrs[key] }]`;
|
|
13
|
+
const attrSelectorInitial = key => `${ attrSelector(key) }:not([${ attrs.init }])`;
|
|
14
|
+
|
|
15
|
+
// @dan change to options and remove options
|
|
16
|
+
// add a preferred print theme option
|
|
17
|
+
export const options = {
|
|
18
|
+
darkTheme: "theme-dark",
|
|
19
|
+
lightTheme: "theme-light",
|
|
20
|
+
defaultTheme: "dark",
|
|
21
|
+
darkIcon: "fa-solid fa-moon",
|
|
22
|
+
lightIcon: "fa-solid fa-sun",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const body = document.querySelector("[data-site-theme]");
|
|
26
|
+
let currentTheme = body.classList.contains(options.darkTheme) ? options.darkTheme : options.lightTheme;
|
|
27
|
+
// used to see if machine preference differs from default theme
|
|
28
|
+
const defaultThemeInverse = options.defaultTheme === "dark" ? "light" : "dark";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Initialize everything in document
|
|
32
|
+
* - This will only initialize elements once, it is safe to call on page changes
|
|
33
|
+
*/
|
|
34
|
+
export function init() {
|
|
35
|
+
// switch to light theme for printing
|
|
36
|
+
document.addEventListener(getName("beforePrint"), () => printSetup());
|
|
37
|
+
// switch back to original theme after printing
|
|
38
|
+
document.addEventListener(getName("afterPrint"), () => printTearDown());
|
|
39
|
+
// document.addEventListener(getName("pageModified"), () => setup());
|
|
40
|
+
setup();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function setup(context = document) {
|
|
44
|
+
const body = context.querySelector("[data-site-theme]");
|
|
45
|
+
// Initial theme on load
|
|
46
|
+
setupTheme(body);
|
|
47
|
+
// Add toggle event listener to buttons
|
|
48
|
+
// @daniel add the init attribute
|
|
49
|
+
const elements = context.querySelectorAll(attrSelectorInitial("trigger"));
|
|
50
|
+
elements.forEach(element => {
|
|
51
|
+
element.setAttribute(attrs.init, "");
|
|
52
|
+
element.addEventListener("click", () => {
|
|
53
|
+
changeTheme(body);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
// Initial icon setup
|
|
57
|
+
changeIcons();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
*
|
|
62
|
+
* @param {Element} body Sets up initial theme on load based on user preference.
|
|
63
|
+
*/
|
|
64
|
+
function setupTheme(body) {
|
|
65
|
+
const sitePreference = localStorage.getItem("data-theme");
|
|
66
|
+
const machinePreference = window.matchMedia && window.matchMedia(`(prefers-color-scheme: ${defaultThemeInverse})`).matches;
|
|
67
|
+
if(sitePreference && sitePreference != currentTheme){
|
|
68
|
+
// Check if local storage has site specific preference. And that preference is not the default.
|
|
69
|
+
changeTheme(body);
|
|
70
|
+
} else if (machinePreference) {
|
|
71
|
+
// Check if user system preference differs from default theme.
|
|
72
|
+
changeTheme(body);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
*
|
|
78
|
+
* @param {Element} body Changes the theme of the body.
|
|
79
|
+
*/
|
|
80
|
+
function changeTheme(body) {
|
|
81
|
+
let newTheme;
|
|
82
|
+
let oldTheme;
|
|
83
|
+
if (body.classList.contains(options.darkTheme)) {
|
|
84
|
+
oldTheme = options.darkTheme;
|
|
85
|
+
newTheme = options.lightTheme;
|
|
86
|
+
} else if (body.classList.contains(options.lightTheme)) {
|
|
87
|
+
oldTheme = options.lightTheme;
|
|
88
|
+
newTheme = options.darkTheme;
|
|
89
|
+
}
|
|
90
|
+
body.classList.remove(oldTheme);
|
|
91
|
+
body.classList.add(newTheme);
|
|
92
|
+
localStorage.setItem("data-theme", newTheme);
|
|
93
|
+
currentTheme = newTheme;
|
|
94
|
+
changeIcons();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
*
|
|
99
|
+
* @param {Element} body Used to check for theme.
|
|
100
|
+
* @param {Element} context Used to find the icons.
|
|
101
|
+
*/
|
|
102
|
+
function changeIcons(context = document) {
|
|
103
|
+
const icons = context.querySelectorAll(attrSelectorInitial("icon"));
|
|
104
|
+
icons.forEach(icon => {
|
|
105
|
+
if (currentTheme == options.lightTheme) {
|
|
106
|
+
icon.classList = options.darkIcon;
|
|
107
|
+
} else {
|
|
108
|
+
icon.classList = options.lightIcon;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// run on beforeprint event
|
|
114
|
+
function printSetup() {
|
|
115
|
+
const body = document.querySelector("body");
|
|
116
|
+
if (body.classList.contains(options.darkTheme)) {
|
|
117
|
+
body.classList.remove(options.darkTheme);
|
|
118
|
+
body.classList.add(options.lightTheme);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// run on afterprint event
|
|
123
|
+
function printTearDown() {
|
|
124
|
+
const body = document.querySelector("body");
|
|
125
|
+
if (!body.classList.contains(currentTheme)) {
|
|
126
|
+
body.classList.remove(options.lightTheme);
|
|
127
|
+
body.classList.add(options.darkTheme);
|
|
128
|
+
}
|
|
129
|
+
}
|