@splendidlabz/utils 1.4.0 → 1.5.0-alpha.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.
- package/CHANGELOG.md +6 -0
- package/actions/intersection-observer.js +37 -0
- package/actions/masonry.js +48 -11
- package/actions/mutation-observer.js +0 -1
- package/actions/prefer-horizontal-scroll.js +2 -1
- package/actions/resize-observer.js +4 -9
- package/dom/accessibility.js +25 -0
- package/dom/index.js +1 -0
- package/dom/media.js +3 -1
- package/lib/strings/markdown.js +1 -0
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// See https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options for options
|
|
2
|
+
const options = {}
|
|
3
|
+
|
|
4
|
+
export function intersectionObserver(node, options) {
|
|
5
|
+
const { callback, opts } = options
|
|
6
|
+
const observer = new IntersectionObserver(observerFn, opts)
|
|
7
|
+
|
|
8
|
+
function observerFn(entries, observer) {
|
|
9
|
+
entries.forEach(entry => {
|
|
10
|
+
for (const entry of entries) {
|
|
11
|
+
// Needs testing to see what's in entry
|
|
12
|
+
if (callback) callback({ node, entry, observer })
|
|
13
|
+
else {
|
|
14
|
+
node.dispatchEvent(
|
|
15
|
+
new CustomEvent('intersect', {
|
|
16
|
+
detail: { node, entry, observer },
|
|
17
|
+
}),
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
observer.observe(node)
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
observer,
|
|
28
|
+
disconnect() {
|
|
29
|
+
observer.disconnect()
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
// Destroy is used for Svelte actions
|
|
33
|
+
destroy() {
|
|
34
|
+
observer.disconnect()
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
}
|
package/actions/masonry.js
CHANGED
|
@@ -1,28 +1,32 @@
|
|
|
1
|
-
import { getChildrenElements, mediaLoaded } from '../dom
|
|
2
|
-
|
|
1
|
+
import { getChildrenElements, mediaLoaded } from '../dom'
|
|
2
|
+
|
|
3
|
+
import { resizeObserver } from './resize-observer'
|
|
3
4
|
|
|
4
5
|
export async function masonry(node) {
|
|
5
6
|
if (nativeMasonrySupport(node)) return
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
const colGap = parseFloat(getComputedStyle(node).columnGap)
|
|
9
|
+
const items = getChildrenElements(node)
|
|
9
10
|
|
|
10
11
|
node.style.setProperty('row-gap', '1px', 'important')
|
|
11
12
|
node.style.gridAutoRows = '0px'
|
|
12
|
-
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
await mediaLoaded(node)
|
|
16
|
+
} catch (e) {}
|
|
17
|
+
|
|
18
|
+
layout({ colGap, items })
|
|
13
19
|
|
|
14
20
|
const obs = resizeObserver(node, {
|
|
15
21
|
async callback(opts) {
|
|
16
|
-
items
|
|
17
|
-
gap = parseFloat(getComputedStyle(node).columnGap)
|
|
18
|
-
layout(node)
|
|
22
|
+
layout({ colGap, items })
|
|
19
23
|
},
|
|
20
24
|
})
|
|
21
25
|
|
|
22
|
-
async function layout() {
|
|
26
|
+
async function layout({ colGap, items }) {
|
|
23
27
|
items.forEach(item => {
|
|
24
|
-
const
|
|
25
|
-
item.style.gridRowEnd = `span ${Math.round(
|
|
28
|
+
const ib = item.getBoundingClientRect()
|
|
29
|
+
item.style.gridRowEnd = `span ${Math.round(ib.height + colGap)}`
|
|
26
30
|
})
|
|
27
31
|
}
|
|
28
32
|
|
|
@@ -33,6 +37,39 @@ export async function masonry(node) {
|
|
|
33
37
|
}
|
|
34
38
|
}
|
|
35
39
|
|
|
40
|
+
// export async function masonry(node) {
|
|
41
|
+
// if (typeof window === 'undefined') return
|
|
42
|
+
// if (nativeMasonrySupport(node)) return
|
|
43
|
+
|
|
44
|
+
// let items
|
|
45
|
+
// let gap
|
|
46
|
+
|
|
47
|
+
// node.style.setProperty('row-gap', '1px', 'important')
|
|
48
|
+
// node.style.gridAutoRows = '0px'
|
|
49
|
+
// // await mediaLoaded(node)
|
|
50
|
+
|
|
51
|
+
// const obs = resizeObserver(node, {
|
|
52
|
+
// async callback(opts) {
|
|
53
|
+
// items = getChildrenElements(node)
|
|
54
|
+
// gap = parseFloat(getComputedStyle(node).columnGap)
|
|
55
|
+
// layout(node)
|
|
56
|
+
// },
|
|
57
|
+
// })
|
|
58
|
+
|
|
59
|
+
// async function layout() {
|
|
60
|
+
// items.forEach(item => {
|
|
61
|
+
// const itemBox = item.getBoundingClientRect()
|
|
62
|
+
// // item.style.gridRowEnd = `span ${Math.round(itemBox.height + gap)}`
|
|
63
|
+
// })
|
|
64
|
+
// }
|
|
65
|
+
|
|
66
|
+
// return {
|
|
67
|
+
// destroy() {
|
|
68
|
+
// obs.disconnect()
|
|
69
|
+
// },
|
|
70
|
+
// }
|
|
71
|
+
// }
|
|
72
|
+
|
|
36
73
|
function nativeMasonrySupport(node) {
|
|
37
74
|
return getComputedStyle(node).gridTemplateRows === 'masonry'
|
|
38
75
|
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
removeListeners,
|
|
5
5
|
setCSSVar,
|
|
6
6
|
} from '../dom/index.js'
|
|
7
|
+
|
|
7
8
|
import { omitEmpty } from '../lib/index.js'
|
|
8
9
|
|
|
9
10
|
const DEFAULT_OPTIONS = {
|
|
@@ -11,7 +12,7 @@ const DEFAULT_OPTIONS = {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export function preferHorizontalScroll(node, props = {}) {
|
|
14
|
-
if (!node.classList.contains('
|
|
15
|
+
if (!node.classList.contains('scrollable-prefer-horizontal-scroll')) return
|
|
15
16
|
|
|
16
17
|
const state = {
|
|
17
18
|
origSnapType: null,
|
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
/* eslint-env browser */
|
|
2
|
-
|
|
3
|
-
const DEFAULT_OBSERVER_OPTIONS = {
|
|
4
|
-
observe: true,
|
|
5
|
-
}
|
|
6
|
-
|
|
7
2
|
export function resizeObserver(node, options) {
|
|
8
3
|
// We set the option here to prevent observer from being created unless necessary.
|
|
9
|
-
options = {
|
|
4
|
+
options = { observe: true, ...options }
|
|
10
5
|
if (!options.observe) return
|
|
11
6
|
|
|
12
7
|
const observer = new ResizeObserver(observerFn)
|
|
13
8
|
|
|
14
9
|
function observerFn(entries) {
|
|
15
10
|
for (const entry of entries) {
|
|
16
|
-
if (options.callback) options.callback({ node, entry, observer })
|
|
11
|
+
if (options.callback) options.callback({ node, entry, entries, observer })
|
|
17
12
|
else {
|
|
18
13
|
node.dispatchEvent(
|
|
19
|
-
new CustomEvent('resize', {
|
|
20
|
-
detail: { node, entry, observer },
|
|
14
|
+
new CustomEvent('resize-obs', {
|
|
15
|
+
detail: { node, entry, entries, observer },
|
|
21
16
|
}),
|
|
22
17
|
)
|
|
23
18
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function stopBodyScroll() {
|
|
2
|
+
const top = document.documentElement.scrollTop
|
|
3
|
+
|
|
4
|
+
element.style.top = -1 * top + 'px'
|
|
5
|
+
element.style.overflow = 'hidden'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function allowBodyScroll() {
|
|
9
|
+
const top = parseFloat(document.body.style.top) * -1
|
|
10
|
+
document.body.style.top = null
|
|
11
|
+
document.body.style.overflow = null
|
|
12
|
+
document.documentElement.scrollTop = top
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function inertOthers() {}
|
|
16
|
+
|
|
17
|
+
export function hasLabel(label, labelledBy) {
|
|
18
|
+
if (label || labelledBy) return true
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isInvalidAriaPopup(value) {
|
|
22
|
+
const allowedPopoupValues = ['dialog', 'menu', 'listbox', 'grid', 'tree']
|
|
23
|
+
if (!allowedPopoupValues.includes(value)) return true
|
|
24
|
+
return false
|
|
25
|
+
}
|
package/dom/index.js
CHANGED
package/dom/media.js
CHANGED
|
@@ -4,7 +4,9 @@ export async function imagesLoaded(node) {
|
|
|
4
4
|
return new Promise((resolve, reject) => {
|
|
5
5
|
if (img.complete) return resolve()
|
|
6
6
|
img.onload = resolve
|
|
7
|
-
img.onerror =
|
|
7
|
+
img.onerror = e => {
|
|
8
|
+
reject('Image failed to load')
|
|
9
|
+
}
|
|
8
10
|
})
|
|
9
11
|
})
|
|
10
12
|
return Promise.all(promises)
|
package/lib/strings/markdown.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@splendidlabz/utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0-alpha.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -21,15 +21,15 @@
|
|
|
21
21
|
},
|
|
22
22
|
"author": "Zell Liew <zellwk@gmail.com>",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"dompurify": "^3.
|
|
25
|
-
"glob-promise": "^6.0.
|
|
24
|
+
"dompurify": "^3.2.4",
|
|
25
|
+
"glob-promise": "^6.0.7",
|
|
26
26
|
"pluralize": "^8.0.0",
|
|
27
27
|
"statuses": "^2.0.1"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@splendidlabz/eslint-config": "*",
|
|
31
|
-
"jsdom": "^
|
|
32
|
-
"np": "^
|
|
33
|
-
"vitest": "^
|
|
31
|
+
"jsdom": "^26.0.0",
|
|
32
|
+
"np": "^10.2.0",
|
|
33
|
+
"vitest": "^3.0.7"
|
|
34
34
|
}
|
|
35
35
|
}
|