@brandocms/jupiter 5.0.0-beta.8 → 5.0.0-beta.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brandocms/jupiter",
3
- "version": "5.0.0-beta.8",
3
+ "version": "5.0.0-beta.9",
4
4
  "description": "Frontend helpers.",
5
5
  "author": "Univers/Twined",
6
6
  "license": "UNLICENSED",
@@ -3,6 +3,91 @@ import _defaultsDeep from 'lodash.defaultsdeep'
3
3
  import * as Events from '../../events'
4
4
  import { set } from '../../utils/motion-helpers'
5
5
 
6
+ /**
7
+ * @module Cookies
8
+ *
9
+ * Cookie consent module with optional dialog and toggle button support.
10
+ *
11
+ * ## Consent dialog
12
+ *
13
+ * The traditional consent banner uses a fixed container at the bottom of the page:
14
+ *
15
+ * ```html
16
+ * <div class="cookie-container">
17
+ * <div class="cookie-container-inner">
18
+ * <div class="cookie-law-text">
19
+ * <p>We use cookies...</p>
20
+ * </div>
21
+ * <div class="cookie-law-buttons">
22
+ * <button class="dismiss-cookielaw">Accept</button>
23
+ * <button class="refuse-cookielaw">Decline</button>
24
+ * </div>
25
+ * </div>
26
+ * </div>
27
+ * ```
28
+ *
29
+ * ## Consent toggle button
30
+ *
31
+ * A toggle button can be placed anywhere on the page to let users change their
32
+ * consent at any time. It can also serve as the sole consent mechanism (no
33
+ * dialog required).
34
+ *
35
+ * ```html
36
+ * <button data-cookie-consent
37
+ * data-cookie-consent-accept="Accept cookies"
38
+ * data-cookie-consent-refuse="Refuse cookies">
39
+ * </button>
40
+ * ```
41
+ *
42
+ * ### Data attributes
43
+ *
44
+ * | Attribute | Description |
45
+ * |---|---|
46
+ * | `data-cookie-consent` | Marks the element as a consent toggle |
47
+ * | `data-cookie-consent-accept` | Label shown when user can accept (currently refused/unset) |
48
+ * | `data-cookie-consent-refuse` | Label shown when user can retract (currently accepted) |
49
+ * | `data-cookie-consent-status` | Set by the module: `"accepted"` or `"refused"` |
50
+ * | `data-cookie-consent-icon` | Set on the injected icon `<span>` |
51
+ * | `data-cookie-consent-label` | Set on the injected label `<span>` |
52
+ *
53
+ * ### CSS styling
54
+ *
55
+ * ```css
56
+ * [data-cookie-consent-status="accepted"] [data-cookie-consent-icon] { color: green; }
57
+ * [data-cookie-consent-status="refused"] [data-cookie-consent-icon] { color: red; }
58
+ * ```
59
+ *
60
+ * ### Gettext / translation
61
+ *
62
+ * ```html
63
+ * <button data-cookie-consent
64
+ * data-cookie-consent-accept="{{ _('Accept cookies') }}"
65
+ * data-cookie-consent-refuse="{{ _('Refuse cookies') }}">
66
+ * </button>
67
+ * ```
68
+ *
69
+ * ## Usage examples
70
+ *
71
+ * Dialog only (default):
72
+ * ```js
73
+ * new Cookies(app)
74
+ * ```
75
+ *
76
+ * Toggle only (no dialog HTML needed):
77
+ * ```js
78
+ * new Cookies(app, { setCookies: (c) => { ... } })
79
+ * ```
80
+ *
81
+ * Both dialog and toggle:
82
+ * ```js
83
+ * new Cookies(app, {
84
+ * onConsentChanged: (c) => {
85
+ * console.log(c.getCookie('COOKIES_CONSENT_STATUS'))
86
+ * }
87
+ * })
88
+ * ```
89
+ */
90
+
6
91
  /**
7
92
  * @typedef {Object} CookiesOptions
8
93
  * @property {Function} [onAccept] - Called when cookies are accepted
@@ -11,6 +96,7 @@ import { set } from '../../utils/motion-helpers'
11
96
  * @property {Function} [alreadyRefused] - Called if user has already refused cookies
12
97
  * @property {Function} [setCookies] - Custom function to set cookies
13
98
  * @property {Function} [showCC] - Custom function to display cookie consent dialog
99
+ * @property {Function} [onConsentChanged] - Called after consent is toggled via the toggle button
14
100
  */
15
101
 
16
102
  /** @type {CookiesOptions} */
@@ -21,6 +107,7 @@ const DEFAULT_OPTIONS = {
21
107
 
22
108
  c.setCookie('COOKIES_CONSENT_STATUS', 1, oneYearFromNow, '/')
23
109
  c.opts.setCookies(c)
110
+ c.updateConsentToggles()
24
111
 
25
112
  const timeline = [
26
113
  [c.cc, { y: '120%' }, { duration: 0.35, ease: 'easeIn', at: 0 }],
@@ -37,6 +124,7 @@ const DEFAULT_OPTIONS = {
37
124
  oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1)
38
125
 
39
126
  c.setCookie('COOKIES_CONSENT_STATUS', 0, oneYearFromNow, '/')
127
+ c.updateConsentToggles()
40
128
 
41
129
  const timeline = [
42
130
  [c.cc, { y: '120%' }, { duration: 0.35, ease: 'easeIn', at: 0 }],
@@ -58,6 +146,8 @@ const DEFAULT_OPTIONS = {
58
146
 
59
147
  setCookies: (c) => {},
60
148
 
149
+ onConsentChanged: (c) => {},
150
+
61
151
  showCC: (c) => {
62
152
  if (c.hasCookie('COOKIES_CONSENT_STATUS')) {
63
153
  if (c.getCookie('COOKIES_CONSENT_STATUS') === '1') {
@@ -107,22 +197,114 @@ export default class Cookies {
107
197
  this.btn = document.querySelector('.dismiss-cookielaw')
108
198
  this.btnRefuse = document.querySelector('.refuse-cookielaw')
109
199
 
110
- if (!this.btn) {
200
+ this.setupConsentToggles()
201
+
202
+ if (!this.btn && this.consentToggles.length === 0) {
111
203
  return
112
204
  }
113
205
 
114
- this.app.registerCallback(Events.APPLICATION_REVEALED, () => {
115
- this.opts.showCC(this)
206
+ if (this.btn) {
207
+ this.app.registerCallback(Events.APPLICATION_REVEALED, () => {
208
+ this.opts.showCC(this)
209
+ })
210
+
211
+ this.btn.addEventListener('click', () => {
212
+ this.opts.onAccept(this)
213
+ })
214
+ if (this.btnRefuse) {
215
+ this.btnRefuse.addEventListener('click', () => {
216
+ this.opts.onRefuse(this)
217
+ })
218
+ }
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Find all `[data-cookie-consent]` elements and wire them up.
224
+ */
225
+ setupConsentToggles() {
226
+ this.consentToggles = [...document.querySelectorAll('[data-cookie-consent]')]
227
+
228
+ this.consentToggles.forEach(el => {
229
+ const icon = document.createElement('span')
230
+ icon.setAttribute('data-cookie-consent-icon', '')
231
+
232
+ const label = document.createElement('span')
233
+ label.setAttribute('data-cookie-consent-label', '')
234
+
235
+ el.appendChild(icon)
236
+ el.appendChild(label)
237
+
238
+ this.updateConsentToggle(el)
239
+
240
+ el.addEventListener('click', () => {
241
+ this.handleConsentToggle()
242
+ })
116
243
  })
244
+ }
117
245
 
118
- this.btn.addEventListener('click', () => {
119
- this.opts.onAccept(this)
246
+ /**
247
+ * Update a single consent toggle element to reflect current cookie state.
248
+ * @param {Element} el - The toggle element
249
+ */
250
+ updateConsentToggle(el) {
251
+ const accepted = this.getCookie('COOKIES_CONSENT_STATUS') === '1'
252
+ const acceptText = el.getAttribute('data-cookie-consent-accept') || 'Accept cookies'
253
+ const refuseText = el.getAttribute('data-cookie-consent-refuse') || 'Refuse cookies'
254
+
255
+ const icon = el.querySelector('[data-cookie-consent-icon]')
256
+ const label = el.querySelector('[data-cookie-consent-label]')
257
+
258
+ if (accepted) {
259
+ el.setAttribute('data-cookie-consent-status', 'accepted')
260
+ icon.textContent = '\u2713'
261
+ label.textContent = refuseText
262
+ } else {
263
+ el.setAttribute('data-cookie-consent-status', 'refused')
264
+ icon.textContent = '\u2715'
265
+ label.textContent = acceptText
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Update all consent toggle elements.
271
+ */
272
+ updateConsentToggles() {
273
+ this.consentToggles.forEach(el => {
274
+ this.updateConsentToggle(el)
120
275
  })
121
- if (this.btnRefuse) {
122
- this.btnRefuse.addEventListener('click', () => {
123
- this.opts.onRefuse(this)
276
+ }
277
+
278
+ /**
279
+ * Handle a click on a consent toggle button.
280
+ */
281
+ handleConsentToggle() {
282
+ const oneYearFromNow = new Date()
283
+ oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1)
284
+
285
+ const accepted = this.getCookie('COOKIES_CONSENT_STATUS') === '1'
286
+
287
+ if (accepted) {
288
+ this.setCookie('COOKIES_CONSENT_STATUS', 0, oneYearFromNow, '/')
289
+ } else {
290
+ this.setCookie('COOKIES_CONSENT_STATUS', 1, oneYearFromNow, '/')
291
+ this.opts.setCookies(this)
292
+ }
293
+
294
+ this.updateConsentToggles()
295
+
296
+ if (this.cc && this.cc.style.display !== 'none') {
297
+ const timeline = [
298
+ [this.cc, { y: '120%' }, { duration: 0.35, ease: 'easeIn', at: 0 }],
299
+ [this.inner, { opacity: 0 }, { duration: 0.3, ease: 'easeIn', at: 0 }]
300
+ ]
301
+
302
+ animate(timeline).finished.then(() => {
303
+ this.cc.style.display = 'none'
124
304
  })
125
305
  }
306
+
307
+ this.opts.onConsentChanged(this)
126
308
  }
127
309
 
128
310
  /**
@@ -209,7 +209,10 @@ export default class Lazyload {
209
209
  images.forEach(img => this.swapImage(img))
210
210
 
211
211
  const pictures = Dom.all($container, '[data-ll-srcset]')
212
- pictures.forEach(picture => this.revealPicture(picture))
212
+ pictures.forEach(picture => {
213
+ this.loadPicture(picture)
214
+ this.revealPicture(picture)
215
+ })
213
216
  }
214
217
 
215
218
  initializeResizeObserver() {
@@ -182,28 +182,9 @@ function horizontalLoop(app, items, config) {
182
182
  container.appendChild(clone)
183
183
  items.push(clone)
184
184
 
185
- // Register cloned lazyload elements with Lazyload module if available
186
- if (app?.lazyload?.observe) {
187
- // Clear data-ll-idx from unloaded [data-ll-image] images
188
- clone.querySelectorAll('[data-ll-image]:not([data-ll-loaded])').forEach(img => {
189
- img.removeAttribute('data-ll-idx')
190
- })
191
-
192
- // Clear attributes from unloaded [data-ll-srcset] pictures so they can be re-observed
193
- clone.querySelectorAll('[data-ll-srcset]:not([data-ll-srcset-ready])').forEach(picture => {
194
- picture.removeAttribute('data-ll-srcset-initialized')
195
- // Clear ready state from sources and img so they can be re-processed
196
- picture.querySelectorAll('source').forEach(source => {
197
- source.removeAttribute('data-ll-ready')
198
- })
199
- picture.querySelectorAll('img').forEach(img => {
200
- img.removeAttribute('data-ll-idx')
201
- img.removeAttribute('data-ll-loaded')
202
- img.removeAttribute('data-ll-ready')
203
- })
204
- })
205
-
206
- app.lazyload.observe(clone)
185
+ // Force-load cloned lazyload elements immediately to prevent flash on wrap
186
+ if (app?.lazyload?.forceLoad) {
187
+ app.lazyload.forceLoad(clone)
207
188
  }
208
189
  }
209
190
 
package/types/index.d.ts CHANGED
@@ -3,4 +3,4 @@ import imagesAreLoaded from './utils/imagesAreLoaded';
3
3
  import loadScript from './utils/loadScript';
4
4
  import prefersReducedMotion from './utils/prefersReducedMotion';
5
5
  import rafCallback from './utils/rafCallback';
6
- export { Application, Breakpoints, Cookies, CoverOverlay, Dataloader, Dom, DoubleHeader, Draggable, Dropdown, EqualHeightElements, EqualHeightImages, Events, FixedHeader, FooterReveal, Parallax, HeroSlider, HeroVideo, Lazyload, Lightbox, Links, Looper, Marquee, MobileMenu, Moonwalk, Popover, Popup, ScrollSpy, StackedBoxes, StickyHeader, Toggler, Typography, imageIsLoaded, imagesAreLoaded, loadScript, prefersReducedMotion, rafCallback, _defaultsDeep };
6
+ export { Application, Breakpoints, Cookies, CoverOverlay, Dataloader, Dom, DoubleHeader, Dropdown, EqualHeightElements, EqualHeightImages, Events, FixedHeader, FooterReveal, Parallax, HeroSlider, HeroVideo, Lazyload, Lightbox, Links, Looper, Marquee, MobileMenu, Moonwalk, Popover, Popup, ScrollSpy, StackedBoxes, StickyHeader, Toggler, Typography, imageIsLoaded, imagesAreLoaded, loadScript, prefersReducedMotion, rafCallback, _defaultsDeep, animate, scroll, stagger, motionValue };
@@ -16,6 +16,24 @@ export default class Cookies {
16
16
  btns: Element;
17
17
  btn: Element;
18
18
  btnRefuse: Element;
19
+ /**
20
+ * Find all `[data-cookie-consent]` elements and wire them up.
21
+ */
22
+ setupConsentToggles(): void;
23
+ consentToggles: Element[];
24
+ /**
25
+ * Update a single consent toggle element to reflect current cookie state.
26
+ * @param {Element} el - The toggle element
27
+ */
28
+ updateConsentToggle(el: Element): void;
29
+ /**
30
+ * Update all consent toggle elements.
31
+ */
32
+ updateConsentToggles(): void;
33
+ /**
34
+ * Handle a click on a consent toggle button.
35
+ */
36
+ handleConsentToggle(): void;
19
37
  /**
20
38
  * Get a cookie value by key
21
39
  * @param {string} sKey - Cookie key
@@ -78,4 +96,8 @@ export type CookiesOptions = {
78
96
  * - Custom function to display cookie consent dialog
79
97
  */
80
98
  showCC?: Function;
99
+ /**
100
+ * - Called after consent is toggled via the toggle button
101
+ */
102
+ onConsentChanged?: Function;
81
103
  };
@@ -20,6 +20,7 @@ export default class DoubleHeader {
20
20
  mobileMenuOpen: boolean;
21
21
  timer: any;
22
22
  resetResizeTimer: any;
23
+ scrollSettleTimeout: NodeJS.Timeout;
23
24
  firstReveal: boolean;
24
25
  initialize(): void;
25
26
  setupObserver(): void;
@@ -5,9 +5,9 @@ export default class Dropdown {
5
5
  elements: {};
6
6
  open: boolean;
7
7
  element: any;
8
- timeline: any;
9
8
  handleDocumentClick(event: any): void;
10
9
  initialize(): void;
10
+ positionMenu(): void;
11
11
  onClick(event: any): Promise<void>;
12
12
  openMenu(): Promise<void>;
13
13
  closeMenu(): Promise<void>;
@@ -30,6 +30,7 @@ export default class FixedHeader {
30
30
  mobileMenuOpen: boolean;
31
31
  timer: any;
32
32
  resetResizeTimer: any;
33
+ scrollSettleTimeout: NodeJS.Timeout;
33
34
  intersectingElements: any;
34
35
  initialize(): void;
35
36
  pageIsScrolledOnReady: boolean;
@@ -19,10 +19,20 @@ export default class HeroSlider {
19
19
  * Switches between slides
20
20
  */
21
21
  slide(type: any): void;
22
+ _currentAnimation: any;
22
23
  /**
23
24
  * Add a window resize handler that resizes slide widths
24
25
  */
25
26
  _addResizeHandler(): void;
26
27
  observer: IntersectionObserver;
27
28
  _resizeSlides(): void;
29
+ resizeAnimation: any;
30
+ /**
31
+ * Add a visibility change handler to restart animations when tab becomes visible
32
+ */
33
+ _addVisibilityHandler(): void;
34
+ /**
35
+ * Reset slide states and restart the animation cycle
36
+ */
37
+ _resetAndRestart(): void;
28
38
  }
@@ -15,6 +15,13 @@ export default class Lazyload {
15
15
  rafId: number;
16
16
  srcsetReadyObserver: MutationObserver;
17
17
  watch(): void;
18
+ /**
19
+ * Observe new lazyload elements within a container
20
+ * Handles both [data-ll-image] and [data-ll-srcset] elements
21
+ * Useful for dynamically added content (e.g., Looper clones)
22
+ * @param {HTMLElement|HTMLElement[]|NodeList} elements - Container element(s) or lazyload element(s) to observe
23
+ */
24
+ observe(elements: HTMLElement | HTMLElement[] | NodeList): void;
18
25
  initialize(): void;
19
26
  lazyPictures: any;
20
27
  loadObserver: IntersectionObserver;
@@ -19,8 +19,8 @@ export default class Lightbox {
19
19
  firstTransition: boolean;
20
20
  previousCaption: any;
21
21
  timelines: {
22
- caption: any;
23
- image: any;
22
+ caption: PausedTimeline;
23
+ image: PausedTimeline;
24
24
  };
25
25
  showBox(section: any, index: any): void;
26
26
  buildBox(section: any, index: any): void;
@@ -121,3 +121,4 @@ export type LightboxOptions = {
121
121
  */
122
122
  onClose?: Function;
123
123
  };
124
+ import { PausedTimeline } from '../../utils/motion-helpers';
@@ -1,127 +1,14 @@
1
1
  /**
2
- * Options for configuring the Looper module
3
- */
4
- export interface LooperOptions {
5
- /** Center the loop container. Can be true, false, or a selector string */
6
- center?: boolean | string;
7
- /** Enable snap-to-item behavior. Can be true, false, or a number for custom snap distance */
8
- snap?: boolean | number;
9
- /** Enable continuous auto-scrolling */
10
- crawl?: boolean;
11
- /** Enable infinite looping. If false, creates linear scrolling */
12
- loop?: boolean;
13
- /** Enable drag interaction with mouse/touch */
14
- draggable?: boolean;
15
- /** Speed multipliers for different breakpoints */
16
- speed?: {
17
- sm?: number;
18
- lg?: number;
19
- };
20
- /** Easing configuration for hover interactions */
21
- ease?: {
22
- mouseOver?: {
23
- speed?: number;
24
- duration?: number;
25
- };
26
- mouseOut?: {
27
- speed?: number;
28
- duration?: number;
29
- };
30
- };
31
- /** CSS selector for looper elements */
32
- selector?: string;
33
- /** Extra padding on the right side in pixels */
34
- paddingRight?: number | string;
35
- /** Start in reversed direction */
36
- reversed?: boolean;
37
- }
38
-
39
- /**
40
- * Loop controller returned by horizontalLoop function
41
- */
42
- export interface LoopController {
43
- /** Motion value tracking the current position */
44
- position: any;
45
- /** Main animation instance */
46
- animation: any;
47
- /** Array of item elements */
48
- items: HTMLElement[];
49
- /** Array of snap time positions */
50
- times: number[];
51
- /** Whether the loop is reversed */
52
- isReversed: boolean;
53
- /** Whether the loop is in looping mode */
54
- isLooping: boolean;
55
-
56
- /** Start/resume the loop animation */
57
- play(): void;
58
-
59
- /** Pause the loop animation */
60
- pause(): void;
61
-
62
- /** Get the current active item index */
63
- current(): number;
64
-
65
- /** Find the closest item index to current position */
66
- closestIndex(setCurrent?: boolean): number;
67
-
68
- /** Navigate to the next item */
69
- next(vars?: { duration?: number; easing?: string }): any;
70
-
71
- /** Navigate to the previous item */
72
- previous(vars?: { duration?: number; easing?: string }): any;
73
-
74
- /** Navigate to a specific item index */
75
- toIndex(index: number, vars?: { duration?: number; easing?: string }): any;
76
-
77
- /** Refresh measurements and recalculate (useful after resize) */
78
- refresh(deep?: boolean): void;
79
-
80
- /** Clean up and destroy the loop */
81
- destroy(): void;
82
- }
83
-
84
- /**
85
- * Looper Module
86
- * Creates seamless horizontal infinite scrolling carousels with drag interaction,
87
- * momentum/inertia, auto-crawl, snap-to-item, and responsive resize handling
2
+ * Looper Module Class
88
3
  */
89
4
  export default class Looper {
90
- /**
91
- * Create a new Looper instance
92
- * @param app - Jupiter application instance
93
- * @param opts - Configuration options
94
- */
95
- constructor(app: any, opts?: Partial<LooperOptions>);
96
-
97
- /** Configuration options */
98
- opts: LooperOptions;
99
-
100
- /** Jupiter application instance */
101
- app: any;
102
-
103
- /** Array of active loop controllers */
104
- loopers: LoopController[];
105
-
106
- /** Array of pending loopers waiting for initialization */
107
- pendingLoopers: any[];
108
-
109
- /** DOM elements matching the selector */
110
- looperElements: HTMLElement[];
111
-
112
- /**
113
- * Initialize the module and find all looper elements
114
- */
115
- init(): void;
116
-
117
- /**
118
- * Finalize loopers after APPLICATION:REVEALED event
119
- * This is when actual measurements and animations are set up
120
- */
121
- finalizeLoopers(): void;
122
-
123
- /**
124
- * Destroy all loopers and clean up
125
- */
126
- destroy(): void;
5
+ constructor(app: any, opts?: {});
6
+ app: any;
7
+ opts: any;
8
+ loopers: any[];
9
+ pendingLoopers: any[];
10
+ init(): void;
11
+ looperElements: any;
12
+ finalizeLoopers(): void;
13
+ destroy(): void;
127
14
  }
@@ -11,6 +11,7 @@ export default class Marquee {
11
11
  duration: number;
12
12
  clearHolders(): void;
13
13
  killTweens(): void;
14
+ speedAnimation: any;
14
15
  initializeTween(): void;
15
16
  play(rampUp?: boolean): void;
16
17
  playing: boolean;
@@ -19,5 +20,6 @@ export default class Marquee {
19
20
  speedUp(): void;
20
21
  setupObserver(): void;
21
22
  fillText(): void;
23
+ measuredHeight: any;
22
24
  setHeight(): void;
23
25
  }
@@ -15,7 +15,11 @@ export default class Moonwalk {
15
15
  id: string;
16
16
  el: any;
17
17
  name: any;
18
- timeline: any;
18
+ animation: {
19
+ lastDelay: number;
20
+ lastDuration: number;
21
+ lastStartTime: any;
22
+ };
19
23
  observer: any;
20
24
  stage: {
21
25
  name: any;
@@ -91,7 +95,11 @@ export default class Moonwalk {
91
95
  id: string;
92
96
  el: any;
93
97
  name: any;
94
- timeline: any;
98
+ animation: {
99
+ lastDelay: number;
100
+ lastDuration: number;
101
+ lastStartTime: any;
102
+ };
95
103
  observer: any;
96
104
  stage: {
97
105
  name: any;
@@ -104,7 +112,11 @@ export default class Moonwalk {
104
112
  id: string;
105
113
  el: any;
106
114
  name: any;
107
- timeline: any;
115
+ animation: {
116
+ lastDelay: number;
117
+ lastDuration: number;
118
+ lastStartTime: any;
119
+ };
108
120
  observer: any;
109
121
  stage: {
110
122
  name: any;
@@ -153,6 +165,24 @@ export default class Moonwalk {
153
165
  * @param {*} children
154
166
  */
155
167
  orderChildren(children: any): any[];
168
+ /**
169
+ * Calculate the delay for the next animation in the section.
170
+ * This replaces GSAP's timeline.recent() logic.
171
+ *
172
+ * @param {*} section - The section object
173
+ * @param {*} duration - Duration of the animation to add
174
+ * @param {*} overlap - How much the animations should overlap
175
+ * @returns {number} The delay in seconds
176
+ */
177
+ calculateDelay(section: any, duration: any, overlap: any): number;
178
+ /**
179
+ * Update the animation state after adding an animation.
180
+ *
181
+ * @param {*} section - The section object
182
+ * @param {*} delay - The delay that was used
183
+ * @param {*} duration - The duration of the animation
184
+ */
185
+ updateAnimationState(section: any, delay: any, duration: any): void;
156
186
  onReady(): void;
157
187
  /**
158
188
  * Called on `APPLICATION_READY` event, if `config.fireOnReady`.
@@ -16,7 +16,7 @@ export default class Popover {
16
16
  handleClick(e: any): void;
17
17
  get isVisible(): boolean;
18
18
  show(): void;
19
- updatePosition(animate?: boolean): void;
19
+ updatePosition(shouldAnimate?: boolean): void;
20
20
  hide(): void;
21
21
  toggle(): void;
22
22
  addDocumentClickHandler(): void;
@@ -31,6 +31,7 @@ export default class StickyHeader {
31
31
  mobileMenuOpen: boolean;
32
32
  timer: any;
33
33
  resetResizeTimer: any;
34
+ scrollSettleTimeout: NodeJS.Timeout;
34
35
  intersectingElements: any;
35
36
  initialize(): void;
36
37
  pageIsScrolledOnReady: boolean;
@@ -2,6 +2,22 @@
2
2
  * Toggler component for show/hide functionality
3
3
  * Uses [data-toggle-trigger] for the toggle button and [data-toggle-content] for toggleable content
4
4
  * Can be grouped using [data-toggle-group] to create accordion-like behavior
5
+ *
6
+ * IMPORTANT: For smooth animations, avoid padding/margins on [data-toggle-content].
7
+ * Instead, wrap content in a child element with padding/margins:
8
+ *
9
+ * @example
10
+ * // ❌ DON'T: Padding/margins directly on toggle content
11
+ * <div data-toggle-content style="padding: 20px; margin-top: 10px">
12
+ * Content here
13
+ * </div>
14
+ *
15
+ * // ✅ DO: Wrap content in child element
16
+ * <div data-toggle-content>
17
+ * <div style="padding: 20px; margin-top: 10px">
18
+ * Content here
19
+ * </div>
20
+ * </div>
5
21
  */
6
22
  export default class Toggler {
7
23
  /**
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Set properties immediately (like gsap.set)
3
+ * Uses direct DOM manipulation for synchronous style application
4
+ *
5
+ * @param {Element|string|NodeList|Array} target - Element(s) or selector
6
+ * @param {Object} values - Properties to set
7
+ */
8
+ export function set(target: Element | string | NodeList | any[], values: any): void;
9
+ /**
10
+ * Animate autoAlpha (opacity + visibility)
11
+ * Mimics GSAP's autoAlpha property
12
+ *
13
+ * @param {Element|string} target - Element or selector
14
+ * @param {number} value - Target alpha value (0 or 1)
15
+ * @param {Object} options - Animation options
16
+ * @returns {Object} Animation object
17
+ */
18
+ export function animateAutoAlpha(target: Element | string, value: number, options?: any): any;
19
+ /**
20
+ * Clear inline styles
21
+ * Mimics GSAP's clearProps
22
+ *
23
+ * @param {Element|string|NodeList|Array} target - Element(s) or selector
24
+ * @param {string|Array} props - Properties to clear or 'all'
25
+ */
26
+ export function clearProps(target: Element | string | NodeList | any[], props?: string | any[]): void;
27
+ /**
28
+ * Delayed call helper
29
+ * Mimics gsap.delayedCall
30
+ * Uses Motion's delay function (locked to animation frame loop for better sync)
31
+ *
32
+ * @param {number} duration - Delay in seconds
33
+ * @param {Function} callback - Callback function
34
+ * @returns {Promise} Promise that resolves after delay
35
+ */
36
+ export function delayedCall(duration: number, callback: Function): Promise<any>;
37
+ /**
38
+ * Convert GSAP easing strings to Motion.js compatible easings
39
+ * Handles common GSAP easing types and returns valid Motion.js easing
40
+ *
41
+ * @param {string|Array} easing - GSAP easing string or bezier array
42
+ * @returns {string|Array} Motion.js compatible easing
43
+ *
44
+ * Valid Motion.js easings:
45
+ * - "linear"
46
+ * - "easeIn"
47
+ * - "easeInOut"
48
+ * - "easeOut"
49
+ * - "circIn"
50
+ * - "circInOut"
51
+ * - "circOut"
52
+ * - "backIn"
53
+ * - "backInOut"
54
+ * - "backOut"
55
+ * - "anticipate"
56
+ * - Bezier arrays: [x1, y1, x2, y2]
57
+ */
58
+ export function convertEasing(easing: string | any[]): string | any[];
59
+ /**
60
+ * Paused Timeline helper
61
+ * Mimics GSAP's paused timeline pattern for building sequences
62
+ * Used by modules like Lightbox that build animations before playing them
63
+ */
64
+ export class PausedTimeline {
65
+ sequence: any[];
66
+ /**
67
+ * Add animation to timeline
68
+ * @param {Element|string} target - Element or selector
69
+ * @param {Object} values - Properties to animate
70
+ * @param {Object} options - Animation options
71
+ * @returns {PausedTimeline} this for chaining
72
+ */
73
+ to(target: Element | string, values: any, options?: any): PausedTimeline;
74
+ /**
75
+ * Add callback to timeline
76
+ * @param {Function} callback - Function to call
77
+ * @returns {PausedTimeline} this for chaining
78
+ */
79
+ call(callback: Function): PausedTimeline;
80
+ /**
81
+ * Clear timeline sequence
82
+ * @returns {PausedTimeline} this for chaining
83
+ */
84
+ clear(): PausedTimeline;
85
+ /**
86
+ * Play timeline sequence
87
+ * Executes all animations and callbacks in order
88
+ * @returns {Promise} Promise that resolves when sequence completes
89
+ */
90
+ play(): Promise<any>;
91
+ }