nanosplash 2.3.3 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.github/workflows/production.yml +5 -2
  2. package/README.md +38 -42
  3. package/dist/iife/nanosplash.iife.js +1 -1
  4. package/dist/module/manifest.json +1 -4
  5. package/dist/module/nanosplash.cjs.js +1 -1
  6. package/dist/module/nanosplash.es.js +132 -74
  7. package/dist/module/style.css +1 -0
  8. package/docs/index.html +73 -19
  9. package/docs/nanosplash.iife.js +6 -1
  10. package/docs/style.css +1 -1
  11. package/docs/typedoc/assets/main.js +2 -2
  12. package/docs/typedoc/assets/search.js +1 -1
  13. package/docs/typedoc/classes/Core_Nanosplash.default.html +133 -0
  14. package/docs/typedoc/index.html +1 -1
  15. package/docs/typedoc/modules/Core_Nanosplash.html +1 -0
  16. package/docs/typedoc/modules/types.html +1 -0
  17. package/index.html +72 -22
  18. package/package.json +16 -15
  19. package/src/Core/Nanosplash.ts +188 -31
  20. package/src/Core/SplashInstance.ts +137 -21
  21. package/src/Exceptions/DestinationException.ts +13 -0
  22. package/src/Exceptions/Exception.ts +9 -0
  23. package/src/Exceptions/IllegalArgumentException.ts +11 -0
  24. package/src/Factory/NanosplashFactory.ts +37 -17
  25. package/src/Interfaces/NanosplashInterface.ts +6 -2
  26. package/src/Repositories/NanosplashRepository.ts +82 -0
  27. package/src/{utilities → Tests}/dom.spec.ts +7 -5
  28. package/src/Utilities/dom.ts +49 -0
  29. package/src/main.ts +5 -2
  30. package/src/style.sass +47 -17
  31. package/src/types.d.ts +23 -14
  32. package/tsconfig.json +1 -0
  33. package/update-all.sh +2 -2
  34. package/vite.config.ts +16 -0
  35. package/vite.mod.config.js +10 -11
  36. package/dist/module/Nanosplash.css +0 -1
  37. package/jest.config.ts +0 -194
  38. package/src/Interfaces/ImageInterface.ts +0 -5
  39. package/src/repositories/NanosplashRepository.ts +0 -39
  40. package/src/utilities/dom.ts +0 -26
package/index.html CHANGED
@@ -13,8 +13,23 @@
13
13
  </head>
14
14
  <body class="flex flex-col justify-between">
15
15
  <div class="w-100 min-h-screen flex flex-col justify-center items-center">
16
- <div class="text-3xl">Nanosplash</div>
17
- <div class="mt-3">Small. Simple. Reliable.</div>
16
+ <div class="text-4xl text-slate-900 drop-shadow-lg">Nanosplash</div>
17
+ <div class="text-pink-500 mt-3 font-mono text-sm">ns.show('text').inside('#id')</div>
18
+ <div class="flex gap-5">
19
+ <div
20
+ id="demo"
21
+ class="bg-pink-500 text-pink-200 p-3 cursor-pointer hover:text-white rounded-xl shadow-xl mt-8"
22
+ >
23
+ <i class="lni lni-play"></i>
24
+ Display demo
25
+ </div>
26
+ <a
27
+ href="#example"
28
+ class="bg-slate-500 text-slate-200 p-3 cursor-pointer hover:text-white rounded-xl shadow-xl mt-8"
29
+ >
30
+ Show examples
31
+ </a>
32
+ </div>
18
33
  <div class="flex flex-col space-y-2 my-10">
19
34
  <div class="flex space-x-2 justify-center">
20
35
  <img src="https://badgen.net/npm/v/nanosplash" />
@@ -28,13 +43,23 @@
28
43
  />
29
44
  </div>
30
45
  </div>
31
- <div class="text-white bg-slate-700 p-3 rounded shadow-xl font-mono text-sm">ns.show('text').inside('#myDiv')</div>
46
+ <div class="flex rounded-xl text-slate-400 shadow-xl overflow-hidden">
47
+ <div data-copy class="p-3 bg-slate-800 text-slate-400 font-mono">
48
+ &lt;script src=&quot;https://unpkg.com/nanosplash/dist/iife/nanosplash.iife.js&quot;&gt;
49
+ </div>
50
+ <div id="copy" class="bg-pink-500 text-pink-200 p-3 cursor-pointer hover:text-white">Copy</div>
51
+ </div>
52
+ <div class="mt-10 flex justify-content items-center divide-x-2 text-slate-400">
53
+ <a href="https://www.npmjs.com/package/nanosplash" target="_blank"><i class="lni lni-npm text-4xl hover:text-pink-500 px-5"></i></a>
54
+ <a href="https://github.com/isakhauge/nanosplash" target="_blank"><i class="lni lni-github-original text-2xl hover:text-pink-500 px-5"></i></a>
55
+ </div>
56
+ <a class="mt-10 text-pink-300 hover:text-pink-500" href="https://rawcdn.githack.com/isakhauge/nanosplash/0a6cdef58b0e47c0cad911952b1a329df58d2c24/docs/typedoc/index.html">API Reference Documentation</a>
32
57
  </div>
33
- <div class="grid grid-cols-2 gap-1">
58
+ <div id="example" class="grid grid-cols-1 xl:grid-cols-2 gap-1">
34
59
  <div id="a" class="p-20 bg-slate-100 flex flex-col items-center">
35
60
  <div class="text-xl mb-10">Give user progress feedback</div>
36
- <div class="text-white bg-slate-800 p-5 rounded-lg shadow-2xl font-mono text-sm">
37
- ns.img(src).progress(<br>
61
+ <div class="text-white bg-slate-800 p-5 rounded-xl shadow-2xl font-mono text-sm break-all">
62
+ ns.progress(<br>
38
63
  &nbsp;&nbsp;[promise1, 'Loading A'],<br>
39
64
  &nbsp;&nbsp;[promise2, 'Loading B'],<br>
40
65
  &nbsp;&nbsp;[promise3, 'Loading C'],<br>
@@ -43,41 +68,66 @@
43
68
  </div>
44
69
  <div id="b" class="p-20 bg-slate-100 flex flex-col items-center">
45
70
  <div class="text-xl mb-10">Handle async functions</div>
46
- <div class="text-white bg-slate-800 p-5 rounded-lg shadow-2xl font-mono text-sm">
71
+ <div class="text-white bg-slate-800 p-5 rounded-xl shadow-2xl font-mono text-sm break-all">
47
72
  ns.while(promise).show('Loading ...').inside('#myDiv')
48
73
  </div>
49
74
  </div>
50
75
  <div id="c" class="p-20 bg-slate-100 flex flex-col items-center">
51
76
  <div class="text-xl mb-10">Display fullscreen</div>
52
- <div class="text-white bg-slate-800 p-5 rounded-lg shadow-2xl font-mono text-sm">
53
- const splash = ns.show('Fullscreen text')<br>
54
- splash.moveTo('#myDiv')<br>
55
- splash.remove()
77
+ <div class="text-white bg-slate-800 p-5 rounded-xl shadow-2xl font-mono text-sm break-all">
78
+ ns.show('Fullscreen text')
56
79
  </div>
57
80
  </div>
58
81
  <div id="d" class="p-20 bg-slate-100 flex flex-col items-center">
59
82
  <div class="text-xl mb-10">Display multiple, independent instances</div>
60
- <div class="text-white bg-slate-800 p-5 rounded-lg shadow-2xl font-mono text-sm">
61
- ns.img(src).show('Loading component A').inside('#a')<br>
62
- ns.show('Loading component A').inside('#b')<br>
63
- ns.show('Loading component A').inside('#c')<br>
64
- <br><br>
65
- ns.hide() // Removes instances in a FIFO manner.<br>
66
- ns.hideAll() // Removes all instances.
83
+ <div class="text-white bg-slate-800 p-5 rounded-xl shadow-2xl font-mono text-sm break-all">
84
+ ns.show('Loading component A').inside('#a')<br>
85
+ ns.show('Loading component B').inside('#b')<br>
86
+ ns.show('Loading component C').inside('#c')
87
+ </div>
88
+ </div>
89
+ <div id="e" class="p-20 bg-slate-100 flex flex-col items-center">
90
+ <div class="text-xl mb-10">Move splash instance to another destination</div>
91
+ <div class="text-white bg-slate-800 p-5 rounded-xl shadow-2xl font-mono text-sm break-all">
92
+ const splash = ns.show('Loading').inside('#a')<br>
93
+ splash.moveTo('#b')
94
+ </div>
95
+ </div>
96
+ <div id="f" class="p-20 bg-slate-100 flex flex-col items-center">
97
+ <div class="text-xl mb-10">Hide splash instances</div>
98
+ <div class="text-white bg-slate-800 p-5 rounded-xl shadow-2xl font-mono text-sm break-all">
99
+ // Hides one instance at a time, in a LIFO-fashion.<br>
100
+ ns.hide()<br><br>
101
+ // Hides all instances.<br>
102
+ ns.hideAll()
67
103
  </div>
68
104
  </div>
69
105
  </div>
70
106
  <footer>
71
107
  <script type="module" src="/src/main.ts"></script>
108
+ <script>
109
+ window.addEventListener('load', () => {
110
+ document.getElementById('demo').onclick = function () {
111
+ const wait = ms => new Promise(r => setTimeout(r, ms))
112
+ window.ns.progress(
113
+ [wait(2000), 'Loading data from API'],
114
+ [wait(4000), 'Restructuring'],
115
+ [wait(6000), 'Indexing'],
116
+ [wait(8000), 'Give this repo a star']
117
+ )
118
+ }
119
+ document.getElementById('copy').onclick = function () {
120
+ const text = document.querySelector('[data-copy]').innerText
121
+ navigator.clipboard.writeText(text)
122
+ alert('Copied to clipboard!')
123
+ }
124
+ })
125
+ </script>
72
126
  </footer>
73
127
  <style>
74
128
  body {
75
129
  min-height: 100vh;
76
130
  }
77
- .pill {
78
- font-size: 10px;
79
- padding: 0.2em 0.5em;
80
- }
81
131
  </style>
82
132
  </body>
83
133
  </html>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nanosplash",
3
- "description": "The simple, 2KB loading screen",
4
- "version": "2.3.3",
3
+ "description": "The simple, tiny loading screen",
4
+ "version": "2.5.1",
5
5
  "author": {
6
6
  "name": "Isak K. Hauge",
7
7
  "email": "isakhauge@gmail.com",
@@ -52,22 +52,23 @@
52
52
  "doc": "typedoc --readme none --excludePrivate --excludeInternal --out docs/typedoc --entryPoints src/Core/Nanosplash.ts src/types.d.ts",
53
53
  "doc.watch": "yarn doc --watch",
54
54
  "serve": "vite preview",
55
- "test": "jest"
55
+ "test": "vitest",
56
+ "coverage": "vitest run --coverage"
56
57
  },
57
58
  "devDependencies": {
58
- "@types/jest": "^27.5.0",
59
+ "@types/jest": "^28.1.1",
59
60
  "@types/jsdom": "^16.2.14",
60
61
  "autoprefixer": "^10.4.7",
61
- "cssnano": "^5.1.7",
62
- "jest": "^28.1.0",
63
- "jest-environment-jsdom": "^28.1.0",
64
- "jsdom": "^19.0.0",
65
- "postcss": "^8.4.13",
66
- "sass": "^1.51.0",
67
- "ts-jest": "^28.0.2",
68
- "ts-node": "^10.7.0",
69
- "typedoc": "^0.22.15",
70
- "typescript": "^4.6.4",
71
- "vite": "^2.9.8"
62
+ "c8": "^7.11.3",
63
+ "cssnano": "^5.1.12",
64
+ "jsdom": "^20.0.0",
65
+ "postcss": "^8.4.14",
66
+ "sass": "^1.52.3",
67
+ "ts-jest": "^28.0.5",
68
+ "ts-node": "^10.8.1",
69
+ "typedoc": "^0.22.17",
70
+ "typescript": "^4.7.4",
71
+ "vite": "^2.9.12",
72
+ "vitest": "^0.15.1"
72
73
  }
73
74
  }
@@ -1,69 +1,219 @@
1
1
  import '../style.sass'
2
+ import {get} from "../Utilities/dom";
2
3
  import {SplashInstance} from "./SplashInstance";
3
- import {SplashJob, StrategyObject} from "../types";
4
4
  import {ShowInterface} from "../Interfaces/ShowInterface";
5
5
  import {NanosplashFactory} from "../Factory/NanosplashFactory";
6
6
  import {NanosplashInterface} from "../Interfaces/NanosplashInterface";
7
- import {ContextualAPIInterface} from "../Interfaces/ContextualAPIInterface";
7
+ import {
8
+ ContextualAPIObject,
9
+ Destination,
10
+ InstanceIterationCallback,
11
+ NanosplashOptions,
12
+ SplashJob,
13
+ } from "../types";
8
14
 
9
- export class Nanosplash implements NanosplashInterface {
15
+ /**
16
+ * # Nanosplash
17
+ * @author Isak K. Hauge <isakhauge@gmail.com>
18
+ */
19
+ class Nanosplash implements NanosplashInterface {
10
20
  public static APP_NAME = 'Nanosplash'
21
+ private static SPINNER_DEFAULT_VISIBILITY = true
22
+ private imgSrc: string | undefined
23
+ private spinner: boolean
24
+ private fontSize: string
11
25
  public readonly instances: Map<string, SplashInstance>
12
26
 
13
- public constructor() {
27
+ /**
28
+ * Options passed to the constructor will persist in the instance.
29
+ * @param {NanosplashOptions | undefined} options Nanosplash options object.
30
+ */
31
+ public constructor(options?: NanosplashOptions) {
32
+ this.imgSrc = options?.imgSrc
33
+ this.spinner = (options?.spinner === undefined)
34
+ ? Nanosplash.SPINNER_DEFAULT_VISIBILITY
35
+ : options.spinner
36
+ this.fontSize = options?.fontSize ?? '18px'
14
37
  this.instances = new Map<string, SplashInstance>()
15
38
  }
16
39
 
17
- public img(src: string): StrategyObject {
18
- return NanosplashFactory.createImgFunction(this, new SplashInstance(this, '', src))(src)
40
+ /**
41
+ * # Set Image Source
42
+ * Set the value as undefined to display no image.
43
+ * @param {string | undefined} value
44
+ * @return Nanosplash
45
+ */
46
+ public setImgSrc(value: string | undefined): Nanosplash {
47
+ this.imgSrc = value
48
+ return this
19
49
  }
20
50
 
21
- public show(text: string): ContextualAPIInterface {
22
- return NanosplashFactory.createShowFunction(this, new SplashInstance(this, text))(text)
51
+ /**
52
+ * # Set Spinner
53
+ * Control spinner visibility.
54
+ * @param {boolean} value
55
+ * @return Nanosplash
56
+ */
57
+ public showSpinner(value: boolean): Nanosplash {
58
+ this.spinner = value
59
+ return this
23
60
  }
24
61
 
25
- public progress(...jobs: SplashJob[]): ContextualAPIInterface {
26
- return NanosplashFactory.createProgressFunction(this, new SplashInstance(this, ''))(...jobs)
62
+ /**
63
+ * # Set Font Size
64
+ * @param {string} value Use CSS compatible values.
65
+ * @return Nanosplash
66
+ */
67
+ public setFontSize(value: string): Nanosplash {
68
+ this.fontSize = value
69
+ return this
27
70
  }
28
71
 
72
+ /**
73
+ * # Get Image Source
74
+ * @return string | undefined
75
+ */
76
+ public getImgSrc(): string | undefined {
77
+ return this.imgSrc
78
+ }
79
+
80
+ /**
81
+ * # Spinner Is Visible
82
+ * @return boolean
83
+ */
84
+ public spinnerIsVisible(): boolean {
85
+ return this.spinner
86
+ }
87
+
88
+ /**
89
+ * # Get Font Size
90
+ * @return string
91
+ */
92
+ public getFontSize(): string {
93
+ return this.fontSize
94
+ }
95
+
96
+ /**
97
+ * # Show
98
+ * @param {string} text
99
+ */
100
+ public show(text: string): ContextualAPIObject {
101
+ return NanosplashFactory.createShowFunction(this, new SplashInstance(this, text, this.imgSrc))(text)
102
+ }
103
+
104
+ /**
105
+ * # Progress
106
+ * @param {SplashJob[]} jobs An array or list of Splash jobs.
107
+ */
108
+ public progress(...jobs: SplashJob[]): ContextualAPIObject {
109
+ return NanosplashFactory.createProgressFunction(this, new SplashInstance(this, '', this.imgSrc))(...jobs)
110
+ }
111
+
112
+ /**
113
+ * # While
114
+ * @param {Promise<any>} asyncTask An asynchronous function or Promise.
115
+ */
29
116
  public while(asyncTask: Promise<any>): ShowInterface {
30
- return NanosplashFactory.createWhileFunction(this, new SplashInstance(this, ''))(asyncTask)
117
+ return NanosplashFactory.createWhileFunction(this, new SplashInstance(this, '', this.imgSrc))(asyncTask)
31
118
  }
32
119
 
33
- private fifoIterate(callback: (id: string, splashInstance: SplashInstance, i: number) => boolean): void {
34
- let i = 0
35
- const instanceEntries = this.instances.entries()
36
- for (const [id, splashInstance] of instanceEntries) {
37
- if (!callback(id, splashInstance, i++)) {
120
+ /**
121
+ * # LIFO Iterate
122
+ * This function will iterate through the splash instances in a LIFO (last in, first out) manner, invoke the
123
+ * callback for each instance and pass the instance as an argument.
124
+ * @param {InstanceIterationCallback} callback This callback will be invoked for each instance.
125
+ * @private
126
+ */
127
+ private lifoIterate(callback: InstanceIterationCallback): void {
128
+ const n = this.instances.size
129
+ const instances = Array.from(this.instances.values())
130
+ for (let i = n - 1; i >= 0; i--) {
131
+ const instance = instances[i]
132
+ const id = instance.getId()
133
+ if (!callback(id, instance, i)) {
38
134
  break
39
135
  }
40
136
  }
41
137
  }
42
138
 
139
+ /**
140
+ * # Delete
141
+ * @param {SplashInstance} splashInstance
142
+ */
43
143
  public delete(splashInstance: SplashInstance): void {
44
144
  this.instances.delete(splashInstance.getId())
45
145
  }
46
146
 
147
+ /**
148
+ * # Hide All
149
+ * Delete all Splash instances.
150
+ */
47
151
  public hideAll(): void
48
152
  {
49
- this.instances.forEach(
50
- (instance: SplashInstance) => instance.delete()
51
- )
153
+ this.instances.forEach((instance: SplashInstance) => instance.delete())
52
154
  }
53
155
 
54
- public hide(id?: string): void {
55
- if (id) {
56
- const splashInstance = this.instances.get(id)
57
- if (splashInstance) {
58
- splashInstance.delete()
59
- } else {
60
- throw new Error(
61
- `Could not find element with id: ${id}`
62
- )
156
+ /**
157
+ * # Hide
158
+ * Delete specific Splash instance or the latest one. There are three different ways of using this function.
159
+ *
160
+ * ## Use SplashInstance IDs
161
+ * Every new splash instance is given a unique, randomized ID. This ID is easily retrieved by using the getId
162
+ * method.
163
+ * <br>
164
+ * <code>
165
+ * const splashInstance = ns.show('Loading');<br>
166
+ * ns.hide(splashInstance.getId());
167
+ * </code>
168
+ * <br>
169
+ *
170
+ * ## Use CSS Selector
171
+ * Pass the selector referring to the element in which the splash instance resides.
172
+ * <br>
173
+ * <code>
174
+ * ns.show('Loading').inside('#my-div');<br>
175
+ * ns.hide('#my-div');
176
+ * </code>
177
+ * <br>
178
+ *
179
+ * ## Pass no argument
180
+ * When calling the hide method without passing arguments, it will delete the latest splash instance added to the
181
+ * DOM, in other words, in a LIFO fashion.<br>
182
+ * <code>
183
+ * ns.show('Loading');<br>
184
+ * ns.hide();
185
+ * </code>
186
+ * <br>
187
+ * @param ref This can either be a SplashInstance ID or a CSS selector referring to the element in which
188
+ * the instance is residing.
189
+ */
190
+ public hide(ref?: Destination): void {
191
+ if (ref) {
192
+ const isString = typeof ref === 'string'
193
+ const isNode = ref instanceof Node
194
+ const deleteInstancesWhereDestination = (destination: Destination) => {
195
+ Array.from(this.instances.values())
196
+ .filter((v: SplashInstance) => v.getDestination() === destination)
197
+ .forEach((v: SplashInstance) => v.delete())
198
+ }
199
+
200
+ if (isString) {
201
+ const splashInstance = this.instances.get(ref)
202
+ if (splashInstance) {
203
+ splashInstance.delete()
204
+ } else {
205
+ const element = get<HTMLElement>(ref)
206
+ if (element) {
207
+ deleteInstancesWhereDestination(element)
208
+ }
209
+ }
210
+ } else if (isNode) {
211
+ deleteInstancesWhereDestination(ref)
63
212
  }
64
213
  } else {
65
- this.fifoIterate((_: string, splashInstance: SplashInstance, i: number) => {
66
- const remove = i === 0
214
+ const n = this.instances.size
215
+ this.lifoIterate((_: string, splashInstance: SplashInstance, i: number) => {
216
+ const remove = i === n - 1
67
217
  if (remove) {
68
218
  splashInstance.delete()
69
219
  }
@@ -72,9 +222,16 @@ export class Nanosplash implements NanosplashInterface {
72
222
  }
73
223
  }
74
224
 
75
- public getSplashesWithDestinationNode(node: HTMLElement): SplashInstance[]
225
+ /**
226
+ * # Get From Destination Node
227
+ * Returns Splash instances having the given destination node.
228
+ * @param {HTMLElement} node
229
+ */
230
+ public getFromDestinationNode(node: HTMLElement): SplashInstance[]
76
231
  {
77
232
  const fnSameDestinationNode = (v: SplashInstance) => v.getDestination() === node
78
233
  return Array.from(this.instances.values()).filter(fnSameDestinationNode)
79
234
  }
80
235
  }
236
+
237
+ export default Nanosplash