nanosplash 3.0.7 → 3.0.9
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/.prettierrc +1 -1
- package/README.md +6 -6
- package/bun.lockb +0 -0
- package/dist/cjs/ns.cjs +1 -2
- package/dist/es/ns.js +61 -340
- package/dist/iife/ns.iife.js +1 -2
- package/docs/.vitepress/{config.ts → config.mts} +42 -43
- package/docs/.vitepress/theme/css/style.css +107 -6
- package/docs/.vitepress/theme/vue/CardGrid.vue +1 -1
- package/docs/.vitepress/theme/vue/Exe.vue +58 -28
- package/docs/.vitepress/theme/vue/PlayGround.vue +5 -21
- package/docs/api/doc/hide.md +10 -31
- package/docs/api/doc/show.md +12 -13
- package/docs/api/start/features.md +1 -1
- package/docs/api/start/install.md +6 -4
- package/docs/api/start/playground.md +1 -1
- package/docs/api/start/usage.md +2 -5
- package/docs/index.md +25 -25
- package/docs/public/macos.jpg +0 -0
- package/eslint.config.js +9 -0
- package/package.json +54 -48
- package/src/style/ns.sass +100 -70
- package/src/ts/Nanosplash.ts +219 -0
- package/src/ts/main.ts +2 -8
- package/src/ts/types/NanosplashInterface.ts +7 -0
- package/src/ts/types/Types.ts +28 -3
- package/src/ts/types/global.d.ts +9 -9
- package/tests/Nanosplash.spec.ts +35 -0
- package/.prettierignore +0 -1
- package/src/ts/core/DomUtilities.ts +0 -161
- package/src/ts/core/Service.ts +0 -211
- package/src/ts/core/ServiceInterface.ts +0 -58
- package/src/ts/core/Splash.ts +0 -121
- package/src/ts/core/SplashInterface.ts +0 -46
- package/src/ts/core/SplashQueue.ts +0 -49
- package/tests/DomUtilities.spec.ts +0 -117
- package/tests/Guid.spec.ts +0 -21
- package/tests/Service.spec.ts +0 -198
- package/tests/Splash.spec.ts +0 -64
- package/tests/TestUtilities.ts +0 -48
package/src/style/ns.sass
CHANGED
|
@@ -1,95 +1,125 @@
|
|
|
1
|
+
// Spinner animations:
|
|
2
|
+
@keyframes ns-rotate
|
|
3
|
+
100%
|
|
4
|
+
transform: rotate(360deg)
|
|
5
|
+
|
|
6
|
+
@keyframes ns-dash
|
|
7
|
+
0%
|
|
8
|
+
stroke-dasharray: 1, 150
|
|
9
|
+
stroke-dashoffset: 0
|
|
10
|
+
50%
|
|
11
|
+
stroke-dasharray: 90, 150
|
|
12
|
+
stroke-dashoffset: -35
|
|
13
|
+
100%
|
|
14
|
+
stroke-dasharray: 90, 150
|
|
15
|
+
stroke-dashoffset: -124
|
|
16
|
+
|
|
17
|
+
@keyframes ns-fade
|
|
18
|
+
from
|
|
19
|
+
opacity: 0
|
|
20
|
+
to
|
|
21
|
+
opacity: 1
|
|
22
|
+
|
|
23
|
+
@keyframes ns-ascend
|
|
24
|
+
from
|
|
25
|
+
opacity: 0
|
|
26
|
+
transform: translateY(13px)
|
|
27
|
+
to
|
|
28
|
+
opacity: 1
|
|
29
|
+
transform: translateY(0)
|
|
30
|
+
|
|
31
|
+
:root
|
|
32
|
+
--ns-top: 0px
|
|
33
|
+
|
|
1
34
|
%maximize
|
|
2
|
-
|
|
3
|
-
|
|
35
|
+
width: 100%
|
|
36
|
+
height: 100%
|
|
4
37
|
|
|
5
|
-
%
|
|
6
|
-
|
|
7
|
-
|
|
38
|
+
%bottom-left
|
|
39
|
+
bottom: 0
|
|
40
|
+
right: 0
|
|
8
41
|
|
|
9
42
|
%flex-center-xy
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
43
|
+
display: flex
|
|
44
|
+
justify-content: center
|
|
45
|
+
align-items: center
|
|
13
46
|
|
|
14
47
|
// Nanosplash host scoped varibles
|
|
15
48
|
.nsh
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
49
|
+
--color: DarkSlateGray
|
|
50
|
+
--size: 20px
|
|
51
|
+
--relSize: calc(var(--size) * 0.9)
|
|
52
|
+
--font: 'Helvetica', 'Arial', sans-serif
|
|
53
|
+
--weight: 400
|
|
54
|
+
--bg: #{ rgba(White, 0.9) }
|
|
55
|
+
--zIdx: 999999999
|
|
56
|
+
--blur: blur(5px)
|
|
24
57
|
|
|
25
58
|
// Nanosplash host
|
|
26
59
|
.nsh
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
60
|
+
position: relative
|
|
61
|
+
z-index: var(--zIdx)
|
|
62
|
+
&::before // The backdrop
|
|
63
|
+
@extend %maximize
|
|
64
|
+
@extend %bottom-left
|
|
65
|
+
position: absolute
|
|
66
|
+
background-color: var(--bg)
|
|
67
|
+
content: ''
|
|
68
|
+
backdrop-filter: var(--blur)
|
|
69
|
+
-webkit-backdrop-filter: var(--blur)
|
|
70
|
+
z-index: calc(var(--zIdx) + 1)
|
|
71
|
+
border-radius: inherit
|
|
39
72
|
|
|
40
73
|
// When Nanosplash host is the document body
|
|
41
74
|
body.nsh
|
|
42
|
-
|
|
75
|
+
&, &::before
|
|
76
|
+
@extend %maximize
|
|
77
|
+
position: fixed
|
|
78
|
+
top: var(--ns-top)
|
|
79
|
+
left: 0
|
|
43
80
|
|
|
44
81
|
// Nanosplash (main element)
|
|
45
82
|
.ns
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
83
|
+
@extend %maximize
|
|
84
|
+
@extend %bottom-left
|
|
85
|
+
@extend %flex-center-xy
|
|
86
|
+
position: absolute
|
|
87
|
+
z-index: calc(var(--zIdx) + 2)
|
|
88
|
+
animation: ns-fade 2s
|
|
51
89
|
|
|
52
90
|
// Nanosplash container
|
|
53
91
|
.nsc
|
|
54
|
-
|
|
55
|
-
|
|
92
|
+
@extend %flex-center-xy
|
|
93
|
+
filter: drop-shadow(0 0 0.07rem #{ rgba(Black, 0.25) })
|
|
56
94
|
|
|
57
95
|
// Nanosplash text
|
|
58
96
|
.nst
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
97
|
+
color: var(--color)
|
|
98
|
+
font-size: var(--size)
|
|
99
|
+
font-family: var(--font)
|
|
100
|
+
font-weight: var(--weight)
|
|
101
|
+
font-optical-sizing: auto
|
|
102
|
+
max-width: 80dvw
|
|
103
|
+
white-space: nowrap
|
|
104
|
+
text-overflow: ellipsis
|
|
105
|
+
overflow: hidden
|
|
106
|
+
margin-right: var(--relSize)
|
|
107
|
+
text-shadow: 0 0 0.06rem #{ rgba(DarkSlateGray, .25) }
|
|
108
|
+
animation: ns-ascend 500ms
|
|
65
109
|
|
|
66
110
|
// Nanosplash spinner
|
|
67
111
|
.nss
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// Spinner animations:
|
|
83
|
-
@keyframes Rotate
|
|
84
|
-
100%
|
|
85
|
-
transform: rotate(360deg)
|
|
86
|
-
@keyframes Dash
|
|
87
|
-
0%
|
|
88
|
-
stroke-dasharray: 1, 150
|
|
89
|
-
stroke-dashoffset: 0
|
|
90
|
-
50%
|
|
91
|
-
stroke-dasharray: 90, 150
|
|
92
|
-
stroke-dashoffset: -35
|
|
93
|
-
100%
|
|
94
|
-
stroke-dasharray: 90, 150
|
|
95
|
-
stroke-dashoffset: -124
|
|
112
|
+
display: block
|
|
113
|
+
width: var(--relSize)
|
|
114
|
+
height: var(--relSize)
|
|
115
|
+
animation: ns-ascend 500ms
|
|
116
|
+
& > svg
|
|
117
|
+
animation: ns-rotate 2s linear infinite
|
|
118
|
+
position: relative
|
|
119
|
+
width: inherit
|
|
120
|
+
height: inherit
|
|
121
|
+
stroke-width: 8
|
|
122
|
+
& .path
|
|
123
|
+
stroke: var(--color)
|
|
124
|
+
stroke-linecap: round
|
|
125
|
+
animation: ns-dash 1.5s ease-in-out infinite
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// @ts-strict
|
|
2
|
+
import style from '../style/ns.sass?inline'
|
|
3
|
+
import { NanosplashInterface } from './types/NanosplashInterface'
|
|
4
|
+
import {
|
|
5
|
+
DOMSelector,
|
|
6
|
+
ElementReference,
|
|
7
|
+
NSElement,
|
|
8
|
+
ScopedSelectors,
|
|
9
|
+
} from './types/Types'
|
|
10
|
+
import { version } from '../../package.json'
|
|
11
|
+
|
|
12
|
+
const StyleID: string = 'nscss'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @param node Node to query.
|
|
17
|
+
* @returns An object containing two, slightly different functions that
|
|
18
|
+
* retrieves elements from the DOM.
|
|
19
|
+
*/
|
|
20
|
+
const scope = (node: ParentNode): ScopedSelectors => {
|
|
21
|
+
const all = (ref: string) => Array.from(node.querySelectorAll(ref))
|
|
22
|
+
return {
|
|
23
|
+
all,
|
|
24
|
+
first: (ref: string) => all(ref)[0] ?? null,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* # Get all
|
|
30
|
+
* @param selector CSS selector used to match nodes in the DOM.
|
|
31
|
+
* @returns An array of Element nodes.
|
|
32
|
+
*/
|
|
33
|
+
const getAll = (selector: DOMSelector): Element[] =>
|
|
34
|
+
scope(document).all(selector)
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* # Get
|
|
38
|
+
* @param selector CSS selector used to match nodes in the DOM.
|
|
39
|
+
* @returns Firs Element node from the DOM matching the selector.
|
|
40
|
+
*/
|
|
41
|
+
const get = (selector: DOMSelector): Element | null =>
|
|
42
|
+
scope(document).first(selector)
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* # Get All NS
|
|
46
|
+
* @returns An array of all Nanosplash elements in the DOM.
|
|
47
|
+
*/
|
|
48
|
+
const getAllNS = (): NSElement[] => getAll('.ns') as NSElement[]
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* # Parse Ref
|
|
52
|
+
* @param ref Element reference which could be a selector or an Element.
|
|
53
|
+
* @returns The Element node or null.
|
|
54
|
+
*/
|
|
55
|
+
const parseRef = (ref: ElementReference): Element => {
|
|
56
|
+
if (ref instanceof Element) return ref
|
|
57
|
+
const element = get(ref)
|
|
58
|
+
if (!element) throw new Error(`Selector (${ref}) returned null`)
|
|
59
|
+
return element
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* # Div
|
|
64
|
+
* @param className Optional string containing class names.
|
|
65
|
+
* @param children Optional list of Nodes or strings.
|
|
66
|
+
* @returns The newly created HTMLDivElement.
|
|
67
|
+
*/
|
|
68
|
+
const div = (
|
|
69
|
+
className?: string,
|
|
70
|
+
...children: (Node | string)[]
|
|
71
|
+
): HTMLDivElement => {
|
|
72
|
+
const el = document.createElement('div')
|
|
73
|
+
if (className) el.classList.add(className)
|
|
74
|
+
el.append(...children)
|
|
75
|
+
return el
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* # Parse
|
|
80
|
+
* @param html HTML string.
|
|
81
|
+
* @returns Parsed node.
|
|
82
|
+
*/
|
|
83
|
+
const parse = (html: string): Node => {
|
|
84
|
+
const el: HTMLDivElement = div()
|
|
85
|
+
el.innerHTML = html
|
|
86
|
+
return el.firstChild as Node
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* # Create NS
|
|
91
|
+
* TODO: Investigate the possibility of inheritence.
|
|
92
|
+
* @returns Nanpslash DOM element.
|
|
93
|
+
*/
|
|
94
|
+
const createNS = (): NSElement => {
|
|
95
|
+
const circle: string = '<circle class=path cx=25 cy=25 r=20 fill=none />'
|
|
96
|
+
const svg = parse(`<svg viewBox="0 0 50 50">${circle}</svg>`) as Element
|
|
97
|
+
const el = div('ns', div('nsc', div('nst'), div('nss', svg))) as NSElement
|
|
98
|
+
el.nsId = Date.now()
|
|
99
|
+
return el
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* # Peek
|
|
104
|
+
* Collect all Nanosplash elements in the DOM, sort them by their NS ID
|
|
105
|
+
* in ascending order, and return the first element.
|
|
106
|
+
* @returns The front of the queue.
|
|
107
|
+
*/
|
|
108
|
+
const peek = (): NSElement | null =>
|
|
109
|
+
getAllNS().sort((a: NSElement, b: NSElement) => a.nsId - b.nsId)[0] ?? null
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* # Set NS Text
|
|
113
|
+
* Replace the text node to trigger the animation which in turn is invoked
|
|
114
|
+
* by the connected callback in the DOM.
|
|
115
|
+
* @param ns Nanosplash element.
|
|
116
|
+
* @param text Text to display adjacent to spinner.
|
|
117
|
+
*/
|
|
118
|
+
const setNSText = (ns: NSElement, text: string): void => {
|
|
119
|
+
const nsScope = scope(ns)
|
|
120
|
+
const oldNst = nsScope.first('.nst') as Element | null
|
|
121
|
+
if (!text) return oldNst?.remove()
|
|
122
|
+
const newNst = div('nst', text)
|
|
123
|
+
if (oldNst) {
|
|
124
|
+
oldNst.replaceWith(newNst)
|
|
125
|
+
} else {
|
|
126
|
+
const nsc = nsScope.first('.nsc') as Element
|
|
127
|
+
nsc.insertBefore(newNst, nsc.firstChild)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* # Set NS Parent
|
|
133
|
+
* Define where inside the DOM to spawn the Nansoplash.
|
|
134
|
+
* @param ns Nanosplash element.
|
|
135
|
+
* @param parent NS element's parent to be.
|
|
136
|
+
*/
|
|
137
|
+
const setNSParent = (ns: NSElement, parent: Element): void => {
|
|
138
|
+
const child = parent.firstElementChild
|
|
139
|
+
if (child) {
|
|
140
|
+
parent.insertBefore(ns, child)
|
|
141
|
+
}
|
|
142
|
+
parent.append(ns)
|
|
143
|
+
parent.classList.add('nsh')
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* # Show
|
|
148
|
+
* @param text Text to display adjacent to spinner.
|
|
149
|
+
* @param inside Selector or element in which the NS element will be spawned.
|
|
150
|
+
* @returns The ID if the NS element — which is a UTC integer.
|
|
151
|
+
*/
|
|
152
|
+
const show = (text?: string, inside?: string | Element): number | null => {
|
|
153
|
+
const parent: Element = inside ? parseRef(inside) : document.body
|
|
154
|
+
let ns: NSElement
|
|
155
|
+
const recycledNs = scope(parent).first('& > .ns')
|
|
156
|
+
if (recycledNs) {
|
|
157
|
+
ns = recycledNs as NSElement
|
|
158
|
+
} else {
|
|
159
|
+
ns = createNS()
|
|
160
|
+
setNSParent(ns, parent as Element)
|
|
161
|
+
}
|
|
162
|
+
setNSText(ns, text ?? '')
|
|
163
|
+
const top: string = window.scrollY + 'px'
|
|
164
|
+
window.document.body.style.setProperty('--ns-top', top)
|
|
165
|
+
return ns.nsId
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* # Delete NS
|
|
170
|
+
* @param ns Nanosplash elememnt.
|
|
171
|
+
*/
|
|
172
|
+
const deleteNS = (ns?: Element | null): void => {
|
|
173
|
+
ns?.parentElement?.classList.remove('nsh')
|
|
174
|
+
ns?.remove()
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* # Find NS
|
|
179
|
+
* @param id The UTC integer returned from the `show` function.
|
|
180
|
+
* @returns Null or the corresponding Nanosplash element.
|
|
181
|
+
*/
|
|
182
|
+
const findNS = (id: number) => getAllNS().find(v => v.nsId === id) ?? null
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* # Hide
|
|
186
|
+
* @param id Optional ID of a Nanosplash element.
|
|
187
|
+
*/
|
|
188
|
+
const hide = (id?: number): void => {
|
|
189
|
+
const ns: NSElement | null = id ? findNS(id) : peek()
|
|
190
|
+
deleteNS(ns)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* # Hide All
|
|
195
|
+
*/
|
|
196
|
+
const hideAll = (): void => getAll('.ns').forEach(deleteNS)
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* # Add style
|
|
200
|
+
*/
|
|
201
|
+
const addStyle = (): void => {
|
|
202
|
+
get('#nscss')?.remove()
|
|
203
|
+
const html: string = `<style id=${StyleID}>${style}</style>`
|
|
204
|
+
document.body.append(parse(html))
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* # Use NS
|
|
209
|
+
* @returns Nanosplash API.
|
|
210
|
+
*/
|
|
211
|
+
export const useNs = (): NanosplashInterface => {
|
|
212
|
+
addStyle()
|
|
213
|
+
return (window.ns = Object.freeze({
|
|
214
|
+
show,
|
|
215
|
+
hide,
|
|
216
|
+
hideAll,
|
|
217
|
+
version,
|
|
218
|
+
}))
|
|
219
|
+
}
|
package/src/ts/main.ts
CHANGED
package/src/ts/types/Types.ts
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export type
|
|
1
|
+
import { NanosplashInterface } from './NanosplashInterface'
|
|
2
|
+
|
|
3
|
+
export type UTCInteger = number
|
|
4
|
+
export type DOMSelector = string
|
|
5
|
+
export type ElementReference = DOMSelector | Element
|
|
6
|
+
|
|
7
|
+
export interface ScopedSelectors {
|
|
8
|
+
/**
|
|
9
|
+
* @param selector Selector to match with a DOM element.
|
|
10
|
+
* @returns An array of elements matching with the selector.
|
|
11
|
+
*/
|
|
12
|
+
all: (selector: DOMSelector) => Element[]
|
|
13
|
+
/**
|
|
14
|
+
* @param selector Selector to match with a DOM element.
|
|
15
|
+
* @returns Null or the first element in the DOM to match the selector.
|
|
16
|
+
*/
|
|
17
|
+
first: (selector: DOMSelector) => Element | null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface NSElement extends HTMLDivElement {
|
|
21
|
+
nsId: number
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
declare global {
|
|
25
|
+
interface Window {
|
|
26
|
+
ns: NanosplashInterface
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/ts/types/global.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ServiceInterface } from '../core/ServiceInterface'
|
|
1
|
+
import { NanosplashInterface } from './NanosplashInterface'
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
interface IWindow {
|
|
4
|
+
ns: NanosplashInterface
|
|
5
|
+
}
|
|
5
6
|
|
|
6
7
|
declare global {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
ns: ServiceInterface
|
|
8
|
+
interface Window extends IWindow {}
|
|
9
|
+
interface window extends IWindow {}
|
|
10
|
+
interface globalThis extends globalThis {
|
|
11
|
+
Window: IWindow
|
|
12
|
+
window: IWindow
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, it, test, expect, beforeEach } from 'vitest'
|
|
2
|
+
import { useNs } from '../src/ts/Nanosplash'
|
|
3
|
+
import { JSDOM } from 'jsdom'
|
|
4
|
+
|
|
5
|
+
let ns
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
const dom = new JSDOM()
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
globalThis.window = dom.window
|
|
11
|
+
globalThis.document = window.document
|
|
12
|
+
globalThis.window.ns = ns = useNs()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
describe('Nanosplash API', () => {
|
|
16
|
+
it('should be defined', () => {
|
|
17
|
+
expect(window.ns).toBeDefined()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should have the "show" method', () => {
|
|
21
|
+
expect(window.ns.show).toBeDefined()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('should have the "hide" method', () => {
|
|
25
|
+
expect(window.ns.hide).toBeDefined()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('should have the "hideAll" method', () => {
|
|
29
|
+
expect(window.ns.hideAll).toBeDefined()
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should have the global instance', () => {
|
|
33
|
+
expect(window.ns).toBe(ns)
|
|
34
|
+
})
|
|
35
|
+
})
|
package/.prettierignore
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
*.sass
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import { Reference } from '../types/Types'
|
|
2
|
-
import { Service } from './Service'
|
|
3
|
-
import { Splash } from './Splash'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* # DOM Utilities
|
|
7
|
-
* A collection of functions that are used by the Nanosplash classes.
|
|
8
|
-
* @see Splash
|
|
9
|
-
* @see Service
|
|
10
|
-
* @author Isak K. Hauge <isakhauge@icloud.com>
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* # Render
|
|
15
|
-
* @param html HTML string to render.
|
|
16
|
-
* @returns Rendered HTML element.
|
|
17
|
-
*/
|
|
18
|
-
export function render(html: string): HTMLElement {
|
|
19
|
-
return (div =>
|
|
20
|
-
// @ts-ignore
|
|
21
|
-
(() => div.firstChild as HTMLElement)((div.innerHTML = html)))(
|
|
22
|
-
document.createElement('div')
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* # Create Element
|
|
28
|
-
* Return the main Nanosplash element.
|
|
29
|
-
*/
|
|
30
|
-
export function createElement(): HTMLDivElement {
|
|
31
|
-
return render(
|
|
32
|
-
'<div class=ns><div class=nsc><div class=nst></div><div class=nss><svg viewBox="0 0 50 50"><circle class=path cx=25 cy=25 r=20 fill=none></circle></svg></div></div></div>'
|
|
33
|
-
) as HTMLDivElement
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* # Inject as First Child
|
|
38
|
-
* Insert element into the target element as its first child.
|
|
39
|
-
* @param element Element to inject.
|
|
40
|
-
* @param targetElement Element in which the first element is to be injected.
|
|
41
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/children
|
|
42
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore
|
|
43
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild
|
|
44
|
-
* @see https://developer.mozilla.org/docs/Web/API/NodeList/item
|
|
45
|
-
*/
|
|
46
|
-
export function injectAsFirstChild(
|
|
47
|
-
element: Element,
|
|
48
|
-
targetElement: Element
|
|
49
|
-
): void {
|
|
50
|
-
const targetHasChild = targetElement.children.length > 0
|
|
51
|
-
if (targetHasChild) {
|
|
52
|
-
targetElement.insertBefore(element, targetElement.children.item(0))
|
|
53
|
-
} else {
|
|
54
|
-
targetElement.append(element)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* # Add NS Host Class
|
|
60
|
-
* Add the `nsHostClassName` class to the `element`.
|
|
61
|
-
* @param element Element to which the `nsHostClassName` class will be added.
|
|
62
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
|
|
63
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/add
|
|
64
|
-
*/
|
|
65
|
-
export function addNSHostClass(element: Element | null): void {
|
|
66
|
-
element?.classList.add(Splash.NSHostClass)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* # Remove NS Host Class
|
|
71
|
-
* Remove the `nsHostClassName` class from the `element`.
|
|
72
|
-
* @param element Element from which the `nsHostClassName` class will be removed.
|
|
73
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
|
|
74
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/remove
|
|
75
|
-
*/
|
|
76
|
-
export function removeNSHostClass(element: Element | null): void {
|
|
77
|
-
element?.classList.remove(Splash.NSHostClass)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* # Show Element
|
|
82
|
-
* Set the `display` property of the `element` to `flex`.
|
|
83
|
-
* @param element Element to show.
|
|
84
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/display
|
|
85
|
-
*/
|
|
86
|
-
export function showElement(element: HTMLElement): void {
|
|
87
|
-
element.style.display = 'flex'
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* # Hide Element
|
|
92
|
-
* Set the `display` property of the `element` to `none`.
|
|
93
|
-
* @param element Element to hide.
|
|
94
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/display
|
|
95
|
-
*/
|
|
96
|
-
export function hideElement(element: HTMLElement): void {
|
|
97
|
-
element.style.display = 'none'
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* # Element From
|
|
102
|
-
* Convert the element reference to an element.
|
|
103
|
-
* @param ref Reference to an element.
|
|
104
|
-
* @returns { Element | null } Element or null.
|
|
105
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
|
|
106
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element
|
|
107
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Node
|
|
108
|
-
*/
|
|
109
|
-
export function elementFrom(ref: Reference): Element | null {
|
|
110
|
-
switch (typeof ref) {
|
|
111
|
-
case 'object':
|
|
112
|
-
const isBody = ref === document.body
|
|
113
|
-
const isElement = ref instanceof Element
|
|
114
|
-
if (isBody || isElement) {
|
|
115
|
-
return ref
|
|
116
|
-
}
|
|
117
|
-
throw new Error(
|
|
118
|
-
'Reference is an object but not an Element instance.'
|
|
119
|
-
)
|
|
120
|
-
case 'string':
|
|
121
|
-
return document.querySelector(ref)
|
|
122
|
-
default:
|
|
123
|
-
throw new Error('Reference is not an object or a string.')
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* # Move
|
|
129
|
-
* Move an Element to another Element.
|
|
130
|
-
* @param element Element to move
|
|
131
|
-
* @param targetElement Target element
|
|
132
|
-
*/
|
|
133
|
-
export function move(element: Element, targetElement: Element): void {
|
|
134
|
-
// Clean the current NS host element.
|
|
135
|
-
removeNSHostClass(element.parentElement)
|
|
136
|
-
// Assign new NS host element.
|
|
137
|
-
addNSHostClass(targetElement)
|
|
138
|
-
injectAsFirstChild(element, targetElement)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* # Get Recycled NS
|
|
143
|
-
* Return the Nanosplash instance inside the target element if it exists.
|
|
144
|
-
* @param targetElement Element wherein the Nanosplash instance is to reside.
|
|
145
|
-
* @returns { Nanosplash | null } Nanosplash instance or null.
|
|
146
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/Document/firstElementChild
|
|
147
|
-
*/
|
|
148
|
-
export function getRecycledSplash(targetElement: Element): Splash | null {
|
|
149
|
-
const children = Array.from(targetElement.children || [])
|
|
150
|
-
const nss = Service.getInstance()
|
|
151
|
-
let splash: Splash | null = null
|
|
152
|
-
const n = children.length
|
|
153
|
-
for (let i = 0; i < n; i++) {
|
|
154
|
-
const child = children[i]
|
|
155
|
-
if (child.classList.contains(Splash.NSClass)) {
|
|
156
|
-
splash = nss.nsQueue.get(child.id) ?? null
|
|
157
|
-
break
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return splash
|
|
161
|
-
}
|