@profitlich/template-toolkit 2.22.0 → 3.0.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.
@@ -4,26 +4,48 @@ export class MenuToggle {
4
4
  static #instance;
5
5
  #menuButton;
6
6
  #menu;
7
- #menuLinkClass;
7
+ #menuLinkSelector;
8
8
  #menuItemClass;
9
9
  #scrollbarWidth;
10
10
  #shiftElement;
11
11
  #shiftDelay;
12
12
  #deferPositionFixed;
13
+ #fixBody;
13
14
  #y;
14
15
  #bodyClickHandler;
15
16
  #resizeHandler;
16
17
  #escapeHandler;
17
18
  isActive;
18
19
 
19
- constructor(menuButtonId, menuId, menuLinkClass, menuItemClass, shiftElementId, shiftDelay = 0, deferPositionFixed = false) {
20
+ /**
21
+ * @param {Object} options
22
+ * @param {string} options.menuButtonId ID des Buttons, der das Menü öffnet/schliesst.
23
+ * @param {string} options.menuId ID des Menü-Containers.
24
+ * @param {string} options.menuLinkSelector Selektor für Menü-Links, die das Menü beim Klick schliessen (z.B. '.menu-link').
25
+ * @param {string} options.menuItemClass Klassenname (ohne Punkt) des Menü-Wrappers; Klicks ausserhalb schliessen das Menü.
26
+ * @param {string?} options.shiftElementId Optional: Element, das beim Öffnen um die Scrollbar-Breite verschoben/verbreitert wird, damit z.B. ein fixierter Header nicht springt.
27
+ * @param {number} options.shiftDelay Verzögerung in Sekunden, bevor Scrollbar gemessen und Body fixiert wird – nützlich, wenn vorher noch eine CSS-Animation läuft, die die Scrollbar entfernt.
28
+ * @param {boolean} options.deferPositionFixed Setzt `data-menu-fixed` erst nach `shiftDelay` statt sofort. Nötig, wenn das Fixieren eine laufende Öffnungs-Animation stören würde.
29
+ * @param {boolean} options.fixBody Wenn `false`, bleibt der Body scrollbar; kein Scrollbar-Ausgleich und kein Shift. Für Menüs, die nur einen Teil der Seite bedecken und Hintergrund-Scroll erlauben sollen.
30
+ */
31
+ constructor({
32
+ menuButtonId,
33
+ menuId,
34
+ menuLinkSelector,
35
+ menuItemClass,
36
+ shiftElementId = null,
37
+ shiftDelay = 0,
38
+ deferPositionFixed = false,
39
+ fixBody = true,
40
+ }) {
20
41
  this.#menuButton = document.getElementById(menuButtonId);
21
42
  this.#menu = document.getElementById(menuId);
22
- this.#menuLinkClass = menuLinkClass;
43
+ this.#menuLinkSelector = menuLinkSelector;
23
44
  this.#menuItemClass = menuItemClass;
24
45
  this.#shiftElement = shiftElementId ? document.getElementById(shiftElementId) : null;
25
46
  this.#shiftDelay = shiftDelay * 1000;
26
47
  this.#deferPositionFixed = deferPositionFixed;
48
+ this.#fixBody = fixBody;
27
49
  this.#scrollbarWidth = 0;
28
50
  this.isActive = false;
29
51
  this.#y = 0;
@@ -39,7 +61,7 @@ export class MenuToggle {
39
61
  });
40
62
 
41
63
  this.#menu.addEventListener('click', (event) => {
42
- if (this.isActive && event.target.matches(this.#menuLinkClass)) {
64
+ if (this.isActive && event.target.matches(this.#menuLinkSelector)) {
43
65
  this.#toggleMenu();
44
66
  }
45
67
  });
@@ -49,12 +71,12 @@ export class MenuToggle {
49
71
  this.#setBodyAttribute('data-menu-fixed', 'false');
50
72
  }
51
73
 
52
- static getInstance(menuButtonId, menuId, menuLinkClass, menuItemClass, shiftElementId, shiftDelay, deferPositionFixed) {
74
+ static getInstance(options) {
53
75
  if (!MenuToggle.#instance) {
54
- if (!menuButtonId || !menuId || !menuLinkClass || !menuItemClass) {
55
- throw new Error("MenuToggle muss beim ersten Aufruf mit menuButtonId, menuId, menuLinkClass und menuItemClass initialisiert werden.");
76
+ if (!options || !options.menuButtonId || !options.menuId || !options.menuLinkSelector || !options.menuItemClass) {
77
+ throw new Error("MenuToggle muss beim ersten Aufruf mit menuButtonId, menuId, menuLinkSelector und menuItemClass initialisiert werden.");
56
78
  }
57
- MenuToggle.#instance = new MenuToggle(menuButtonId, menuId, menuLinkClass, menuItemClass, shiftElementId, shiftDelay, deferPositionFixed);
79
+ MenuToggle.#instance = new MenuToggle(options);
58
80
  }
59
81
  return MenuToggle.#instance;
60
82
  }
@@ -65,39 +87,43 @@ export class MenuToggle {
65
87
  document.body.removeEventListener('click', this.#bodyClickHandler);
66
88
  window.removeEventListener('resize', this.#resizeHandler);
67
89
  this.#setBodyAttribute('data-menu-active', 'false');
68
- this.#setBodyAttribute('data-menu-fixed', 'false');
69
- if (this.#shiftElement) {
70
- this.#shiftElement.style.marginRight = '';
71
- this.#shiftElement.style.width = '';
90
+ if (this.#fixBody) {
91
+ this.#setBodyAttribute('data-menu-fixed', 'false');
92
+ if (this.#shiftElement) {
93
+ this.#shiftElement.style.marginRight = '';
94
+ this.#shiftElement.style.width = '';
95
+ }
96
+ document.body.style.paddingRight = '';
97
+ document.body.style.top = '';
98
+ window.scrollTo(0, this.#y);
72
99
  }
73
- document.body.style.paddingRight = '';
74
- document.body.style.top = '';
75
- window.scrollTo(0, this.#y);
76
100
  this.#toggleEscape(false);
77
101
  } else {
78
102
  this.isActive = true;
79
103
  document.body.addEventListener('click', this.#bodyClickHandler);
80
- window.addEventListener('resize', this.#resizeHandler);
81
104
  this.#setBodyAttribute('data-menu-active', 'true');
82
- this.#setBodyAttribute('data-menu-moving', 'true');
83
- if (!this.#deferPositionFixed) {
84
- this.#setBodyAttribute('data-menu-fixed', 'true');
85
- }
86
- setTimeout(() => {
87
- this.#scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
88
- this.#y = window.scrollY;
89
- document.body.style.paddingRight = `${this.#scrollbarWidth}px`;
90
- document.body.style.top = `-${this.#y}px`;
91
- if (this.#deferPositionFixed) {
105
+ if (this.#fixBody) {
106
+ window.addEventListener('resize', this.#resizeHandler);
107
+ this.#setBodyAttribute('data-menu-moving', 'true');
108
+ if (!this.#deferPositionFixed) {
92
109
  this.#setBodyAttribute('data-menu-fixed', 'true');
93
110
  }
94
- if (this.#shiftElement) {
95
- const marginOriginal = parseFloat(window.getComputedStyle(this.#menuButton).marginRight);
96
- this.#shiftElement.style.marginRight = `${marginOriginal + this.#scrollbarWidth}px`;
97
- this.#adjustShiftElementWidth();
98
- }
99
- this.#setBodyAttribute('data-menu-moving', 'false');
100
- }, this.#shiftDelay);
111
+ setTimeout(() => {
112
+ this.#scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
113
+ this.#y = window.scrollY;
114
+ document.body.style.paddingRight = `${this.#scrollbarWidth}px`;
115
+ document.body.style.top = `-${this.#y}px`;
116
+ if (this.#deferPositionFixed) {
117
+ this.#setBodyAttribute('data-menu-fixed', 'true');
118
+ }
119
+ if (this.#shiftElement) {
120
+ const marginOriginal = parseFloat(window.getComputedStyle(this.#menuButton).marginRight);
121
+ this.#shiftElement.style.marginRight = `${marginOriginal + this.#scrollbarWidth}px`;
122
+ this.#adjustShiftElementWidth();
123
+ }
124
+ this.#setBodyAttribute('data-menu-moving', 'false');
125
+ }, this.#shiftDelay);
126
+ }
101
127
  this.#toggleEscape(true);
102
128
  }
103
129
  const event = new CustomEvent('eventMenuestatus', {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profitlich/template-toolkit",
3
- "version": "2.22.0",
3
+ "version": "3.0.0",
4
4
  "description": "Shared SCSS layout system, JS utilities, components and build scripts for profitlich template repos",
5
5
  "type": "module",
6
6
  "exports": {