@madj2k/fe-frontend-kit 2.0.3 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/index.js +7 -4
  2. package/index.scss +8 -1
  3. package/menus/flyout-menu/{flyout-menu-2.0.0.js → flyout-menu-2.0.js} +149 -54
  4. package/menus/flyout-menu/index.js +1 -1
  5. package/menus/flyout-menu/index.scss +1 -1
  6. package/menus/pulldown-menu/index.js +1 -1
  7. package/menus/pulldown-menu/index.scss +1 -1
  8. package/package.json +1 -1
  9. package/readme.md +23 -14
  10. package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_page.scss +2 -2
  11. package/tools/banner/index.js +1 -1
  12. package/tools/banner/index.scss +1 -1
  13. package/tools/owl-thumbnail/index.js +2 -0
  14. package/tools/owl-thumbnail/index.scss +1 -0
  15. package/tools/resize-end/index.js +1 -1
  16. package/tools/resize-end/index.scss +1 -1
  17. package/tools/scrolling/index.js +1 -1
  18. package/tools/scrolling/index.scss +1 -1
  19. package/tools/toggled-overlay/index.js +2 -0
  20. package/tools/toggled-overlay/index.scss +1 -0
  21. package/tools/toggled-overlay/toggled-overlay-2.0.js +125 -0
  22. package/tools/toggled-overlay/toggled-overlay-2.0.scss +11 -0
  23. package/tools/owl/index.js +0 -2
  24. package/tools/owl/index.scss +0 -1
  25. /package/menus/flyout-menu/{flyout-menu-2.0.0.scss → flyout-menu-2.0.scss} +0 -0
  26. /package/menus/pulldown-menu/{pulldown-menu-2.0.0.js → pulldown-menu-2.0.js} +0 -0
  27. /package/menus/pulldown-menu/{pulldown-menu-2.0.0.scss → pulldown-menu-2.0.scss} +0 -0
  28. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_accessibility.scss +0 -0
  29. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_colors.scss +0 -0
  30. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_flex-box.scss +0 -0
  31. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_form.scss +0 -0
  32. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_format.scss +0 -0
  33. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_icons.scss +0 -0
  34. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_nav.scss +0 -0
  35. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_section.scss +0 -0
  36. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_toggle-list.scss +0 -0
  37. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/_unit.scss +0 -0
  38. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/10_mixins/index.scss +0 -0
  39. /package/sass/{bootstrap-5.3.0 → bootstrap-5.3}/index.scss +0 -0
  40. /package/tools/banner/{banner-2.0.0.js → banner-2.0.js} +0 -0
  41. /package/tools/banner/{banner-2.0.0.scss → banner-2.0.scss} +0 -0
  42. /package/tools/{owl/owl-thumbnail-2.0.0.js → owl-thumbnail/owl-thumbnail-2.0.js} +0 -0
  43. /package/tools/{owl/owl-thumbnail-2.0.0.scss → owl-thumbnail/owl-thumbnail-2.0.scss} +0 -0
  44. /package/tools/resize-end/{resize-end-2.0.0.js → resize-end-2.0.js} +0 -0
  45. /package/tools/resize-end/{resize-end-2.0.0.scss → resize-end-2.0.scss} +0 -0
  46. /package/tools/scrolling/{scrolling-2.0.0.js → scrolling-2.0.js} +0 -0
  47. /package/tools/scrolling/{scrolling-2.0.0.scss → scrolling-2.0.scss} +0 -0
package/index.js CHANGED
@@ -1,7 +1,10 @@
1
1
  // Tools
2
- export { Madj2kOwlThumbnail } from './tools/owl/owl-thumbnail.js';
3
- export { Madj2kScrolling } from './tools/scrolling/scrolling.js';
2
+ export { Madj2kBanner } from './tools/banner';
3
+ export { Madj2kOwlThumbnail } from './tools/owl-thumbnail';
4
+ export { Madj2kResizeEnd } from './tools/resize-end';
5
+ export { Madj2kScrolling } from './tools/scrolling';
6
+ export { Madj2kToggledOverlay } from './tools/toggled-overlay';
4
7
 
5
8
  // Menus
6
- export { Madj2kFlyoutMenu } from './menus/flyout-menu-1.0';
7
- export { Madj2kPulldownMenu } from './menus/pulldown-menu-1.0';
9
+ export { Madj2kFlyoutMenu } from './menus/flyout-menu';
10
+ export { Madj2kPulldownMenu } from './menus/pulldown-menu';
package/index.scss CHANGED
@@ -1,6 +1,13 @@
1
1
  // Forward all mixins
2
- @forward './sass/bootstrap-5.3.0/index';
2
+ @forward 'sass/bootstrap-5.3/index';
3
3
 
4
4
  // Forward all menu styles
5
5
  @forward './menus/flyout-menu';
6
6
  @forward './menus/pulldown-menu';
7
+
8
+ // Forward all tools
9
+ @forward 'tools/banner/index';
10
+ @forward 'tools/owl-thumbnail/index';
11
+ @forward 'tools/resize-end/index';
12
+ @forward 'tools/scrolling/index';
13
+ @forward 'tools/toggled-overlay/index';
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * @author Steffen Kroggel <developer@steffenkroggel.de>
9
9
  * @copyright 2025 Steffen Kroggel
10
- * @version 2.0.0
10
+ * @version 2.0.1
11
11
  * @license GNU General Public License v3.0
12
12
  * @see https://www.gnu.org/licenses/gpl-3.0.en.html
13
13
  *
@@ -49,7 +49,7 @@ class Madj2kFlyoutMenu {
49
49
  menuCloseClass: "js-flyout-close",
50
50
  menuContainerClass: "js-flyout-container",
51
51
  menuInnerClass: "js-flyout-inner",
52
- heightMode: 'maxContent',
52
+ heightMode: 'full',
53
53
  paddingBehavior: 0,
54
54
  paddingViewPortMinWidth: 0,
55
55
  animationDuration: 500
@@ -76,25 +76,7 @@ class Madj2kFlyoutMenu {
76
76
  this.resizeAndPositionMenu();
77
77
  this.paddingMenu();
78
78
  this.bindEvents();
79
- }
80
-
81
- /**
82
- * Binds all necessary event listeners
83
- */
84
- bindEvents() {
85
- if (this.settings.$closeBtn) {
86
- this.settings.$closeBtn.addEventListener('click', e => this.closeEvent(e));
87
- this.settings.$closeBtn.addEventListener('keydown', e => this.keyboardEvent(e));
88
- }
89
-
90
- this.$element.addEventListener('click', e => this.toggleEvent(e));
91
- this.$element.addEventListener('keydown', e => this.keyboardEvent(e));
92
-
93
- this.settings.$menu.querySelectorAll('a,button,input,textarea,select')
94
- .forEach(el => el.addEventListener('keydown', e => this.keyboardEvent(e)));
95
-
96
- document.addEventListener('madj2k-flyoutmenu-close', e => this.closeEvent(e));
97
- document.addEventListener('madj2k-flyoutmenu-resize', e => this.resizeAndPositionMenuEvent(e));
79
+ this.initObservers();
98
80
  }
99
81
 
100
82
  /**
@@ -128,6 +110,88 @@ class Madj2kFlyoutMenu {
128
110
  }
129
111
  }
130
112
 
113
+ /**
114
+ * Binds all necessary event listeners
115
+ */
116
+ bindEvents() {
117
+ if (this.settings.$closeBtn) {
118
+ this.settings.$closeBtn.addEventListener('click', e => this.closeEvent(e));
119
+ this.settings.$closeBtn.addEventListener('keydown', e => this.keyboardEvent(e));
120
+ }
121
+
122
+ this.$element.addEventListener('click', e => this.toggleEvent(e));
123
+ this.$element.addEventListener('keydown', e => this.keyboardEvent(e));
124
+
125
+ this.settings.$menu.querySelectorAll('a,button,input,textarea,select')
126
+ .forEach(el => el.addEventListener('keydown', e => this.keyboardEvent(e)));
127
+
128
+ document.addEventListener('madj2k-flyoutmenu-close', e => this.closeEvent(e));
129
+ document.addEventListener('madj2k-flyoutmenu-resize', e => this.resizeAndPositionMenuEvent(e));
130
+ }
131
+
132
+ /**
133
+ * Initializes ResizeObserver to auto-resize menu
134
+ */
135
+ initObservers() {
136
+ // check if supported
137
+ if (typeof ResizeObserver === 'undefined') {
138
+ console.warn('ResizeObserver is not supported in this browser.');
139
+ return;
140
+ }
141
+
142
+ // create observer
143
+ this.resizeObserver = new ResizeObserver(entries => {
144
+ for (let entry of entries) {
145
+ this.resizeMenu();
146
+ }
147
+ });
148
+
149
+ // observe inner container
150
+ if (this.settings.$menuInner) {
151
+ this.resizeObserver.observe(this.settings.$menuInner);
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Unbinds all event listeners
157
+ */
158
+ destroyEvents() {
159
+ if (this.settings.$closeBtn) {
160
+ this.settings.$closeBtn.removeEventListener('click', e => this.closeEvent(e));
161
+ this.settings.$closeBtn.removeEventListener('keydown', e => this.keyboardEvent(e));
162
+ }
163
+
164
+ this.$element.removeEventListener('click', e => this.toggleEvent(e));
165
+ this.$element.removeEventListener('keydown', e => this.keyboardEvent(e));
166
+
167
+ this.settings.$menu.querySelectorAll('a,button,input,textarea,select')
168
+ .forEach(el => el.removeEventListener('keydown', e => this.keyboardEvent(e)));
169
+
170
+ document.removeEventListener('madj2k-flyoutmenu-close', e => this.closeEvent(e));
171
+ document.removeEventListener('madj2k-flyoutmenu-resize', e => this.resizeAndPositionMenuEvent(e));
172
+ }
173
+
174
+ /**
175
+ * Destroys ResizeObserver
176
+ */
177
+ destroyResizeObserver() {
178
+ if (this.resizeObserver && this.settings.$menuInner) {
179
+ this.resizeObserver.unobserve(this.settings.$menuInner);
180
+ this.resizeObserver.disconnect();
181
+ this.resizeObserver = null;
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Destroys flyout menu instance
187
+ */
188
+ destroy() {
189
+ this.destroyEvents();
190
+ this.destroyResizeObserver();
191
+ this.close();
192
+ }
193
+
194
+
131
195
  /**
132
196
  * Handles toggle click event
133
197
  * @param {Event} e - The click event
@@ -153,6 +217,15 @@ class Madj2kFlyoutMenu {
153
217
  }
154
218
  }
155
219
 
220
+ /**
221
+ * Sets focus to the toggle element
222
+ * @param {number} timeout - Delay before focusing
223
+ */
224
+ focusToggle(timeout = 0) {
225
+ setTimeout(() => this.$element.focus(), timeout);
226
+ }
227
+
228
+
156
229
  /**
157
230
  * Opens the flyout menu
158
231
  */
@@ -184,6 +257,14 @@ class Madj2kFlyoutMenu {
184
257
  }
185
258
  }
186
259
 
260
+ /**
261
+ * Returns true if menu is currently open
262
+ * @returns {boolean}
263
+ */
264
+ isOpen() {
265
+ return this.settings.$menu.classList.contains(this.settings.openStatusClass);
266
+ }
267
+
187
268
  /**
188
269
  * Handles close event
189
270
  * @param {Event} e - The close event
@@ -237,29 +318,51 @@ class Madj2kFlyoutMenu {
237
318
  }
238
319
 
239
320
  /**
240
- * Resizes and positions the menu based on reference elements
321
+ * Resizes and positions the menu
241
322
  */
242
323
  resizeAndPositionMenu() {
243
- const refObj = this.settings.$positionReference || this.$element;
244
- const refPos = refObj.getBoundingClientRect();
245
- const flyoutTop = refPos.top + refObj.offsetHeight;
324
+ this.positionMenu();
325
+ this.resizeMenu();
326
+ }
327
+
328
+ /**
329
+ * Resizes the menu based on height mode and inner content
330
+ */
331
+ resizeMenu() {
246
332
  let height = this.settings.$menuInner.offsetHeight || this.settings.$menu.offsetHeight;
247
333
 
248
- this.settings.$menu.style.top = `${flyoutTop}px`;
334
+ if ('fullHeight' in this.settings) {
335
+ console.warn('Option "fullHeight" is deprecated. Please use "heightMode" instead.');
336
+ }
249
337
 
250
- // deprecated fullHeight-setting as fallback
338
+ // heightMode "full" with deprecated fullHeight-setting as fallback
251
339
  if (this.settings.heightMode === 'full' || this.settings.fullHeight === true) {
252
- height = window.innerHeight - refPos.top - refObj.offsetHeight;
340
+ const viewPortHeight = window.innerHeight;
341
+ if (height < viewPortHeight) {
342
+ height = viewPortHeight;
343
+ }
253
344
  this.settings.$menu.style.height = `${height}px`;
254
345
 
255
- } else if (this.settings.heightMode === 'maxContent'){
346
+ } else if (this.settings.heightMode === 'maxContent') {
256
347
  this.settings.$menu.style.height = `max-content`;
348
+ console.warn('heightMode: maxContent is not working on Apple Safari. Please use heightMode: full instead.');
257
349
 
258
350
  } else {
259
351
  this.settings.$menu.style.height = `${height}px`;
260
352
  }
261
353
  }
262
354
 
355
+ /**
356
+ * Positions the menu based on the reference element
357
+ */
358
+ positionMenu() {
359
+ const refObj = this.settings.$positionReference || this.$element;
360
+ const refPos = refObj.getBoundingClientRect();
361
+ const flyoutTop = refPos.top + refObj.offsetHeight;
362
+
363
+ this.settings.$menu.style.top = `${flyoutTop}px`;
364
+ }
365
+
263
366
  /**
264
367
  * Adjusts menu padding based on settings
265
368
  */
@@ -275,6 +378,23 @@ class Madj2kFlyoutMenu {
275
378
  this.settings.$menuInner.setAttribute('data-padding-set', 'true');
276
379
  }
277
380
 
381
+ /**
382
+ * Initializes the no-scroll helper elements
383
+ */
384
+ initNoScrollHelper() {
385
+ const body = document.body;
386
+ let helper = body.querySelector('.no-scroll-helper');
387
+ const content = document.querySelector(`.${this.settings.contentSectionClass}`);
388
+
389
+ if (!helper) {
390
+ if (content) {
391
+ content.innerHTML = `<div class="no-scroll-helper"><div class="no-scroll-helper-inner">${content.innerHTML}</div></div>`;
392
+ } else {
393
+ body.innerHTML = `<div class="no-scroll-helper"><div class="no-scroll-helper-inner">${body.innerHTML}</div></div>`;
394
+ }
395
+ }
396
+ }
397
+
278
398
  /**
279
399
  * Toggles scroll behavior of the page
280
400
  */
@@ -303,29 +423,4 @@ class Madj2kFlyoutMenu {
303
423
  window.scrollTo({top: scrollTop, behavior: 'instant'});
304
424
  }
305
425
  }
306
-
307
- /**
308
- * Initializes the no-scroll helper elements
309
- */
310
- initNoScrollHelper() {
311
- const body = document.body;
312
- let helper = body.querySelector('.no-scroll-helper');
313
- const content = document.querySelector(`.${this.settings.contentSectionClass}`);
314
-
315
- if (!helper) {
316
- if (content) {
317
- content.innerHTML = `<div class="no-scroll-helper"><div class="no-scroll-helper-inner">${content.innerHTML}</div></div>`;
318
- } else {
319
- body.innerHTML = `<div class="no-scroll-helper"><div class="no-scroll-helper-inner">${body.innerHTML}</div></div>`;
320
- }
321
- }
322
- }
323
-
324
- /**
325
- * Sets focus to the toggle element
326
- * @param {number} timeout - Delay before focusing
327
- */
328
- focusToggle(timeout = 0) {
329
- setTimeout(() => this.$element.focus(), timeout);
330
- }
331
426
  }
@@ -1,2 +1,2 @@
1
- import Madj2kFlyoutMenu from './flyout-menu-2.0.0.js';
1
+ import Madj2kFlyoutMenu from './flyout-menu-2.0.js';
2
2
  export { Madj2kFlyoutMenu };
@@ -1 +1 @@
1
- @forward './flyout-menu-2.0.0';
1
+ @forward './flyout-menu-2.0';
@@ -1,2 +1,2 @@
1
- import Madj2kPulldownMenu from './pulldown-menu-2.0.0.js';
1
+ import Madj2kPulldownMenu from './pulldown-menu-2.0.js';
2
2
  export { Madj2kPulldownMenu };
@@ -1 +1 @@
1
- @forward './pulldown-menu-2.0.0';
1
+ @forward './pulldown-menu-2.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madj2k/fe-frontend-kit",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "description": "Shared frontend utilities, menus and mixins for projects",
5
5
  "main": "index.js",
6
6
  "style": "index.scss",
package/readme.md CHANGED
@@ -26,6 +26,25 @@ Or import individual mixins:
26
26
  ### Menu components (JS and SCSS):
27
27
  Each menu component can be used separately.
28
28
 
29
+ # JS: Banner
30
+ A lightweight class to show a full-page overlay (banner, popup, hint or cookie layer),
31
+ with opening and closing animation and optional cookie persistence.
32
+
33
+ # JS: OWL-Thumbnails
34
+ A JavaScript helper class to create a main OWL carousel with a synchronized thumbnail navigation carousel.
35
+
36
+ Supports flexible configurations for both the main and the thumbnail carousels,
37
+ including:
38
+ - Custom navigation
39
+ - Syncing main carousel to clicked thumbnails
40
+ - Syncing thumbnails to main carousel changes
41
+ - Optionally equalizing thumbnail heights
42
+ - Optionally preventing the centered thumbnail stage shift (for designs where thumbs should stay left aligned)
43
+ - Responsive and CMS-friendly (works with dynamic content)
44
+
45
+ This is especially useful for image galleries or product carousels in CMS setups (e.g. TYPO3, WordPress, etc.)
46
+ where content may change dynamically.
47
+
29
48
  # JS: Resize-End
30
49
  A lightweight helper class that triggers a debounced 'madj2k-resize-end' event
31
50
  when the user finishes resizing the browser window.
@@ -43,20 +62,10 @@ A lightweight scrolling helper class that enables:
43
62
  The class is fully configurable via options and is designed to be used in CMS contexts
44
63
  where elements can be added, removed or re-ordered dynamically.
45
64
 
46
- # JS: OWL-Thumbnails
47
- A JavaScript helper class to create a main OWL carousel with a synchronized thumbnail navigation carousel.
48
-
49
- Supports flexible configurations for both the main and the thumbnail carousels,
50
- including:
51
- - Custom navigation
52
- - Syncing main carousel to clicked thumbnails
53
- - Syncing thumbnails to main carousel changes
54
- - Optionally equalizing thumbnail heights
55
- - Optionally preventing the centered thumbnail stage shift (for designs where thumbs should stay left aligned)
56
- - Responsive and CMS-friendly (works with dynamic content)
57
-
58
- This is especially useful for image galleries or product carousels in CMS setups (e.g. TYPO3, WordPress, etc.)
59
- where content may change dynamically.
65
+ # JS: Toggled Overlay
66
+ This class toggles the visibility of any target element referenced by the `aria-controls`
67
+ attribute of a trigger element (button, link, etc.). It manages ARIA attributes for accessibility
68
+ and allows overlays to be closed externally via a custom event.
60
69
 
61
70
  # Flyout-Navigation
62
71
  ## Usage
@@ -242,8 +242,8 @@
242
242
  }
243
243
 
244
244
  @mixin page-padding-row ($padding-x) {
245
- padding-left: $padding-x;
246
- padding-right: $padding-x;
245
+ padding-left: 0;
246
+ padding-right: 0;
247
247
  margin-left: $padding-x * -1;
248
248
  margin-right: $padding-x * -1;
249
249
  }
@@ -1,2 +1,2 @@
1
- import Madj2kBanner from './banner-2.0.0.js';
1
+ import Madj2kBanner from './banner-2.0.js';
2
2
  export { Madj2kBanner };
@@ -1 +1 @@
1
- @forward './banner-2.0.0';
1
+ @forward './banner-2.0';
@@ -0,0 +1,2 @@
1
+ import Madj2kOwlThumbnail from './owl-thumbnail-2.0.js';
2
+ export { Madj2kOwlThumbnail };
@@ -0,0 +1 @@
1
+ @forward 'owl-thumbnail-2.0';
@@ -1,2 +1,2 @@
1
- import Madj2kResizeEnd from './resize-end-2.0.0.js';
1
+ import Madj2kResizeEnd from './resize-end-2.0.js';
2
2
  export { Madj2kResizeEnd };
@@ -1 +1 @@
1
- @forward './resize-end-2.0.0';
1
+ @forward './resize-end-2.0';
@@ -1,2 +1,2 @@
1
- import Madj2kScrolling from './scrolling-2.0.0.js';
1
+ import Madj2kScrolling from './scrolling-2.0.js';
2
2
  export { Madj2kScrolling };
@@ -1 +1 @@
1
- @forward './scrolling-2.0.0';
1
+ @forward './scrolling-2.0';
@@ -0,0 +1,2 @@
1
+ import Madj2kToggledOverlay from './toggled-overlay-2.0.js';
2
+ export { Madj2kToggledOverlay };
@@ -0,0 +1 @@
1
+ @forward './toggled-overlay-2.0';
@@ -0,0 +1,125 @@
1
+ /**!
2
+ * ToggledOverlay
3
+ *
4
+ * @author Steffen Kroggel <developer@steffenkroggel.de>
5
+ * @copyright 2025 Steffen Kroggel
6
+ * @version 2.0.0
7
+ * @license GNU General Public License v3.0
8
+ * @see https://www.gnu.org/licenses/gpl-3.0.en.html
9
+ *
10
+ * This class toggles the visibility of any target element referenced by the `aria-controls`
11
+ * attribute of a trigger element (button, link, etc.). It manages ARIA attributes for accessibility
12
+ * and allows overlays to be closed externally via a custom event.
13
+ *
14
+ * @example
15
+ * Example HTML:
16
+ * <button class="js-toggled-overlay toggled-overlay-button"
17
+ * aria-label="Open overlay"
18
+ * aria-controls="my-overlay"
19
+ * aria-expanded="false">
20
+ * <span class="icon icon-info"></span>
21
+ * </button>
22
+ *
23
+ * <div id="my-overlay" class="toggled-overlay" aria-hidden="true">
24
+ * <!-- Overlay content -->
25
+ * </div>
26
+ *
27
+ * Example JavaScript:
28
+ * const overlayToggle = new Madj2kToggledOverlay('.js-toggled-overlay');
29
+ *
30
+ * // External close trigger
31
+ * window.dispatchEvent(new CustomEvent('madj2k-toggledoverlay-close'));
32
+ *
33
+ * Example CSS:
34
+ * .toggled-overlay {
35
+ * opacity: 0;
36
+ * visibility: hidden;
37
+ * transition: opacity 0.5s ease-in-out, visibility 0s linear 0.5s;
38
+ *
39
+ * &.is-visible {
40
+ * opacity: 1;
41
+ * visibility: visible;
42
+ * transition: opacity 0.5s ease-in-out, visibility 0s linear 0s;
43
+ * }
44
+ * }
45
+ *
46
+ * .toggled-overlay-button[aria-expanded="true"] .icon-info::before {
47
+ * content: "\e8bb"; // Example: "close" icon (replace with actual icon code)
48
+ * }
49
+ */
50
+ class Madj2kToggledOverlay {
51
+ /**
52
+ * Creates a new ToggledOverlay instance.
53
+ * @param {string} toggleSelector - CSS selector to identify all toggle buttons.
54
+ */
55
+ constructor(toggleSelector) {
56
+ /** @type {NodeListOf<HTMLElement>} */
57
+ this.toggles = document.querySelectorAll(toggleSelector);
58
+ this.init();
59
+ this.registerEvents();
60
+ }
61
+
62
+ /**
63
+ * Initializes toggle buttons and sets up toggle behavior.
64
+ */
65
+ init() {
66
+ this.toggles.forEach(toggle => {
67
+ const targetId = toggle.getAttribute('aria-controls');
68
+ const target = document.getElementById(targetId);
69
+ if (!target) return;
70
+
71
+ // Set initial ARIA state
72
+ target.setAttribute('aria-hidden', 'true');
73
+ toggle.setAttribute('aria-expanded', 'false');
74
+
75
+ toggle.addEventListener('click', () => {
76
+ const isExpanded = toggle.getAttribute('aria-expanded') === 'true';
77
+ toggle.setAttribute('aria-expanded', String(!isExpanded));
78
+ target.setAttribute('aria-hidden', String(isExpanded));
79
+ target.classList.toggle('is-visible', !isExpanded);
80
+ });
81
+ });
82
+ }
83
+
84
+ /**
85
+ * Closes all overlays by removing the 'is-visible' class and updating ARIA attributes.
86
+ */
87
+ close() {
88
+ this.toggles.forEach(toggle => {
89
+ const targetId = toggle.getAttribute('aria-controls');
90
+ const target = document.getElementById(targetId);
91
+ if (!target) return;
92
+
93
+ toggle.setAttribute('aria-expanded', 'false');
94
+ target.setAttribute('aria-hidden', 'true');
95
+ target.classList.remove('is-visible');
96
+ });
97
+ }
98
+
99
+ /**
100
+ * Handles clicks outside the overlay and toggles to close them.
101
+ * @param {MouseEvent} event
102
+ */
103
+ handleClickOutside(event) {
104
+ this.toggles.forEach(toggle => {
105
+ const targetId = toggle.getAttribute('aria-controls');
106
+ const target = document.getElementById(targetId);
107
+ if (!target) return;
108
+
109
+ const clickedInsideToggle = toggle.contains(event.target);
110
+ const clickedInsideTarget = target.contains(event.target);
111
+
112
+ if (!clickedInsideToggle && !clickedInsideTarget && toggle.getAttribute('aria-expanded') === 'true') {
113
+ this.close();
114
+ }
115
+ });
116
+ }
117
+
118
+ /**
119
+ * Registers all global event listeners.
120
+ */
121
+ registerEvents() {
122
+ document.addEventListener('click', this.handleClickOutside.bind(this));
123
+ document.addEventListener('madj2k-toggledoverlay-close', this.close.bind(this));
124
+ }
125
+ }
@@ -0,0 +1,11 @@
1
+ .toggled-overlay {
2
+ opacity: 0;
3
+ visibility: hidden;
4
+ transition: opacity 0.5s ease-in-out, visibility 0s linear 0.5s;
5
+
6
+ &.is-visible {
7
+ opacity: 1;
8
+ visibility: visible;
9
+ transition: opacity 0.5s ease-in-out, visibility 0s linear 0s;
10
+ }
11
+ }
@@ -1,2 +0,0 @@
1
- import Madj2kOwlThumbnail from './owl-thumbnail-2.0.0.js';
2
- export { Madj2kOwlThumbnail };
@@ -1 +0,0 @@
1
- @forward './owl-thumbnail-2.0.0';
File without changes