@brandocms/jupiter 3.55.0 → 4.0.0-beta.2
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/README.md +509 -54
- package/package.json +30 -18
- package/src/index.js +15 -10
- package/src/modules/Application/index.js +236 -158
- package/src/modules/Breakpoints/index.js +116 -36
- package/src/modules/Cookies/index.js +95 -64
- package/src/modules/CoverOverlay/index.js +21 -14
- package/src/modules/Dataloader/index.js +71 -24
- package/src/modules/Dataloader/url-sync.js +238 -0
- package/src/modules/Dom/index.js +24 -0
- package/src/modules/DoubleHeader/index.js +571 -0
- package/src/modules/Dropdown/index.js +108 -73
- package/src/modules/EqualHeightElements/index.js +8 -8
- package/src/modules/EqualHeightImages/index.js +15 -7
- package/src/modules/FixedHeader/index.js +116 -30
- package/src/modules/FooterReveal/index.js +5 -5
- package/src/modules/HeroSlider/index.js +231 -106
- package/src/modules/HeroVideo/index.js +72 -44
- package/src/modules/Lazyload/index.js +128 -80
- package/src/modules/Lightbox/index.js +101 -80
- package/src/modules/Links/index.js +77 -51
- package/src/modules/Looper/index.js +1737 -0
- package/src/modules/Marquee/index.js +106 -37
- package/src/modules/MobileMenu/index.js +105 -130
- package/src/modules/Moonwalk/index.js +479 -153
- package/src/modules/Parallax/index.js +280 -57
- package/src/modules/Popover/index.js +187 -17
- package/src/modules/Popup/index.js +172 -53
- package/src/modules/ScrollSpy/index.js +21 -0
- package/src/modules/StackedBoxes/index.js +8 -6
- package/src/modules/StickyHeader/index.js +394 -164
- package/src/modules/Toggler/index.js +207 -11
- package/src/modules/Typography/index.js +33 -20
- package/src/utils/motion-helpers.js +330 -0
- package/types/README.md +159 -0
- package/types/events/index.d.ts +20 -0
- package/types/index.d.ts +6 -0
- package/types/modules/Application/index.d.ts +168 -0
- package/types/modules/Breakpoints/index.d.ts +40 -0
- package/types/modules/Cookies/index.d.ts +81 -0
- package/types/modules/CoverOverlay/index.d.ts +6 -0
- package/types/modules/Dataloader/index.d.ts +38 -0
- package/types/modules/Dataloader/url-sync.d.ts +36 -0
- package/types/modules/Dom/index.d.ts +47 -0
- package/types/modules/DoubleHeader/index.d.ts +63 -0
- package/types/modules/Dropdown/index.d.ts +15 -0
- package/types/modules/EqualHeightElements/index.d.ts +8 -0
- package/types/modules/EqualHeightImages/index.d.ts +11 -0
- package/types/modules/FeatureTests/index.d.ts +27 -0
- package/types/modules/FixedHeader/index.d.ts +219 -0
- package/types/modules/Fontloader/index.d.ts +5 -0
- package/types/modules/FooterReveal/index.d.ts +5 -0
- package/types/modules/HeroSlider/index.d.ts +28 -0
- package/types/modules/HeroVideo/index.d.ts +83 -0
- package/types/modules/Lazyload/index.d.ts +80 -0
- package/types/modules/Lightbox/index.d.ts +123 -0
- package/types/modules/Links/index.d.ts +55 -0
- package/types/modules/Looper/index.d.ts +127 -0
- package/types/modules/Marquee/index.d.ts +23 -0
- package/types/modules/MobileMenu/index.d.ts +63 -0
- package/types/modules/Moonwalk/index.d.ts +322 -0
- package/types/modules/Parallax/index.d.ts +71 -0
- package/types/modules/Popover/index.d.ts +29 -0
- package/types/modules/Popup/index.d.ts +76 -0
- package/types/modules/ScrollSpy/index.d.ts +29 -0
- package/types/modules/StackedBoxes/index.d.ts +9 -0
- package/types/modules/StickyHeader/index.d.ts +220 -0
- package/types/modules/Toggler/index.d.ts +48 -0
- package/types/modules/Typography/index.d.ts +77 -0
- package/types/utils/dispatchElementEvent.d.ts +1 -0
- package/types/utils/imageIsLoaded.d.ts +1 -0
- package/types/utils/imagesAreLoaded.d.ts +1 -0
- package/types/utils/loadScript.d.ts +2 -0
- package/types/utils/prefersReducedMotion.d.ts +4 -0
- package/types/utils/rafCallback.d.ts +2 -0
- package/types/utils/zoom.d.ts +4 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { animate } from 'motion'
|
|
2
2
|
import _defaultsDeep from 'lodash.defaultsdeep'
|
|
3
3
|
import Dom from '../Dom'
|
|
4
|
+
import { set, clearProps } from '../../utils/motion-helpers'
|
|
4
5
|
|
|
5
6
|
const DEFAULT_OPTIONS = {
|
|
6
7
|
speed: 100,
|
|
@@ -11,7 +12,7 @@ const DEFAULT_OPTIONS = {
|
|
|
11
12
|
spacer: '<span> — </span>',
|
|
12
13
|
|
|
13
14
|
onReveal: marqueeEl => {
|
|
14
|
-
|
|
15
|
+
animate(marqueeEl, { opacity: 1 }, { ease: 'linear' })
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -31,7 +32,7 @@ export default class Marquee {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
initialize() {
|
|
34
|
-
|
|
35
|
+
set(this.elements.$marquee, { opacity: 0 })
|
|
35
36
|
window.addEventListener('APPLICATION:RESIZE', this.updateMarquee.bind(this))
|
|
36
37
|
window.addEventListener('APPLICATION:REVEALED', this.revealMarquee.bind(this))
|
|
37
38
|
this.updateMarquee()
|
|
@@ -57,15 +58,19 @@ export default class Marquee {
|
|
|
57
58
|
|
|
58
59
|
this.killTweens()
|
|
59
60
|
this.clearHolders()
|
|
60
|
-
this.setHeight()
|
|
61
61
|
this.fillText()
|
|
62
|
+
this.setHeight()
|
|
62
63
|
|
|
63
64
|
const holderWidth = this.elements.$holder.offsetWidth
|
|
64
65
|
const $allHolders = Dom.all(this.elements.$el, '[data-marquee-holder]')
|
|
65
66
|
const marqueeWidth = holderWidth * $allHolders.length
|
|
66
|
-
|
|
67
|
+
// Cap duration at 40s to prevent precision issues at slow speeds
|
|
68
|
+
this.duration = Math.min(
|
|
69
|
+
(holderWidth + marqueeWidth) / this.opts.speed,
|
|
70
|
+
40
|
|
71
|
+
)
|
|
67
72
|
|
|
68
|
-
|
|
73
|
+
set(this.elements.$marquee, { width: marqueeWidth })
|
|
69
74
|
this.initializeTween()
|
|
70
75
|
|
|
71
76
|
if (Dom.inViewport(this.elements.$el)) {
|
|
@@ -75,29 +80,43 @@ export default class Marquee {
|
|
|
75
80
|
|
|
76
81
|
clearHolders() {
|
|
77
82
|
const $allHolders = Dom.all(this.elements.$el, '[data-marquee-holder]')
|
|
78
|
-
Array.from($allHolders).forEach(h =>
|
|
83
|
+
Array.from($allHolders).forEach(h => clearProps(h, 'all'))
|
|
79
84
|
}
|
|
80
85
|
|
|
81
86
|
killTweens() {
|
|
82
87
|
if (this.timeline) {
|
|
83
|
-
this.timeline.
|
|
88
|
+
this.timeline.stop()
|
|
84
89
|
this.timeline = null
|
|
85
90
|
}
|
|
91
|
+
if (this.speedAnimation) {
|
|
92
|
+
this.speedAnimation.stop()
|
|
93
|
+
this.speedAnimation = null
|
|
94
|
+
}
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
initializeTween() {
|
|
89
98
|
const $allHolders = Dom.all(this.elements.$el, '[data-marquee-holder]')
|
|
90
99
|
|
|
91
100
|
Array.from($allHolders).forEach((h, idx) => {
|
|
92
|
-
|
|
101
|
+
set(h, {
|
|
102
|
+
position: 'absolute',
|
|
103
|
+
left: h.offsetWidth * idx,
|
|
104
|
+
transform: 'translateZ(0)',
|
|
105
|
+
willChange: 'transform'
|
|
106
|
+
})
|
|
93
107
|
})
|
|
94
108
|
|
|
95
|
-
this.timeline =
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
.repeat
|
|
109
|
+
this.timeline = animate(
|
|
110
|
+
$allHolders,
|
|
111
|
+
{ transform: ['translateX(0) translateZ(0)', 'translateX(-100%) translateZ(0)'] },
|
|
112
|
+
{ duration: this.duration, ease: 'linear', repeat: Infinity }
|
|
113
|
+
)
|
|
114
|
+
this.timeline.pause()
|
|
99
115
|
|
|
100
|
-
|
|
116
|
+
// Set initial progress if specified
|
|
117
|
+
if (this.opts.startProgress > 0) {
|
|
118
|
+
this.timeline.currentTime = this.opts.startProgress * this.duration
|
|
119
|
+
}
|
|
101
120
|
|
|
102
121
|
window.timeline = this.timeline
|
|
103
122
|
window.marquee = this
|
|
@@ -105,45 +124,85 @@ export default class Marquee {
|
|
|
105
124
|
|
|
106
125
|
play(rampUp = false) {
|
|
107
126
|
this.playing = true
|
|
108
|
-
|
|
127
|
+
if (this.speedAnimation) {
|
|
128
|
+
this.speedAnimation.stop()
|
|
129
|
+
}
|
|
109
130
|
|
|
110
131
|
if (rampUp) {
|
|
111
132
|
this.timeline.play()
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
133
|
+
const state = { speed: this.timeline.speed || 0 }
|
|
134
|
+
this.speedAnimation = animate(
|
|
135
|
+
state,
|
|
136
|
+
{ speed: 1 },
|
|
137
|
+
{
|
|
138
|
+
duration: 0.8,
|
|
139
|
+
ease: 'easeIn',
|
|
140
|
+
onUpdate: () => {
|
|
141
|
+
this.timeline.speed = state.speed
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
)
|
|
117
145
|
} else {
|
|
118
|
-
this.timeline.
|
|
146
|
+
this.timeline.speed = 1
|
|
119
147
|
this.timeline.play()
|
|
120
148
|
}
|
|
121
149
|
}
|
|
122
150
|
|
|
123
151
|
pause() {
|
|
124
152
|
this.playing = false
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
153
|
+
const state = { speed: this.timeline.speed || 1 }
|
|
154
|
+
this.speedAnimation = animate(
|
|
155
|
+
state,
|
|
156
|
+
{ speed: 0.01 },
|
|
157
|
+
{
|
|
158
|
+
duration: 0.8,
|
|
159
|
+
onUpdate: () => {
|
|
160
|
+
this.timeline.speed = state.speed
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
this.speedAnimation.finished.then(() => {
|
|
165
|
+
// Only pause if we're still in paused state (haven't called play() in the meantime)
|
|
166
|
+
if (!this.playing) {
|
|
128
167
|
this.timeline.pause()
|
|
129
|
-
}
|
|
130
|
-
duration: 0.8
|
|
168
|
+
}
|
|
131
169
|
})
|
|
132
170
|
}
|
|
133
171
|
|
|
134
172
|
slowDown() {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
173
|
+
if (this.speedAnimation) {
|
|
174
|
+
this.speedAnimation.stop()
|
|
175
|
+
}
|
|
176
|
+
const state = { speed: this.timeline.speed || 1 }
|
|
177
|
+
this.speedAnimation = animate(
|
|
178
|
+
state,
|
|
179
|
+
{ speed: 0.5 },
|
|
180
|
+
{
|
|
181
|
+
duration: 0.3,
|
|
182
|
+
ease: [0.4, 0, 0.2, 1], // ease-out
|
|
183
|
+
onUpdate: () => {
|
|
184
|
+
this.timeline.speed = state.speed
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
)
|
|
139
188
|
}
|
|
140
189
|
|
|
141
190
|
speedUp() {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
191
|
+
if (this.speedAnimation) {
|
|
192
|
+
this.speedAnimation.stop()
|
|
193
|
+
}
|
|
194
|
+
const state = { speed: this.timeline.speed || 0.5 }
|
|
195
|
+
this.speedAnimation = animate(
|
|
196
|
+
state,
|
|
197
|
+
{ speed: 1 },
|
|
198
|
+
{
|
|
199
|
+
duration: 0.3,
|
|
200
|
+
ease: [0.4, 0, 0.2, 1], // ease-out
|
|
201
|
+
onUpdate: () => {
|
|
202
|
+
this.timeline.speed = state.speed
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
)
|
|
147
206
|
}
|
|
148
207
|
|
|
149
208
|
setupObserver() {
|
|
@@ -169,12 +228,19 @@ export default class Marquee {
|
|
|
169
228
|
}
|
|
170
229
|
|
|
171
230
|
fillText() {
|
|
231
|
+
// Clear any previously set heights to get accurate measurement
|
|
232
|
+
clearProps(this.elements.$el, 'height')
|
|
233
|
+
clearProps(this.elements.$marquee, 'height')
|
|
234
|
+
|
|
172
235
|
this.elements.$marquee.innerHTML = ''
|
|
173
236
|
this.elements.$marquee.appendChild(this.elements.$holder)
|
|
174
237
|
|
|
175
238
|
this.elements.$holder.innerHTML = ''
|
|
176
239
|
this.elements.$holder.appendChild(this.elements.$item)
|
|
177
240
|
|
|
241
|
+
// Measure height of item only (marquee padding will be added by CSS)
|
|
242
|
+
this.measuredHeight = this.elements.$item.offsetHeight
|
|
243
|
+
|
|
178
244
|
const textWidth = this.elements.$item.offsetWidth
|
|
179
245
|
if (textWidth) {
|
|
180
246
|
if (this.opts.spacer) {
|
|
@@ -199,7 +265,10 @@ export default class Marquee {
|
|
|
199
265
|
}
|
|
200
266
|
|
|
201
267
|
setHeight() {
|
|
202
|
-
|
|
203
|
-
|
|
268
|
+
// Use the height measured in fillText() (before cloning) plus any extra height
|
|
269
|
+
const height = this.measuredHeight + this.opts.extraHeight
|
|
270
|
+
// Set height on both container and marquee to preserve it when holders become absolute
|
|
271
|
+
set(this.elements.$el, { height })
|
|
272
|
+
set(this.elements.$marquee, { height })
|
|
204
273
|
}
|
|
205
274
|
}
|
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { animate, stagger } from 'motion'
|
|
2
2
|
import _defaultsDeep from 'lodash.defaultsdeep'
|
|
3
3
|
import * as Events from '../../events'
|
|
4
|
+
import { set, clearProps } from '../../utils/motion-helpers'
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} MobileMenuOptions
|
|
8
|
+
* @property {string} [logoColor='#000'] - Color for logo when menu is open
|
|
9
|
+
* @property {string} [logoPathSelector='svg path'] - Selector for logo SVG paths
|
|
10
|
+
* @property {string} [contentSelector='section'] - Selector for menu content
|
|
11
|
+
* @property {string} [liSelector='li'] - Selector for menu items
|
|
12
|
+
* @property {string} [hamburgerColor='#000'] - Color for hamburger icon
|
|
13
|
+
* @property {Function|null} [onResize=null] - Called when window is resized
|
|
14
|
+
* @property {Function} [openTween] - Animation for opening menu
|
|
15
|
+
* @property {Function} [closeTween] - Animation for closing menu
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** @type {MobileMenuOptions} */
|
|
5
19
|
const DEFAULT_OPTIONS = {
|
|
6
20
|
logoColor: '#000',
|
|
7
21
|
logoPathSelector: 'svg path',
|
|
@@ -10,140 +24,93 @@ const DEFAULT_OPTIONS = {
|
|
|
10
24
|
hamburgerColor: '#000',
|
|
11
25
|
|
|
12
26
|
onResize: null,
|
|
13
|
-
openTween: m => {
|
|
14
|
-
const timeline = gsap.timeline()
|
|
15
|
-
|
|
27
|
+
openTween: async (m) => {
|
|
16
28
|
m.hamburger.classList.toggle('is-active')
|
|
17
29
|
document.body.classList.toggle('open-menu')
|
|
18
30
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
})
|
|
55
|
-
.set(m.nav, { height: window.innerHeight })
|
|
56
|
-
.set(m.content, { display: 'block' })
|
|
57
|
-
.set(m.logoPath, { fill: m.opts.logoColor })
|
|
58
|
-
.set(m.logo, { xPercent: 3 })
|
|
59
|
-
.staggerFromTo(
|
|
60
|
-
m.lis,
|
|
61
|
-
{
|
|
62
|
-
duration: 1,
|
|
63
|
-
opacity: 0,
|
|
64
|
-
x: 20
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
duration: 1,
|
|
68
|
-
x: 0,
|
|
69
|
-
opacity: 1,
|
|
70
|
-
ease: 'power3.out'
|
|
71
|
-
},
|
|
72
|
-
0.05
|
|
73
|
-
)
|
|
74
|
-
.to(
|
|
75
|
-
m.logo,
|
|
76
|
-
{
|
|
77
|
-
duration: 0.55,
|
|
78
|
-
opacity: 1,
|
|
79
|
-
xPercent: 0,
|
|
80
|
-
ease: 'power3.inOut'
|
|
81
|
-
},
|
|
82
|
-
'-=1.2'
|
|
83
|
-
)
|
|
84
|
-
.call(m._emitMobileMenuOpenEvent)
|
|
31
|
+
// Set initial state for bg
|
|
32
|
+
set(m.bg, { x: '0%', opacity: 0, height: window.innerHeight })
|
|
33
|
+
|
|
34
|
+
// Parallel animations at start (0-0.35s)
|
|
35
|
+
const timeline = [
|
|
36
|
+
[m.bg, { opacity: 1 }, { duration: 0.35, ease: 'easeIn', at: 0 }],
|
|
37
|
+
[m.logo, { opacity: 0 }, { duration: 0.35, ease: 'easeOut', at: 0 }],
|
|
38
|
+
[m.header, { backgroundColor: 'transparent' }, { duration: 0.55, ease: 'easeOut', at: 0 }]
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
await animate(timeline).finished
|
|
42
|
+
|
|
43
|
+
// Immediate settings
|
|
44
|
+
m.nav.style.gridTemplateRows = 'auto 1fr'
|
|
45
|
+
set(m.nav, { height: window.innerHeight })
|
|
46
|
+
Array.from(m.content).forEach(el => set(el, { display: 'block' }))
|
|
47
|
+
Array.from(m.logoPath).forEach(path => path.setAttribute('fill', m.opts.logoColor))
|
|
48
|
+
set(m.logo, { x: '3%' })
|
|
49
|
+
|
|
50
|
+
// Staggered li animations and logo animation in parallel
|
|
51
|
+
const lisAnimation = animate(
|
|
52
|
+
m.lis,
|
|
53
|
+
{ opacity: [0, 1], x: [20, 0] },
|
|
54
|
+
{ duration: 1, ease: 'easeOut', delay: stagger(0.05) }
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
const logoAnimation = animate(
|
|
58
|
+
m.logo,
|
|
59
|
+
{ opacity: 1, x: ['3%', '0%'] },
|
|
60
|
+
{ duration: 0.55, ease: 'easeInOut', at: 0.15 }
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
await Promise.all([lisAnimation.finished, logoAnimation.finished])
|
|
64
|
+
|
|
65
|
+
m._emitMobileMenuOpenEvent()
|
|
85
66
|
},
|
|
86
67
|
|
|
87
|
-
closeTween: m => {
|
|
68
|
+
closeTween: async (m) => {
|
|
88
69
|
document.body.classList.toggle('open-menu')
|
|
89
|
-
|
|
70
|
+
m.hamburger.classList.toggle('is-active')
|
|
90
71
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
m.bg,
|
|
123
|
-
{
|
|
124
|
-
duration: 0.25,
|
|
125
|
-
x: '100%',
|
|
126
|
-
ease: 'sine.in'
|
|
127
|
-
},
|
|
128
|
-
'-=0.3'
|
|
129
|
-
)
|
|
130
|
-
.call(() => {
|
|
131
|
-
m._emitMobileMenuClosedEvent()
|
|
132
|
-
})
|
|
133
|
-
.set(m.content, { display: 'none' })
|
|
134
|
-
.call(() => {
|
|
135
|
-
m.nav.style.gridTemplateRows = 'auto'
|
|
136
|
-
})
|
|
137
|
-
.set(m.lis, { clearProps: 'opacity' })
|
|
138
|
-
.to(m.logo, {
|
|
139
|
-
duration: 0.35,
|
|
140
|
-
opacity: 1,
|
|
141
|
-
ease: 'power3.in'
|
|
142
|
-
})
|
|
143
|
-
}
|
|
72
|
+
// Fade out logo
|
|
73
|
+
await animate(m.logo, { opacity: 0, x: '5%' }, { duration: 0.2, ease: 'easeOut' }).finished
|
|
74
|
+
|
|
75
|
+
// Clear logo fill
|
|
76
|
+
Array.from(m.logoPath).forEach(path => path.removeAttribute('fill'))
|
|
77
|
+
|
|
78
|
+
// Stagger out lis and slide bg in parallel
|
|
79
|
+
const lisAnimation = animate(
|
|
80
|
+
m.lis,
|
|
81
|
+
{ opacity: 0, x: 20 },
|
|
82
|
+
{ duration: 0.5, ease: 'easeOut', delay: stagger(0.04) }
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
// bg animation starts 0.3s before lis finish
|
|
86
|
+
// lis duration is 0.5s + last stagger delay, so starts around 0.2s
|
|
87
|
+
setTimeout(() => {
|
|
88
|
+
animate(m.bg, { x: '100%' }, { duration: 0.25, ease: 'easeIn' })
|
|
89
|
+
}, 200)
|
|
90
|
+
|
|
91
|
+
await lisAnimation.finished
|
|
92
|
+
|
|
93
|
+
// Cleanup
|
|
94
|
+
clearProps(m.nav, 'height')
|
|
95
|
+
m._emitMobileMenuClosedEvent()
|
|
96
|
+
Array.from(m.content).forEach(el => set(el, { display: 'none' }))
|
|
97
|
+
m.nav.style.gridTemplateRows = 'auto'
|
|
98
|
+
Array.from(m.lis).forEach(li => clearProps(li, 'opacity'))
|
|
99
|
+
|
|
100
|
+
// Fade logo back in
|
|
101
|
+
await animate(m.logo, { opacity: 1 }, { duration: 0.35, ease: 'easeIn' }).finished
|
|
102
|
+
},
|
|
144
103
|
}
|
|
145
104
|
|
|
105
|
+
/**
|
|
106
|
+
* MobileMenu component for mobile navigation menu
|
|
107
|
+
*/
|
|
146
108
|
export default class MobileMenu {
|
|
109
|
+
/**
|
|
110
|
+
* Create a new MobileMenu instance
|
|
111
|
+
* @param {Object} app - Application instance
|
|
112
|
+
* @param {MobileMenuOptions} [opts={}] - MobileMenu options
|
|
113
|
+
*/
|
|
147
114
|
constructor(app, opts = {}) {
|
|
148
115
|
this.app = app
|
|
149
116
|
this.opts = _defaultsDeep(opts, DEFAULT_OPTIONS)
|
|
@@ -152,9 +119,13 @@ export default class MobileMenu {
|
|
|
152
119
|
this.header = document.querySelector('header')
|
|
153
120
|
this.bg = this.header.querySelector('.mobile-bg')
|
|
154
121
|
this.logo = this.header.querySelector('figure.brand')
|
|
155
|
-
this.logoPath = this.logo
|
|
122
|
+
this.logoPath = this.logo
|
|
123
|
+
? this.logo.querySelectorAll(this.opts.logoPathSelector)
|
|
124
|
+
: null
|
|
156
125
|
this.menuButton = this.header.querySelector('figure.menu-button')
|
|
157
|
-
this.hamburger = this.menuButton
|
|
126
|
+
this.hamburger = this.menuButton
|
|
127
|
+
? this.menuButton.querySelector('.hamburger')
|
|
128
|
+
: null
|
|
158
129
|
this.hamburgerInner = this.menuButton
|
|
159
130
|
? this.menuButton.querySelector('.hamburger-inner')
|
|
160
131
|
: null
|
|
@@ -163,7 +134,7 @@ export default class MobileMenu {
|
|
|
163
134
|
this.nav = this.header.querySelector('nav')
|
|
164
135
|
|
|
165
136
|
if (this.hamburger) {
|
|
166
|
-
this.hamburger.addEventListener('click', e => {
|
|
137
|
+
this.hamburger.addEventListener('click', (e) => {
|
|
167
138
|
e.preventDefault()
|
|
168
139
|
e.stopPropagation()
|
|
169
140
|
this.toggleMenu()
|
|
@@ -198,12 +169,16 @@ export default class MobileMenu {
|
|
|
198
169
|
}
|
|
199
170
|
|
|
200
171
|
_emitMobileMenuOpenEvent() {
|
|
201
|
-
const mobileMenuOpenEvent = new window.CustomEvent(
|
|
172
|
+
const mobileMenuOpenEvent = new window.CustomEvent(
|
|
173
|
+
Events.APPLICATION_MOBILE_MENU_OPEN
|
|
174
|
+
)
|
|
202
175
|
window.dispatchEvent(mobileMenuOpenEvent)
|
|
203
176
|
}
|
|
204
177
|
|
|
205
178
|
_emitMobileMenuClosedEvent() {
|
|
206
|
-
const mobileMenuClosedEvent = new window.CustomEvent(
|
|
179
|
+
const mobileMenuClosedEvent = new window.CustomEvent(
|
|
180
|
+
Events.APPLICATION_MOBILE_MENU_CLOSED
|
|
181
|
+
)
|
|
207
182
|
window.dispatchEvent(mobileMenuClosedEvent)
|
|
208
183
|
}
|
|
209
184
|
}
|