@brandocms/jupiter 4.0.0-beta.1 → 5.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 (50) hide show
  1. package/README.md +191 -2
  2. package/package.json +20 -18
  3. package/src/index.js +10 -10
  4. package/src/modules/Application/index.js +203 -157
  5. package/src/modules/Cookies/index.js +34 -55
  6. package/src/modules/CoverOverlay/index.js +20 -13
  7. package/src/modules/Dataloader/index.js +71 -24
  8. package/src/modules/Dataloader/url-sync.js +238 -0
  9. package/src/modules/Dom/index.js +18 -0
  10. package/src/modules/DoubleHeader/index.js +571 -0
  11. package/src/modules/Dropdown/index.js +101 -75
  12. package/src/modules/EqualHeightElements/index.js +5 -7
  13. package/src/modules/EqualHeightImages/index.js +7 -2
  14. package/src/modules/FixedHeader/index.js +60 -30
  15. package/src/modules/FooterReveal/index.js +3 -3
  16. package/src/modules/HeroSlider/index.js +207 -91
  17. package/src/modules/HeroVideo/index.js +15 -27
  18. package/src/modules/Lazyload/index.js +101 -80
  19. package/src/modules/Lightbox/index.js +17 -55
  20. package/src/modules/Links/index.js +54 -49
  21. package/src/modules/Looper/index.js +1737 -0
  22. package/src/modules/Marquee/index.js +106 -37
  23. package/src/modules/MobileMenu/index.js +70 -124
  24. package/src/modules/Moonwalk/index.js +349 -150
  25. package/src/modules/Popover/index.js +186 -28
  26. package/src/modules/Popup/index.js +27 -34
  27. package/src/modules/StackedBoxes/index.js +3 -3
  28. package/src/modules/StickyHeader/index.js +364 -155
  29. package/src/modules/Toggler/index.js +184 -27
  30. package/src/utils/motion-helpers.js +330 -0
  31. package/types/index.d.ts +1 -30
  32. package/types/modules/Application/index.d.ts +6 -6
  33. package/types/modules/Breakpoints/index.d.ts +2 -0
  34. package/types/modules/Dataloader/index.d.ts +5 -2
  35. package/types/modules/Dataloader/url-sync.d.ts +36 -0
  36. package/types/modules/Dom/index.d.ts +7 -0
  37. package/types/modules/DoubleHeader/index.d.ts +63 -0
  38. package/types/modules/Dropdown/index.d.ts +7 -30
  39. package/types/modules/EqualHeightImages/index.d.ts +1 -1
  40. package/types/modules/FixedHeader/index.d.ts +1 -1
  41. package/types/modules/Lazyload/index.d.ts +9 -9
  42. package/types/modules/Lightbox/index.d.ts +0 -5
  43. package/types/modules/Looper/index.d.ts +127 -0
  44. package/types/modules/Moonwalk/index.d.ts +6 -15
  45. package/types/modules/Parallax/index.d.ts +10 -32
  46. package/types/modules/Popover/index.d.ts +12 -0
  47. package/types/modules/Popup/index.d.ts +6 -19
  48. package/types/modules/ScrollSpy/index.d.ts +1 -1
  49. package/types/modules/StickyHeader/index.d.ts +171 -14
  50. package/types/modules/Toggler/index.d.ts +24 -2
package/README.md CHANGED
@@ -237,7 +237,6 @@ include images from this section. Otherwise, all lightboxed images will be inclu
237
237
 
238
238
  - `trigger` - `false` - selector representing an element you want to use as a trigger to open lightbox
239
239
  - `captions` - `false` - whether to show captions or not in the overlay
240
- - `swipe` - `true` – if swipe is true, native zoom won't work, so allow choosing
241
240
  - `elements` - `object` - switch out default elements in the overlay
242
241
  - `arrowRight` - `function` - returns an element
243
242
  - `arrowLeft` - `function` - returns an element
@@ -277,6 +276,33 @@ HTML
277
276
  </div>
278
277
  ```
279
278
 
279
+ #### Group Functionality
280
+
281
+ You can group togglers together to create an accordion-like behavior where only one toggler in the group can be open at a time. When you open one toggler, all others in the same group will close automatically.
282
+
283
+ ```html
284
+ <div data-toggle data-toggle-group="phases">
285
+ <button data-toggle-trigger="phase1">Phase 1 <span class="arrow icon">&darr;</span></button>
286
+ <div class="panel" data-toggle-content="phase1">
287
+ Phase 1 content
288
+ </div>
289
+ </div>
290
+
291
+ <div data-toggle data-toggle-group="phases">
292
+ <button data-toggle-trigger="phase2">Phase 2 <span class="arrow icon">&darr;</span></button>
293
+ <div class="panel" data-toggle-content="phase2">
294
+ Phase 2 content
295
+ </div>
296
+ </div>
297
+
298
+ <div data-toggle data-toggle-group="phases">
299
+ <button data-toggle-trigger="phase3">Phase 3 <span class="arrow icon">&darr;</span></button>
300
+ <div class="panel" data-toggle-content="phase3">
301
+ Phase 3 content
302
+ </div>
303
+ </div>
304
+ ```
305
+
280
306
  CSS
281
307
  ```css
282
308
  [data-toggle-trigger] {
@@ -290,6 +316,14 @@ CSS
290
316
  }
291
317
  }
292
318
 
319
+ /* Style active trigger elements */
320
+ [data-toggle-trigger][data-toggle-trigger-active] {
321
+ background-color: #e8f4ff;
322
+ border-color: #4a90e2;
323
+ color: #0056b3;
324
+ font-weight: bold;
325
+ }
326
+
293
327
  [data-toggle-content] {
294
328
  height: 0;
295
329
  overflow: hidden;
@@ -313,6 +347,136 @@ togglers.forEach(toggleEl => {
313
347
  #### Options
314
348
 
315
349
 
350
+ ## Dataloader
351
+
352
+ A component for dynamically loading and filtering content via AJAX with optional URL synchronization.
353
+
354
+ ### Basic Usage
355
+
356
+ HTML:
357
+ ```html
358
+ <div data-loader="/api/articles" data-loader-id="articles">
359
+ <div class="filters">
360
+ <a href="#" data-loader-param="all" data-loader-param-selected>All</a>
361
+ <a href="#" data-loader-param="tech" data-loader-param-key="category">Technology</a>
362
+ <a href="#" data-loader-param="design" data-loader-param-key="category">Design</a>
363
+ </div>
364
+
365
+ <div data-loader-canvas>
366
+ <!-- Content will be loaded here -->
367
+ </div>
368
+
369
+ <button data-loader-more>Load More</button>
370
+ </div>
371
+ ```
372
+
373
+ JavaScript:
374
+ ```js
375
+ import { Dataloader } from '@brandocms/jupiter'
376
+
377
+ const dataloader = new Dataloader(app, $loaderEl, {
378
+ onFetch: (dataloader) => {
379
+ // Initialize components after content loads
380
+ const mw = new Moonwalk(app, {}, dataloader.$canvasEl)
381
+ new Lazyload(app, {}, dataloader.$canvasEl)
382
+ mw.ready()
383
+ }
384
+ })
385
+ ```
386
+
387
+ ### URL Synchronization
388
+
389
+ Enable bidirectional sync between dataloader parameters and browser URL:
390
+
391
+ ```js
392
+ // Configure URL patterns for different dataloaders
393
+ const urlConfigs = {
394
+ events: {
395
+ templates: {
396
+ en: '/events/:location/:type',
397
+ no: '/arrangementer/:location/:type'
398
+ },
399
+ updateOnInit: false // Don't update URL on initialization
400
+ },
401
+ news: {
402
+ templates: {
403
+ en: '/news/:category/:year',
404
+ no: '/nyheter/:category/:year'
405
+ }
406
+ }
407
+ }
408
+
409
+ // Initialize all dataloaders with URL sync
410
+ app.dataloaders = []
411
+ Dom.all('[data-loader]').forEach($dl => {
412
+ app.dataloaders.push(
413
+ new Dataloader(app, $dl, {
414
+ urlSync: urlConfigs,
415
+ onFetch: (dataloader) => {
416
+ // Your onFetch logic
417
+ }
418
+ })
419
+ )
420
+ })
421
+ ```
422
+
423
+ ### Split Layout
424
+
425
+ Components can be placed outside the main dataloader element:
426
+
427
+ ```html
428
+ <!-- Sidebar -->
429
+ <div data-loader="/api/articles" data-loader-id="articles">
430
+ <a href="#" data-loader-param="tech" data-loader-param-key="category">Tech</a>
431
+ </div>
432
+
433
+ <!-- Main content area -->
434
+ <div data-loader-canvas-for="articles">
435
+ <!-- Content loads here -->
436
+ </div>
437
+
438
+ <!-- Footer -->
439
+ <button data-loader-more-for="articles">Load More</button>
440
+ <input data-loader-filter-for="articles" placeholder="Search...">
441
+ ```
442
+
443
+ ### Options
444
+
445
+ - `page` - `number` - Initial page number (default: 0)
446
+ - `loaderParam` - `object` - Initial parameters
447
+ - `filter` - `string` - Initial filter value
448
+ - `onFetch` - `function` - Called after content is fetched
449
+ - `urlSync` - `object` - URL synchronization configuration:
450
+ - `templates` - Language-specific URL templates with `:param` placeholders
451
+ - `updateOnInit` - `boolean` - Update URL on initialization (default: true)
452
+ - `languageInPath` - `boolean` - Include language in URL path
453
+ - `hideDefaultLanguage` - `boolean` - Hide default language from URL (default: true)
454
+ - `defaultLanguage` - `string` - Default language code (default: 'en')
455
+ - `buildUrl` - `function` - Custom URL building function
456
+ - `parseUrl` - `function` - Custom URL parsing function
457
+
458
+ ### Attributes
459
+
460
+ - `data-loader="/api/endpoint"` - Main container with API endpoint
461
+ - `data-loader-id="unique-id"` - Unique identifier for the dataloader
462
+ - `data-loader-canvas` - Container where content will be loaded
463
+ - `data-loader-canvas-for="id"` - Canvas for specific dataloader (split layout)
464
+ - `data-loader-param="value"` - Parameter value to send to API
465
+ - `data-loader-param-key="key"` - Parameter key (default: 'defaultParam')
466
+ - `data-loader-param-multi` - Allow multiple selections for this parameter
467
+ - `data-loader-param-selected` - Marks parameter as selected
468
+ - `data-loader-more` - Load more button
469
+ - `data-loader-more-for="id"` - Load more for specific dataloader (split layout)
470
+ - `data-loader-filter` - Filter input field
471
+ - `data-loader-filter-for="id"` - Filter for specific dataloader (split layout)
472
+ - `data-loader-loading` - Added during loading
473
+ - `data-loader-starved` - Added to load more button when no more content
474
+
475
+ ### API Response Headers
476
+
477
+ - `jpt-dataloader: starved` - Set this header when there's no more content to load
478
+
479
+
316
480
  ## Links
317
481
 
318
482
  #### Options
@@ -752,7 +916,15 @@ const customPopup = new Popup(app, '[data-popup][data-popup-key="custom"]', {
752
916
  </div>
753
917
  ```
754
918
 
755
- ## StickyHeader
919
+ ## DoubleHeader
920
+
921
+ A dual-header module that clones the original header element. The clone stays fixed and
922
+ hides when scrolling down, revealing on scroll up. Uses IntersectionObserver to detect
923
+ when the original header is visible.
924
+
925
+ > **Note:** This module was previously named `StickyHeader`. It was renamed to `DoubleHeader`
926
+ > to better reflect its dual-header/clone architecture. The new `StickyHeader` module uses
927
+ > CSS `position: sticky` instead.
756
928
 
757
929
  * header element should not have position: fixed
758
930
 
@@ -785,6 +957,23 @@ const customPopup = new Popup(app, '[data-popup][data-popup-key="custom"]', {
785
957
  before tweening into view
786
958
 
787
959
 
960
+ ## StickyHeader
961
+
962
+ A header that uses `position: sticky`. Hides when scrolling down and is revealed on scrolling up.
963
+ Unlike FixedHeader, the sticky header stays in document flow - when hidden via transform,
964
+ its space is still reserved.
965
+
966
+ > **Note:** This is a new module. If you were using the old `StickyHeader` (which cloned the header),
967
+ > you should now use `DoubleHeader` instead.
968
+
969
+ * header element needs `position: sticky; top: 0;`
970
+ * No padding-top needed on content below (header stays in document flow)
971
+
972
+ ### Options
973
+
974
+ Same options as FixedHeader - see FixedHeader documentation below.
975
+
976
+
788
977
  ## FixedHeader
789
978
 
790
979
  * header element needs position: fixed;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brandocms/jupiter",
3
- "version": "4.0.0-beta.1",
3
+ "version": "5.0.0-beta.1",
4
4
  "description": "Frontend helpers.",
5
5
  "author": "Univers/Twined",
6
6
  "license": "UNLICENSED",
@@ -23,34 +23,36 @@
23
23
  "scripts": {
24
24
  "test": "playwright test",
25
25
  "types": "tsc",
26
- "playwright": "playwright test",
26
+ "playwright": "playwright test --project=chromium --reporter line",
27
27
  "playwright:ui": "playwright test --ui",
28
28
  "playwright:report": "playwright show-report",
29
- "playwright:moonwalk": "playwright test e2e/moonwalk.spec.js --project=chromium",
30
- "playwright:lazyload": "playwright test e2e/lazyload.spec.js --project=chromium",
31
- "playwright:toggler": "playwright test e2e/toggler.spec.js --project=chromium",
32
- "playwright:breakpoints": "playwright test e2e/breakpoints.spec.js --project=chromium",
33
- "playwright:typography": "playwright test e2e/typography.spec.js --project=chromium",
34
- "playwright:popover": "playwright test e2e/popover.spec.js --project=chromium",
35
- "playwright:popup": "playwright test e2e/popup.spec.js --project=chromium",
36
- "playwright:dataloader": "playwright test e2e/dataloader.spec.js --project=chromium",
37
- "playwright:parallax": "playwright test e2e/parallax.spec.js --project=chromium ",
29
+ "playwright:moonwalk": "playwright test e2e/moonwalk.spec.js --project=chromium --reporter line",
30
+ "playwright:lazyload": "playwright test e2e/lazyload.spec.js --project=chromium --reporter line",
31
+ "playwright:toggler": "playwright test e2e/toggler.spec.js --project=chromium --reporter line",
32
+ "playwright:breakpoints": "playwright test e2e/breakpoints.spec.js --project=chromium --reporter line",
33
+ "playwright:typography": "playwright test e2e/typography.spec.js --project=chromium --reporter line",
34
+ "playwright:popover": "playwright test e2e/popover.spec.js e2e/popover.click.spec.js e2e/popover.follow.spec.js --project=chromium --reporter line",
35
+ "playwright:popup": "playwright test e2e/popup.spec.js --project=chromium --reporter line",
36
+ "playwright:dataloader": "playwright test e2e/dataloader.spec.js --project=chromium --reporter line",
37
+ "playwright:dataloader-url-sync": "playwright test e2e/dataloader-url-sync.spec.js --project=chromium --reporter line",
38
+ "playwright:parallax": "playwright test e2e/parallax.spec.js --project=chromium --reporter line",
38
39
  "vite": "vite",
39
40
  "vite:build": "vite build",
40
41
  "vite:preview": "vite preview"
41
42
  },
42
43
  "types": "types/index.d.ts",
43
44
  "dependencies": {
44
- "@egjs/hammerjs": "^2.0.17",
45
45
  "body-scroll-lock": "^4.0.0-beta.0",
46
- "gsap": "^3.12.7",
47
- "lodash.defaultsdeep": "^4.6.1"
46
+ "gsap": "^3.13.0",
47
+ "lodash.defaultsdeep": "^4.6.1",
48
+ "motion": "^12.23.24",
49
+ "virtual-scroll": "^2.2.1"
48
50
  },
49
51
  "devDependencies": {
50
- "@playwright/test": "^1.51.1",
51
- "@types/node": "^22.13.10",
52
- "typescript": "^5.8.2",
53
- "vite": "^6.2.2"
52
+ "@playwright/test": "^1.52.0",
53
+ "@types/node": "^22.15.16",
54
+ "typescript": "^5.8.3",
55
+ "vite": "^6.3.5"
54
56
  },
55
57
  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
56
58
  }
package/src/index.js CHANGED
@@ -3,9 +3,8 @@
3
3
  * @module jupiter
4
4
  */
5
5
 
6
- import { CSSPlugin, Draggable, ScrollToPlugin, ScrollTrigger, gsap } from 'gsap/all'
6
+ import { animate, scroll, stagger, motionValue } from 'motion'
7
7
 
8
- import Hammer from '@egjs/hammerjs'
9
8
  import _defaultsDeep from 'lodash.defaultsdeep'
10
9
 
11
10
  import Application from './modules/Application'
@@ -14,6 +13,7 @@ import Cookies from './modules/Cookies'
14
13
  import CoverOverlay from './modules/CoverOverlay'
15
14
  import Dataloader from './modules/Dataloader'
16
15
  import Dom from './modules/Dom'
16
+ import DoubleHeader from './modules/DoubleHeader'
17
17
  import Dropdown from './modules/Dropdown'
18
18
  import EqualHeightElements from './modules/EqualHeightElements'
19
19
  import EqualHeightImages from './modules/EqualHeightImages'
@@ -26,6 +26,7 @@ import HeroVideo from './modules/HeroVideo'
26
26
  import Lazyload from './modules/Lazyload'
27
27
  import Lightbox from './modules/Lightbox'
28
28
  import Links from './modules/Links'
29
+ import Looper from './modules/Looper'
29
30
  import Marquee from './modules/Marquee'
30
31
  import MobileMenu from './modules/MobileMenu'
31
32
  import Moonwalk from './modules/Moonwalk'
@@ -50,7 +51,7 @@ export {
50
51
  CoverOverlay,
51
52
  Dataloader,
52
53
  Dom,
53
- Draggable,
54
+ DoubleHeader,
54
55
  Dropdown,
55
56
  EqualHeightElements,
56
57
  EqualHeightImages,
@@ -63,6 +64,7 @@ export {
63
64
  Lazyload,
64
65
  Lightbox,
65
66
  Links,
67
+ Looper,
66
68
  Marquee,
67
69
  MobileMenu,
68
70
  Moonwalk,
@@ -82,11 +84,9 @@ export {
82
84
  rafCallback,
83
85
  _defaultsDeep,
84
86
 
85
- // Export some of the libs we use,
86
- // that can also be used in the main frontend.
87
- gsap,
88
- CSSPlugin,
89
- ScrollToPlugin,
90
- ScrollTrigger,
91
- Hammer
87
+ // Export Motion functions for animation
88
+ animate,
89
+ scroll,
90
+ stagger,
91
+ motionValue,
92
92
  }