@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,7 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { animate } from 'motion'
|
|
2
|
+
import { set } from '../../utils/motion-helpers'
|
|
2
3
|
import _defaultsDeep from 'lodash.defaultsdeep'
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} PopupOptions
|
|
7
|
+
* @property {string} [selector] - CSS selector to find popup elements
|
|
8
|
+
* @property {Function} [responsive] - Function that determines if popup should be shown on current breakpoint
|
|
9
|
+
* @property {Function} [onOpen] - Called when popup opens
|
|
10
|
+
* @property {Function} [onClose] - Called when popup closes
|
|
11
|
+
* @property {Function} [tweenIn] - Animation function for opening popup
|
|
12
|
+
* @property {Function} [tweenOut] - Animation function for closing popup
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** @type {PopupOptions} */
|
|
4
16
|
const DEFAULT_OPTIONS = {
|
|
17
|
+
/**
|
|
18
|
+
* selector
|
|
19
|
+
*
|
|
20
|
+
* CSS selector to find popup elements
|
|
21
|
+
* Default: '[data-popup]'
|
|
22
|
+
*/
|
|
23
|
+
selector: '[data-popup]',
|
|
24
|
+
|
|
5
25
|
/**
|
|
6
26
|
* responsive
|
|
7
27
|
*
|
|
@@ -17,117 +37,216 @@ const DEFAULT_OPTIONS = {
|
|
|
17
37
|
onClose: () => {},
|
|
18
38
|
|
|
19
39
|
tweenIn: (trigger, target, popup) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
40
|
+
popup.backdrop.style.display = 'block'
|
|
41
|
+
animate(popup.backdrop, { opacity: 1 }, { duration: 0.3 })
|
|
42
|
+
.finished
|
|
43
|
+
.then(() => {
|
|
44
|
+
target.style.display = 'block'
|
|
45
|
+
animate(
|
|
26
46
|
target,
|
|
27
47
|
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
opacity: 0,
|
|
33
|
-
display: 'block'
|
|
48
|
+
transform: [
|
|
49
|
+
'translate(calc(-50% - 5px), -50%)',
|
|
50
|
+
'translate(-50%, -50%)'
|
|
51
|
+
],
|
|
52
|
+
opacity: [0, 1]
|
|
34
53
|
},
|
|
35
|
-
{
|
|
36
|
-
duration: 0.3,
|
|
37
|
-
yPercent: -50,
|
|
38
|
-
xPercent: -50,
|
|
39
|
-
x: 0,
|
|
40
|
-
opacity: 1
|
|
41
|
-
}
|
|
54
|
+
{ duration: 0.3, ease: [0.4, 0, 0.2, 1] }
|
|
42
55
|
)
|
|
43
|
-
}
|
|
44
|
-
})
|
|
56
|
+
})
|
|
45
57
|
},
|
|
46
58
|
|
|
47
|
-
tweenOut: popup => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
opacity: 0,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
tweenOut: (popup) => {
|
|
60
|
+
console.log('default tweenOut')
|
|
61
|
+
const popupElement = popup.currentPopup
|
|
62
|
+
if (popupElement) {
|
|
63
|
+
animate(popupElement, { opacity: 0 }, { duration: 0.3 })
|
|
64
|
+
.finished
|
|
65
|
+
.then(() => {
|
|
66
|
+
popupElement.style.display = 'none'
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
animate(popup.backdrop, { opacity: 0 }, { duration: 0.3 })
|
|
70
|
+
.finished
|
|
71
|
+
.then(() => {
|
|
72
|
+
// Remove the backdrop completely instead of just hiding it
|
|
73
|
+
popup.backdrop.remove()
|
|
74
|
+
})
|
|
75
|
+
},
|
|
62
76
|
}
|
|
63
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Popup component for modal dialogs and popups
|
|
80
|
+
*/
|
|
64
81
|
export default class Popup {
|
|
65
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Create a new Popup instance
|
|
84
|
+
* @param {Object} app - Application instance
|
|
85
|
+
* @param {string} [selector] - CSS selector to find popup elements
|
|
86
|
+
* @param {PopupOptions} [opts={}] - Popup options
|
|
87
|
+
*/
|
|
88
|
+
constructor(app, selector = '[data-popup]', opts = {}) {
|
|
66
89
|
this.app = app
|
|
67
90
|
this.opts = _defaultsDeep(opts, DEFAULT_OPTIONS)
|
|
68
|
-
this.
|
|
91
|
+
this.opts.selector = selector
|
|
92
|
+
this.backdrop = null
|
|
93
|
+
this.currentPopup = null
|
|
94
|
+
this.popupKey = null
|
|
69
95
|
this.bindTriggers()
|
|
70
96
|
}
|
|
71
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Bind click handlers to popup triggers and close buttons
|
|
100
|
+
*/
|
|
72
101
|
bindTriggers() {
|
|
73
|
-
|
|
74
|
-
const
|
|
102
|
+
// Find all triggers that match this popup's selector
|
|
103
|
+
const allTriggers = document.querySelectorAll('[data-popup-trigger]')
|
|
104
|
+
const matchingTriggers = Array.from(allTriggers).filter(trigger => {
|
|
105
|
+
const target = trigger.getAttribute('data-popup-trigger')
|
|
106
|
+
if (typeof target === 'string') {
|
|
107
|
+
const element = document.querySelector(target)
|
|
108
|
+
return element && element.matches(this.opts.selector)
|
|
109
|
+
}
|
|
110
|
+
return false
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// Get all popups that match this instance's selector
|
|
114
|
+
const popups = document.querySelectorAll(this.opts.selector)
|
|
115
|
+
|
|
116
|
+
// Find all close buttons inside matching popups
|
|
117
|
+
const closers = []
|
|
118
|
+
popups.forEach(popup => {
|
|
119
|
+
const popupClosers = popup.querySelectorAll('[data-popup-close]')
|
|
120
|
+
closers.push(...popupClosers)
|
|
121
|
+
})
|
|
75
122
|
|
|
76
|
-
|
|
123
|
+
// Bind click handlers to matching triggers
|
|
124
|
+
matchingTriggers.forEach((trigger) => {
|
|
77
125
|
const triggerTarget = trigger.getAttribute('data-popup-trigger')
|
|
78
|
-
|
|
126
|
+
// Get the popup key if present
|
|
127
|
+
const popupKey = trigger.getAttribute('data-popup-key') || this.getKeyFromTarget(triggerTarget)
|
|
128
|
+
|
|
129
|
+
trigger.addEventListener('click', (event) => {
|
|
79
130
|
if (this.opts.responsive(this.app)) {
|
|
80
131
|
event.stopImmediatePropagation()
|
|
81
132
|
event.preventDefault()
|
|
82
|
-
this.open(trigger, triggerTarget)
|
|
133
|
+
this.open(trigger, triggerTarget, popupKey)
|
|
83
134
|
}
|
|
84
135
|
})
|
|
85
136
|
})
|
|
86
137
|
|
|
87
|
-
|
|
88
|
-
|
|
138
|
+
// Bind click handlers to close buttons
|
|
139
|
+
closers.forEach((closer) => {
|
|
140
|
+
// Get the popup key from the closest parent popup element
|
|
141
|
+
const popupElement = closer.closest(this.opts.selector)
|
|
142
|
+
const popupKey = popupElement ? popupElement.getAttribute('data-popup-key') : null
|
|
143
|
+
|
|
144
|
+
closer.addEventListener('click', (event) => {
|
|
89
145
|
event.stopImmediatePropagation()
|
|
90
146
|
event.preventDefault()
|
|
91
|
-
|
|
92
|
-
|
|
147
|
+
|
|
148
|
+
// Only close if keys match or no key is set
|
|
149
|
+
if (!this.popupKey || !popupKey || this.popupKey === popupKey) {
|
|
150
|
+
this.opts.onClose(this)
|
|
151
|
+
this.close()
|
|
152
|
+
}
|
|
93
153
|
})
|
|
94
154
|
})
|
|
95
155
|
}
|
|
96
156
|
|
|
97
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Extract key from target selector or element
|
|
159
|
+
* @param {HTMLElement|string} target - Target element or selector
|
|
160
|
+
* @returns {string|null} - The popup key or null
|
|
161
|
+
*/
|
|
162
|
+
getKeyFromTarget(target) {
|
|
163
|
+
if (typeof target === 'string') {
|
|
164
|
+
const element = document.querySelector(target)
|
|
165
|
+
return element ? element.getAttribute('data-popup-key') : null
|
|
166
|
+
} else if (target instanceof HTMLElement) {
|
|
167
|
+
return target.getAttribute('data-popup-key')
|
|
168
|
+
}
|
|
169
|
+
return null
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Create backdrop element for popup
|
|
174
|
+
* @param {string|null} key - Optional popup key to associate with backdrop
|
|
175
|
+
* @returns {HTMLElement} The created backdrop element
|
|
176
|
+
*/
|
|
177
|
+
createBackdrop(key) {
|
|
98
178
|
const backdrop = document.createElement('div')
|
|
99
179
|
backdrop.setAttribute('data-popup-backdrop', '')
|
|
100
|
-
|
|
180
|
+
if (key) {
|
|
181
|
+
backdrop.setAttribute('data-popup-key', key)
|
|
182
|
+
}
|
|
183
|
+
backdrop.style.display = 'none'
|
|
184
|
+
backdrop.style.zIndex = '4999'
|
|
185
|
+
set(backdrop, { opacity: 0 })
|
|
101
186
|
|
|
102
|
-
backdrop.addEventListener('click', e => {
|
|
187
|
+
backdrop.addEventListener('click', (e) => {
|
|
103
188
|
e.stopPropagation()
|
|
104
189
|
this.close()
|
|
105
190
|
})
|
|
106
191
|
|
|
107
192
|
document.body.append(backdrop)
|
|
108
|
-
|
|
193
|
+
return backdrop
|
|
109
194
|
}
|
|
110
195
|
|
|
111
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Open a popup
|
|
198
|
+
* @param {HTMLElement} trigger - Element that triggered the popup
|
|
199
|
+
* @param {HTMLElement|string} target - Popup element or selector
|
|
200
|
+
* @param {string|null} key - Optional popup key
|
|
201
|
+
*/
|
|
202
|
+
open(trigger, target, key = null) {
|
|
112
203
|
this.keyUpListener = this.onKeyup.bind(this)
|
|
113
204
|
document.addEventListener('keyup', this.keyUpListener)
|
|
205
|
+
|
|
206
|
+
// Store the popup key
|
|
207
|
+
this.popupKey = key || this.getKeyFromTarget(target)
|
|
208
|
+
|
|
209
|
+
// Create a new backdrop for this popup
|
|
210
|
+
this.backdrop = this.createBackdrop(this.popupKey)
|
|
211
|
+
|
|
114
212
|
if (typeof target === 'string') {
|
|
115
213
|
target = document.querySelector(target)
|
|
116
214
|
}
|
|
117
215
|
|
|
118
216
|
if (!target) {
|
|
119
217
|
console.error(`JUPITER/POPUP >>> Element ${target} not found`)
|
|
218
|
+
return
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Store the current popup element for reference
|
|
222
|
+
this.currentPopup = target
|
|
223
|
+
|
|
224
|
+
// If key isn't already set on the popup element, set it now
|
|
225
|
+
if (this.popupKey && !target.hasAttribute('data-popup-key')) {
|
|
226
|
+
target.setAttribute('data-popup-key', this.popupKey)
|
|
120
227
|
}
|
|
228
|
+
|
|
121
229
|
this.opts.onOpen(trigger, target, this)
|
|
122
230
|
this.opts.tweenIn(trigger, target, this)
|
|
123
231
|
}
|
|
124
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Close the popup
|
|
235
|
+
*/
|
|
125
236
|
close() {
|
|
126
237
|
document.removeEventListener('keyup', this.keyUpListener)
|
|
127
238
|
this.opts.onClose(this)
|
|
128
239
|
this.opts.tweenOut(this)
|
|
240
|
+
|
|
241
|
+
// Reset popup state
|
|
242
|
+
this.popupKey = null
|
|
243
|
+
this.currentPopup = null
|
|
129
244
|
}
|
|
130
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Handle keyup event for Escape key to close popup
|
|
248
|
+
* @param {KeyboardEvent} e - Keyboard event
|
|
249
|
+
*/
|
|
131
250
|
onKeyup(e) {
|
|
132
251
|
const key = e.keyCode || e.which
|
|
133
252
|
|
|
@@ -1,17 +1,34 @@
|
|
|
1
1
|
import _defaultsDeep from 'lodash.defaultsdeep'
|
|
2
2
|
import Dom from '../Dom'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {Object} ScrollSpyOptions
|
|
6
|
+
* @property {Function} [onIntersect] - Called when a target intersects with the viewport
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** @type {ScrollSpyOptions} */
|
|
4
10
|
const DEFAULT_OPTIONS = {
|
|
5
11
|
onIntersect: (target, trigger) => {}
|
|
6
12
|
}
|
|
7
13
|
|
|
14
|
+
/**
|
|
15
|
+
* ScrollSpy component for highlighting active sections during scrolling
|
|
16
|
+
*/
|
|
8
17
|
export default class ScrollSpy {
|
|
18
|
+
/**
|
|
19
|
+
* Create a new ScrollSpy instance
|
|
20
|
+
* @param {Object} app - Application instance
|
|
21
|
+
* @param {ScrollSpyOptions} [opts={}] - ScrollSpy options
|
|
22
|
+
*/
|
|
9
23
|
constructor(app, opts = {}) {
|
|
10
24
|
this.app = app
|
|
11
25
|
this.opts = _defaultsDeep(opts, DEFAULT_OPTIONS)
|
|
12
26
|
this.initialize()
|
|
13
27
|
}
|
|
14
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Initialize ScrollSpy
|
|
31
|
+
*/
|
|
15
32
|
initialize() {
|
|
16
33
|
this.triggers = Dom.all('[data-scrollspy-trigger]')
|
|
17
34
|
const config = {
|
|
@@ -29,6 +46,10 @@ export default class ScrollSpy {
|
|
|
29
46
|
this.triggers.forEach(section => observer.observe(section))
|
|
30
47
|
}
|
|
31
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Handle intersection with viewport
|
|
51
|
+
* @param {IntersectionObserverEntry} entry - Intersection observer entry
|
|
52
|
+
*/
|
|
32
53
|
intersectionHandler(entry) {
|
|
33
54
|
const id = entry.target.dataset.scrollspyTrigger
|
|
34
55
|
const currentlyActive = document.querySelector('[data-scrollspy-active]')
|
|
@@ -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 = {}
|
|
@@ -13,14 +13,14 @@ export default class StackedBoxes {
|
|
|
13
13
|
initialize() {
|
|
14
14
|
const boxes = document.querySelectorAll('[data-boxes-stacked]')
|
|
15
15
|
|
|
16
|
-
const observer = new IntersectionObserver(entries => {
|
|
16
|
+
const observer = new IntersectionObserver((entries) => {
|
|
17
17
|
const [{ isIntersecting, target }] = entries
|
|
18
18
|
if (isIntersecting) {
|
|
19
19
|
this.adjustBox(target)
|
|
20
20
|
}
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
Array.from(boxes).forEach(box => {
|
|
23
|
+
Array.from(boxes).forEach((box) => {
|
|
24
24
|
observer.observe(box)
|
|
25
25
|
})
|
|
26
26
|
}
|
|
@@ -53,17 +53,19 @@ export default class StackedBoxes {
|
|
|
53
53
|
break
|
|
54
54
|
|
|
55
55
|
default:
|
|
56
|
-
console.error(
|
|
56
|
+
console.error(
|
|
57
|
+
'==> JUPITER/STACKEDBOXES: `data-boxes-stacked-pull` has wrong value'
|
|
58
|
+
)
|
|
57
59
|
}
|
|
58
60
|
this.pull(pull, pullPx)
|
|
59
61
|
}
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
pull(box, amnt) {
|
|
63
|
-
|
|
65
|
+
set(box, { y: amnt * -1, marginBottom: amnt * -1 })
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
size(target, src) {
|
|
67
|
-
|
|
69
|
+
set(target, { height: src.clientHeight })
|
|
68
70
|
}
|
|
69
71
|
}
|