@vettvangur/vanilla 0.0.58 → 0.0.60

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/dist/index.esm.js CHANGED
@@ -1,30 +1,30 @@
1
- /**
2
- * vanilla :: index.mjs.
3
- *
4
- * Vanilla JS helper utilities.
5
- *
6
- * These docs are generated from inline JSDoc in the repo and are intended for contributors.
7
- *
8
- * @generated
9
- * @module vanilla
1
+ /**
2
+ * vanilla :: index.mjs.
3
+ *
4
+ * Vanilla JS helper utilities.
5
+ *
6
+ * These docs are generated from inline JSDoc in the repo and are intended for contributors.
7
+ *
8
+ * @generated
9
+ * @module vanilla
10
10
  */
11
11
 
12
- /**
13
- * @memberof @vettvangur/vanilla
12
+ /**
13
+ * @memberof @vettvangur/vanilla
14
14
  */
15
15
 
16
- /**
17
- * Capitalize.
18
- *
19
- * @param value - Value.
20
- * @param lowerRest - Value.
21
- * @returns Result of the operation.
22
- *
23
- * @example
24
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
25
- * // import { capitalize } from '@vettvangur/vanilla'
26
- *
27
- * capitalize(value, lowerRest)
16
+ /**
17
+ * Capitalize.
18
+ *
19
+ * @param value - Value.
20
+ * @param lowerRest - Value.
21
+ * @returns Result of the operation.
22
+ *
23
+ * @example
24
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
25
+ * // import { capitalize } from '@vettvangur/vanilla'
26
+ *
27
+ * capitalize(value, lowerRest)
28
28
  */
29
29
  function capitalize(value, lowerRest = false) {
30
30
  if (!value) {
@@ -35,50 +35,62 @@ function capitalize(value, lowerRest = false) {
35
35
  return firstChar + rest;
36
36
  }
37
37
 
38
- /**
39
- * Dictionary.
40
- *
41
- * @param key - Value.
42
- * @param data - Value.
43
- * @param culture - Value.
44
- * @returns Result of the operation.
45
- *
46
- * @example
47
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
48
- * // import { dictionary } from '@vettvangur/vanilla'
49
- *
50
- * dictionary(key, data, culture)
38
+ /**
39
+ * Dictionary.
40
+ *
41
+ * @param key - Value.
42
+ * @param data - Value.
43
+ * @param culture - Value.
44
+ * @returns Result of the operation.
45
+ *
46
+ * @example
47
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
48
+ * // import { dictionary } from '@vettvangur/vanilla'
49
+ *
50
+ * dictionary(key, data, culture)
51
51
  */
52
+ // WeakMap keyed by the input `data` array gives us O(1) memo lookups while
53
+ // still letting unreachable translation arrays be garbage-collected.
54
+ const dictionaryIndex = new WeakMap();
52
55
  function dictionary(key, data, culture = 'is-IS') {
56
+ var _item$values$find;
53
57
  const notFound = '[Translation not found]';
54
58
  if (data === null || data === undefined) {
55
59
  return notFound;
56
60
  }
57
- for (const item of data) {
58
- if (item.itemKey === key) {
59
- var _item$values$find;
60
- const translation = (_item$values$find = item.values.find(b => b.language === culture)) === null || _item$values$find === void 0 ? void 0 : _item$values$find.value;
61
- return translation || notFound;
61
+ let byKey = dictionaryIndex.get(data);
62
+ if (!byKey) {
63
+ byKey = new Map();
64
+ for (const _item of data) {
65
+ if (_item && _item.itemKey) {
66
+ byKey.set(_item.itemKey, _item);
67
+ }
62
68
  }
69
+ dictionaryIndex.set(data, byKey);
70
+ }
71
+ const item = byKey.get(key);
72
+ if (!item) {
73
+ return notFound;
63
74
  }
64
- return notFound;
75
+ const translation = (_item$values$find = item.values.find(b => b.language === culture)) === null || _item$values$find === void 0 ? void 0 : _item$values$find.value;
76
+ return translation || notFound;
65
77
  }
66
78
 
67
- /**
68
- * Fetcher.
69
- *
70
- * @param {object} options - Options object.
71
- * @param {string} options.url - Value.
72
- * @param {any} [options.options=null] - Options that control behavior.
73
- * @param {boolean} [options.throwOnError=false] - Value.
74
- * @returns Result of the operation.
75
- * @throws When the operation fails.
76
- *
77
- * @example
78
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
79
- * // import { fetcher } from '@vettvangur/vanilla'
80
- *
81
- * await fetcher({ url: url, options: {}, throwOnError: throwOnError })
79
+ /**
80
+ * Fetcher.
81
+ *
82
+ * @param {object} options - Options object.
83
+ * @param {string} options.url - Value.
84
+ * @param {any} [options.options=null] - Options that control behavior.
85
+ * @param {boolean} [options.throwOnError=false] - Value.
86
+ * @returns Result of the operation.
87
+ * @throws When the operation fails.
88
+ *
89
+ * @example
90
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
91
+ * // import { fetcher } from '@vettvangur/vanilla'
92
+ *
93
+ * await fetcher({ url: url, options: {}, throwOnError: throwOnError })
82
94
  */
83
95
 
84
96
  async function fetcher({
@@ -90,35 +102,27 @@ async function fetcher({
90
102
  try {
91
103
  const request = await fetch(url, options);
92
104
  if (!request.ok) {
93
- const errorDetails = await request.text();
94
- const fullErrorMessage = `${errorMessage} - Status: ${request.status}, ${request.statusText}, Details: ${errorDetails}`;
95
- console.error(fullErrorMessage);
96
105
  if (throwOnError) {
97
- throw new Error(fullErrorMessage);
106
+ const errorDetails = await request.text();
107
+ throw new Error(`${errorMessage} - Status: ${request.status}, ${request.statusText}, Details: ${errorDetails}`);
98
108
  }
99
-
100
- // Return null instead of undefined on error for predictable handling
101
109
  return null;
102
110
  }
103
111
  return await request.json();
104
112
  } catch (error) {
105
- const fullErrorMessage = `${errorMessage} - ${error}`;
106
- console.error(fullErrorMessage);
107
113
  if (throwOnError) {
108
114
  throw error;
109
115
  }
110
-
111
- // Return null instead of undefined on error for predictable handling
112
116
  return null;
113
117
  }
114
118
  }
115
119
 
116
- /**
117
- * Checks if a given string is a valid regular expression pattern.
118
- *
119
- * @ignore
120
- * @param {string} pattern - The regex pattern to validate.
121
- * @returns {boolean} Returns `true` if the pattern is a valid regex, otherwise `false`.
120
+ /**
121
+ * Checks if a given string is a valid regular expression pattern.
122
+ *
123
+ * @ignore
124
+ * @param {string} pattern - The regex pattern to validate.
125
+ * @returns {boolean} Returns `true` if the pattern is a valid regex, otherwise `false`.
122
126
  */
123
127
  function isValidRegex(pattern) {
124
128
  try {
@@ -129,25 +133,25 @@ function isValidRegex(pattern) {
129
133
  }
130
134
  }
131
135
 
132
- /**
133
- * Regexr.
134
- *
135
- * @example
136
- * console.log(regexr)
136
+ /**
137
+ * Regexr.
138
+ *
139
+ * @example
140
+ * console.log(regexr)
137
141
  */
138
142
  const regexr = {
139
- /**
140
- * Tests whether a given value matches a regex pattern.
141
- *
142
- * @param {Object} params - Parameters for testing regex.
143
- * @param {string} params.value - The string to test against the regex.
144
- * @param {string} params.pattern - The regex pattern to match.
145
- * @param {string} [params.flags='g'] - Regex flags (default: 'g').
146
- * @returns {boolean} Returns `true` if the value matches the pattern, otherwise `false`.
147
- *
148
- * @example
149
- * const isMatch = regexr.match(pattern)
150
- * console.log(isMatch) // return true or false
143
+ /**
144
+ * Tests whether a given value matches a regex pattern.
145
+ *
146
+ * @param {Object} params - Parameters for testing regex.
147
+ * @param {string} params.value - The string to test against the regex.
148
+ * @param {string} params.pattern - The regex pattern to match.
149
+ * @param {string} [params.flags='g'] - Regex flags (default: 'g').
150
+ * @returns {boolean} Returns `true` if the value matches the pattern, otherwise `false`.
151
+ *
152
+ * @example
153
+ * const isMatch = regexr.match(pattern)
154
+ * console.log(isMatch) // return true or false
151
155
  */
152
156
  test({
153
157
  value,
@@ -160,14 +164,14 @@ const regexr = {
160
164
  const regexp = new RegExp(pattern, flags);
161
165
  return regexp.test(value);
162
166
  },
163
- /**
164
- * Matches a given value against a regex pattern and returns the matches.
165
- *
166
- * @param {Object} params - Parameters for matching regex.
167
- * @param {string} params.value - The string to match against the regex.
168
- * @param {string} params.pattern - The regex pattern to match.
169
- * @param {string} [params.flags='g'] - Regex flags (default: 'g').
170
- * @returns {Array<string>|null} Returns an array of matches, or `null` if no match is found.
167
+ /**
168
+ * Matches a given value against a regex pattern and returns the matches.
169
+ *
170
+ * @param {Object} params - Parameters for matching regex.
171
+ * @param {string} params.value - The string to match against the regex.
172
+ * @param {string} params.pattern - The regex pattern to match.
173
+ * @param {string} [params.flags='g'] - Regex flags (default: 'g').
174
+ * @returns {Array<string>|null} Returns an array of matches, or `null` if no match is found.
171
175
  */
172
176
  match({
173
177
  value,
@@ -182,54 +186,49 @@ const regexr = {
182
186
  }
183
187
  };
184
188
 
185
- /**
186
- * Flatten.
187
- *
188
- * @param obj - Value.
189
- * @param prefix - Value.
190
- * @returns Result of the operation.
191
- *
192
- * @example
193
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
194
- * // import { flatten } from '@vettvangur/vanilla'
195
- *
196
- * flatten(obj, prefix)
189
+ /**
190
+ * Flatten.
191
+ *
192
+ * @param obj - Value.
193
+ * @param prefix - Value.
194
+ * @returns Result of the operation.
195
+ *
196
+ * @example
197
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
198
+ * // import { flatten } from '@vettvangur/vanilla'
199
+ *
200
+ * flatten(obj, prefix)
197
201
  */
198
202
  const flatten = (obj, prefix = '') => {
199
- try {
200
- if (!obj || typeof obj !== 'object') {
201
- console.error('❌ FLATTEN ERROR: Received invalid data:', obj);
202
- return {};
203
- }
204
- return Object.keys(obj).reduce((acc, key) => {
205
- const fullKey = key === 'DEFAULT' ? prefix : prefix ? `${prefix}-${key}` : key;
206
- if (typeof obj[key] === 'object' && key !== 'DEFAULT') {
207
- Object.assign(acc, flatten(obj[key], fullKey));
208
- } else if (typeof obj[key] === 'string') {
209
- acc[fullKey] = obj[key];
210
- } else {
211
- console.warn('! Skipping Invalid Key:', key, 'Value:', obj[key]);
212
- }
213
- return acc;
214
- }, {});
215
- } catch (error) {
216
- console.error('🚨 Flatten Function Error:', error);
217
- return {}; // Prevents Tailwind from crashing
203
+ if (obj == null) {
204
+ return {};
218
205
  }
206
+ if (typeof obj !== 'object') {
207
+ throw new TypeError(`flatten: expected an object, got ${typeof obj}`);
208
+ }
209
+ return Object.keys(obj).reduce((acc, key) => {
210
+ const fullKey = key === 'DEFAULT' ? prefix : prefix ? `${prefix}-${key}` : key;
211
+ if (typeof obj[key] === 'object' && key !== 'DEFAULT') {
212
+ Object.assign(acc, flatten(obj[key], fullKey));
213
+ } else if (typeof obj[key] === 'string') {
214
+ acc[fullKey] = obj[key];
215
+ }
216
+ return acc;
217
+ }, {});
219
218
  };
220
219
 
221
- /**
222
- * Get template.
223
- *
224
- * @param alias - Value.
225
- * @param templates - Value.
226
- * @returns Result of the operation.
227
- *
228
- * @example
229
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
230
- * // import { getTemplate } from '@vettvangur/vanilla'
231
- *
232
- * getTemplate(alias, templates)
220
+ /**
221
+ * Get template.
222
+ *
223
+ * @param alias - Value.
224
+ * @param templates - Value.
225
+ * @returns Result of the operation.
226
+ *
227
+ * @example
228
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
229
+ * // import { getTemplate } from '@vettvangur/vanilla'
230
+ *
231
+ * getTemplate(alias, templates)
233
232
  */
234
233
  function getTemplate(alias, templates) {
235
234
  const template = templates[capitalize(alias)];
@@ -239,18 +238,18 @@ function getTemplate(alias, templates) {
239
238
  return template;
240
239
  }
241
240
 
242
- /**
243
- * Get block.
244
- *
245
- * @param alias - Value.
246
- * @param blocks - Value.
247
- * @returns Result of the operation.
248
- *
249
- * @example
250
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
251
- * // import { getBlock } from '@vettvangur/vanilla'
252
- *
253
- * getBlock(alias, blocks)
241
+ /**
242
+ * Get block.
243
+ *
244
+ * @param alias - Value.
245
+ * @param blocks - Value.
246
+ * @returns Result of the operation.
247
+ *
248
+ * @example
249
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
250
+ * // import { getBlock } from '@vettvangur/vanilla'
251
+ *
252
+ * getBlock(alias, blocks)
254
253
  */
255
254
  function getBlock(alias, blocks) {
256
255
  if (!blocks) {
@@ -263,17 +262,17 @@ function getBlock(alias, blocks) {
263
262
  return block;
264
263
  }
265
264
 
266
- /**
267
- * Return whether empty is enabled.
268
- *
269
- * @param value - Value.
270
- * @returns Boolean indicating whether empty is enabled.
271
- *
272
- * @example
273
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
274
- * // import { isEmpty } from '@vettvangur/vanilla'
275
- *
276
- * isEmpty(value)
265
+ /**
266
+ * Return whether empty is enabled.
267
+ *
268
+ * @param value - Value.
269
+ * @returns Boolean indicating whether empty is enabled.
270
+ *
271
+ * @example
272
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
273
+ * // import { isEmpty } from '@vettvangur/vanilla'
274
+ *
275
+ * isEmpty(value)
277
276
  */
278
277
  function isEmpty(value) {
279
278
  if (value === '' || value === undefined || value === null) {
@@ -282,89 +281,92 @@ function isEmpty(value) {
282
281
  return false;
283
282
  }
284
283
 
285
- /**
286
- * Preload timeout.
287
- *
288
- * @returns Nothing.
289
- *
290
- * @example
291
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
292
- * // import { preloadTimeout } from '@vettvangur/vanilla'
293
- *
294
- * preloadTimeout()
284
+ /**
285
+ * Preload timeout.
286
+ *
287
+ * @returns Nothing.
288
+ *
289
+ * @example
290
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
291
+ * // import { preloadTimeout } from '@vettvangur/vanilla'
292
+ *
293
+ * preloadTimeout()
295
294
  */
296
295
  function preloadTimeout() {
296
+ if (typeof document === 'undefined') {
297
+ return () => {};
298
+ }
297
299
  const body = document.querySelector('.body');
298
300
  if (!body) {
299
- return;
301
+ return () => {};
300
302
  }
301
- setTimeout(() => body.classList.add('loaded'), 100);
302
- setTimeout(() => {
303
+ const t1 = setTimeout(() => body.classList.add('loaded'), 100);
304
+ const t2 = setTimeout(() => {
303
305
  body.classList.add('preload--hidden');
304
306
  body.classList.remove('preload--transitions');
305
307
  }, 400);
308
+ return () => {
309
+ clearTimeout(t1);
310
+ clearTimeout(t2);
311
+ };
306
312
  }
307
313
 
308
- /**
309
- * Click outside.
310
- *
311
- * @param callback - Value.
312
- * @returns Nothing.
313
- *
314
- * @example
315
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
316
- * // import { clickOutside } from '@vettvangur/vanilla'
317
- *
318
- * clickOutside(callback)
314
+ /**
315
+ * Click outside.
316
+ *
317
+ * @param callback - Value.
318
+ * @returns Nothing.
319
+ *
320
+ * @example
321
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
322
+ * // import { clickOutside } from '@vettvangur/vanilla'
323
+ *
324
+ * clickOutside(callback)
319
325
  */
320
326
  function clickOutside(callback) {
321
- // Clicks
322
- document.addEventListener('click', e => {
327
+ if (typeof document === 'undefined') {
328
+ return () => {};
329
+ }
330
+ const onClick = e => {
323
331
  const target = e.target;
324
332
  const classTargets = document.querySelectorAll('.co-el');
325
333
 
326
- // Check if the click target is inside an element with class `.co-trigger`
327
334
  // @ts-ignore
328
335
  if (target.closest('.co-trigger')) {
329
336
  return;
330
337
  }
331
-
332
- // Execute the callback function
333
338
  callback(e);
334
-
335
- // Close open elements
336
339
  Array.prototype.forEach.call(classTargets, item => {
337
340
  if (item.classList.contains('open')) {
338
341
  item.classList.remove('open');
339
342
  }
340
343
  });
341
- }, false);
342
-
343
- // ESC key
344
- document.addEventListener('keyup', e => {
344
+ };
345
+ const onKeyUp = e => {
345
346
  const openElements = document.querySelectorAll('.open');
346
347
  const keys = e.keyCode || e.which;
347
-
348
- // If ESC key (key code 27) is pressed
349
348
  if (keys === 27) {
350
- // Execute the callback function
351
349
  callback(e);
352
-
353
- // Close open elements
354
350
  Array.prototype.forEach.call(openElements, item => {
355
351
  if (item.classList.contains('open')) {
356
352
  item.classList.remove('open');
357
353
  }
358
354
  });
359
355
  }
360
- });
356
+ };
357
+ document.addEventListener('click', onClick, false);
358
+ document.addEventListener('keyup', onKeyUp);
359
+ return () => {
360
+ document.removeEventListener('click', onClick, false);
361
+ document.removeEventListener('keyup', onKeyUp);
362
+ };
361
363
  }
362
364
 
363
- /**
364
- * Umbraco.
365
- *
366
- * @example
367
- * console.log(Umbraco)
365
+ /**
366
+ * Umbraco.
367
+ *
368
+ * @example
369
+ * console.log(Umbraco)
368
370
  */
369
371
  const Umbraco = Object.freeze({
370
372
  NODE: 'node',
@@ -374,45 +376,42 @@ const Umbraco = Object.freeze({
374
376
  EXTRA: 'extra'
375
377
  });
376
378
 
377
- /**
378
- * Get translation.
379
- *
380
- * @param key - Value.
381
- * @param translations - Value.
382
- * @returns Result of the operation.
383
- *
384
- * @example
385
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
386
- * // import { getTranslation } from '@vettvangur/vanilla'
387
- *
388
- * getTranslation(key, translations)
379
+ /**
380
+ * Get translation.
381
+ *
382
+ * @param key - Value.
383
+ * @param translations - Value.
384
+ * @returns Result of the operation.
385
+ *
386
+ * @example
387
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
388
+ * // import { getTranslation } from '@vettvangur/vanilla'
389
+ *
390
+ * getTranslation(key, translations)
389
391
  */
390
392
  function getTranslation(key, translations) {
391
393
  if (!translations) {
392
394
  return;
393
395
  }
394
- const translation = translations[key];
395
- if (!translation) {
396
- console.error(`[vettvangur-vanilla :: getTranslation] No translation for key ${key} found.`);
397
- return;
398
- }
399
- return translation;
396
+ return translations[key];
400
397
  }
401
398
 
402
- /**
403
- * Get culture.
404
- *
405
- * @param path - Value.
406
- * @returns Result of the operation.
407
- *
408
- * @example
409
- * // vanilla (src/tools/javascript/vanilla/index.mjs)
410
- * // import { getCulture } from '@vettvangur/vanilla'
411
- *
412
- * getCulture(path)
399
+ /**
400
+ * Get culture.
401
+ *
402
+ * @param path - Value.
403
+ * @returns Result of the operation.
404
+ *
405
+ * @example
406
+ * // vanilla (src/tools/javascript/vanilla/index.mjs)
407
+ * // import { getCulture } from '@vettvangur/vanilla'
408
+ *
409
+ * getCulture(path)
413
410
  */
414
411
  function getCulture(path) {
415
- const match = path.match(/^\/([a-z]{2})(\/|$)/i);
412
+ // Match BCP-47-ish prefixes: 2-3 letter language, optionally followed by
413
+ // a region subtag (e.g. `en-US`, `eng-US`, `is`, `pt-BR`).
414
+ const match = path.match(/^\/([a-z]{2,3}(?:-[a-z]{2,4})?)(\/|$)/i);
416
415
  return match ? match[1].toLowerCase() : null;
417
416
  }
418
417