@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
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL synchronization module for Dataloader
|
|
3
|
+
* Handles bidirectional sync between dataloader parameters and browser URL
|
|
4
|
+
*/
|
|
5
|
+
export default class DataloaderUrlSync {
|
|
6
|
+
constructor(dataloader, config) {
|
|
7
|
+
this.dataloader = dataloader
|
|
8
|
+
this.config = config
|
|
9
|
+
this.language = document.documentElement.lang || 'en'
|
|
10
|
+
|
|
11
|
+
// Language handling options
|
|
12
|
+
this.languageInPath = config.languageInPath || false
|
|
13
|
+
this.hideDefaultLanguage = config.hideDefaultLanguage !== false // default true
|
|
14
|
+
this.defaultLanguage = config.defaultLanguage || 'en'
|
|
15
|
+
|
|
16
|
+
// Configure values that should be omitted from URLs (like "all" filters)
|
|
17
|
+
this.omitFromUrl = config.omitFromUrl || {
|
|
18
|
+
en: ['all'],
|
|
19
|
+
no: ['alle'],
|
|
20
|
+
// Add more languages as needed
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.initialize()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
initialize() {
|
|
27
|
+
// Set initial state from URL
|
|
28
|
+
this.syncFromUrl()
|
|
29
|
+
|
|
30
|
+
// Listen for browser navigation
|
|
31
|
+
this.popstateHandler = () => {
|
|
32
|
+
this.syncFromUrl()
|
|
33
|
+
this.dataloader.fetch()
|
|
34
|
+
}
|
|
35
|
+
window.addEventListener('popstate', this.popstateHandler)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Build URL from parameters using template
|
|
40
|
+
*/
|
|
41
|
+
buildUrl(params) {
|
|
42
|
+
// Use custom buildUrl function if provided
|
|
43
|
+
if (typeof this.config.buildUrl === 'function') {
|
|
44
|
+
return this.config.buildUrl(params, this.language, window.location.pathname)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const template = this.config.templates[this.language] ||
|
|
48
|
+
this.config.templates[this.defaultLanguage] ||
|
|
49
|
+
Object.values(this.config.templates)[0] // Fallback to first template
|
|
50
|
+
|
|
51
|
+
if (!template) {
|
|
52
|
+
console.error('No URL template found for dataloader:', this.dataloader.id)
|
|
53
|
+
return window.location.pathname
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Replace tokens in template
|
|
57
|
+
let url = template
|
|
58
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
59
|
+
// Check if this value should be omitted from URL for the current language
|
|
60
|
+
const omitValues = this.omitFromUrl[this.language] || this.omitFromUrl[this.defaultLanguage] || []
|
|
61
|
+
const shouldOmit = !value || omitValues.includes(value)
|
|
62
|
+
|
|
63
|
+
url = url.replace(`:${key}`, shouldOmit ? '' : value)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// Clean up any remaining tokens and trailing slashes
|
|
67
|
+
url = url.replace(/\/:[^\/]+/g, '')
|
|
68
|
+
url = url.replace(/\/+$/, '') // Remove trailing slashes
|
|
69
|
+
|
|
70
|
+
// Ensure we don't end up with empty path
|
|
71
|
+
if (!url || url === '') {
|
|
72
|
+
url = template.split(':')[0].replace(/\/+$/, '') || '/'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Add language prefix if configured
|
|
76
|
+
if (this.languageInPath) {
|
|
77
|
+
const shouldAddLang = this.language !== this.defaultLanguage || !this.hideDefaultLanguage
|
|
78
|
+
if (shouldAddLang && !url.startsWith(`/${this.language}/`)) {
|
|
79
|
+
url = `/${this.language}${url}`
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return url
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Parse current URL and extract parameters based on template
|
|
88
|
+
*/
|
|
89
|
+
parseUrl() {
|
|
90
|
+
// Use custom parseUrl function if provided
|
|
91
|
+
if (typeof this.config.parseUrl === 'function') {
|
|
92
|
+
return this.config.parseUrl(window.location.pathname, this.language)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const template = this.config.templates[this.language] ||
|
|
96
|
+
this.config.templates[this.defaultLanguage] ||
|
|
97
|
+
Object.values(this.config.templates)[0]
|
|
98
|
+
|
|
99
|
+
if (!template) {
|
|
100
|
+
return {}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let path = window.location.pathname
|
|
104
|
+
|
|
105
|
+
// Strip language prefix if configured
|
|
106
|
+
if (this.languageInPath) {
|
|
107
|
+
const langPrefix = `/${this.language}/`
|
|
108
|
+
if (path.startsWith(langPrefix)) {
|
|
109
|
+
path = path.substring(langPrefix.length - 1)
|
|
110
|
+
} else if (this.hideDefaultLanguage && path.startsWith('/')) {
|
|
111
|
+
// Path might not have language prefix if it's the default language
|
|
112
|
+
// Continue with the path as-is
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Convert template to regex pattern
|
|
117
|
+
// First escape special regex characters (except for our tokens)
|
|
118
|
+
let pattern = template.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
119
|
+
|
|
120
|
+
// Extract parameter names from template
|
|
121
|
+
const paramNames = []
|
|
122
|
+
pattern = pattern.replace(/:(\w+)/g, (match, paramName) => {
|
|
123
|
+
paramNames.push(paramName)
|
|
124
|
+
return '([^/]+)'
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// Make trailing parameters optional by replacing them with optional groups
|
|
128
|
+
const templateParts = template.split('/')
|
|
129
|
+
const pathParts = path.split('/')
|
|
130
|
+
|
|
131
|
+
// If path is shorter than template, try matching partial patterns
|
|
132
|
+
if (pathParts.length <= templateParts.length) {
|
|
133
|
+
const partialTemplate = templateParts.slice(0, pathParts.length).join('/')
|
|
134
|
+
let partialPattern = partialTemplate.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
135
|
+
const partialParamNames = []
|
|
136
|
+
partialPattern = partialPattern.replace(/:(\w+)/g, (match, paramName) => {
|
|
137
|
+
partialParamNames.push(paramName)
|
|
138
|
+
return '([^/]+)'
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
const partialRegex = new RegExp(`^${partialPattern}$`)
|
|
142
|
+
const partialMatch = path.match(partialRegex)
|
|
143
|
+
|
|
144
|
+
if (partialMatch) {
|
|
145
|
+
// Build params object from partial matches
|
|
146
|
+
const params = {}
|
|
147
|
+
partialParamNames.forEach((name, index) => {
|
|
148
|
+
if (partialMatch[index + 1]) {
|
|
149
|
+
params[name] = decodeURIComponent(partialMatch[index + 1])
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
return params
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Try full pattern match
|
|
157
|
+
const regex = new RegExp(`^${pattern}$`)
|
|
158
|
+
const match = path.match(regex)
|
|
159
|
+
|
|
160
|
+
if (!match) {
|
|
161
|
+
return {}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Build params object from matches
|
|
165
|
+
const params = {}
|
|
166
|
+
paramNames.forEach((name, index) => {
|
|
167
|
+
if (match[index + 1]) {
|
|
168
|
+
params[name] = decodeURIComponent(match[index + 1])
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
return params
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Update browser URL with current parameters
|
|
177
|
+
*/
|
|
178
|
+
updateUrl(params) {
|
|
179
|
+
const url = this.buildUrl(params)
|
|
180
|
+
|
|
181
|
+
// Only update if URL actually changed
|
|
182
|
+
if (url !== window.location.pathname) {
|
|
183
|
+
history.pushState(
|
|
184
|
+
{ dataloaderId: this.dataloader.id, params },
|
|
185
|
+
'',
|
|
186
|
+
url
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Sync dataloader parameters from current URL
|
|
193
|
+
*/
|
|
194
|
+
syncFromUrl() {
|
|
195
|
+
const params = this.parseUrl()
|
|
196
|
+
|
|
197
|
+
// Clear all current selections first
|
|
198
|
+
this.dataloader.$paramEls.forEach($el => {
|
|
199
|
+
$el.removeAttribute('data-loader-param-selected')
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
// Clear internal state
|
|
203
|
+
this.dataloader.opts.loaderParam = {}
|
|
204
|
+
|
|
205
|
+
// Update dataloader parameters from URL
|
|
206
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
207
|
+
// Find the corresponding data-loader-param element
|
|
208
|
+
const $paramEl = this.dataloader.$paramEls.find($el => {
|
|
209
|
+
const paramKey = $el.dataset.loaderParamKey || 'defaultParam'
|
|
210
|
+
return paramKey === key && $el.dataset.loaderParam === value
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
if ($paramEl) {
|
|
215
|
+
// Mark as selected
|
|
216
|
+
$paramEl.setAttribute('data-loader-param-selected', '')
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Always update internal state, even if no UI element found
|
|
220
|
+
// This ensures the API gets the parameter for filtering
|
|
221
|
+
if (key === 'defaultParam') {
|
|
222
|
+
this.dataloader.opts.loaderParam.defaultParam = value
|
|
223
|
+
} else {
|
|
224
|
+
this.dataloader.opts.loaderParam[key] = value
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Clean up event listeners
|
|
232
|
+
*/
|
|
233
|
+
destroy() {
|
|
234
|
+
if (this.popstateHandler) {
|
|
235
|
+
window.removeEventListener('popstate', this.popstateHandler)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
package/src/modules/Dom/index.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM utility class for simplifying DOM operations
|
|
3
|
+
*/
|
|
1
4
|
class DOM {
|
|
5
|
+
/**
|
|
6
|
+
* Create a new DOM utility instance
|
|
7
|
+
*/
|
|
2
8
|
constructor() {
|
|
3
9
|
this.body = document.body
|
|
4
10
|
this.html = document.documentElement
|
|
@@ -157,6 +163,24 @@ class DOM {
|
|
|
157
163
|
|
|
158
164
|
return vertInView && horInView
|
|
159
165
|
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Strict viewport check - element must be fully contained within viewport bounds
|
|
169
|
+
* Useful for popovers/tooltips that need to be completely visible
|
|
170
|
+
*
|
|
171
|
+
* @param {*} el
|
|
172
|
+
*/
|
|
173
|
+
inViewportStrict(el) {
|
|
174
|
+
const rect = el.getBoundingClientRect()
|
|
175
|
+
const windowHeight = window.innerHeight || document.documentElement.clientHeight
|
|
176
|
+
const windowWidth = window.innerWidth || document.documentElement.clientWidth
|
|
177
|
+
|
|
178
|
+
// Element must be fully within viewport bounds
|
|
179
|
+
const vertInView = rect.top >= 0 && rect.bottom <= windowHeight
|
|
180
|
+
const horInView = rect.left >= 0 && rect.right <= windowWidth
|
|
181
|
+
|
|
182
|
+
return vertInView && horInView
|
|
183
|
+
}
|
|
160
184
|
}
|
|
161
185
|
|
|
162
186
|
export default new DOM()
|