@vettvangur/vanilla 0.0.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 +0 -0
- package/dist/index.esm.js +587 -0
- package/dist/types/index.d.mts +249 -0
- package/dist/types/index.d.ts +249 -0
- package/package.json +37 -0
package/README.md
ADDED
|
File without changes
|
|
@@ -0,0 +1,587 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @memberof @vettvangur/react
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Capitalizes the first letter of a given string.
|
|
12
|
+
*
|
|
13
|
+
* @function capitalize
|
|
14
|
+
* @param {string|null|undefined} value - The string to capitalize. If null or undefined, returns an empty string.
|
|
15
|
+
* @param {boolean} [lowerRest=false] - If true, converts the rest of the string to lowercase.
|
|
16
|
+
* @returns {string} The capitalized string, or an empty string if the input is falsy.
|
|
17
|
+
*
|
|
18
|
+
* @example capitalize(string)
|
|
19
|
+
*/
|
|
20
|
+
function capitalize(value, lowerRest = false) {
|
|
21
|
+
if (!value) {
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
const firstChar = value[0].toUpperCase();
|
|
25
|
+
const rest = lowerRest ? value.slice(1).toLowerCase() : value.slice(1);
|
|
26
|
+
return firstChar + rest;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Retrieves a translated string from a dictionary based on a given key and culture.
|
|
31
|
+
*
|
|
32
|
+
* @function dictionary
|
|
33
|
+
* @param {string} key - The key for the translation.
|
|
34
|
+
* @param {Array} data - The array of translation objects.
|
|
35
|
+
* @param {string} [culture='is-IS'] - The language code to search for (default: 'is-IS').
|
|
36
|
+
* @returns {string} The translated string if found, otherwise '[Translation not found]'.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* dictionary(key)
|
|
40
|
+
*/
|
|
41
|
+
function dictionary(key, data, culture = 'is-IS') {
|
|
42
|
+
const notFound = '[Translation not found]';
|
|
43
|
+
for (const item of data) {
|
|
44
|
+
if (item.itemKey === key) {
|
|
45
|
+
const translation = item.values.find(b => b.language === culture)?.value;
|
|
46
|
+
return translation || notFound;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return notFound;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Fetches data from a given URL with customizable options and error handling.
|
|
54
|
+
*
|
|
55
|
+
* @async
|
|
56
|
+
* @function fetcher
|
|
57
|
+
* @param {Object} params - The parameters for the fetcher function.
|
|
58
|
+
* @param {string} params.url - The URL to fetch data from.
|
|
59
|
+
* @param {RequestInit|null} [params.options={}] - Fetch API options (headers, method, body, etc.).
|
|
60
|
+
* @param {boolean} [params.throwOnError=false] - Whether to throw an error on non-OK HTTP responses.
|
|
61
|
+
* @returns {Promise<Object|null>} The parsed JSON response or null if an error occurs.
|
|
62
|
+
* @throws Will throw an error if `throwOnError` is true and the fetch fails or returns a non-OK status.
|
|
63
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const getData = await fetcher({
|
|
67
|
+
* url,
|
|
68
|
+
* {
|
|
69
|
+
* method: 'POST',
|
|
70
|
+
* headers: {
|
|
71
|
+
* 'Content-Type': 'application/json'
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
* })
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
async function fetcher({
|
|
78
|
+
url,
|
|
79
|
+
options = null,
|
|
80
|
+
throwOnError = false
|
|
81
|
+
}) {
|
|
82
|
+
const errorMessage = `[fetcher :: fetcher] Error: ${url}`;
|
|
83
|
+
try {
|
|
84
|
+
const request = await fetch(url, options);
|
|
85
|
+
if (!request.ok) {
|
|
86
|
+
const errorDetails = await request.text();
|
|
87
|
+
const fullErrorMessage = `${errorMessage} - Status: ${request.status}, ${request.statusText}, Details: ${errorDetails}`;
|
|
88
|
+
console.error(fullErrorMessage);
|
|
89
|
+
if (throwOnError) {
|
|
90
|
+
throw new Error(fullErrorMessage);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Return null instead of undefined on error for predictable handling
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
return await request.json();
|
|
97
|
+
} catch (error) {
|
|
98
|
+
const fullErrorMessage = `${errorMessage} - ${error}`;
|
|
99
|
+
console.error(fullErrorMessage);
|
|
100
|
+
if (throwOnError) {
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Return null instead of undefined on error for predictable handling
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Loads environment variables from `.env` and `.env.[NODE_ENV]` files.
|
|
111
|
+
*
|
|
112
|
+
* This function first loads the base `.env` file, then loads an environment-specific file
|
|
113
|
+
* based on `NODE_ENV` (e.g., `.env.production`, `.env.development`). If `NODE_ENV` is not set,
|
|
114
|
+
* it defaults to `'development'`.
|
|
115
|
+
*
|
|
116
|
+
* @async
|
|
117
|
+
* @function loadEnvFiles
|
|
118
|
+
* @param {boolean} [showMessage=true] - Whether to log a message indicating which env file was loaded.
|
|
119
|
+
* @throws {Error} Throws an error if loading the environment-specific file fails.
|
|
120
|
+
* @returns {Promise<void>} Resolves when environment files are loaded.
|
|
121
|
+
*/
|
|
122
|
+
async function loadEnvFiles(showMessage = true) {
|
|
123
|
+
// Always load the .env file first
|
|
124
|
+
const envFilePath = path.resolve(process.cwd(), '.env');
|
|
125
|
+
const baseResult = dotenv.config({
|
|
126
|
+
path: envFilePath
|
|
127
|
+
});
|
|
128
|
+
if (baseResult.error) {
|
|
129
|
+
console.warn(`Warning: Failed to load environment variables from .env: ${baseResult.error.message}`);
|
|
130
|
+
}
|
|
131
|
+
const env = process.env.NODE_ENV || 'development'; // Default to 'development' if NODE_ENV is not set
|
|
132
|
+
const envFile = `.env.${env}`;
|
|
133
|
+
|
|
134
|
+
// Load the specified environment file
|
|
135
|
+
const result = dotenv.config({
|
|
136
|
+
path: path.resolve(process.cwd(), envFile)
|
|
137
|
+
});
|
|
138
|
+
if (result.error) {
|
|
139
|
+
throw new Error(`Failed to load environment variables from ${envFile}: ${result.error.message}`);
|
|
140
|
+
}
|
|
141
|
+
if (showMessage) {
|
|
142
|
+
console.log(`Loaded environment variables from ${envFile}\n`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Checks if a given string is a valid regular expression pattern.
|
|
148
|
+
*
|
|
149
|
+
* @ignore
|
|
150
|
+
* @param {string} pattern - The regex pattern to validate.
|
|
151
|
+
* @returns {boolean} Returns `true` if the pattern is a valid regex, otherwise `false`.
|
|
152
|
+
*/
|
|
153
|
+
function isValidRegex(pattern) {
|
|
154
|
+
try {
|
|
155
|
+
new RegExp(pattern);
|
|
156
|
+
return true;
|
|
157
|
+
} catch {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Utility object for regex operations.
|
|
164
|
+
*/
|
|
165
|
+
const regexr = {
|
|
166
|
+
/**
|
|
167
|
+
* Tests whether a given value matches a regex pattern.
|
|
168
|
+
*
|
|
169
|
+
* @param {Object} params - Parameters for testing regex.
|
|
170
|
+
* @param {string} params.value - The string to test against the regex.
|
|
171
|
+
* @param {string} params.pattern - The regex pattern to match.
|
|
172
|
+
* @param {string} [params.flags='g'] - Regex flags (default: 'g').
|
|
173
|
+
* @returns {boolean} Returns `true` if the value matches the pattern, otherwise `false`.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* const isMatch = regexr.match(pattern)
|
|
177
|
+
* console.log(isMatch) // return true or false
|
|
178
|
+
*/
|
|
179
|
+
test({
|
|
180
|
+
value,
|
|
181
|
+
pattern,
|
|
182
|
+
flags = 'g'
|
|
183
|
+
}) {
|
|
184
|
+
if (!value || !pattern || !isValidRegex(pattern)) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
const regexp = new RegExp(pattern, flags);
|
|
188
|
+
return regexp.test(value);
|
|
189
|
+
},
|
|
190
|
+
/**
|
|
191
|
+
* Matches a given value against a regex pattern and returns the matches.
|
|
192
|
+
*
|
|
193
|
+
* @param {Object} params - Parameters for matching regex.
|
|
194
|
+
* @param {string} params.value - The string to match against the regex.
|
|
195
|
+
* @param {string} params.pattern - The regex pattern to match.
|
|
196
|
+
* @param {string} [params.flags='g'] - Regex flags (default: 'g').
|
|
197
|
+
* @returns {Array<string>|null} Returns an array of matches, or `null` if no match is found.
|
|
198
|
+
*/
|
|
199
|
+
match({
|
|
200
|
+
value,
|
|
201
|
+
pattern,
|
|
202
|
+
flags = 'g'
|
|
203
|
+
}) {
|
|
204
|
+
if (!value || !pattern || !isValidRegex(pattern)) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
const regexp = new RegExp(pattern, flags);
|
|
208
|
+
return value.match(regexp);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Recursively flattens a nested object into a single-level object with prefixed keys.
|
|
214
|
+
*
|
|
215
|
+
* @param {Object} obj - The object to flatten.
|
|
216
|
+
* @param {string} [prefix=''] - The prefix to append to keys for nested properties.
|
|
217
|
+
* @returns {Object} A new object with flattened keys.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* const nested = { sm: '640px', md: { base: '768px', xl: '1024px' } };
|
|
221
|
+
* const result = flatten(nested);
|
|
222
|
+
* console.log(result); // { sm: '640px', md-base: '768px', md-xl: '1024px' }
|
|
223
|
+
*/
|
|
224
|
+
const flatten = (obj, prefix = '') => {
|
|
225
|
+
try {
|
|
226
|
+
if (!obj || typeof obj !== 'object') {
|
|
227
|
+
console.error('❌ FLATTEN ERROR: Received invalid data:', obj);
|
|
228
|
+
return {};
|
|
229
|
+
}
|
|
230
|
+
return Object.keys(obj).reduce((acc, key) => {
|
|
231
|
+
const fullKey = key === 'DEFAULT' ? prefix : prefix ? `${prefix}-${key}` : key;
|
|
232
|
+
if (typeof obj[key] === 'object' && key !== 'DEFAULT') {
|
|
233
|
+
Object.assign(acc, flatten(obj[key], fullKey));
|
|
234
|
+
} else if (typeof obj[key] === 'string') {
|
|
235
|
+
acc[fullKey] = obj[key];
|
|
236
|
+
} else {
|
|
237
|
+
console.warn('⚠️ Skipping Invalid Key:', key, 'Value:', obj[key]);
|
|
238
|
+
}
|
|
239
|
+
return acc;
|
|
240
|
+
}, {});
|
|
241
|
+
} catch (error) {
|
|
242
|
+
console.error('🚨 Flatten Function Error:', error);
|
|
243
|
+
return {}; // Prevents Tailwind from crashing
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Retrieves a template based on an alias, capitalizing the alias before lookup.
|
|
249
|
+
*
|
|
250
|
+
* @param {string} alias - The alias to search for in the templates object.
|
|
251
|
+
* @param {Object} templates - An object containing templates indexed by alias.
|
|
252
|
+
* @returns {*} - The matching template, or the 'Subpage' template if not found.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* const template = getTemplate('name', templates);
|
|
256
|
+
*
|
|
257
|
+
*/
|
|
258
|
+
function getTemplate(alias, templates) {
|
|
259
|
+
const template = templates[capitalize(alias)];
|
|
260
|
+
if (!template) {
|
|
261
|
+
return templates.Subpage;
|
|
262
|
+
}
|
|
263
|
+
return template;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Checks if a given value is empty (i.e., '', undefined, or null).
|
|
268
|
+
*
|
|
269
|
+
* @param {*} value - The value to check.
|
|
270
|
+
* @returns {boolean} - Returns `true` if the value is empty, otherwise `false`.
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* console.log(isEmpty('')); // true
|
|
274
|
+
* console.log(isEmpty(null)); // true
|
|
275
|
+
* console.log(isEmpty('hello')); // false
|
|
276
|
+
*/
|
|
277
|
+
function isEmpty(value) {
|
|
278
|
+
if (value === '' || value === undefined || value === null) {
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Compiles a module map, converting a selector-importer pair into a `Map` for efficient lookups.
|
|
285
|
+
*
|
|
286
|
+
* @function createModuleMap
|
|
287
|
+
* @param {Object} moduleMap - The module map where selectors are keys and dynamic imports are values.
|
|
288
|
+
* @returns {Map} A Map where selectors are keys and dynamic import functions are values.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* const moduleMap = {
|
|
292
|
+
* '.selector': () => import('components/component'),
|
|
293
|
+
* '.selector-1, .selector-2, .selector-3': () => import('components/component')
|
|
294
|
+
* };
|
|
295
|
+
* const compiledMap = createModuleMap(moduleMap);
|
|
296
|
+
*/
|
|
297
|
+
function createModuleMap(moduleMap) {
|
|
298
|
+
const compiledModuleMap = new Map();
|
|
299
|
+
Object.entries(moduleMap).forEach(([selector, importer]) => {
|
|
300
|
+
selector.split(',').forEach(subSelector => {
|
|
301
|
+
compiledModuleMap.set(subSelector.trim(), importer);
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
return compiledModuleMap;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Adds a preload class to the body element after a short delay.
|
|
309
|
+
* Also hides the preload animation after another delay.
|
|
310
|
+
*
|
|
311
|
+
* @function preloadTimeout
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* preloadTimeout(); // Adds 'loaded' class after a short delay, hides preload animation after another delay.
|
|
315
|
+
*/
|
|
316
|
+
function preloadTimeout() {
|
|
317
|
+
const body = document.querySelector('.body');
|
|
318
|
+
if (!body) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
setTimeout(() => body.classList.add('loaded'), 100);
|
|
322
|
+
setTimeout(() => {
|
|
323
|
+
body.classList.add('preload--hidden');
|
|
324
|
+
body.classList.remove('preload--transitions');
|
|
325
|
+
}, 400);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Lazy loads modules based on a selector in the provided module map using the IntersectionObserver API.
|
|
330
|
+
*
|
|
331
|
+
* @function lazyModules
|
|
332
|
+
* @param {Map} moduleMap - A map of selectors to dynamic import functions.
|
|
333
|
+
* @param {Element} [root=document] - The root element to query for selectors (defaults to `document`).
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* const moduleMap = new Map([
|
|
337
|
+
* ['.selector', () => import('components/component')],
|
|
338
|
+
* ['.selector-1, .selector-2, .selector-3', () => import('components/compomnent')],
|
|
339
|
+
* ]);
|
|
340
|
+
* lazyModules(moduleMap); // Lazy load the components when their selectors are in view.
|
|
341
|
+
*/
|
|
342
|
+
// @ts-ignore
|
|
343
|
+
function lazyModules(moduleMap, root = document) {
|
|
344
|
+
const observer = new IntersectionObserver(entries => {
|
|
345
|
+
entries.forEach(entry => {
|
|
346
|
+
if (entry.isIntersecting) {
|
|
347
|
+
const target = entry.target;
|
|
348
|
+
const matchedImporters = Array.from(moduleMap.entries()).filter(([selector]) => target.matches(selector)).map(([_, importer]) => importer);
|
|
349
|
+
if (matchedImporters.length > 0) {
|
|
350
|
+
Promise.allSettled(matchedImporters.map(importer => importer())).then(results => {
|
|
351
|
+
results.forEach(result => {
|
|
352
|
+
if (result.status === 'fulfilled' && result.value?.default?.init) {
|
|
353
|
+
result.value.default.init(target);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}).catch(console.error);
|
|
357
|
+
}
|
|
358
|
+
observer.unobserve(target);
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
moduleMap.forEach((_, selector) => {
|
|
363
|
+
root.querySelectorAll(selector).forEach(element => observer.observe(element));
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Initializes core scripts with an optional callback function.
|
|
369
|
+
*
|
|
370
|
+
* @function initCoreScripts
|
|
371
|
+
* @param {Function} callback - The callback function to initialize core scripts.
|
|
372
|
+
*
|
|
373
|
+
* @example
|
|
374
|
+
* initCoreScripts(() => { console.log('Core scripts initialized'); });
|
|
375
|
+
*/
|
|
376
|
+
function initCoreScripts(callback = null) {
|
|
377
|
+
import(path.resolve(process.cwd(), 'scripts', 'core', 'prefetch.ts')).then(module => module.default.init());
|
|
378
|
+
import(path.resolve(process.cwd(), 'scripts', 'core', 'recaptcha.ts')).then(module => module.default.init());
|
|
379
|
+
if (callback) {
|
|
380
|
+
callback();
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Handles the `DOMContentLoaded` event to initialize core scripts and lazy load modules.
|
|
386
|
+
*
|
|
387
|
+
* @function onDomReady
|
|
388
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
389
|
+
* @param {Function} initCoreScriptsCallback - The callback function to initialize core scripts.
|
|
390
|
+
* @param {Function} [callback] - An optional callback to execute during `DOMContentLoaded` event handling.
|
|
391
|
+
*
|
|
392
|
+
* @example
|
|
393
|
+
* onDomReady(moduleMap, () => { console.log('Core scripts initialized'); }, () => { console.log('DOM content loaded'); });
|
|
394
|
+
*/
|
|
395
|
+
function onDomReady(moduleMap, initCoreScriptsCallback, callback = null) {
|
|
396
|
+
document.addEventListener('DOMContentLoaded', e => {
|
|
397
|
+
preloadTimeout();
|
|
398
|
+
initCoreScripts(initCoreScriptsCallback);
|
|
399
|
+
lazyModules(moduleMap);
|
|
400
|
+
if (callback) {
|
|
401
|
+
callback(e);
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Handles the `popstate` event to initialize core scripts and lazy load modules.
|
|
408
|
+
*
|
|
409
|
+
* @function onPopstate
|
|
410
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
411
|
+
* @param {Function} initCoreScriptsCallback - The callback function to initialize core scripts.
|
|
412
|
+
* @param {Function} [callback] - An optional callback to execute during `popstate` event handling.
|
|
413
|
+
*
|
|
414
|
+
* @example
|
|
415
|
+
* onPopstate(moduleMap, () => { console.log('Core scripts initialized'); }, () => { console.log('Popstate event triggered'); });
|
|
416
|
+
*/
|
|
417
|
+
function onPopstate(moduleMap, initCoreScriptsCallback, callback = null) {
|
|
418
|
+
window.addEventListener('popstate', e => {
|
|
419
|
+
initCoreScripts(initCoreScriptsCallback);
|
|
420
|
+
lazyModules(moduleMap);
|
|
421
|
+
if (callback) {
|
|
422
|
+
callback(e);
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Handles the `htmx:beforeSwap` event to perform actions before HTMX swaps.
|
|
429
|
+
*
|
|
430
|
+
* @function onHtmxBeforeSwap
|
|
431
|
+
* @param {Function} callback - The callback function to execute during `htmx:beforeSwap` event handling.
|
|
432
|
+
*
|
|
433
|
+
* @example
|
|
434
|
+
* onHtmxBeforeSwap((e) => { console.log('HTMX before swap:', e); });
|
|
435
|
+
*/
|
|
436
|
+
function onHtmxBeforeSwap(callback = null) {
|
|
437
|
+
document.body.addEventListener('htmx:beforeSwap', e => {
|
|
438
|
+
document.querySelectorAll('.button--loading')?.forEach(btn => btn.classList.remove('button--loading'));
|
|
439
|
+
if (callback) {
|
|
440
|
+
callback(e);
|
|
441
|
+
}
|
|
442
|
+
setTimeout(() => window.scrollTo({
|
|
443
|
+
top: 0,
|
|
444
|
+
behavior: 'smooth'
|
|
445
|
+
}), 100);
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Handles the `htmx:afterSwap` event to initialize core scripts and lazy load modules.
|
|
451
|
+
*
|
|
452
|
+
* @function onHtmxAfterSwap
|
|
453
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
454
|
+
* @param {Function} [callback] - An optional callback to execute during `htmx:afterSwap` event handling.
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* onHtmxAfterSwap(moduleMap, () => { console.log('HTMX after swap completed'); });
|
|
458
|
+
*/
|
|
459
|
+
function onHtmxAfterSwap(moduleMap, callback = null) {
|
|
460
|
+
document.body.addEventListener('htmx:afterSwap', e => {
|
|
461
|
+
// TODO: is initCoreScripts needed here?
|
|
462
|
+
// initCoreScripts()
|
|
463
|
+
lazyModules(moduleMap);
|
|
464
|
+
if (callback) {
|
|
465
|
+
callback(e);
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Handles the `htmx:afterSettle` event to initialize core scripts and lazy load modules.
|
|
472
|
+
*
|
|
473
|
+
* @function onHtmxAfterSettle
|
|
474
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
475
|
+
* @param {Function} initCoreScriptsCallback - The callback function to initialize core scripts.
|
|
476
|
+
* @param {Function} [callback] - An optional callback to execute during `htmx:afterSettle` event handling.
|
|
477
|
+
*
|
|
478
|
+
* @example
|
|
479
|
+
* onHtmxAfterSettle(moduleMap, () => { console.log('Core scripts initialized'); }, () => { console.log('HTMX settle completed'); });
|
|
480
|
+
*/
|
|
481
|
+
function onHtmxAfterSettle(moduleMap, initCoreScriptsCallback, callback = null) {
|
|
482
|
+
document.body.addEventListener('htmx:afterSettle', e => {
|
|
483
|
+
initCoreScripts(initCoreScriptsCallback);
|
|
484
|
+
lazyModules(moduleMap);
|
|
485
|
+
if (callback) {
|
|
486
|
+
callback(e);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// /**
|
|
492
|
+
// * Handles the `htmx:responseErrnr` event to display error messages based on the HTTP status code.
|
|
493
|
+
// *
|
|
494
|
+
// * @function onHtmxResponseError
|
|
495
|
+
// * @param {Function} [callback] - An optional callback function to execute during handling of the error.
|
|
496
|
+
// * @ignore
|
|
497
|
+
// * @example
|
|
498
|
+
// * onHtmxResponseError(toaster, (e) => {
|
|
499
|
+
// * console.log('Custom error handling:', e);
|
|
500
|
+
// * });
|
|
501
|
+
// */
|
|
502
|
+
// export function onHtmxResponseError(callback) {
|
|
503
|
+
// if (!toaster) {
|
|
504
|
+
// console.error('[@vettvangur/vanilla | onHtmxResponseError | No toaster provided.')
|
|
505
|
+
// return
|
|
506
|
+
// }
|
|
507
|
+
|
|
508
|
+
// document.addEventListener('htmx:responseError', (e) => {
|
|
509
|
+
// e.stopImmediatePropagation()
|
|
510
|
+
// // @ts-ignore
|
|
511
|
+
// const statusCode = e?.detail?.xhr?.status
|
|
512
|
+
|
|
513
|
+
// if (statusCode === 404) {
|
|
514
|
+
// toaster.error('Page not found (404)')
|
|
515
|
+
// } else if (statusCode === 500) {
|
|
516
|
+
// toaster.error('Server error (500)')
|
|
517
|
+
// } else {
|
|
518
|
+
// toaster.error(`HTMX error with status code: ${statusCode}`)
|
|
519
|
+
// }
|
|
520
|
+
|
|
521
|
+
// e.stopPropagation()
|
|
522
|
+
|
|
523
|
+
// if (callback) {
|
|
524
|
+
// callback(e)
|
|
525
|
+
// }
|
|
526
|
+
// })
|
|
527
|
+
// }
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Handles click outside and ESC key events to trigger a callback and close open elements with the `open` class.
|
|
531
|
+
*
|
|
532
|
+
* @function clickOutside
|
|
533
|
+
* @param {Function} callback - The callback function to be executed when a click outside or ESC key event occurs.
|
|
534
|
+
* @description
|
|
535
|
+
* This function listens for `click` events and `keyup` events:
|
|
536
|
+
* - When a click outside of `.co-trigger` is detected, the provided callback is executed.
|
|
537
|
+
* - When the `ESC` key is pressed, the provided callback is executed, and any open elements (with the `open` class) are closed.
|
|
538
|
+
*
|
|
539
|
+
* @example
|
|
540
|
+
* ClickOutside(() => {
|
|
541
|
+
* console.log('Click outside or ESC pressed!');
|
|
542
|
+
* });
|
|
543
|
+
*/
|
|
544
|
+
function clickOutside(callback) {
|
|
545
|
+
// Clicks
|
|
546
|
+
document.addEventListener('click', e => {
|
|
547
|
+
const target = e.target;
|
|
548
|
+
const classTargets = document.querySelectorAll('.co-el');
|
|
549
|
+
|
|
550
|
+
// Check if the click target is inside an element with class `.co-trigger`
|
|
551
|
+
// @ts-ignore
|
|
552
|
+
if (target.closest('.co-trigger')) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Execute the callback function
|
|
557
|
+
callback(e);
|
|
558
|
+
|
|
559
|
+
// Close open elements
|
|
560
|
+
Array.prototype.forEach.call(classTargets, item => {
|
|
561
|
+
if (item.classList.contains('open')) {
|
|
562
|
+
item.classList.remove('open');
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
}, false);
|
|
566
|
+
|
|
567
|
+
// ESC key
|
|
568
|
+
document.addEventListener('keyup', e => {
|
|
569
|
+
const openElements = document.querySelectorAll('.open');
|
|
570
|
+
const keys = e.keyCode || e.which;
|
|
571
|
+
|
|
572
|
+
// If ESC key (key code 27) is pressed
|
|
573
|
+
if (keys === 27) {
|
|
574
|
+
// Execute the callback function
|
|
575
|
+
callback(e);
|
|
576
|
+
|
|
577
|
+
// Close open elements
|
|
578
|
+
Array.prototype.forEach.call(openElements, item => {
|
|
579
|
+
if (item.classList.contains('open')) {
|
|
580
|
+
item.classList.remove('open');
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export { capitalize, clickOutside, createModuleMap, dictionary, fetcher, flatten, getTemplate, initCoreScripts, isEmpty, lazyModules, loadEnvFiles, onDomReady, onHtmxAfterSettle, onHtmxAfterSwap, onHtmxBeforeSwap, onPopstate, preloadTimeout, regexr };
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capitalizes the first letter of a given string.
|
|
3
|
+
*
|
|
4
|
+
* @function capitalize
|
|
5
|
+
* @param {string|null|undefined} value - The string to capitalize. If null or undefined, returns an empty string.
|
|
6
|
+
* @param {boolean} [lowerRest=false] - If true, converts the rest of the string to lowercase.
|
|
7
|
+
* @returns {string} The capitalized string, or an empty string if the input is falsy.
|
|
8
|
+
*
|
|
9
|
+
* @example capitalize(string)
|
|
10
|
+
*/
|
|
11
|
+
export function capitalize(value: string | null | undefined, lowerRest?: boolean): string;
|
|
12
|
+
/**
|
|
13
|
+
* Retrieves a translated string from a dictionary based on a given key and culture.
|
|
14
|
+
*
|
|
15
|
+
* @function dictionary
|
|
16
|
+
* @param {string} key - The key for the translation.
|
|
17
|
+
* @param {Array} data - The array of translation objects.
|
|
18
|
+
* @param {string} [culture='is-IS'] - The language code to search for (default: 'is-IS').
|
|
19
|
+
* @returns {string} The translated string if found, otherwise '[Translation not found]'.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* dictionary(key)
|
|
23
|
+
*/
|
|
24
|
+
export function dictionary(key: string, data: any[], culture?: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Fetches data from a given URL with customizable options and error handling.
|
|
27
|
+
*
|
|
28
|
+
* @async
|
|
29
|
+
* @function fetcher
|
|
30
|
+
* @param {Object} params - The parameters for the fetcher function.
|
|
31
|
+
* @param {string} params.url - The URL to fetch data from.
|
|
32
|
+
* @param {RequestInit|null} [params.options={}] - Fetch API options (headers, method, body, etc.).
|
|
33
|
+
* @param {boolean} [params.throwOnError=false] - Whether to throw an error on non-OK HTTP responses.
|
|
34
|
+
* @returns {Promise<Object|null>} The parsed JSON response or null if an error occurs.
|
|
35
|
+
* @throws Will throw an error if `throwOnError` is true and the fetch fails or returns a non-OK status.
|
|
36
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* const getData = await fetcher({
|
|
40
|
+
* url,
|
|
41
|
+
* {
|
|
42
|
+
* method: 'POST',
|
|
43
|
+
* headers: {
|
|
44
|
+
* 'Content-Type': 'application/json'
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* })
|
|
48
|
+
*/
|
|
49
|
+
export function fetcher({ url, options, throwOnError }: {
|
|
50
|
+
url: string;
|
|
51
|
+
options?: RequestInit | null;
|
|
52
|
+
throwOnError?: boolean;
|
|
53
|
+
}): Promise<any | null>;
|
|
54
|
+
/**
|
|
55
|
+
* Loads environment variables from `.env` and `.env.[NODE_ENV]` files.
|
|
56
|
+
*
|
|
57
|
+
* This function first loads the base `.env` file, then loads an environment-specific file
|
|
58
|
+
* based on `NODE_ENV` (e.g., `.env.production`, `.env.development`). If `NODE_ENV` is not set,
|
|
59
|
+
* it defaults to `'development'`.
|
|
60
|
+
*
|
|
61
|
+
* @async
|
|
62
|
+
* @function loadEnvFiles
|
|
63
|
+
* @param {boolean} [showMessage=true] - Whether to log a message indicating which env file was loaded.
|
|
64
|
+
* @throws {Error} Throws an error if loading the environment-specific file fails.
|
|
65
|
+
* @returns {Promise<void>} Resolves when environment files are loaded.
|
|
66
|
+
*/
|
|
67
|
+
export function loadEnvFiles(showMessage?: boolean): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Retrieves a template based on an alias, capitalizing the alias before lookup.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} alias - The alias to search for in the templates object.
|
|
72
|
+
* @param {Object} templates - An object containing templates indexed by alias.
|
|
73
|
+
* @returns {*} - The matching template, or the 'Subpage' template if not found.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* const template = getTemplate('name', templates);
|
|
77
|
+
*
|
|
78
|
+
*/
|
|
79
|
+
export function getTemplate(alias: string, templates: any): any;
|
|
80
|
+
/**
|
|
81
|
+
* Checks if a given value is empty (i.e., '', undefined, or null).
|
|
82
|
+
*
|
|
83
|
+
* @param {*} value - The value to check.
|
|
84
|
+
* @returns {boolean} - Returns `true` if the value is empty, otherwise `false`.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* console.log(isEmpty('')); // true
|
|
88
|
+
* console.log(isEmpty(null)); // true
|
|
89
|
+
* console.log(isEmpty('hello')); // false
|
|
90
|
+
*/
|
|
91
|
+
export function isEmpty(value: any): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Compiles a module map, converting a selector-importer pair into a `Map` for efficient lookups.
|
|
94
|
+
*
|
|
95
|
+
* @function createModuleMap
|
|
96
|
+
* @param {Object} moduleMap - The module map where selectors are keys and dynamic imports are values.
|
|
97
|
+
* @returns {Map} A Map where selectors are keys and dynamic import functions are values.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const moduleMap = {
|
|
101
|
+
* '.selector': () => import('components/component'),
|
|
102
|
+
* '.selector-1, .selector-2, .selector-3': () => import('components/component')
|
|
103
|
+
* };
|
|
104
|
+
* const compiledMap = createModuleMap(moduleMap);
|
|
105
|
+
*/
|
|
106
|
+
export function createModuleMap(moduleMap: any): Map<any, any>;
|
|
107
|
+
/**
|
|
108
|
+
* Adds a preload class to the body element after a short delay.
|
|
109
|
+
* Also hides the preload animation after another delay.
|
|
110
|
+
*
|
|
111
|
+
* @function preloadTimeout
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* preloadTimeout(); // Adds 'loaded' class after a short delay, hides preload animation after another delay.
|
|
115
|
+
*/
|
|
116
|
+
export function preloadTimeout(): void;
|
|
117
|
+
/**
|
|
118
|
+
* Lazy loads modules based on a selector in the provided module map using the IntersectionObserver API.
|
|
119
|
+
*
|
|
120
|
+
* @function lazyModules
|
|
121
|
+
* @param {Map} moduleMap - A map of selectors to dynamic import functions.
|
|
122
|
+
* @param {Element} [root=document] - The root element to query for selectors (defaults to `document`).
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* const moduleMap = new Map([
|
|
126
|
+
* ['.selector', () => import('components/component')],
|
|
127
|
+
* ['.selector-1, .selector-2, .selector-3', () => import('components/compomnent')],
|
|
128
|
+
* ]);
|
|
129
|
+
* lazyModules(moduleMap); // Lazy load the components when their selectors are in view.
|
|
130
|
+
*/
|
|
131
|
+
export function lazyModules(moduleMap: Map<any, any>, root?: Element): void;
|
|
132
|
+
/**
|
|
133
|
+
* Initializes core scripts with an optional callback function.
|
|
134
|
+
*
|
|
135
|
+
* @function initCoreScripts
|
|
136
|
+
* @param {Function} callback - The callback function to initialize core scripts.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* initCoreScripts(() => { console.log('Core scripts initialized'); });
|
|
140
|
+
*/
|
|
141
|
+
export function initCoreScripts(callback?: Function): void;
|
|
142
|
+
/**
|
|
143
|
+
* Handles the `DOMContentLoaded` event to initialize core scripts and lazy load modules.
|
|
144
|
+
*
|
|
145
|
+
* @function onDomReady
|
|
146
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
147
|
+
* @param {Function} initCoreScriptsCallback - The callback function to initialize core scripts.
|
|
148
|
+
* @param {Function} [callback] - An optional callback to execute during `DOMContentLoaded` event handling.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* onDomReady(moduleMap, () => { console.log('Core scripts initialized'); }, () => { console.log('DOM content loaded'); });
|
|
152
|
+
*/
|
|
153
|
+
export function onDomReady(moduleMap: Map<any, any>, initCoreScriptsCallback: Function, callback?: Function): void;
|
|
154
|
+
/**
|
|
155
|
+
* Handles the `popstate` event to initialize core scripts and lazy load modules.
|
|
156
|
+
*
|
|
157
|
+
* @function onPopstate
|
|
158
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
159
|
+
* @param {Function} initCoreScriptsCallback - The callback function to initialize core scripts.
|
|
160
|
+
* @param {Function} [callback] - An optional callback to execute during `popstate` event handling.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* onPopstate(moduleMap, () => { console.log('Core scripts initialized'); }, () => { console.log('Popstate event triggered'); });
|
|
164
|
+
*/
|
|
165
|
+
export function onPopstate(moduleMap: Map<any, any>, initCoreScriptsCallback: Function, callback?: Function): void;
|
|
166
|
+
/**
|
|
167
|
+
* Handles the `htmx:beforeSwap` event to perform actions before HTMX swaps.
|
|
168
|
+
*
|
|
169
|
+
* @function onHtmxBeforeSwap
|
|
170
|
+
* @param {Function} callback - The callback function to execute during `htmx:beforeSwap` event handling.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* onHtmxBeforeSwap((e) => { console.log('HTMX before swap:', e); });
|
|
174
|
+
*/
|
|
175
|
+
export function onHtmxBeforeSwap(callback?: Function): void;
|
|
176
|
+
/**
|
|
177
|
+
* Handles the `htmx:afterSwap` event to initialize core scripts and lazy load modules.
|
|
178
|
+
*
|
|
179
|
+
* @function onHtmxAfterSwap
|
|
180
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
181
|
+
* @param {Function} [callback] - An optional callback to execute during `htmx:afterSwap` event handling.
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* onHtmxAfterSwap(moduleMap, () => { console.log('HTMX after swap completed'); });
|
|
185
|
+
*/
|
|
186
|
+
export function onHtmxAfterSwap(moduleMap: Map<any, any>, callback?: Function): void;
|
|
187
|
+
/**
|
|
188
|
+
* Handles the `htmx:afterSettle` event to initialize core scripts and lazy load modules.
|
|
189
|
+
*
|
|
190
|
+
* @function onHtmxAfterSettle
|
|
191
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
192
|
+
* @param {Function} initCoreScriptsCallback - The callback function to initialize core scripts.
|
|
193
|
+
* @param {Function} [callback] - An optional callback to execute during `htmx:afterSettle` event handling.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* onHtmxAfterSettle(moduleMap, () => { console.log('Core scripts initialized'); }, () => { console.log('HTMX settle completed'); });
|
|
197
|
+
*/
|
|
198
|
+
export function onHtmxAfterSettle(moduleMap: Map<any, any>, initCoreScriptsCallback: Function, callback?: Function): void;
|
|
199
|
+
/**
|
|
200
|
+
* Handles click outside and ESC key events to trigger a callback and close open elements with the `open` class.
|
|
201
|
+
*
|
|
202
|
+
* @function clickOutside
|
|
203
|
+
* @param {Function} callback - The callback function to be executed when a click outside or ESC key event occurs.
|
|
204
|
+
* @description
|
|
205
|
+
* This function listens for `click` events and `keyup` events:
|
|
206
|
+
* - When a click outside of `.co-trigger` is detected, the provided callback is executed.
|
|
207
|
+
* - When the `ESC` key is pressed, the provided callback is executed, and any open elements (with the `open` class) are closed.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ClickOutside(() => {
|
|
211
|
+
* console.log('Click outside or ESC pressed!');
|
|
212
|
+
* });
|
|
213
|
+
*/
|
|
214
|
+
export function clickOutside(callback: Function): void;
|
|
215
|
+
export namespace regexr {
|
|
216
|
+
/**
|
|
217
|
+
* Tests whether a given value matches a regex pattern.
|
|
218
|
+
*
|
|
219
|
+
* @param {Object} params - Parameters for testing regex.
|
|
220
|
+
* @param {string} params.value - The string to test against the regex.
|
|
221
|
+
* @param {string} params.pattern - The regex pattern to match.
|
|
222
|
+
* @param {string} [params.flags='g'] - Regex flags (default: 'g').
|
|
223
|
+
* @returns {boolean} Returns `true` if the value matches the pattern, otherwise `false`.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* const isMatch = regexr.match(pattern)
|
|
227
|
+
* console.log(isMatch) // return true or false
|
|
228
|
+
*/
|
|
229
|
+
function test({ value, pattern, flags }: {
|
|
230
|
+
value: string;
|
|
231
|
+
pattern: string;
|
|
232
|
+
flags?: string;
|
|
233
|
+
}): boolean;
|
|
234
|
+
/**
|
|
235
|
+
* Matches a given value against a regex pattern and returns the matches.
|
|
236
|
+
*
|
|
237
|
+
* @param {Object} params - Parameters for matching regex.
|
|
238
|
+
* @param {string} params.value - The string to match against the regex.
|
|
239
|
+
* @param {string} params.pattern - The regex pattern to match.
|
|
240
|
+
* @param {string} [params.flags='g'] - Regex flags (default: 'g').
|
|
241
|
+
* @returns {Array<string>|null} Returns an array of matches, or `null` if no match is found.
|
|
242
|
+
*/
|
|
243
|
+
function match({ value, pattern, flags }: {
|
|
244
|
+
value: string;
|
|
245
|
+
pattern: string;
|
|
246
|
+
flags?: string;
|
|
247
|
+
}): Array<string> | null;
|
|
248
|
+
}
|
|
249
|
+
export function flatten(obj: any, prefix?: string): any;
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capitalizes the first letter of a given string.
|
|
3
|
+
*
|
|
4
|
+
* @function capitalize
|
|
5
|
+
* @param {string|null|undefined} value - The string to capitalize. If null or undefined, returns an empty string.
|
|
6
|
+
* @param {boolean} [lowerRest=false] - If true, converts the rest of the string to lowercase.
|
|
7
|
+
* @returns {string} The capitalized string, or an empty string if the input is falsy.
|
|
8
|
+
*
|
|
9
|
+
* @example capitalize(string)
|
|
10
|
+
*/
|
|
11
|
+
export function capitalize(value: string | null | undefined, lowerRest?: boolean): string;
|
|
12
|
+
/**
|
|
13
|
+
* Retrieves a translated string from a dictionary based on a given key and culture.
|
|
14
|
+
*
|
|
15
|
+
* @function dictionary
|
|
16
|
+
* @param {string} key - The key for the translation.
|
|
17
|
+
* @param {Array} data - The array of translation objects.
|
|
18
|
+
* @param {string} [culture='is-IS'] - The language code to search for (default: 'is-IS').
|
|
19
|
+
* @returns {string} The translated string if found, otherwise '[Translation not found]'.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* dictionary(key)
|
|
23
|
+
*/
|
|
24
|
+
export function dictionary(key: string, data: any[], culture?: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Fetches data from a given URL with customizable options and error handling.
|
|
27
|
+
*
|
|
28
|
+
* @async
|
|
29
|
+
* @function fetcher
|
|
30
|
+
* @param {Object} params - The parameters for the fetcher function.
|
|
31
|
+
* @param {string} params.url - The URL to fetch data from.
|
|
32
|
+
* @param {RequestInit|null} [params.options={}] - Fetch API options (headers, method, body, etc.).
|
|
33
|
+
* @param {boolean} [params.throwOnError=false] - Whether to throw an error on non-OK HTTP responses.
|
|
34
|
+
* @returns {Promise<Object|null>} The parsed JSON response or null if an error occurs.
|
|
35
|
+
* @throws Will throw an error if `throwOnError` is true and the fetch fails or returns a non-OK status.
|
|
36
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* const getData = await fetcher({
|
|
40
|
+
* url,
|
|
41
|
+
* {
|
|
42
|
+
* method: 'POST',
|
|
43
|
+
* headers: {
|
|
44
|
+
* 'Content-Type': 'application/json'
|
|
45
|
+
* }
|
|
46
|
+
* }
|
|
47
|
+
* })
|
|
48
|
+
*/
|
|
49
|
+
export function fetcher({ url, options, throwOnError }: {
|
|
50
|
+
url: string;
|
|
51
|
+
options?: RequestInit | null;
|
|
52
|
+
throwOnError?: boolean;
|
|
53
|
+
}): Promise<any | null>;
|
|
54
|
+
/**
|
|
55
|
+
* Loads environment variables from `.env` and `.env.[NODE_ENV]` files.
|
|
56
|
+
*
|
|
57
|
+
* This function first loads the base `.env` file, then loads an environment-specific file
|
|
58
|
+
* based on `NODE_ENV` (e.g., `.env.production`, `.env.development`). If `NODE_ENV` is not set,
|
|
59
|
+
* it defaults to `'development'`.
|
|
60
|
+
*
|
|
61
|
+
* @async
|
|
62
|
+
* @function loadEnvFiles
|
|
63
|
+
* @param {boolean} [showMessage=true] - Whether to log a message indicating which env file was loaded.
|
|
64
|
+
* @throws {Error} Throws an error if loading the environment-specific file fails.
|
|
65
|
+
* @returns {Promise<void>} Resolves when environment files are loaded.
|
|
66
|
+
*/
|
|
67
|
+
export function loadEnvFiles(showMessage?: boolean): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Retrieves a template based on an alias, capitalizing the alias before lookup.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} alias - The alias to search for in the templates object.
|
|
72
|
+
* @param {Object} templates - An object containing templates indexed by alias.
|
|
73
|
+
* @returns {*} - The matching template, or the 'Subpage' template if not found.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* const template = getTemplate('name', templates);
|
|
77
|
+
*
|
|
78
|
+
*/
|
|
79
|
+
export function getTemplate(alias: string, templates: any): any;
|
|
80
|
+
/**
|
|
81
|
+
* Checks if a given value is empty (i.e., '', undefined, or null).
|
|
82
|
+
*
|
|
83
|
+
* @param {*} value - The value to check.
|
|
84
|
+
* @returns {boolean} - Returns `true` if the value is empty, otherwise `false`.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* console.log(isEmpty('')); // true
|
|
88
|
+
* console.log(isEmpty(null)); // true
|
|
89
|
+
* console.log(isEmpty('hello')); // false
|
|
90
|
+
*/
|
|
91
|
+
export function isEmpty(value: any): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Compiles a module map, converting a selector-importer pair into a `Map` for efficient lookups.
|
|
94
|
+
*
|
|
95
|
+
* @function createModuleMap
|
|
96
|
+
* @param {Object} moduleMap - The module map where selectors are keys and dynamic imports are values.
|
|
97
|
+
* @returns {Map} A Map where selectors are keys and dynamic import functions are values.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const moduleMap = {
|
|
101
|
+
* '.selector': () => import('components/component'),
|
|
102
|
+
* '.selector-1, .selector-2, .selector-3': () => import('components/component')
|
|
103
|
+
* };
|
|
104
|
+
* const compiledMap = createModuleMap(moduleMap);
|
|
105
|
+
*/
|
|
106
|
+
export function createModuleMap(moduleMap: any): Map<any, any>;
|
|
107
|
+
/**
|
|
108
|
+
* Adds a preload class to the body element after a short delay.
|
|
109
|
+
* Also hides the preload animation after another delay.
|
|
110
|
+
*
|
|
111
|
+
* @function preloadTimeout
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* preloadTimeout(); // Adds 'loaded' class after a short delay, hides preload animation after another delay.
|
|
115
|
+
*/
|
|
116
|
+
export function preloadTimeout(): void;
|
|
117
|
+
/**
|
|
118
|
+
* Lazy loads modules based on a selector in the provided module map using the IntersectionObserver API.
|
|
119
|
+
*
|
|
120
|
+
* @function lazyModules
|
|
121
|
+
* @param {Map} moduleMap - A map of selectors to dynamic import functions.
|
|
122
|
+
* @param {Element} [root=document] - The root element to query for selectors (defaults to `document`).
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* const moduleMap = new Map([
|
|
126
|
+
* ['.selector', () => import('components/component')],
|
|
127
|
+
* ['.selector-1, .selector-2, .selector-3', () => import('components/compomnent')],
|
|
128
|
+
* ]);
|
|
129
|
+
* lazyModules(moduleMap); // Lazy load the components when their selectors are in view.
|
|
130
|
+
*/
|
|
131
|
+
export function lazyModules(moduleMap: Map<any, any>, root?: Element): void;
|
|
132
|
+
/**
|
|
133
|
+
* Initializes core scripts with an optional callback function.
|
|
134
|
+
*
|
|
135
|
+
* @function initCoreScripts
|
|
136
|
+
* @param {Function} callback - The callback function to initialize core scripts.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* initCoreScripts(() => { console.log('Core scripts initialized'); });
|
|
140
|
+
*/
|
|
141
|
+
export function initCoreScripts(callback?: Function): void;
|
|
142
|
+
/**
|
|
143
|
+
* Handles the `DOMContentLoaded` event to initialize core scripts and lazy load modules.
|
|
144
|
+
*
|
|
145
|
+
* @function onDomReady
|
|
146
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
147
|
+
* @param {Function} initCoreScriptsCallback - The callback function to initialize core scripts.
|
|
148
|
+
* @param {Function} [callback] - An optional callback to execute during `DOMContentLoaded` event handling.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* onDomReady(moduleMap, () => { console.log('Core scripts initialized'); }, () => { console.log('DOM content loaded'); });
|
|
152
|
+
*/
|
|
153
|
+
export function onDomReady(moduleMap: Map<any, any>, initCoreScriptsCallback: Function, callback?: Function): void;
|
|
154
|
+
/**
|
|
155
|
+
* Handles the `popstate` event to initialize core scripts and lazy load modules.
|
|
156
|
+
*
|
|
157
|
+
* @function onPopstate
|
|
158
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
159
|
+
* @param {Function} initCoreScriptsCallback - The callback function to initialize core scripts.
|
|
160
|
+
* @param {Function} [callback] - An optional callback to execute during `popstate` event handling.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* onPopstate(moduleMap, () => { console.log('Core scripts initialized'); }, () => { console.log('Popstate event triggered'); });
|
|
164
|
+
*/
|
|
165
|
+
export function onPopstate(moduleMap: Map<any, any>, initCoreScriptsCallback: Function, callback?: Function): void;
|
|
166
|
+
/**
|
|
167
|
+
* Handles the `htmx:beforeSwap` event to perform actions before HTMX swaps.
|
|
168
|
+
*
|
|
169
|
+
* @function onHtmxBeforeSwap
|
|
170
|
+
* @param {Function} callback - The callback function to execute during `htmx:beforeSwap` event handling.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* onHtmxBeforeSwap((e) => { console.log('HTMX before swap:', e); });
|
|
174
|
+
*/
|
|
175
|
+
export function onHtmxBeforeSwap(callback?: Function): void;
|
|
176
|
+
/**
|
|
177
|
+
* Handles the `htmx:afterSwap` event to initialize core scripts and lazy load modules.
|
|
178
|
+
*
|
|
179
|
+
* @function onHtmxAfterSwap
|
|
180
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
181
|
+
* @param {Function} [callback] - An optional callback to execute during `htmx:afterSwap` event handling.
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* onHtmxAfterSwap(moduleMap, () => { console.log('HTMX after swap completed'); });
|
|
185
|
+
*/
|
|
186
|
+
export function onHtmxAfterSwap(moduleMap: Map<any, any>, callback?: Function): void;
|
|
187
|
+
/**
|
|
188
|
+
* Handles the `htmx:afterSettle` event to initialize core scripts and lazy load modules.
|
|
189
|
+
*
|
|
190
|
+
* @function onHtmxAfterSettle
|
|
191
|
+
* @param {Map} moduleMap - The compiled module map for lazy loading.
|
|
192
|
+
* @param {Function} initCoreScriptsCallback - The callback function to initialize core scripts.
|
|
193
|
+
* @param {Function} [callback] - An optional callback to execute during `htmx:afterSettle` event handling.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* onHtmxAfterSettle(moduleMap, () => { console.log('Core scripts initialized'); }, () => { console.log('HTMX settle completed'); });
|
|
197
|
+
*/
|
|
198
|
+
export function onHtmxAfterSettle(moduleMap: Map<any, any>, initCoreScriptsCallback: Function, callback?: Function): void;
|
|
199
|
+
/**
|
|
200
|
+
* Handles click outside and ESC key events to trigger a callback and close open elements with the `open` class.
|
|
201
|
+
*
|
|
202
|
+
* @function clickOutside
|
|
203
|
+
* @param {Function} callback - The callback function to be executed when a click outside or ESC key event occurs.
|
|
204
|
+
* @description
|
|
205
|
+
* This function listens for `click` events and `keyup` events:
|
|
206
|
+
* - When a click outside of `.co-trigger` is detected, the provided callback is executed.
|
|
207
|
+
* - When the `ESC` key is pressed, the provided callback is executed, and any open elements (with the `open` class) are closed.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ClickOutside(() => {
|
|
211
|
+
* console.log('Click outside or ESC pressed!');
|
|
212
|
+
* });
|
|
213
|
+
*/
|
|
214
|
+
export function clickOutside(callback: Function): void;
|
|
215
|
+
export namespace regexr {
|
|
216
|
+
/**
|
|
217
|
+
* Tests whether a given value matches a regex pattern.
|
|
218
|
+
*
|
|
219
|
+
* @param {Object} params - Parameters for testing regex.
|
|
220
|
+
* @param {string} params.value - The string to test against the regex.
|
|
221
|
+
* @param {string} params.pattern - The regex pattern to match.
|
|
222
|
+
* @param {string} [params.flags='g'] - Regex flags (default: 'g').
|
|
223
|
+
* @returns {boolean} Returns `true` if the value matches the pattern, otherwise `false`.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* const isMatch = regexr.match(pattern)
|
|
227
|
+
* console.log(isMatch) // return true or false
|
|
228
|
+
*/
|
|
229
|
+
function test({ value, pattern, flags }: {
|
|
230
|
+
value: string;
|
|
231
|
+
pattern: string;
|
|
232
|
+
flags?: string;
|
|
233
|
+
}): boolean;
|
|
234
|
+
/**
|
|
235
|
+
* Matches a given value against a regex pattern and returns the matches.
|
|
236
|
+
*
|
|
237
|
+
* @param {Object} params - Parameters for matching regex.
|
|
238
|
+
* @param {string} params.value - The string to match against the regex.
|
|
239
|
+
* @param {string} params.pattern - The regex pattern to match.
|
|
240
|
+
* @param {string} [params.flags='g'] - Regex flags (default: 'g').
|
|
241
|
+
* @returns {Array<string>|null} Returns an array of matches, or `null` if no match is found.
|
|
242
|
+
*/
|
|
243
|
+
function match({ value, pattern, flags }: {
|
|
244
|
+
value: string;
|
|
245
|
+
pattern: string;
|
|
246
|
+
flags?: string;
|
|
247
|
+
}): Array<string> | null;
|
|
248
|
+
}
|
|
249
|
+
export function flatten(obj: any, prefix?: string): any;
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vettvangur/vanilla",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Vettvangur | Vanilla JS Utility Library",
|
|
5
|
+
"access": "private",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [],
|
|
8
|
+
"author": "Vettvangur",
|
|
9
|
+
"license": "ISC",
|
|
10
|
+
"main": "./dist/index.esm.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": "./dist/index.esm.js"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"dotenv": "16.4.5"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@rollup/plugin-babel": "6.0.4",
|
|
23
|
+
"@rollup/plugin-commonjs": "28.0.1",
|
|
24
|
+
"@rollup/plugin-json": "6.1.0",
|
|
25
|
+
"@rollup/plugin-node-resolve": "15.3.0",
|
|
26
|
+
"@rollup/plugin-typescript": "12.1.1",
|
|
27
|
+
"rollup": "4.28.1",
|
|
28
|
+
"rollup-plugin-terser": "7.0.2",
|
|
29
|
+
"shx": "0.3.4",
|
|
30
|
+
"typescript": "^5.7.3"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"bundle": "pnpm types & rollup -c",
|
|
34
|
+
"dist": "pnpm publish",
|
|
35
|
+
"types": "tsc -p tsconfig.json & shx mv dist/types/index.d.mts dist/types/index.d.ts"
|
|
36
|
+
}
|
|
37
|
+
}
|