@madj2k/fe-frontend-kit 2.0.37 → 2.0.39

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/index.js CHANGED
@@ -11,3 +11,4 @@ export { Madj2kElementInViewport } from './tools/element-in-viewport';
11
11
  // Menus
12
12
  export { Madj2kFlyoutMenu } from './menus/flyout-menu';
13
13
  export { Madj2kPulldownMenu } from './menus/pulldown-menu';
14
+ export { Madj2kSlideMenu } from './menus/slide-menu';
package/index.scss CHANGED
@@ -4,6 +4,7 @@
4
4
  // Forward all menu styles
5
5
  @forward './menus/flyout-menu';
6
6
  @forward './menus/pulldown-menu';
7
+ @forward './menus/slide-menu';
7
8
 
8
9
  // Forward all tools
9
10
  @forward 'tools/banner/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.2
10
+ * @version 2.0.4
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,11 +49,13 @@ class Madj2kFlyoutMenu {
49
49
  menuCloseClass: "js-flyout-close",
50
50
  menuContainerClass: "js-flyout-container",
51
51
  menuInnerClass: "js-flyout-inner",
52
+ hoverParentClass: 'nav-main',
52
53
  heightCalculationClass: 'calculate',
53
54
  heightMode: 'full',
55
+ heightModeClassPrefix: 'height-mode',
56
+ scrollMode: 'default',
57
+ scrollModeClassPrefix: 'scroll-mode',
54
58
  eventMode: 'click',
55
- eventModeOpen: '',
56
- eventModeClose: '',
57
59
  paddingBehavior: 0,
58
60
  paddingViewPortMinWidth: 0,
59
61
  animationDuration: 500,
@@ -77,6 +79,11 @@ class Madj2kFlyoutMenu {
77
79
  this.settings.$menuContainer = this.settings.$menu.querySelector(`.${this.settings.menuContainerClass}`);
78
80
  this.settings.$menuInner = this.settings.$menu.querySelector(`.${this.settings.menuInnerClass}`);
79
81
 
82
+ // add mode classes
83
+ this.settings.$menu.classList.add(this.settings.heightModeClassPrefix + '-' + this.settings.heightMode);
84
+ this.settings.$menuInner.classList.add(this.settings.scrollModeClassPrefix + '-' + this.settings.scrollMode);
85
+
86
+ // Bind persistent event handlers
80
87
  this.initNoScrollHelper();
81
88
  this.resizeAndPositionMenu();
82
89
  this.paddingMenu();
@@ -115,40 +122,102 @@ class Madj2kFlyoutMenu {
115
122
  }
116
123
  }
117
124
 
125
+
126
+ /**
127
+ * Handles mouseleave on menu container
128
+ * @param {MouseEvent} e
129
+ */
130
+ containerLeaveEvent(e) {
131
+ const to = e.relatedTarget;
132
+ const parentContainer = this.$element.closest(this.settings.hoverParentSelector) || null;
133
+ if (to && this.$element.contains(to)) return;
134
+ if (to && parentContainer?.contains(to)) return;
135
+ if (this.$element.classList.contains(this.settings.openStatusClass)) {
136
+ document.dispatchEvent(new CustomEvent('madj2k-flyoutmenu-close'));
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Handles mouseleave on trigger element
142
+ * @param {MouseEvent} e
143
+ */
144
+ triggerLeaveEvent(e) {
145
+ const to = e.relatedTarget;
146
+ const parentContainer = this.$element.closest('.' + this.settings.hoverParentClass) || null;
147
+
148
+ if (to && this.settings.$menu.contains(to)) return;
149
+ if (to && parentContainer?.contains(to)) return;
150
+ if (this.$element.classList.contains(this.settings.openStatusClass)) {
151
+ document.dispatchEvent(new CustomEvent('madj2k-flyoutmenu-close'));
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Handles touchstart outside the flyout menu
157
+ * @param {TouchEvent} e
158
+ */
159
+ touchStartEvent(e) {
160
+ const target = e.target;
161
+ if (!target) return;
162
+ if (this.settings.$menuInner.contains(target)) return;
163
+ if (this.$element.classList.contains(this.settings.openStatusClass)) {
164
+ document.dispatchEvent(new CustomEvent('madj2k-flyoutmenu-close'));
165
+ }
166
+ }
167
+
118
168
  /**
119
169
  * Binds all necessary event listeners
120
170
  */
121
171
  bindEvents() {
122
172
  if (this.settings.$closeBtn) {
123
-
124
- if (this.settings.eventModeClose) {
125
- this.settings.$closeBtn.addEventListener(this.settings.eventModeClose, e => this.closeEvent(e));
126
- } else {
127
- this.settings.$closeBtn.addEventListener(this.settings.eventMode, e => this.closeEvent(e));
128
- }
173
+ const closeEvent = this.settings.eventMode === 'mouseover' ? 'mouseenter' : 'click';
174
+ this.settings.$closeBtn.addEventListener(closeEvent, e => this.closeEvent(e));
129
175
  this.settings.$closeBtn.addEventListener('keydown', e => this.keyboardEvent(e));
130
176
  }
131
177
 
132
- if (this.settings.eventModeOpen || this.settings.eventModeClose) {
133
- if (this.settings.eventModeOpen) {
134
- this.$element.addEventListener(this.settings.eventModeOpen, e => this.openEvent(e));
135
- }
136
- if (this.settings.eventModeClose) {
137
- this.$element.addEventListener(this.settings.eventModeClose, e => this.closeEvent(e));
138
- }
178
+ if (this.settings.eventMode === 'mouseover') {
179
+ this.$element.addEventListener('mouseenter', e => this.openEvent(e));
180
+ this.$element.addEventListener('mouseleave',e => this.triggerLeaveEvent(e));
181
+ this.settings.$menuContainer?.addEventListener('mouseleave', e => this.containerLeaveEvent(e));
182
+ document.addEventListener('touchstart', e => this.touchStartEvent(e), { passive: true });
139
183
  } else {
140
- this.$element.addEventListener(this.settings.eventMode, e => this.toggleEvent(e));
184
+ this.$element.addEventListener('click', e => this.toggleEvent(e));
141
185
  }
142
186
 
143
187
  this.$element.addEventListener('keydown', e => this.keyboardEvent(e));
144
-
145
188
  this.settings.$menu.querySelectorAll('a,button,input,textarea,select')
146
189
  .forEach(el => el.addEventListener('keydown', e => this.keyboardEvent(e)));
147
-
148
190
  document.addEventListener('madj2k-flyoutmenu-close', e => this.closeEvent(e));
149
191
  document.addEventListener('madj2k-flyoutmenu-resize', e => this.resizeAndPositionMenuEvent(e));
150
192
  }
151
193
 
194
+
195
+ /**
196
+ * Removes all event listeners (including dynamic hover/touch)
197
+ */
198
+ destroyEvents() {
199
+ if (this.settings.$closeBtn) {
200
+ const closeEvent = this.settings.eventMode === 'mouseover' ? 'mouseenter' : 'click';
201
+ this.settings.$closeBtn.removeEventListener(closeEvent, e => this.closeEvent(e));
202
+ this.settings.$closeBtn.removeEventListener('keydown', e => this.keyboardEvent(e));
203
+ }
204
+
205
+ if (this.settings.eventMode === 'mouseover') {
206
+ this.$element.removeEventListener('mouseenter', e => this.openEvent(e));
207
+ this.settings.$menuContainer?.removeEventListener('mouseleave', e => this.containerLeaveEvent(e));
208
+ document.removeEventListener('touchstart', e => this.touchStartEvent(e), { passive: true });
209
+ } else {
210
+ this.$element.removeEventListener('click', e => this.toggleEvent(e));
211
+ }
212
+
213
+ this.$element.removeEventListener('keydown', e => this.keyboardEvent(e));
214
+ this.settings.$menu.querySelectorAll('a,button,input,textarea,select')
215
+ .forEach(el => el.removeEventListener('keydown', e => this.keyboardEvent(e)));
216
+ document.removeEventListener('madj2k-flyoutmenu-close', e => this.closeEvent(e));
217
+ document.removeEventListener('madj2k-flyoutmenu-resize', e => this.resizeAndPositionMenuEvent(e));
218
+ }
219
+
220
+
152
221
  /**
153
222
  * Initializes ResizeObserver to auto-resize menu
154
223
  */
@@ -172,37 +241,6 @@ class Madj2kFlyoutMenu {
172
241
  }
173
242
  }
174
243
 
175
- /**
176
- * Unbinds all event listeners
177
- */
178
- destroyEvents() {
179
- if (this.settings.$closeBtn) {
180
- if (this.settings.eventModeClose) {
181
- this.settings.$closeBtn.removeEventListener(this.settings.eventModeClose, e => this.closeEvent(e));
182
- } else {
183
- this.settings.$closeBtn.removeEventListener(this.settings.eventMode, e => this.closeEvent(e));
184
- }
185
- this.settings.$closeBtn.removeEventListener('keydown', e => this.keyboardEvent(e));
186
- }
187
-
188
- if (this.settings.eventModeOpen || this.settings.eventModeClose) {
189
- if (this.settings.eventModeOpen) {
190
- this.$element.removeEventListener(this.settings.eventModeOpen, e => this.openEvent(e));
191
- }
192
- if (this.settings.eventModeClose) {
193
- this.$element.removeEventListener(this.settings.eventModeClose, e => this.closeEvent(e));
194
- }
195
- } else {
196
- this.$element.removeEventListener(this.settings.eventMode, e => this.toggleEvent(e));
197
- }
198
- this.$element.removeEventListener('keydown', e => this.keyboardEvent(e));
199
-
200
- this.settings.$menu.querySelectorAll('a,button,input,textarea,select')
201
- .forEach(el => el.removeEventListener('keydown', e => this.keyboardEvent(e)));
202
-
203
- document.removeEventListener('madj2k-flyoutmenu-close', e => this.closeEvent(e));
204
- document.removeEventListener('madj2k-flyoutmenu-resize', e => this.resizeAndPositionMenuEvent(e));
205
- }
206
244
 
207
245
  /**
208
246
  * Destroys ResizeObserver
@@ -412,6 +450,10 @@ class Madj2kFlyoutMenu {
412
450
  newHeight = `${innerHeight}px`;
413
451
  }
414
452
 
453
+ if (this.settings.scrollMode === 'inner') {
454
+ this.settings.$menuInner.style.height = newHeight;
455
+ }
456
+
415
457
  // set max-height again so that longer flyouts do not lead to scrolling on smaller ones
416
458
  this.settings.$menu.classList.remove(this.settings.heightCalculationClass);
417
459
  this.settings.$menu.style.height = newHeight;
@@ -436,6 +478,7 @@ class Madj2kFlyoutMenu {
436
478
 
437
479
  if (!this.settings.$paddingReference) return;
438
480
  if (this.settings.paddingBehavior === 0) return;
481
+
439
482
  // should be re-evaluated on a resize event after re-opening the menu
440
483
  // if (this.settings.paddingBehavior === 1 && this.settings.$menuInner.hasAttribute('data-padding-set')) return;
441
484
 
@@ -472,8 +515,7 @@ class Madj2kFlyoutMenu {
472
515
  */
473
516
  toggleNoScroll() {
474
517
 
475
- // heightMode "full" with deprecated fullHeight-setting as fallback
476
- if (this.settings.heightMode === 'full' || this.settings.fullHeight === true) {
518
+ if (this.settings.scrollHelper) {
477
519
  const body = document.body;
478
520
  const helper = body.querySelector('.no-scroll-helper');
479
521
  const inner = body.querySelector('.no-scroll-helper-inner');
@@ -55,4 +55,10 @@ html, body {
55
55
  background-color: #fff;
56
56
  overflow: hidden;
57
57
  }
58
+
59
+ &-inner.scroll-mode-inner {
60
+ overflow-y: auto;
61
+ overflow-x: hidden;
62
+ }
58
63
  }
64
+
@@ -0,0 +1,146 @@
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of the TYPO3 CMS project.
5
+ *
6
+ * It is free software; you can redistribute it and/or modify it under
7
+ * the terms of the GNU General Public License, either version 2
8
+ * of the License, or any later version.
9
+ *
10
+ * For the full copyright and license information, please read the
11
+ * LICENSE.txt file that was distributed with this source code.
12
+ *
13
+ * The TYPO3 project - inspiring people to share!
14
+ */
15
+
16
+ use TYPO3\CMS\Core\Utility\GeneralUtility;
17
+ use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
18
+ use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
19
+ use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
20
+
21
+ /**
22
+ * Class JsonMenuViewHelper
23
+ *
24
+ * @author Steffen Kroggel <developer@steffenkroggel.de>
25
+ * @copyright Steffen Kroggel <developer@steffenkroggel.de>
26
+ * @package Madj2k_SiteDefault
27
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
28
+ */
29
+ class JsonMenuViewHelper extends AbstractViewHelper
30
+ {
31
+
32
+ /**
33
+ * Initialize arguments
34
+ *
35
+ * @return void
36
+ */
37
+ public function initializeArguments(): void
38
+ {
39
+ parent::initializeArguments();
40
+ $this->registerArgument('items', 'array', 'The recursive menu-array');
41
+ $this->registerArgument('parseFuncTSPath', 'string', 'Path to the TypoScript parseFunc setup.', false, '');
42
+ }
43
+
44
+
45
+ /**
46
+ * @param array $arguments
47
+ * @param \Closure $renderChildrenClosure
48
+ * @param \TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface $renderingContext
49
+ * @return string
50
+ */
51
+ public static function renderStatic(
52
+ array $arguments,
53
+ \Closure $renderChildrenClosure,
54
+ RenderingContextInterface $renderingContext
55
+ ): string {
56
+
57
+ /** @var array $items */
58
+ $items = $arguments['items'];
59
+
60
+ /** @var string $parseFuncTSPath */
61
+ $parseFuncTSPath = $arguments['parseFuncTSPath'];
62
+
63
+ /** @var \Psr\Http\Message\ServerRequestInterface $request */
64
+ $request = $renderingContext->getRequest();
65
+
66
+ /** @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject */
67
+ $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
68
+ $contentObject->setRequest($request);
69
+ $contentObject->start([]);
70
+
71
+ $result = [];
72
+ foreach ($items as $item) {
73
+ $result[] = self::callback($item, $contentObject, $parseFuncTSPath);
74
+ }
75
+
76
+ return json_encode($result);
77
+ }
78
+
79
+
80
+ /**
81
+ * @param array $item
82
+ * @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject
83
+ * @param string $parseFuncTSPath
84
+ * @return array
85
+ */
86
+ public static function callback (
87
+ array $item,
88
+ ContentObjectRenderer $contentObject,
89
+ string $parseFuncTSPath = ''
90
+ ): array {
91
+
92
+ /*
93
+ Build a reduced structure:
94
+ "data": {"uid": 2, "pid": 1, "title": "Lorem Ipsum"},
95
+ "title": "Lorem Ipsum",
96
+ "link": "\/lorem\/Ipsum",
97
+ "target": "_blank",
98
+ "active": 1,
99
+ "current": 0,
100
+ "spacer": 0,
101
+ "hasSubpages": 1,
102
+ "children": [ ]
103
+ */
104
+
105
+ $result = $item;
106
+ $result['data'] = [
107
+ 'uid' => $item['data']['uid'],
108
+ 'pid' => $item['data']['pid'],
109
+ 'title'=> $item['data']['title'],
110
+ ];
111
+
112
+ $result['children'] = [];
113
+ if (
114
+ (isset($item['children']))
115
+ && (is_array($item['children']))
116
+ ){
117
+ foreach ($item['children'] as $child) {
118
+ $result['children'][] = self::callback($child, $contentObject, $parseFuncTSPath);
119
+ }
120
+ }
121
+
122
+ if (!isset($result['hasSubpages'])) {
123
+ $result['hasSubpages'] = $result['children'] ? 1 : 0;
124
+ }
125
+
126
+ if (isset($item['data']['doktype'])) {
127
+ $result['linkType'] = $item['data']['doktype'];
128
+ }
129
+
130
+ // Parse title with HTML-parser
131
+ if ($parseFuncTSPath) {
132
+ $result['title'] = $contentObject->parseFunc($result['title'], null, '< ' . $parseFuncTSPath);
133
+ }
134
+
135
+ // do not link sites, that only link to the next subpage!
136
+ $result['isLinked'] = 1;
137
+ if (
138
+ ($item['data']['doktype'] == 4)
139
+ && (in_array($item['data']['shortcut_mode'], [1,3]))
140
+ ){
141
+ $result['isLinked'] = 0;
142
+ }
143
+
144
+ return $result;
145
+ }
146
+ }
@@ -0,0 +1,165 @@
1
+ <html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
2
+ xmlns:siteDefault="http://typo3.org/ns/Madj2k/SiteDefault/ViewHelpers"
3
+ data-namespace-typo3-fluid="true"
4
+ >
5
+
6
+ <f:if condition="{menuItems}">
7
+ <f:then>
8
+ <f:comment>
9
+ <!--
10
+ Templates for mobile menu. We don't want this to be loaded on default because
11
+ it would duplicate the menu for search engines and would enlarge the body to parse
12
+ -->
13
+ </f:comment>
14
+ <template class="js-slide-nav-tmpl" data-type="menuWrap">
15
+ <div class="slide-nav-container js-slide-nav-container">
16
+ <div class="slide-nav-card js-slide-nav-card %levelClass%" id="slide-card-%uid%">
17
+ <div class="slide-nav-inner pd-3">
18
+ <ul class="slide-nav-list" role="none">
19
+ <li class="slide-nav-headline %levelClass%" role="none">
20
+ <a href="/"
21
+ title="{f:translate(key:'menu.home', extensionName:'siteDefault')}"
22
+ role="menuitem"
23
+ class="slide-nav-headline-link level-1">
24
+ <span>{f:translate(key:'menu.home', extensionName:'siteDefault')}</span>
25
+ </a>
26
+ </li>
27
+
28
+ <li class="slide-nav-wrap">
29
+ <ul class="slide-nav-list toggle-list" role="none">
30
+ %menuItems%
31
+ </ul>
32
+ </li>
33
+
34
+ <f:if condition="{topMenuItems}">
35
+ <li class="slide-nav-item-footer" role="none">
36
+ <ul class="slide-nav-meta-list" role="none">
37
+ <f:for each="{topMenuItems}" as="menuItem" iteration="iterator">
38
+ <li class="slide-nav-meta-item level1{f:if(condition:'{menuItem.active}', then:' active')}" role="none">
39
+ <a class="slide-nav-meta-link level1{f:if(condition:'{menuItem.active}', then:' active')}"
40
+ href="{menuItem.link}"
41
+ target="{menuItem.target}"
42
+ title="{menuItem.data.title}"
43
+ role="menuitem"
44
+ >
45
+ <span><f:format.html parseFuncTSPath="lib.parseFunc_Inline">{menuItem.title}</f:format.html></span>
46
+ </a>
47
+ </li>
48
+ </f:for>
49
+ </ul>
50
+ </li>
51
+ </f:if>
52
+
53
+ <f:if condition="{footerMenuItems}">
54
+ <li class="slide-nav-item-footer" role="none">
55
+ <ul class="slide-nav-meta-list" role="none">
56
+ <f:for each="{footerMenuItems}" as="menuItem" iteration="iterator">
57
+ <li class="slide-nav-meta-item level1{f:if(condition:'{menuItem.active}', then:' active')}" role="none">
58
+ <a class="slide-nav-meta-link level1{f:if(condition:'{menuItem.active}', then:' active')}"
59
+ href="{menuItem.link}"
60
+ target="{menuItem.target}"
61
+ title="{menuItem.data.title}"
62
+ role="menuitem"
63
+ >
64
+ <span><f:format.html parseFuncTSPath="lib.parseFunc_Inline">{menuItem.title}</f:format.html></span>
65
+ </a>
66
+ </li>
67
+ </f:for>
68
+ </ul>
69
+ </li>
70
+ </f:if>
71
+ </ul>
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </template>
76
+
77
+ <template class="js-slide-nav-tmpl" data-type="menuItem">
78
+ <li class="slide-nav-item toggle-list-item js-slide-nav-item %activeClass% %hasChildrenClass%" role="none">
79
+ <f:comment><!-- normal link that opens the menu-item --></f:comment>
80
+
81
+ %ifHasNoChildrenStart%
82
+ <a href="%link%"
83
+ title="%titleRaw%"
84
+ role="menuitem"
85
+ class="slide-nav-link toggle-list-link %activeClass% %hasChildrenClass%"
86
+ target="%target%"
87
+ aria-current="%ariaCurrent%">
88
+ <span class="toggle-list-text">%title%</span>
89
+ </a>
90
+ %ifHasNoChildrenEnd%
91
+
92
+ <f:comment><!-- link that opens next card --></f:comment>
93
+ %ifHasChildrenStart%
94
+ <a class="slide-nav-link slide-nav-next toggle-list-link js-slide-nav-next %activeClass% %hasChildrenClass%"
95
+ href="#"
96
+ role="button"
97
+ title="{f:translate(key:'menu.openSubmenu', extensionName:'siteDefault')}"
98
+ aria-label="{f:translate(key:'menu.openSubmenu', extensionName:'siteDefault')}"
99
+ aria-haspopup="true"
100
+ aria-expanded="%ariaExpanded%"
101
+ aria-controls="slide-card-%uid%">
102
+ <span class="toggle-list-text">%title%</span><span class="icon-arrow-right icon"></span>
103
+ </a>
104
+ %ifHasChildrenEnd%
105
+
106
+ %submenu%
107
+ </li>
108
+ </template>
109
+
110
+ <template class="js-slide-nav-tmpl" data-type="subMenuWrap">
111
+ <div class="slide-nav-card js-slide-nav-card %activeClass% %levelClass%" id="slide-card-%uid%">
112
+ <div class="slide-nav-inner pd-3">
113
+ <ul class="slide-nav-list">
114
+ <li class="slide-nav-item-back" role="none">
115
+ <button class="slide-nav-back js-slide-nav-back"
116
+ title="{f:translate(key:'menu.levelUp', extensionName:'siteDefault')}"
117
+ aria-haspopup="true"
118
+ aria-label="{f:translate(key:'menu.levelUp', extensionName:'siteDefault')}"
119
+ aria-controls="slide-card-%uid%"
120
+ data-parent-card="slide-card-%parentUid%"><span class="icon-arrow-left icon"></span><span
121
+ class="slide-nav-back-label">{f:translate(key:'menu.back', extensionName:'siteDefault')}</span>
122
+ </button>
123
+ </li>
124
+ <li class="slide-nav-headline %levelClass%" role="none">
125
+
126
+ <f:comment><!-- normal parent --></f:comment>
127
+ %ifIsNotLinkedStart%
128
+ <span class="slide-nav-headline-text %currentClass% %isLinkedClass%">%title%</span>
129
+ %ifIsNotLinkedEnd%
130
+
131
+ <f:comment><!-- linked parent --></f:comment>
132
+ %ifIsLinkedStart%
133
+ <a href="%link%"
134
+ title="%titleRaw%"
135
+ role="menuitem"
136
+ class="slide-nav-headline-link %currentClass% %hasChildrenClass% %isLinkedClass%"
137
+ target="%target%"
138
+ aria-current="%ariaCurrent%">
139
+ <span>%title%</span>
140
+ </a>
141
+ %ifIsLinkedEnd%
142
+ </li>
143
+
144
+ <li class="slide-nav-wrap">
145
+ <ul class="slide-nav-list toggle-list" role="none">
146
+ %menuItems%
147
+ </ul>
148
+ </li>
149
+
150
+ </ul>
151
+ </div>
152
+ </div>
153
+ </template>
154
+
155
+ <script>
156
+ let slideNavItems = <f:format.raw><siteDefault:jsonMenu items="{menuItems}" parseFuncTSPath="lib.parseFunc_Inline" /></f:format.raw>;
157
+ </script>
158
+ </f:then>
159
+ <f:else>
160
+ <script>
161
+ let slideNavItems = {};
162
+ </script>
163
+ </f:else>
164
+ </f:if>
165
+ </html>
@@ -0,0 +1,2 @@
1
+ import Madj2kSlideMenu from './slide-menu-2.0.js';
2
+ export { Madj2kSlideMenu };
@@ -0,0 +1 @@
1
+ @forward './slide-menu-2.0';