@brandocms/jupiter 3.54.4 → 4.0.0-beta.1

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.
Files changed (67) hide show
  1. package/README.md +318 -52
  2. package/package.json +26 -16
  3. package/src/index.js +5 -0
  4. package/src/modules/Application/index.js +37 -5
  5. package/src/modules/Breakpoints/index.js +116 -36
  6. package/src/modules/Cookies/index.js +67 -15
  7. package/src/modules/CoverOverlay/index.js +2 -2
  8. package/src/modules/Dom/index.js +6 -0
  9. package/src/modules/Dropdown/index.js +15 -6
  10. package/src/modules/EqualHeightElements/index.js +8 -6
  11. package/src/modules/EqualHeightImages/index.js +9 -6
  12. package/src/modules/FixedHeader/index.js +57 -1
  13. package/src/modules/FooterReveal/index.js +3 -3
  14. package/src/modules/HeroSlider/index.js +39 -30
  15. package/src/modules/HeroVideo/index.js +64 -24
  16. package/src/modules/Lazyload/index.js +27 -0
  17. package/src/modules/Lightbox/index.js +90 -31
  18. package/src/modules/Links/index.js +23 -2
  19. package/src/modules/MobileMenu/index.js +50 -21
  20. package/src/modules/Moonwalk/index.js +131 -4
  21. package/src/modules/Parallax/index.js +280 -57
  22. package/src/modules/Popover/index.js +28 -16
  23. package/src/modules/Popup/index.js +155 -29
  24. package/src/modules/ScrollSpy/index.js +21 -0
  25. package/src/modules/StackedBoxes/index.js +6 -4
  26. package/src/modules/StickyHeader/index.js +45 -24
  27. package/src/modules/Toggler/index.js +44 -5
  28. package/src/modules/Typography/index.js +33 -20
  29. package/types/README.md +159 -0
  30. package/types/events/index.d.ts +20 -0
  31. package/types/index.d.ts +35 -0
  32. package/types/modules/Application/index.d.ts +168 -0
  33. package/types/modules/Breakpoints/index.d.ts +38 -0
  34. package/types/modules/Cookies/index.d.ts +81 -0
  35. package/types/modules/CoverOverlay/index.d.ts +6 -0
  36. package/types/modules/Dataloader/index.d.ts +35 -0
  37. package/types/modules/Dom/index.d.ts +40 -0
  38. package/types/modules/Dropdown/index.d.ts +38 -0
  39. package/types/modules/EqualHeightElements/index.d.ts +8 -0
  40. package/types/modules/EqualHeightImages/index.d.ts +11 -0
  41. package/types/modules/FeatureTests/index.d.ts +27 -0
  42. package/types/modules/FixedHeader/index.d.ts +219 -0
  43. package/types/modules/Fontloader/index.d.ts +5 -0
  44. package/types/modules/FooterReveal/index.d.ts +5 -0
  45. package/types/modules/HeroSlider/index.d.ts +28 -0
  46. package/types/modules/HeroVideo/index.d.ts +83 -0
  47. package/types/modules/Lazyload/index.d.ts +80 -0
  48. package/types/modules/Lightbox/index.d.ts +128 -0
  49. package/types/modules/Links/index.d.ts +55 -0
  50. package/types/modules/Marquee/index.d.ts +23 -0
  51. package/types/modules/MobileMenu/index.d.ts +63 -0
  52. package/types/modules/Moonwalk/index.d.ts +331 -0
  53. package/types/modules/Parallax/index.d.ts +93 -0
  54. package/types/modules/Popover/index.d.ts +17 -0
  55. package/types/modules/Popup/index.d.ts +89 -0
  56. package/types/modules/ScrollSpy/index.d.ts +29 -0
  57. package/types/modules/StackedBoxes/index.d.ts +9 -0
  58. package/types/modules/StickyHeader/index.d.ts +63 -0
  59. package/types/modules/Toggler/index.d.ts +26 -0
  60. package/types/modules/Typography/index.d.ts +77 -0
  61. package/types/utils/dispatchElementEvent.d.ts +1 -0
  62. package/types/utils/imageIsLoaded.d.ts +1 -0
  63. package/types/utils/imagesAreLoaded.d.ts +1 -0
  64. package/types/utils/loadScript.d.ts +2 -0
  65. package/types/utils/prefersReducedMotion.d.ts +4 -0
  66. package/types/utils/rafCallback.d.ts +2 -0
  67. package/types/utils/zoom.d.ts +4 -0
@@ -9,8 +9,7 @@
9
9
  *
10
10
  */
11
11
 
12
- import { gsap } from 'gsap'
13
- import { CSSPlugin } from 'gsap/CSSPlugin'
12
+ import { gsap, CSSPlugin } from 'gsap/all'
14
13
  import _defaultsDeep from 'lodash.defaultsdeep'
15
14
  import prefersReducedMotion from '../../utils/prefersReducedMotion'
16
15
  import * as Events from '../../events'
@@ -30,7 +29,7 @@ const DEFAULT_OPTIONS = {
30
29
  zIndex: {
31
30
  visible: 5,
32
31
  next: 4,
33
- regular: 3
32
+ regular: 3,
34
33
  },
35
34
  transition: {
36
35
  /* how long the actual transition from slide to slide takes */
@@ -38,10 +37,10 @@ const DEFAULT_OPTIONS = {
38
37
  /* the transition type. 'parallax' or 'fade' */
39
38
  type: 'parallax',
40
39
  /* how much to scale when 'idle' */
41
- scale: 1.05
40
+ scale: 1.05,
42
41
  },
43
42
 
44
- onTransition: hs => {
43
+ onTransition: (hs) => {
45
44
  hs.slide('parallax')
46
45
  },
47
46
 
@@ -54,15 +53,15 @@ const DEFAULT_OPTIONS = {
54
53
  opacity: 1,
55
54
  onComplete: () => {
56
55
  callback()
57
- }
56
+ },
58
57
  })
59
58
  } else {
60
59
  gsap.to(hs.el, {
61
60
  duration: 0.25,
62
- opacity: 1
61
+ opacity: 1,
63
62
  })
64
63
  }
65
- }
64
+ },
66
65
  }
67
66
 
68
67
  export default class HeroSlider {
@@ -92,7 +91,7 @@ export default class HeroSlider {
92
91
  left: 0,
93
92
  width: '100%',
94
93
  height: '100%',
95
- overflow: 'hidden'
94
+ overflow: 'hidden',
96
95
  })
97
96
 
98
97
  this.slides = this.el.querySelectorAll('[data-hero-slide]')
@@ -102,14 +101,14 @@ export default class HeroSlider {
102
101
  this._currentSlideIdx = this.opts.initialSlideNumber
103
102
 
104
103
  // style the slides
105
- Array.from(this.slides).forEach(s => {
104
+ Array.from(this.slides).forEach((s) => {
106
105
  gsap.set(s, {
107
106
  zIndex: this.opts.zIndex.regular,
108
107
  position: 'absolute',
109
108
  top: 0,
110
109
  left: 0,
111
110
  width: '100%',
112
- height: '100%'
111
+ height: '100%',
113
112
  })
114
113
 
115
114
  const img = s.querySelector('.hero-slide-img')
@@ -120,10 +119,12 @@ export default class HeroSlider {
120
119
  height: '100%',
121
120
  top: 0,
122
121
  left: 0,
123
- position: 'absolute'
122
+ position: 'absolute',
124
123
  })
125
124
  } else {
126
- console.error('==> JUPITER/HEROSLIDER: MISSING .hero-slide-img INSIDE [data-hero-slide]')
125
+ console.error(
126
+ '==> JUPITER/HEROSLIDER: MISSING .hero-slide-img INSIDE [data-hero-slide]'
127
+ )
127
128
  }
128
129
  })
129
130
 
@@ -188,24 +189,24 @@ export default class HeroSlider {
188
189
  .set(this._currentSlide, {
189
190
  opacity: 0,
190
191
  scale: 1,
191
- zIndex: this.opts.zIndex.visible
192
+ zIndex: this.opts.zIndex.visible,
192
193
  })
193
194
  .set(this._nextSlide, {
194
- opacity: 0
195
+ opacity: 0,
195
196
  })
196
197
  .to(this._previousSlide, {
197
198
  duration: this.opts.interval,
198
- scale: this.opts.transition.scale
199
+ scale: this.opts.transition.scale,
199
200
  })
200
201
  .to(this._currentSlide, {
201
202
  duration: this.opts.transition.duration,
202
203
  opacity: 1,
203
204
  delay: this.opts.interval - this.opts.transition.duration,
204
205
  force3D: true,
205
- ease: 'sine.inOut'
206
+ ease: 'sine.inOut',
206
207
  })
207
208
  .set(this._previousSlide, {
208
- opacity: 0
209
+ opacity: 0,
209
210
  })
210
211
  .call(
211
212
  () => {
@@ -225,17 +226,17 @@ export default class HeroSlider {
225
226
  .set(this._currentSlide, {
226
227
  zIndex: this.opts.zIndex.next,
227
228
  scale: 1.0,
228
- width: '100%'
229
+ width: '100%',
229
230
  })
230
231
  .fromTo(
231
232
  this._previousSlide,
232
233
  {
233
234
  duration: this.opts.interval,
234
- overflow: 'hidden'
235
+ overflow: 'hidden',
235
236
  },
236
237
  {
237
238
  duration: this.opts.interval,
238
- scale: this.opts.transition.scale
239
+ scale: this.opts.transition.scale,
239
240
  }
240
241
  )
241
242
  .to(this._previousSlide, {
@@ -243,19 +244,19 @@ export default class HeroSlider {
243
244
  width: 0,
244
245
  ease: 'power3.in',
245
246
  autoRound: true,
246
- overwrite: 'preexisting'
247
+ overwrite: 'preexisting',
247
248
  })
248
249
  .set(this._nextSlide, {
249
- zIndex: this.opts.zIndex.next
250
+ zIndex: this.opts.zIndex.next,
250
251
  })
251
252
  .set(this._currentSlide, {
252
253
  zIndex: this.opts.zIndex.visible,
253
- width: '100%'
254
+ width: '100%',
254
255
  })
255
256
  .set(this._previousSlide, {
256
257
  zIndex: this.opts.zIndex.regular,
257
258
  scale: 1.0,
258
- width: '100%'
259
+ width: '100%',
259
260
  })
260
261
  .call(() => {
261
262
  this.next()
@@ -264,7 +265,9 @@ export default class HeroSlider {
264
265
  break
265
266
 
266
267
  default:
267
- console.error('==> JUPITER/HEROSLIDER: Unrecognized `opts.transition.type` option.')
268
+ console.error(
269
+ '==> JUPITER/HEROSLIDER: Unrecognized `opts.transition.type` option.'
270
+ )
268
271
  }
269
272
  }
270
273
 
@@ -272,13 +275,19 @@ export default class HeroSlider {
272
275
  * Add a window resize handler that resizes slide widths
273
276
  */
274
277
  _addResizeHandler() {
275
- this.observer = new IntersectionObserver(entries => {
278
+ this.observer = new IntersectionObserver((entries) => {
276
279
  const [{ isIntersecting }] = entries
277
280
  if (isIntersecting) {
278
281
  this._resizeSlides()
279
- window.addEventListener(Events.APPLICATION_RESIZE, this._resizeSlides.bind(this))
282
+ window.addEventListener(
283
+ Events.APPLICATION_RESIZE,
284
+ this._resizeSlides.bind(this)
285
+ )
280
286
  } else {
281
- window.removeEventListener(Events.APPLICATION_RESIZE, this._resizeSlides.bind(this))
287
+ window.removeEventListener(
288
+ Events.APPLICATION_RESIZE,
289
+ this._resizeSlides.bind(this)
290
+ )
282
291
  }
283
292
  })
284
293
 
@@ -289,7 +298,7 @@ export default class HeroSlider {
289
298
  gsap.to(this.images, {
290
299
  duration: 0.15,
291
300
  width: document.body.clientWidth,
292
- overwrite: 'all'
301
+ overwrite: 'all',
293
302
  })
294
303
  }
295
304
  }
@@ -1,15 +1,15 @@
1
1
  /**
2
- *
3
2
  * HERO VIDEO
4
3
  *
5
- * ## Example
4
+ * Module for handling hero video elements with cover images, play/pause controls,
5
+ * and responsive behavior.
6
6
  *
7
- * const hs = HeroVideo(opts)
7
+ * ## Example
8
8
  *
9
+ * const heroVideo = new HeroVideo(app, opts)
9
10
  */
10
11
 
11
- import { gsap } from 'gsap'
12
- import { CSSPlugin } from 'gsap/CSSPlugin'
12
+ import { gsap, CSSPlugin } from 'gsap/all'
13
13
  import _defaultsDeep from 'lodash.defaultsdeep'
14
14
  import * as Events from '../../events'
15
15
  import prefersReducedMotion from '../../utils/prefersReducedMotion'
@@ -18,26 +18,46 @@ import Dom from '../Dom'
18
18
 
19
19
  gsap.registerPlugin(CSSPlugin)
20
20
 
21
+ /**
22
+ * @typedef {Object} HeroVideoElementGenerators
23
+ * @property {Function} [pause] - Function that returns the pause button HTML
24
+ * @property {Function} [play] - Function that returns the play button HTML
25
+ */
26
+
27
+ /**
28
+ * @typedef {Object} HeroVideoOptions
29
+ * @property {string|HTMLElement} [el='[data-hero-video]'] - Target element selector or element
30
+ * @property {Function} [onFadeIn] - Called when video fades in
31
+ * @property {Function} [onFadeInCover] - Called when cover fades in
32
+ * @property {Function} [onFadeOutCover] - Called when cover fades out
33
+ * @property {Function} [onPlayReady] - Called when video is ready to play
34
+ * @property {Function} [onClickPlay] - Called when play button is clicked
35
+ * @property {Function} [onClickPause] - Called when pause button is clicked
36
+ * @property {string} [pauseParent='.hero-content'] - Selector for parent element to append pause button to
37
+ * @property {HeroVideoElementGenerators} [elements] - Element generators for UI components
38
+ */
39
+
40
+ /** @type {HeroVideoOptions} */
21
41
  const DEFAULT_OPTIONS = {
22
42
  el: '[data-hero-video]',
23
- onFadeIn: hero => {
43
+ onFadeIn: (hero) => {
24
44
  gsap.to(hero.videoDiv, {
25
45
  duration: 1,
26
- autoAlpha: 1
46
+ autoAlpha: 1,
27
47
  })
28
48
  },
29
49
 
30
- onFadeInCover: hero => {
50
+ onFadeInCover: (hero) => {
31
51
  gsap.to(hero.cover, {
32
52
  duration: 0.35,
33
- autoAlpha: 1
53
+ autoAlpha: 1,
34
54
  })
35
55
  },
36
56
 
37
- onFadeOutCover: hero => {
57
+ onFadeOutCover: (hero) => {
38
58
  gsap.set(hero.cover, {
39
59
  duration: 0.35,
40
- autoAlpha: 0
60
+ autoAlpha: 0,
41
61
  })
42
62
  },
43
63
 
@@ -57,11 +77,19 @@ const DEFAULT_OPTIONS = {
57
77
 
58
78
  play: () => `
59
79
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 350 350"><circle cx="175" cy="175" r="172.5" stroke="#000" stroke-width="10"/><path stroke="#000" stroke-width="10" d="M240 174l-112-72v148l112-76z"/></svg>
60
- `
61
- }
80
+ `,
81
+ },
62
82
  }
63
83
 
84
+ /**
85
+ * HeroVideo component for handling responsive background videos with controls
86
+ */
64
87
  export default class HeroVideo {
88
+ /**
89
+ * Create a new HeroVideo instance
90
+ * @param {Object} app - Application instance
91
+ * @param {HeroVideoOptions} [opts={}] - HeroVideo options
92
+ */
65
93
  constructor(app, opts = {}) {
66
94
  this.app = app
67
95
  this.booting = true
@@ -92,7 +120,7 @@ export default class HeroVideo {
92
120
  left: 0,
93
121
  width: '100%',
94
122
  height: '100%',
95
- overflow: 'hidden'
123
+ overflow: 'hidden',
96
124
  })
97
125
 
98
126
  this.cover = Dom.find(this.el, '[data-cover]')
@@ -124,11 +152,13 @@ export default class HeroVideo {
124
152
  left: 0,
125
153
  width: '100%',
126
154
  height: '100%',
127
- opacity: 0
155
+ opacity: 0,
128
156
  })
129
157
 
130
158
  if (!this.video) {
131
- console.error('==> JUPITER/HEROVIDEO: MISSING <video> INSIDE [data-hero-video-content]')
159
+ console.error(
160
+ '==> JUPITER/HEROVIDEO: MISSING <video> INSIDE [data-hero-video-content]'
161
+ )
132
162
  return
133
163
  }
134
164
  this.video.muted = true
@@ -138,7 +168,7 @@ export default class HeroVideo {
138
168
  height: '100%',
139
169
  top: 0,
140
170
  left: 0,
141
- position: 'absolute'
171
+ position: 'absolute',
142
172
  })
143
173
 
144
174
  if (this.cover) {
@@ -149,7 +179,11 @@ export default class HeroVideo {
149
179
 
150
180
  window.addEventListener(Events.APPLICATION_READY, () => {
151
181
  /* Wait for the video to load, then fade in container element */
152
- if (!this.video.playing && !prefersReducedMotion() && this.video.readyState >= 3) {
182
+ if (
183
+ !this.video.playing &&
184
+ !prefersReducedMotion() &&
185
+ this.video.readyState >= 3
186
+ ) {
153
187
  this.play()
154
188
  this.fadeIn()
155
189
  this.booting = false
@@ -193,7 +227,7 @@ export default class HeroVideo {
193
227
  }
194
228
  })
195
229
  if (this.elements.pause) {
196
- this.elements.pause.addEventListener('click', e => {
230
+ this.elements.pause.addEventListener('click', (e) => {
197
231
  e.preventDefault()
198
232
  e.stopPropagation()
199
233
  if (this.playing) {
@@ -233,7 +267,7 @@ export default class HeroVideo {
233
267
  }
234
268
 
235
269
  addObserver() {
236
- const observer = new IntersectionObserver(entries => {
270
+ const observer = new IntersectionObserver((entries) => {
237
271
  const [{ isIntersecting }] = entries
238
272
  if (isIntersecting) {
239
273
  if (this.forcePaused) {
@@ -255,13 +289,19 @@ export default class HeroVideo {
255
289
  * Add a window resize handler that resizes video width
256
290
  */
257
291
  _addResizeHandler() {
258
- this.observer = new IntersectionObserver(entries => {
292
+ this.observer = new IntersectionObserver((entries) => {
259
293
  const [{ isIntersecting }] = entries
260
294
  if (isIntersecting) {
261
295
  this._resize()
262
- window.addEventListener(Events.APPLICATION_RESIZE, this._resize.bind(this))
296
+ window.addEventListener(
297
+ Events.APPLICATION_RESIZE,
298
+ this._resize.bind(this)
299
+ )
263
300
  } else {
264
- window.removeEventListener(Events.APPLICATION_RESIZE, this._resize.bind(this))
301
+ window.removeEventListener(
302
+ Events.APPLICATION_RESIZE,
303
+ this._resize.bind(this)
304
+ )
265
305
  }
266
306
  })
267
307
 
@@ -272,7 +312,7 @@ export default class HeroVideo {
272
312
  gsap.to(this.video, {
273
313
  duration: 0.15,
274
314
  width: document.body.clientWidth,
275
- overwrite: 'all'
315
+ overwrite: 'all',
276
316
  })
277
317
  }
278
318
  }
@@ -4,6 +4,25 @@ import imagesAreLoaded from '../../utils/imagesAreLoaded'
4
4
  import Dom from '../Dom'
5
5
  import * as Events from '../../events'
6
6
 
7
+ /**
8
+ * @typedef {Object} IntersectionObserverConfig
9
+ * @property {string} [rootMargin] - Margin around the root
10
+ * @property {number} [threshold] - Threshold for intersection
11
+ */
12
+
13
+ /**
14
+ * @typedef {Object} LazyloadOptions
15
+ * @property {IntersectionObserverConfig} [revealIntersectionObserverConfig] - Configuration for the reveal intersection observer
16
+ * @property {IntersectionObserverConfig} [loadIntersectionObserverConfig] - Configuration for the load intersection observer
17
+ * @property {IntersectionObserverConfig} [intersectionObserverConfig] - Configuration for general intersection observers
18
+ * @property {boolean} [useNativeLazyloadIfAvailable=true] - Whether to use native lazyloading if available
19
+ * @property {string} [mode='default'] - Lazyload mode
20
+ * @property {number} [minSize=40] - Minimum size for auto sizing
21
+ * @property {boolean} [updateSizes=true] - Whether to update sizes attribute
22
+ * @property {boolean} [registerCallback=true] - Whether to register a callback for APPLICATION_REVEALED event
23
+ */
24
+
25
+ /** @type {LazyloadOptions} */
7
26
  const DEFAULT_OPTIONS = {
8
27
  revealIntersectionObserverConfig: {
9
28
  rootMargin: '0px 100px 0px 100px',
@@ -20,7 +39,15 @@ const DEFAULT_OPTIONS = {
20
39
  registerCallback: true,
21
40
  }
22
41
 
42
+ /**
43
+ * Lazyload class for handling image lazy loading
44
+ */
23
45
  export default class Lazyload {
46
+ /**
47
+ * Create a new Lazyload instance
48
+ * @param {Object} app - Application instance
49
+ * @param {LazyloadOptions} [opts={}] - Lazyload options
50
+ */
24
51
  constructor(app, opts = {}) {
25
52
  this.app = app
26
53
  this.opts = _defaultsDeep(opts, DEFAULT_OPTIONS)