@brandocms/jupiter 4.0.0-beta.1 → 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 +191 -2
- package/package.json +20 -18
- package/src/index.js +10 -10
- package/src/modules/Application/index.js +203 -157
- package/src/modules/Cookies/index.js +34 -55
- package/src/modules/CoverOverlay/index.js +20 -13
- package/src/modules/Dataloader/index.js +71 -24
- package/src/modules/Dataloader/url-sync.js +238 -0
- package/src/modules/Dom/index.js +18 -0
- package/src/modules/DoubleHeader/index.js +571 -0
- package/src/modules/Dropdown/index.js +101 -75
- package/src/modules/EqualHeightElements/index.js +5 -7
- package/src/modules/EqualHeightImages/index.js +7 -2
- package/src/modules/FixedHeader/index.js +60 -30
- package/src/modules/FooterReveal/index.js +3 -3
- package/src/modules/HeroSlider/index.js +207 -91
- package/src/modules/HeroVideo/index.js +15 -27
- package/src/modules/Lazyload/index.js +101 -80
- package/src/modules/Lightbox/index.js +17 -55
- package/src/modules/Links/index.js +54 -49
- package/src/modules/Looper/index.js +1737 -0
- package/src/modules/Marquee/index.js +106 -37
- package/src/modules/MobileMenu/index.js +70 -124
- package/src/modules/Moonwalk/index.js +349 -150
- package/src/modules/Popover/index.js +186 -28
- package/src/modules/Popup/index.js +27 -34
- package/src/modules/StackedBoxes/index.js +3 -3
- package/src/modules/StickyHeader/index.js +364 -155
- package/src/modules/Toggler/index.js +184 -27
- package/src/utils/motion-helpers.js +330 -0
- package/types/index.d.ts +1 -30
- package/types/modules/Application/index.d.ts +6 -6
- package/types/modules/Breakpoints/index.d.ts +2 -0
- package/types/modules/Dataloader/index.d.ts +5 -2
- package/types/modules/Dataloader/url-sync.d.ts +36 -0
- package/types/modules/Dom/index.d.ts +7 -0
- package/types/modules/DoubleHeader/index.d.ts +63 -0
- package/types/modules/Dropdown/index.d.ts +7 -30
- package/types/modules/EqualHeightImages/index.d.ts +1 -1
- package/types/modules/FixedHeader/index.d.ts +1 -1
- package/types/modules/Lazyload/index.d.ts +9 -9
- package/types/modules/Lightbox/index.d.ts +0 -5
- package/types/modules/Looper/index.d.ts +127 -0
- package/types/modules/Moonwalk/index.d.ts +6 -15
- package/types/modules/Parallax/index.d.ts +10 -32
- package/types/modules/Popover/index.d.ts +12 -0
- package/types/modules/Popup/index.d.ts +6 -19
- package/types/modules/ScrollSpy/index.d.ts +1 -1
- package/types/modules/StickyHeader/index.d.ts +171 -14
- package/types/modules/Toggler/index.d.ts +24 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { animate, stagger } from 'motion'
|
|
2
2
|
import _defaultsDeep from 'lodash.defaultsdeep'
|
|
3
3
|
import Dom from '../Dom'
|
|
4
|
+
import { set } from '../../utils/motion-helpers'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* <ul data-dropdown>
|
|
@@ -50,10 +51,15 @@ export default class Dropdown {
|
|
|
50
51
|
this.elements = {}
|
|
51
52
|
this.open = false
|
|
52
53
|
this.element = opts.el
|
|
53
|
-
this.timeline = gsap.timeline({ paused: true, reversed: true })
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
if (this.
|
|
55
|
+
// Check if the element itself is the trigger, or find it inside
|
|
56
|
+
if (this.element.matches && this.element.matches(this.opts.selectors.trigger)) {
|
|
57
|
+
this.elements.trigger = this.element
|
|
58
|
+
} else {
|
|
59
|
+
this.elements.trigger = Dom.find(this.element, this.opts.selectors.trigger)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (this.elements.trigger && this.elements.trigger.hasAttribute('data-dropdown-target')) {
|
|
57
63
|
const dropdownTarget = this.elements.trigger.getAttribute(
|
|
58
64
|
'data-dropdown-target'
|
|
59
65
|
)
|
|
@@ -75,78 +81,62 @@ export default class Dropdown {
|
|
|
75
81
|
}
|
|
76
82
|
|
|
77
83
|
initialize() {
|
|
78
|
-
this.
|
|
79
|
-
.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
this.elements.menu,
|
|
83
|
-
{
|
|
84
|
-
className: `${this.elements.menu.className} zero-height`,
|
|
85
|
-
duration: 0.05,
|
|
86
|
-
},
|
|
87
|
-
'open'
|
|
88
|
-
)
|
|
89
|
-
.to(
|
|
90
|
-
this.elements.menu,
|
|
91
|
-
{
|
|
92
|
-
height: 'auto',
|
|
93
|
-
duration: 0.05,
|
|
94
|
-
},
|
|
95
|
-
'open'
|
|
96
|
-
)
|
|
97
|
-
.call(() => {
|
|
98
|
-
// Get current bounds and viewport dimensions
|
|
99
|
-
const menuRect = this.elements.menu.getBoundingClientRect()
|
|
100
|
-
const viewportHeight = window.innerHeight
|
|
101
|
-
const viewportWidth = window.innerWidth
|
|
102
|
-
const menuHeight = menuRect.height
|
|
103
|
-
const menuTop = menuRect.top
|
|
104
|
-
|
|
105
|
-
// Update CSS variable for height (if used in your styles)
|
|
106
|
-
Dom.setCSSVar(
|
|
107
|
-
'dropdown-menu-height',
|
|
108
|
-
`${menuHeight}px`,
|
|
109
|
-
this.elements.menu
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
// Vertical placement: if the menu overflows the bottom, set placement to "top"
|
|
113
|
-
if (menuHeight + menuTop > viewportHeight) {
|
|
114
|
-
this.elements.menu.setAttribute('data-dropdown-placement', 'top')
|
|
115
|
-
} else {
|
|
116
|
-
this.elements.menu.setAttribute('data-dropdown-placement', 'bottom')
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Horizontal check: adjust left offset if the menu is offscreen
|
|
120
|
-
const computedStyle = window.getComputedStyle(this.elements.menu)
|
|
121
|
-
let currentLeft = parseFloat(computedStyle.left) || 0
|
|
84
|
+
if (!this.elements.menu) {
|
|
85
|
+
console.error('Dropdown menu element not found')
|
|
86
|
+
return
|
|
87
|
+
}
|
|
122
88
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
} else if (menuRect.right > viewportWidth) {
|
|
127
|
-
// Shift left by the amount it’s off the right edge
|
|
128
|
-
this.elements.menu.style.left = `${currentLeft - (menuRect.right - viewportWidth)}px`
|
|
129
|
-
}
|
|
130
|
-
})
|
|
131
|
-
.to(this.elements.menu, {
|
|
132
|
-
opacity: 1,
|
|
133
|
-
duration: this.opts.menuOpenDuration,
|
|
134
|
-
})
|
|
89
|
+
// Initial setup - menu hidden with height cleared
|
|
90
|
+
this.elements.menu.style.removeProperty('height')
|
|
91
|
+
set(this.elements.menu, { display: 'none', opacity: 0 })
|
|
135
92
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
this.opts.tweens.items,
|
|
140
|
-
`open+=${this.opts.menuOpenDuration}`
|
|
141
|
-
)
|
|
93
|
+
// Store initial menu items opacity
|
|
94
|
+
if (this.elements.menuItems && this.elements.menuItems.length) {
|
|
95
|
+
set(this.elements.menuItems, { opacity: 0 })
|
|
142
96
|
}
|
|
143
97
|
|
|
144
98
|
if (!this.elements.trigger) {
|
|
99
|
+
console.error('Dropdown trigger element not found')
|
|
145
100
|
return
|
|
146
101
|
}
|
|
147
102
|
this.elements.trigger.addEventListener('click', this.onClick.bind(this))
|
|
148
103
|
}
|
|
149
104
|
|
|
105
|
+
positionMenu() {
|
|
106
|
+
// Get current bounds and viewport dimensions
|
|
107
|
+
const menuRect = this.elements.menu.getBoundingClientRect()
|
|
108
|
+
const viewportHeight = window.innerHeight
|
|
109
|
+
const viewportWidth = window.innerWidth
|
|
110
|
+
const menuHeight = menuRect.height
|
|
111
|
+
const menuTop = menuRect.top
|
|
112
|
+
|
|
113
|
+
// Update CSS variable for height (if used in your styles)
|
|
114
|
+
Dom.setCSSVar(
|
|
115
|
+
'dropdown-menu-height',
|
|
116
|
+
`${menuHeight}px`,
|
|
117
|
+
this.elements.menu
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
// Vertical placement: if the menu overflows the bottom, set placement to "top"
|
|
121
|
+
if (menuHeight + menuTop > viewportHeight) {
|
|
122
|
+
this.elements.menu.setAttribute('data-dropdown-placement', 'top')
|
|
123
|
+
} else {
|
|
124
|
+
this.elements.menu.setAttribute('data-dropdown-placement', 'bottom')
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Horizontal check: adjust left offset if the menu is offscreen
|
|
128
|
+
const computedStyle = window.getComputedStyle(this.elements.menu)
|
|
129
|
+
let currentLeft = parseFloat(computedStyle.left) || 0
|
|
130
|
+
|
|
131
|
+
if (menuRect.left < 0) {
|
|
132
|
+
// Shift right by the amount it's off the left edge
|
|
133
|
+
this.elements.menu.style.left = `${currentLeft - menuRect.left}px`
|
|
134
|
+
} else if (menuRect.right > viewportWidth) {
|
|
135
|
+
// Shift left by the amount it's off the right edge
|
|
136
|
+
this.elements.menu.style.left = `${currentLeft - (menuRect.right - viewportWidth)}px`
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
150
140
|
async onClick(event) {
|
|
151
141
|
event.preventDefault()
|
|
152
142
|
event.stopPropagation()
|
|
@@ -179,10 +169,30 @@ export default class Dropdown {
|
|
|
179
169
|
// Add document click listener when menu is open.
|
|
180
170
|
document.addEventListener('click', this.handleDocumentClick)
|
|
181
171
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
172
|
+
// Show menu (display: flex, still invisible)
|
|
173
|
+
set(this.elements.menu, { display: 'flex', opacity: 0 })
|
|
174
|
+
|
|
175
|
+
// Add zero-height class for animation
|
|
176
|
+
this.elements.menu.classList.add('zero-height')
|
|
177
|
+
|
|
178
|
+
// Brief delay to let browser calculate dimensions, then remove zero-height
|
|
179
|
+
await new Promise(resolve => setTimeout(resolve, 50))
|
|
180
|
+
this.elements.menu.classList.remove('zero-height')
|
|
181
|
+
|
|
182
|
+
// Position menu based on viewport
|
|
183
|
+
this.positionMenu()
|
|
184
|
+
|
|
185
|
+
// Fade in menu
|
|
186
|
+
await animate(this.elements.menu, { opacity: 1 }, {
|
|
187
|
+
duration: this.opts.menuOpenDuration
|
|
188
|
+
}).finished
|
|
189
|
+
|
|
190
|
+
// Animate menu items if present
|
|
191
|
+
if (this.elements.menuItems.length) {
|
|
192
|
+
await animate(this.elements.menuItems, { opacity: 1 }, {
|
|
193
|
+
duration: this.opts.tweens.items.duration,
|
|
194
|
+
delay: stagger(this.opts.tweens.items.stagger)
|
|
195
|
+
}).finished
|
|
186
196
|
}
|
|
187
197
|
}
|
|
188
198
|
|
|
@@ -194,11 +204,27 @@ export default class Dropdown {
|
|
|
194
204
|
// Remove the document click listener when menu closes.
|
|
195
205
|
document.removeEventListener('click', this.handleDocumentClick)
|
|
196
206
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
207
|
+
// Animate menu items out first (reverse order, faster)
|
|
208
|
+
if (this.elements.menuItems.length) {
|
|
209
|
+
await animate(this.elements.menuItems, { opacity: 0 }, {
|
|
210
|
+
duration: this.opts.tweens.items.duration * 0.5,
|
|
211
|
+
}).finished
|
|
201
212
|
}
|
|
213
|
+
|
|
214
|
+
// Fade out menu
|
|
215
|
+
await animate(this.elements.menu, { opacity: 0 }, {
|
|
216
|
+
duration: this.opts.menuOpenDuration
|
|
217
|
+
}).finished
|
|
218
|
+
|
|
219
|
+
// Add zero-height class back for collapse
|
|
220
|
+
this.elements.menu.classList.add('zero-height')
|
|
221
|
+
|
|
222
|
+
// Brief delay for height animation
|
|
223
|
+
await new Promise(resolve => setTimeout(resolve, 50))
|
|
224
|
+
|
|
225
|
+
// Finally hide completely
|
|
226
|
+
set(this.elements.menu, { display: 'none' })
|
|
227
|
+
this.elements.menu.classList.remove('zero-height')
|
|
202
228
|
}
|
|
203
229
|
|
|
204
230
|
// Handler that checks if a click was outside the dropdown element.
|
|
@@ -211,7 +237,7 @@ export default class Dropdown {
|
|
|
211
237
|
}
|
|
212
238
|
|
|
213
239
|
checkForInitialOpen() {
|
|
214
|
-
if (this.elements.trigger.hasAttribute('data-dropdown-active')) {
|
|
240
|
+
if (this.elements.trigger && this.elements.trigger.hasAttribute('data-dropdown-active')) {
|
|
215
241
|
this.openMenu()
|
|
216
242
|
}
|
|
217
243
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { clearProps } from '../../utils/motion-helpers'
|
|
2
2
|
import Dom from '../Dom'
|
|
3
3
|
import _defaultsDeep from 'lodash.defaultsdeep'
|
|
4
4
|
import * as Events from '../../events'
|
|
@@ -13,9 +13,7 @@ export default class EqualHeightElements {
|
|
|
13
13
|
this.selector = selector
|
|
14
14
|
this.initialize()
|
|
15
15
|
window.addEventListener(Events.APPLICATION_RESIZE, () => {
|
|
16
|
-
|
|
17
|
-
clearProps: 'minHeight',
|
|
18
|
-
})
|
|
16
|
+
clearProps('[data-eq-height-elements-adjusted]', 'minHeight')
|
|
19
17
|
this.initialize()
|
|
20
18
|
})
|
|
21
19
|
}
|
|
@@ -61,9 +59,9 @@ export default class EqualHeightElements {
|
|
|
61
59
|
|
|
62
60
|
if (actionables.length) {
|
|
63
61
|
actionables.forEach((a) => {
|
|
64
|
-
|
|
65
|
-
minHeight
|
|
66
|
-
|
|
62
|
+
a.elements.forEach(el => {
|
|
63
|
+
el.style.minHeight = `${a.height}px`
|
|
64
|
+
el.setAttribute('data-eq-height-elements-adjusted', 'true')
|
|
67
65
|
})
|
|
68
66
|
})
|
|
69
67
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { gsap } from 'gsap/all'
|
|
2
1
|
import Dom from '../Dom'
|
|
3
2
|
import * as Events from '../../events'
|
|
4
3
|
import imagesAreLoaded from '../../utils/imagesAreLoaded'
|
|
@@ -30,6 +29,10 @@ export default class EqualHeightImages {
|
|
|
30
29
|
let height = 0
|
|
31
30
|
const imgs = Dom.all(canvas, 'img')
|
|
32
31
|
|
|
32
|
+
if (imgs.length === 0) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
33
36
|
imagesAreLoaded(imgs, false).then(() => {
|
|
34
37
|
imgs.forEach((el) => {
|
|
35
38
|
const rect = el.getBoundingClientRect()
|
|
@@ -63,7 +66,9 @@ export default class EqualHeightImages {
|
|
|
63
66
|
|
|
64
67
|
if (actionables.length) {
|
|
65
68
|
actionables.forEach((a) => {
|
|
66
|
-
|
|
69
|
+
a.elements.forEach((el) => {
|
|
70
|
+
el.style.minHeight = `${a.height}px`
|
|
71
|
+
})
|
|
67
72
|
})
|
|
68
73
|
}
|
|
69
74
|
})
|
|
@@ -23,10 +23,11 @@
|
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import {
|
|
26
|
+
import { animate, stagger } from 'motion'
|
|
27
27
|
import _defaultsDeep from 'lodash.defaultsdeep'
|
|
28
28
|
import * as Events from '../../events'
|
|
29
29
|
import Dom from '../Dom'
|
|
30
|
+
import { set } from '../../utils/motion-helpers'
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
33
|
* @typedef {Object} FixedHeaderEvents
|
|
@@ -77,41 +78,42 @@ import Dom from '../Dom'
|
|
|
77
78
|
/** @type {FixedHeaderEvents} */
|
|
78
79
|
const DEFAULT_EVENTS = {
|
|
79
80
|
onPin: (h) => {
|
|
80
|
-
|
|
81
|
+
animate(h.el, {
|
|
82
|
+
yPercent: '0'
|
|
83
|
+
}, {
|
|
81
84
|
duration: 0.35,
|
|
82
|
-
|
|
83
|
-
ease: 'sine.out',
|
|
84
|
-
autoRound: true,
|
|
85
|
+
ease: 'easeOut'
|
|
85
86
|
})
|
|
86
87
|
},
|
|
87
88
|
|
|
88
89
|
onUnpin: (h) => {
|
|
89
90
|
h._hiding = true
|
|
90
|
-
|
|
91
|
+
animate(h.el, {
|
|
92
|
+
yPercent: '-100'
|
|
93
|
+
}, {
|
|
91
94
|
duration: 0.25,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
onComplete: () => {
|
|
96
|
-
h._hiding = false
|
|
97
|
-
},
|
|
95
|
+
ease: 'easeIn'
|
|
96
|
+
}).finished.then(() => {
|
|
97
|
+
h._hiding = false
|
|
98
98
|
})
|
|
99
99
|
},
|
|
100
100
|
|
|
101
101
|
onAltBg: (h) => {
|
|
102
102
|
if (h.opts.altBgColor) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
animate(h.el, {
|
|
104
|
+
backgroundColor: h.opts.altBgColor
|
|
105
|
+
}, {
|
|
106
|
+
duration: 0.2
|
|
106
107
|
})
|
|
107
108
|
}
|
|
108
109
|
},
|
|
109
110
|
|
|
110
111
|
onNotAltBg: (h) => {
|
|
111
112
|
if (h.opts.regBgColor) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
animate(h.el, {
|
|
114
|
+
backgroundColor: h.opts.regBgColor
|
|
115
|
+
}, {
|
|
116
|
+
duration: 0.4
|
|
115
117
|
})
|
|
116
118
|
}
|
|
117
119
|
},
|
|
@@ -154,21 +156,28 @@ const DEFAULT_OPTIONS = {
|
|
|
154
156
|
canvas: window,
|
|
155
157
|
intersects: null,
|
|
156
158
|
beforeEnter: (h) => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
+
set(h.el, { yPercent: -100 })
|
|
160
|
+
set(h.lis, { opacity: 0 })
|
|
159
161
|
},
|
|
160
162
|
|
|
161
163
|
enter: (h) => {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
164
|
+
// Header slides down
|
|
165
|
+
animate(h.el, {
|
|
166
|
+
yPercent: 0
|
|
167
|
+
}, {
|
|
168
|
+
duration: 1,
|
|
169
|
+
delay: h.opts.enterDelay,
|
|
170
|
+
ease: 'easeOut'
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
// Menu items fade in with stagger (starts at same time as header: '-=1' means 1s overlap)
|
|
174
|
+
animate(h.lis, {
|
|
175
|
+
opacity: 1
|
|
176
|
+
}, {
|
|
177
|
+
duration: 0.8,
|
|
178
|
+
delay: stagger(0.1, { startDelay: h.opts.enterDelay }),
|
|
179
|
+
ease: 'easeIn'
|
|
180
|
+
})
|
|
172
181
|
},
|
|
173
182
|
|
|
174
183
|
enterDelay: 0,
|
|
@@ -227,6 +236,7 @@ export default class FixedHeader {
|
|
|
227
236
|
this.mobileMenuOpen = false
|
|
228
237
|
this.timer = null
|
|
229
238
|
this.resetResizeTimer = null
|
|
239
|
+
this.scrollSettleTimeout = null
|
|
230
240
|
|
|
231
241
|
if (this.opts.intersects) {
|
|
232
242
|
this.intersectingElements = Dom.all('[data-intersect]')
|
|
@@ -297,6 +307,26 @@ export default class FixedHeader {
|
|
|
297
307
|
capture: false,
|
|
298
308
|
passive: true,
|
|
299
309
|
})
|
|
310
|
+
|
|
311
|
+
// Add debounced scroll listener for accurate top/bottom detection after scroll settles
|
|
312
|
+
// RAF-throttled events can lag behind actual scroll position during fast scrolls
|
|
313
|
+
window.addEventListener('scroll', () => {
|
|
314
|
+
clearTimeout(this.scrollSettleTimeout)
|
|
315
|
+
this.scrollSettleTimeout = setTimeout(() => {
|
|
316
|
+
// Get real-time scroll position after scroll has settled
|
|
317
|
+
const actualScrollY = this.opts.canvas === window || this.opts.canvas === document.body
|
|
318
|
+
? window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
|
|
319
|
+
: this.opts.canvas.scrollTop
|
|
320
|
+
|
|
321
|
+
// Update current scroll and force accurate boundary checks
|
|
322
|
+
this.currentScrollY = actualScrollY
|
|
323
|
+
this.checkTop(true)
|
|
324
|
+
this.checkBot(true)
|
|
325
|
+
}, 100)
|
|
326
|
+
}, {
|
|
327
|
+
capture: false,
|
|
328
|
+
passive: true,
|
|
329
|
+
})
|
|
300
330
|
})
|
|
301
331
|
|
|
302
332
|
this.app.registerCallback(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { set } from '../../utils/motion-helpers'
|
|
2
2
|
import _defaultsDeep from 'lodash.defaultsdeep'
|
|
3
3
|
|
|
4
4
|
const DEFAULT_OPTIONS = {
|
|
@@ -14,14 +14,14 @@ export default class FooterReveal {
|
|
|
14
14
|
const main = document.querySelector('main')
|
|
15
15
|
const footer = document.querySelector('[data-footer-reveal]')
|
|
16
16
|
// fix footer
|
|
17
|
-
|
|
17
|
+
set(footer, {
|
|
18
18
|
'z-index': -100,
|
|
19
19
|
position: 'fixed',
|
|
20
20
|
bottom: 0,
|
|
21
21
|
})
|
|
22
22
|
const footerHeight = footer.offsetHeight
|
|
23
23
|
// add height as margin
|
|
24
|
-
|
|
24
|
+
set(main, { marginBottom: footerHeight })
|
|
25
25
|
if (this.opts.shadow) {
|
|
26
26
|
const shadowStyle = `0 50px 50px -20px ${this.opts.shadowColor}`
|
|
27
27
|
main.style.mozBoxShadow = shadowStyle
|