nanosplash 2.2.4 → 2.3.0

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 (52) hide show
  1. package/.github/workflows/production.yml +57 -0
  2. package/.github/workflows/release.yml +61 -0
  3. package/README.md +17 -15
  4. package/dist/iife/nanosplash.iife.js +1 -1
  5. package/dist/module/Nanosplash.css +1 -0
  6. package/dist/module/manifest.json +6 -3
  7. package/dist/module/nanosplash.cjs.js +1 -1
  8. package/dist/module/nanosplash.es.js +244 -330
  9. package/docs/index.html +54 -430
  10. package/docs/nanosplash.iife.js +1 -1
  11. package/docs/style.css +1 -1
  12. package/docs/typedoc/assets/highlight.css +1 -50
  13. package/docs/typedoc/assets/main.js +2 -2
  14. package/docs/typedoc/assets/search.js +1 -1
  15. package/docs/typedoc/assets/style.css +32 -2
  16. package/docs/typedoc/classes/Core_Nanosplash.Nanosplash.html +1 -0
  17. package/docs/typedoc/index.html +1 -1
  18. package/docs/typedoc/modules/types.html +1 -1
  19. package/index.html +51 -412
  20. package/jest.config.ts +194 -0
  21. package/package.json +70 -65
  22. package/src/Core/Nanosplash.ts +74 -0
  23. package/src/Core/SplashInstance.ts +154 -0
  24. package/src/Factory/NanosplashFactory.ts +73 -0
  25. package/src/Interfaces/ContextualAPIInterface.ts +8 -0
  26. package/src/Interfaces/IdentityInterface.ts +3 -0
  27. package/src/Interfaces/ImageInterface.ts +5 -0
  28. package/src/Interfaces/InsideInterface.ts +5 -0
  29. package/src/Interfaces/NanosplashInterface.ts +4 -0
  30. package/src/Interfaces/ProgressInterface.ts +5 -0
  31. package/src/Interfaces/ShowInterface.ts +5 -0
  32. package/src/Interfaces/WhileInterface.ts +5 -0
  33. package/src/main.ts +2 -6
  34. package/src/repositories/NanosplashRepository.ts +34 -55
  35. package/src/style.sass +36 -61
  36. package/src/types.d.ts +45 -200
  37. package/src/utilities/dom.spec.ts +70 -0
  38. package/src/utilities/dom.ts +17 -256
  39. package/update-all.sh +3 -0
  40. package/vite.iife.config.js +46 -18
  41. package/vite.mod.config.js +48 -12
  42. package/vite.site.config.js +0 -3
  43. package/dist/module/style.css +0 -1
  44. package/docs/typedoc/classes/Nanosplash.Nanosplash-1.html +0 -56
  45. package/docs/typedoc/classes/types.Nanosplash.html +0 -56
  46. package/docs/typedoc/modules/Nanosplash.html +0 -1
  47. package/src/Exceptions/Exception.ts +0 -12
  48. package/src/Exceptions/IllegalArgumentException.ts +0 -9
  49. package/src/Exceptions/InvalidDestinationException.ts +0 -9
  50. package/src/Exceptions/MissingResourceException.ts +0 -9
  51. package/src/Nanosplash.ts +0 -484
  52. package/update-latest.sh +0 -21
package/src/Nanosplash.ts DELETED
@@ -1,484 +0,0 @@
1
- import {
2
- BlurMode,
3
- Config,
4
- Destination,
5
- DisplayController,
6
- SplashAnimation,
7
- } from 'nanosplash'
8
- import IllegalArgumentException from './Exceptions/IllegalArgumentException'
9
- import InvalidDestinationException from './Exceptions/InvalidDestinationException'
10
- import MissingResourceException from './Exceptions/MissingResourceException'
11
- import { NanosplashRepository } from './repositories/NanosplashRepository'
12
- import './style.sass'
13
- import {
14
- display,
15
- fitToParent,
16
- invokeOn,
17
- isElementOrNode,
18
- isFunction,
19
- move,
20
- ref,
21
- refAll,
22
- setAttribute,
23
- setStyle,
24
- } from './utilities/dom'
25
-
26
- /**
27
- * Nanosplash
28
- *
29
- * @author Isak K. Hauge
30
- */
31
- export class Nanosplash {
32
- private defaultDestination: Element
33
- private defaultText: string
34
- private readonly mainElement: HTMLDivElement
35
- private readonly splashElement: HTMLImageElement
36
- private readonly textElement: HTMLDivElement
37
- private cache = {
38
- parentPosition: '',
39
- }
40
-
41
- /**
42
- * Constructor
43
- *
44
- * @public
45
- * @constructor
46
- * @param {Config | undefined} config The configuration object.
47
- *
48
- * @example
49
- * ```js
50
- * // Instantiatie without config object.
51
- * new Nanosplash()
52
- * ```
53
- *
54
- * @example
55
- * ```js
56
- * // Instantiate with config object.
57
- * new Nanosplash(config)
58
- * ```
59
- */
60
- public constructor(config?: Config) {
61
- this.defaultText =
62
- config?.default?.text ?? NanosplashRepository.DEFAULT.TEXT
63
- this.defaultDestination = Nanosplash.getDestinationElement(
64
- config?.default?.destination ??
65
- NanosplashRepository.DEFAULT.DESTINATION_NODE
66
- )
67
-
68
- // Build UI elements
69
- this.mainElement = NanosplashRepository.makeMainElement()
70
- this.splashElement = NanosplashRepository.makeSplashElement()
71
- this.textElement = NanosplashRepository.makeTextElement()
72
-
73
- // Set default configuration
74
- this.setDefaultStyles()
75
-
76
- // Assemble UI elements
77
- const splashSrc = config?.splash?.src
78
- if (splashSrc) {
79
- this.setSplashSource(splashSrc)
80
- move(this.splashElement).to(this.mainElement)
81
- }
82
- move(this.textElement).to(this.mainElement)
83
-
84
- // Insert loader into destination element
85
- move(this.mainElement).to(this.defaultDestination, true)
86
- display(this.mainElement, false) // Hide by default
87
- fitToParent(this.mainElement)
88
-
89
- // Apply custom configuration
90
- if (config) {
91
- this.configure(config)
92
- }
93
- }
94
-
95
- /**
96
- * Install
97
- *
98
- * @description Assigns itself to the Window object and sets essential event
99
- * listeners that responds to changes in the browser. The instance is
100
- * globally accessible through the property "loading".
101
- *
102
- * @example
103
- * ```js
104
- * // Install
105
- * (new Nanosplash()).install()
106
- *
107
- * // Access the instance globally
108
- * loading.show('Some text')
109
- * ```
110
- */
111
- public install(): void {
112
- Object.defineProperty(window, 'loading', {
113
- value: this,
114
- writable: false,
115
- })
116
- invokeOn(window, () => fitToParent(this.mainElement), ['resize', 'scroll'])
117
- Nanosplash.checkStyleResources()
118
- }
119
-
120
- /**
121
- * Configure
122
- *
123
- * @param {Config} config The config object.
124
- * @return {Nanosplash} The updated instance.
125
- *
126
- * @description Mutates the existing configuration and returns the updated
127
- * instance.
128
- *
129
- * @example
130
- * ```js
131
- * nanosplash.configure(config)
132
- * ```
133
- *
134
- * @example
135
- * ```js
136
- * window.loading.configure(config).show(text)
137
- * ```
138
- */
139
- public configure(config: Config): Nanosplash {
140
- if (config?.default?.destination) {
141
- this.defaultDestination = Nanosplash.getDestinationElement(
142
- config.default.destination
143
- )
144
- }
145
-
146
- this.defaultText ||= config.default?.text as string
147
-
148
- // Text:
149
- if (config.text?.family) {
150
- this.setTextFontFamily(config.text.family)
151
- }
152
- if (config.text?.weight) {
153
- this.setTextWeight(config.text.weight)
154
- }
155
- if (config.text?.color) {
156
- this.setTextColor(config.text.color)
157
- }
158
- if (config.text?.size) {
159
- this.setTextSize(config.text.size)
160
- }
161
-
162
- // Background:
163
- if (config.background?.color) {
164
- this.setBackgroundColor(config.background.color)
165
- }
166
- if (config.background?.blur) {
167
- this.setBackgroundBlur(config.background.blur)
168
- }
169
-
170
- // Splash:
171
- if (config.splash) {
172
- if (config.splash?.src) {
173
- const hasSplashElement = this.mainElement.contains(this.splashElement)
174
- if (!hasSplashElement) {
175
- move(this.splashElement).to(this.mainElement, true)
176
- }
177
- this.setSplashSource(config.splash.src)
178
- }
179
- if (config.splash?.width) {
180
- this.setSplashWidth(config.splash.width)
181
- }
182
- if (config.splash?.height) {
183
- this.setSplashHeight(config.splash.height)
184
- }
185
- if (config.splash?.animation) {
186
- this.setSplashAnimation(config.splash.animation)
187
- }
188
- } else {
189
- display(this.splashElement, false)
190
- }
191
-
192
- return this
193
- }
194
-
195
- /**
196
- * Show
197
- *
198
- * @param {string | undefined} text The text that will be shown in the
199
- * loading screen. If undefined, Nanosplash will use the default text.
200
- * @return {DisplayController} An object with a function that controls the
201
- * visibility and destination of the loading screen.
202
- *
203
- * @description Shows the loading screen. Invoking the inside function will
204
- * display the loading screen within the constraints of the defined
205
- * destination.
206
- *
207
- * Basic usage.
208
- * @example
209
- * ```js
210
- * // Basic usage.
211
- * loading.show(text)
212
- * ```
213
- *
214
- * Display Nanosplash inside other DOM elements.
215
- * @example
216
- * ```js
217
- * // Show loading screen within another element using CSS selector.
218
- * loading.show(text).inside('#my-element')
219
- * // Use DOM element reference.
220
- * loading.show(text).inside(document.getElementById(id))
221
- * // Use function that returns a DOM element reference.
222
- * loading.show(text).inside(() => getDomReference())
223
- * ```
224
- *
225
- * Display Nanosplash while an asynchronous task is resolving.
226
- * @example
227
- * ```js
228
- * // Define an asynchronous task.
229
- * const task = async () => await getDataFromApi()
230
- * // Show loading screen while the task is running.
231
- * loading.show(text).during(task)
232
- * loading.show(text).inside('#my-element').during(task)
233
- * ```
234
- */
235
- public show(text?: string): DisplayController {
236
- this.setText(text ?? NanosplashRepository.DEFAULT.TEXT)
237
- display(this.mainElement, true)
238
-
239
- // Async task handler
240
- const during = (task: Promise<any>) => {
241
- return task.finally(() => this.hide())
242
- }
243
-
244
- // Returns a
245
- return {
246
- inside: (destination: Destination) => {
247
- this.restoreParentPosition()
248
- const element = Nanosplash.getDestinationElement(destination)
249
- move(this.mainElement).to(element, true)
250
- fitToParent(this.mainElement)
251
- this.setParentPositionToRelative()
252
- return { during }
253
- },
254
- during,
255
- }
256
- }
257
-
258
- /**
259
- * Hide
260
- *
261
- * @description Hides the loading screen and moves to its default destination.
262
- * If no custom default destination is defined, it will move to the document
263
- * body.
264
- *
265
- * @example
266
- * ```js
267
- * // Basic usage
268
- * loading.hide()
269
- * // Use with async functions
270
- * loading.show('Loading ...')
271
- * await fetchStuffFromApi()
272
- * loading.hide()
273
- * ```
274
- */
275
- public hide(): void {
276
- this.restoreParentPosition()
277
- display(this.mainElement, false)
278
- this.setText(this.defaultText)
279
- move(this.mainElement).to(this.defaultDestination, true)
280
- fitToParent(this.mainElement)
281
- }
282
-
283
- /**
284
- * Set Default Styles
285
- * @private
286
- */
287
- private setDefaultStyles(): void {
288
- this.setTextFontFamily(NanosplashRepository.DEFAULT.TEXT_FONT)
289
- this.setTextWeight(NanosplashRepository.DEFAULT.TEXT_WEIGHT)
290
- this.setTextColor(NanosplashRepository.DEFAULT.TEXT_COLOR)
291
- this.setTextSize(NanosplashRepository.DEFAULT.TEXT_SIZE)
292
- this.setSplashWidth(NanosplashRepository.DEFAULT.SPLASH_WIDTH)
293
- this.setSplashHeight(NanosplashRepository.DEFAULT.SPLASH_HEIGHT)
294
- this.setSplashAnimation(NanosplashRepository.DEFAULT.SPLASH_ANIMATION)
295
- this.setBackgroundColor(NanosplashRepository.DEFAULT.BACKGROUND_COLOR)
296
- this.setBackgroundBlur(NanosplashRepository.DEFAULT.BACKGROUND_BLUR)
297
- }
298
-
299
- private doIfParentExist(callback: (parent: HTMLElement) => any): void {
300
- ;(parent => {
301
- if (parent) {
302
- callback(parent)
303
- }
304
- })(this.mainElement.parentElement as HTMLElement)
305
- }
306
-
307
- private setParentPosition(position: string): void {
308
- this.doIfParentExist(parent => {
309
- setStyle(parent, 'position', position)
310
- })
311
- }
312
-
313
- private cacheParentPosition(): void {
314
- this.doIfParentExist(parent => {
315
- this.cache.parentPosition = parent.style.position
316
- })
317
- }
318
-
319
- private restoreParentPosition(): void {
320
- this.setParentPosition(this.cache.parentPosition)
321
- }
322
-
323
- private setParentPositionToRelative(): void {
324
- this.cacheParentPosition()
325
- this.setParentPosition('relative')
326
- }
327
-
328
- /**
329
- * Set Text
330
- *
331
- * @param {string} text
332
- * @private
333
- */
334
- private setText(text: string) {
335
- this.textElement.innerText = text
336
- }
337
-
338
- /**
339
- * Set Text Font Family
340
- *
341
- * @param {string} fontFamily
342
- * @private
343
- */
344
- private setTextFontFamily(fontFamily: string): void {
345
- setStyle(this.textElement, 'fontFamily', fontFamily)
346
- }
347
-
348
- /**
349
- * Set Text Font Weight
350
- *
351
- * @param {string} fontWeight
352
- * @private
353
- */
354
- private setTextWeight(fontWeight: string): void {
355
- setStyle(this.textElement, 'fontWeight', fontWeight)
356
- }
357
-
358
- /**
359
- * Set Text Color
360
- *
361
- * @param {string} color
362
- * @private
363
- */
364
- private setTextColor(color: string): void {
365
- setStyle(this.textElement, 'color', color)
366
- }
367
-
368
- /**
369
- * Set Text Size
370
- *
371
- * @param {string} fontSize
372
- * @private
373
- */
374
- private setTextSize(fontSize: string): void {
375
- setStyle(this.textElement, 'fontSize', fontSize)
376
- }
377
-
378
- /**
379
- * Set Splash Source
380
- *
381
- * @param {string} src
382
- * @private
383
- */
384
- private setSplashSource(src: string): void {
385
- this.splashElement.src = src
386
- display(this.splashElement, true)
387
- }
388
-
389
- /**
390
- * Set Splash Width
391
- *
392
- * @param {string} width
393
- * @private
394
- */
395
- private setSplashWidth(width: string): void {
396
- setStyle(this.splashElement, 'width', width)
397
- }
398
-
399
- /**
400
- * Set Splash Height
401
- *
402
- * @param {string} height
403
- * @private
404
- */
405
- private setSplashHeight(height: string): void {
406
- setStyle(this.splashElement, 'height', height)
407
- }
408
-
409
- /**
410
- * Set Splash Animation
411
- *
412
- * @param {SplashAnimation} animation
413
- * @private
414
- */
415
- private setSplashAnimation(animation: SplashAnimation): void {
416
- setAttribute(this.mainElement, 'data-splash-animation', animation)
417
- }
418
-
419
- /**
420
- * Set Background Color
421
- *
422
- * @param color
423
- * @private
424
- */
425
- private setBackgroundColor(color: string): void {
426
- setStyle(this.mainElement, 'backgroundColor', color)
427
- }
428
-
429
- /**
430
- * Set Background Blur
431
- *
432
- * @param {BlurMode} blurMode
433
- * @private
434
- */
435
- private setBackgroundBlur(blurMode: BlurMode): void {
436
- setAttribute(this.mainElement, 'data-blur', blurMode)
437
- }
438
-
439
- /**
440
- * @throws {MissingResourceException}
441
- * @description Throws an exception if the CSS is missing from the browser.
442
- */
443
- private static checkStyleResources(): void {
444
- window.addEventListener('load', async function() {
445
- const hrefElements = refAll('link[href*="nanosplash"]')
446
- const nanosplashFilter = (v: HTMLElement) =>
447
- /\.nanosplash/.test(v.innerText)
448
- const styleElements = refAll('style').filter(nanosplashFilter)
449
- const hasRequiredCss = hrefElements.length > 0 || styleElements.length > 0
450
- if (!hasRequiredCss) {
451
- throw new MissingResourceException('Missing the Nanosplash CSS')
452
- }
453
- })
454
- }
455
-
456
- /**
457
- * @throws InvalidDestinationException
458
- * @throws IllegalArgumentException
459
- * @private
460
- */
461
- private static getDestinationElement(destination: Destination): HTMLElement {
462
- const isString = typeof destination === 'string'
463
- const isCallback = isFunction(destination)
464
- const isElement = isElementOrNode(destination)
465
-
466
- let destinationNode: HTMLElement | null
467
-
468
- if (isString) {
469
- destinationNode = ref(destination as string) as HTMLElement
470
- } else if (isCallback) {
471
- destinationNode = (destination as Function)() as HTMLElement
472
- } else if (isElement) {
473
- destinationNode = destination as HTMLElement
474
- } else {
475
- throw new IllegalArgumentException()
476
- }
477
-
478
- if (!destinationNode) {
479
- throw new InvalidDestinationException('Destination element is falsy')
480
- }
481
-
482
- return destinationNode as HTMLElement
483
- }
484
- }
package/update-latest.sh DELETED
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env bash
2
- PACKAGES=(
3
- @vitejs/plugin-vue
4
- @vue/compiler-sfc
5
- autoprefixer
6
- cssnano
7
- postcss
8
- sass
9
- typedoc
10
- typescript
11
- vite
12
- vite-plugin-singlefile
13
- )
14
-
15
- PACKAGE_STR=""
16
-
17
- for package in ${PACKAGES[@]}
18
- do PACKAGE_STR+=" $package@latest"
19
- done
20
-
21
- yarn add -D $PACKAGE_STR