@splendidlabz/utils 1.9.1 → 1.10.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.
- package/CHANGELOG.md +13 -0
- package/dist/cjs/dom/actions/index.cjs +75 -73
- package/dist/cjs/dom/actions/masonry.cjs +4 -2
- package/dist/cjs/dom/actions/prefer-horizontal-scroll.cjs +24 -24
- package/dist/cjs/dom/actions/sticky.cjs +4 -2
- package/dist/cjs/dom/font-size.cjs +9 -3
- package/dist/cjs/dom/index.cjs +81 -66
- package/dist/cjs/dom/observers/index.cjs +24 -17
- package/dist/cjs/dom/observers/resize-observer.cjs +4 -2
- package/dist/cjs/dom/observers/scroll-observer.cjs +24 -17
- package/dist/esm/dom/actions/index.js +75 -73
- package/dist/esm/dom/actions/masonry.js +4 -2
- package/dist/esm/dom/actions/prefer-horizontal-scroll.js +24 -24
- package/dist/esm/dom/actions/sticky.js +4 -2
- package/dist/esm/dom/font-size.js +8 -3
- package/dist/esm/dom/index.js +80 -66
- package/dist/esm/dom/observers/index.js +24 -17
- package/dist/esm/dom/observers/resize-observer.js +4 -2
- package/dist/esm/dom/observers/scroll-observer.js +24 -17
- package/dist/types/dom/events.d.cts +2 -2
- package/dist/types/dom/font-size.d.cts +3 -2
- package/dist/types/dom/index.d.cts +2 -2
- package/dist/types/dom/observers/index.d.cts +1 -1
- package/dist/types/dom/observers/resize-observer.d.cts +3 -3
- package/dist/types/dom/observers/scroll-observer.d.cts +34 -21
- package/dist/types/dom/spam-prevention.d.cts +7 -7
- package/dist/types/lib/checks.d.cts +1 -1
- package/package.json +1 -1
- package/src/dom/actions/prefer-horizontal-scroll.js +3 -8
- package/src/dom/events.js +1 -1
- package/src/dom/font-size.js +9 -4
- package/src/dom/observers/resize-observer.js +6 -4
- package/src/dom/observers/scroll-observer.js +41 -27
- package/src/dom/spam-prevention.js +5 -4
- package/src/dom/events.test.js +0 -99
|
@@ -57,12 +57,14 @@ function useObserverMethodOnTarget(target, observer, method = "observe", options
|
|
|
57
57
|
function resizeObserver(target, options) {
|
|
58
58
|
const { callback, ...opts } = options;
|
|
59
59
|
const observer = new ResizeObserver(observerFn);
|
|
60
|
-
if (target === window
|
|
60
|
+
if (target === window || target === document)
|
|
61
|
+
target = document.documentElement;
|
|
61
62
|
useObserverMethodOnTarget(target, observer, "observe", opts);
|
|
62
63
|
function observerFn(entries) {
|
|
63
64
|
for (const entry of entries) {
|
|
64
65
|
if (callback) callback({ entry, entries, observer });
|
|
65
|
-
else
|
|
66
|
+
else
|
|
67
|
+
dispatchEvent(entry.target, "resize-obs", { entry, entries, observer });
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
return {
|
|
@@ -57,12 +57,14 @@ function useObserverMethodOnTarget(target, observer, method = "observe", options
|
|
|
57
57
|
function resizeObserver(target, options) {
|
|
58
58
|
const { callback, ...opts } = options;
|
|
59
59
|
const observer = new ResizeObserver(observerFn);
|
|
60
|
-
if (target === window
|
|
60
|
+
if (target === window || target === document)
|
|
61
|
+
target = document.documentElement;
|
|
61
62
|
useObserverMethodOnTarget(target, observer, "observe", opts);
|
|
62
63
|
function observerFn(entries) {
|
|
63
64
|
for (const entry of entries) {
|
|
64
65
|
if (callback) callback({ entry, entries, observer });
|
|
65
|
-
else
|
|
66
|
+
else
|
|
67
|
+
dispatchEvent(entry.target, "resize-obs", { entry, entries, observer });
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
return {
|
|
@@ -83,40 +85,44 @@ var defaultOptions = {
|
|
|
83
85
|
// Float between 0 to 1.
|
|
84
86
|
tolerance: 0.1,
|
|
85
87
|
// Float between 0 to 1. Tolerance for event firing
|
|
86
|
-
throttle: 16,
|
|
87
|
-
// Throttle interval in ms (default: ~60fps)
|
|
88
88
|
once: false
|
|
89
89
|
// Only fire threshold callback once
|
|
90
90
|
};
|
|
91
|
+
function getScrollElement(node) {
|
|
92
|
+
if (node === document || node === window || node === document.documentElement) {
|
|
93
|
+
return document.documentElement;
|
|
94
|
+
}
|
|
95
|
+
return (
|
|
96
|
+
/** @type {Element} */
|
|
97
|
+
node
|
|
98
|
+
);
|
|
99
|
+
}
|
|
91
100
|
function scrollObserver(node, options = {}) {
|
|
92
101
|
const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
|
|
93
102
|
const opts = { ...defaultOptions, ...userOpts };
|
|
94
|
-
const { threshold, tolerance,
|
|
95
|
-
|
|
103
|
+
const { threshold, tolerance, once } = opts;
|
|
104
|
+
let prevScrollDirection = null;
|
|
96
105
|
let prevScrollTop = 0;
|
|
97
106
|
let prevScrollPercent = 0;
|
|
98
|
-
let lastThrottleTime = 0;
|
|
99
107
|
let thresholdFired = false;
|
|
100
108
|
let rafId = null;
|
|
101
|
-
const isDocumentScroll = node === document || node === window;
|
|
102
|
-
const scrollElement =
|
|
109
|
+
const isDocumentScroll = node === document || node === window || node === document.documentElement;
|
|
110
|
+
const scrollElement = getScrollElement(node);
|
|
111
|
+
const eventTarget = isDocumentScroll ? window : node;
|
|
103
112
|
let cachedScrollHeight = 0;
|
|
104
113
|
let cachedClientHeight = 0;
|
|
105
114
|
updateCache();
|
|
106
115
|
const cacheObserver = resizeObserver(scrollElement, {
|
|
107
116
|
callback: updateCache
|
|
108
117
|
});
|
|
109
|
-
|
|
118
|
+
eventTarget.addEventListener("scroll", throttledObserve, { passive: true });
|
|
119
|
+
function throttledObserve() {
|
|
120
|
+
rafId = requestAnimationFrame(observe);
|
|
121
|
+
}
|
|
110
122
|
function updateCache() {
|
|
111
123
|
cachedScrollHeight = scrollElement.scrollHeight;
|
|
112
124
|
cachedClientHeight = scrollElement.clientHeight;
|
|
113
125
|
}
|
|
114
|
-
function throttledObserve() {
|
|
115
|
-
const now = Date.now();
|
|
116
|
-
if (now - lastThrottleTime < throttle) return;
|
|
117
|
-
lastThrottleTime = now;
|
|
118
|
-
rafId = requestAnimationFrame(observe);
|
|
119
|
-
}
|
|
120
126
|
function observe() {
|
|
121
127
|
const scrollTop = scrollElement.scrollTop;
|
|
122
128
|
if (Math.abs(scrollTop - prevScrollTop) < 1) return;
|
|
@@ -155,10 +161,11 @@ function scrollObserver(node, options = {}) {
|
|
|
155
161
|
}
|
|
156
162
|
prevScrollTop = scrollTop;
|
|
157
163
|
prevScrollPercent = scrollPercent;
|
|
164
|
+
prevScrollDirection = scrollDirection;
|
|
158
165
|
}
|
|
159
166
|
return {
|
|
160
167
|
destroy() {
|
|
161
|
-
|
|
168
|
+
eventTarget.removeEventListener("scroll", throttledObserve);
|
|
162
169
|
if (rafId) cancelAnimationFrame(rafId);
|
|
163
170
|
cacheObserver.destroy();
|
|
164
171
|
}
|
|
@@ -81,12 +81,14 @@ function useObserverMethodOnTarget(target, observer, method = "observe", options
|
|
|
81
81
|
function resizeObserver(target, options) {
|
|
82
82
|
const { callback, ...opts } = options;
|
|
83
83
|
const observer = new ResizeObserver(observerFn);
|
|
84
|
-
if (target === window
|
|
84
|
+
if (target === window || target === document)
|
|
85
|
+
target = document.documentElement;
|
|
85
86
|
useObserverMethodOnTarget(target, observer, "observe", opts);
|
|
86
87
|
function observerFn(entries) {
|
|
87
88
|
for (const entry of entries) {
|
|
88
89
|
if (callback) callback({ entry, entries, observer });
|
|
89
|
-
else
|
|
90
|
+
else
|
|
91
|
+
dispatchEvent(entry.target, "resize-obs", { entry, entries, observer });
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
94
|
return {
|
|
@@ -134,58 +136,6 @@ function nativeMasonrySupport(node) {
|
|
|
134
136
|
return getComputedStyle(node).gridTemplateRows === "masonry";
|
|
135
137
|
}
|
|
136
138
|
|
|
137
|
-
// src/dom/bounding-box.js
|
|
138
|
-
function boundingBox(element, { containsPadding = true } = {}) {
|
|
139
|
-
const box = element.getBoundingClientRect();
|
|
140
|
-
const ret = {};
|
|
141
|
-
for (const prop in box) ret[prop] = box[prop];
|
|
142
|
-
if (!containsPadding) {
|
|
143
|
-
const style = getComputedStyle(element);
|
|
144
|
-
const paddingTop = parseFloat(style.paddingTop);
|
|
145
|
-
const paddingRight = parseFloat(style.paddingRight);
|
|
146
|
-
const paddingBottom = parseFloat(style.paddingBottom);
|
|
147
|
-
const paddingLeft = parseFloat(style.paddingLeft);
|
|
148
|
-
ret.x = ret.x + paddingLeft;
|
|
149
|
-
ret.y = ret.y + paddingTop;
|
|
150
|
-
ret.width = ret.width - paddingLeft - paddingRight;
|
|
151
|
-
ret.height = ret.height - paddingTop - paddingBottom;
|
|
152
|
-
ret.top = ret.top + paddingTop;
|
|
153
|
-
ret.bottom = ret.bottom - paddingBottom;
|
|
154
|
-
ret.right = ret.right - paddingRight;
|
|
155
|
-
ret.left = ret.left + paddingLeft;
|
|
156
|
-
}
|
|
157
|
-
ret.xCenter = (ret.left + ret.right) / 2;
|
|
158
|
-
ret.yCenter = (ret.top + ret.bottom) / 2;
|
|
159
|
-
return ret;
|
|
160
|
-
}
|
|
161
|
-
function boundingBoxRelativeToAncestor({ element, ancestorElement }) {
|
|
162
|
-
ancestorElement = ancestorElement || element.parentElement;
|
|
163
|
-
const box = boundingBox(element);
|
|
164
|
-
const ancestorBox = boundingBox(ancestorElement, {
|
|
165
|
-
containsPadding: false
|
|
166
|
-
});
|
|
167
|
-
return {
|
|
168
|
-
top: box.top - ancestorBox.top,
|
|
169
|
-
right: box.right - ancestorBox.right,
|
|
170
|
-
bottom: box.bottom - ancestorBox.bottom,
|
|
171
|
-
left: box.left - ancestorBox.left,
|
|
172
|
-
width: box.width,
|
|
173
|
-
height: box.height,
|
|
174
|
-
xCenter: (box.left + box.right) / 2 - ancestorBox.left,
|
|
175
|
-
yCenter: (box.top + box.bottom) / 2 - ancestorBox.top
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// src/dom/css-vars.js
|
|
180
|
-
function getCSSVar(element, prop) {
|
|
181
|
-
element = getElement(element);
|
|
182
|
-
return getComputedStyle(element).getPropertyValue(prop);
|
|
183
|
-
}
|
|
184
|
-
function setCSSVar(element, prop, value) {
|
|
185
|
-
element = getElement(element);
|
|
186
|
-
element.style.setProperty(prop, value);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
139
|
// src/lib/objects/omit-empty.js
|
|
190
140
|
function omitEmpty(obj, shallow = false) {
|
|
191
141
|
if (typeof obj !== "object" || obj === null) return obj;
|
|
@@ -200,25 +150,14 @@ function omitEmpty(obj, shallow = false) {
|
|
|
200
150
|
return result;
|
|
201
151
|
}
|
|
202
152
|
|
|
203
|
-
// src/dom/
|
|
204
|
-
function
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return parent;
|
|
212
|
-
}
|
|
213
|
-
if (direction === "horizontal") {
|
|
214
|
-
if (overflowX === "auto" || overflowX === "scroll") return parent;
|
|
215
|
-
}
|
|
216
|
-
if (direction === "vertical") {
|
|
217
|
-
if (overflowY === "auto" || overflowY === "scroll") return parent;
|
|
218
|
-
}
|
|
219
|
-
parent = parent.parentElement;
|
|
220
|
-
}
|
|
221
|
-
return document.documentElement;
|
|
153
|
+
// src/dom/css-vars.js
|
|
154
|
+
function getCSSVar(element, prop) {
|
|
155
|
+
element = getElement(element);
|
|
156
|
+
return getComputedStyle(element).getPropertyValue(prop);
|
|
157
|
+
}
|
|
158
|
+
function setCSSVar(element, prop, value) {
|
|
159
|
+
element = getElement(element);
|
|
160
|
+
element.style.setProperty(prop, value);
|
|
222
161
|
}
|
|
223
162
|
|
|
224
163
|
// src/dom/actions/prefer-horizontal-scroll.js
|
|
@@ -307,6 +246,69 @@ function isTrackpad(event) {
|
|
|
307
246
|
if (event.wheelDeltaY === event.deltaY * -3) return true;
|
|
308
247
|
}
|
|
309
248
|
|
|
249
|
+
// src/dom/bounding-box.js
|
|
250
|
+
function boundingBox(element, { containsPadding = true } = {}) {
|
|
251
|
+
const box = element.getBoundingClientRect();
|
|
252
|
+
const ret = {};
|
|
253
|
+
for (const prop in box) ret[prop] = box[prop];
|
|
254
|
+
if (!containsPadding) {
|
|
255
|
+
const style = getComputedStyle(element);
|
|
256
|
+
const paddingTop = parseFloat(style.paddingTop);
|
|
257
|
+
const paddingRight = parseFloat(style.paddingRight);
|
|
258
|
+
const paddingBottom = parseFloat(style.paddingBottom);
|
|
259
|
+
const paddingLeft = parseFloat(style.paddingLeft);
|
|
260
|
+
ret.x = ret.x + paddingLeft;
|
|
261
|
+
ret.y = ret.y + paddingTop;
|
|
262
|
+
ret.width = ret.width - paddingLeft - paddingRight;
|
|
263
|
+
ret.height = ret.height - paddingTop - paddingBottom;
|
|
264
|
+
ret.top = ret.top + paddingTop;
|
|
265
|
+
ret.bottom = ret.bottom - paddingBottom;
|
|
266
|
+
ret.right = ret.right - paddingRight;
|
|
267
|
+
ret.left = ret.left + paddingLeft;
|
|
268
|
+
}
|
|
269
|
+
ret.xCenter = (ret.left + ret.right) / 2;
|
|
270
|
+
ret.yCenter = (ret.top + ret.bottom) / 2;
|
|
271
|
+
return ret;
|
|
272
|
+
}
|
|
273
|
+
function boundingBoxRelativeToAncestor({ element, ancestorElement }) {
|
|
274
|
+
ancestorElement = ancestorElement || element.parentElement;
|
|
275
|
+
const box = boundingBox(element);
|
|
276
|
+
const ancestorBox = boundingBox(ancestorElement, {
|
|
277
|
+
containsPadding: false
|
|
278
|
+
});
|
|
279
|
+
return {
|
|
280
|
+
top: box.top - ancestorBox.top,
|
|
281
|
+
right: box.right - ancestorBox.right,
|
|
282
|
+
bottom: box.bottom - ancestorBox.bottom,
|
|
283
|
+
left: box.left - ancestorBox.left,
|
|
284
|
+
width: box.width,
|
|
285
|
+
height: box.height,
|
|
286
|
+
xCenter: (box.left + box.right) / 2 - ancestorBox.left,
|
|
287
|
+
yCenter: (box.top + box.bottom) / 2 - ancestorBox.top
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/dom/ui/scroll-container.js
|
|
292
|
+
function findScrollContainer(element, direction = "both") {
|
|
293
|
+
if (!element) return;
|
|
294
|
+
let parent = element.parentElement;
|
|
295
|
+
while (parent) {
|
|
296
|
+
const { overflow, overflowX, overflowY } = getComputedStyle(parent);
|
|
297
|
+
if (direction === "both") {
|
|
298
|
+
if (overflow.includes("auto") || overflow.includes("scroll"))
|
|
299
|
+
return parent;
|
|
300
|
+
}
|
|
301
|
+
if (direction === "horizontal") {
|
|
302
|
+
if (overflowX === "auto" || overflowX === "scroll") return parent;
|
|
303
|
+
}
|
|
304
|
+
if (direction === "vertical") {
|
|
305
|
+
if (overflowY === "auto" || overflowY === "scroll") return parent;
|
|
306
|
+
}
|
|
307
|
+
parent = parent.parentElement;
|
|
308
|
+
}
|
|
309
|
+
return document.documentElement;
|
|
310
|
+
}
|
|
311
|
+
|
|
310
312
|
// src/dom/actions/sticky.js
|
|
311
313
|
function sticky(node, props = {}) {
|
|
312
314
|
const scrollContainer = findScrollContainer(node);
|
|
@@ -66,12 +66,14 @@ function useObserverMethodOnTarget(target, observer, method = "observe", options
|
|
|
66
66
|
function resizeObserver(target, options) {
|
|
67
67
|
const { callback, ...opts } = options;
|
|
68
68
|
const observer = new ResizeObserver(observerFn);
|
|
69
|
-
if (target === window
|
|
69
|
+
if (target === window || target === document)
|
|
70
|
+
target = document.documentElement;
|
|
70
71
|
useObserverMethodOnTarget(target, observer, "observe", opts);
|
|
71
72
|
function observerFn(entries) {
|
|
72
73
|
for (const entry of entries) {
|
|
73
74
|
if (callback) callback({ entry, entries, observer });
|
|
74
|
-
else
|
|
75
|
+
else
|
|
76
|
+
dispatchEvent(entry.target, "resize-obs", { entry, entries, observer });
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
return {
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
// src/lib/objects/omit-empty.js
|
|
2
|
+
function omitEmpty(obj, shallow = false) {
|
|
3
|
+
if (typeof obj !== "object" || obj === null) return obj;
|
|
4
|
+
if (obj instanceof Date) return obj;
|
|
5
|
+
const result = Array.isArray(obj) ? [] : {};
|
|
6
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
7
|
+
if (value === null || value === void 0 || value === "" || typeof value === "object" && !(value instanceof Date) && Object.keys(value).length === 0) {
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
result[key] = shallow ? value : omitEmpty(value);
|
|
11
|
+
}
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
|
|
1
15
|
// src/dom/get-element.js
|
|
2
16
|
function getElement(selector) {
|
|
3
17
|
if (!selector) return;
|
|
@@ -5,18 +19,6 @@ function getElement(selector) {
|
|
|
5
19
|
return document.querySelector(selector);
|
|
6
20
|
}
|
|
7
21
|
|
|
8
|
-
// src/dom/events.js
|
|
9
|
-
function addListeners(listeners) {
|
|
10
|
-
listeners.forEach(({ node, event, handler }) => {
|
|
11
|
-
node.addEventListener(event, handler);
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
function removeListeners(listeners) {
|
|
15
|
-
listeners.forEach(({ node, event, handler }) => {
|
|
16
|
-
node.removeEventListener(event, handler);
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
|
|
20
22
|
// src/dom/css-vars.js
|
|
21
23
|
function getCSSVar(element, prop) {
|
|
22
24
|
element = getElement(element);
|
|
@@ -27,18 +29,16 @@ function setCSSVar(element, prop, value) {
|
|
|
27
29
|
element.style.setProperty(prop, value);
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
// src/
|
|
31
|
-
function
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
return result;
|
|
32
|
+
// src/dom/events.js
|
|
33
|
+
function addListeners(listeners) {
|
|
34
|
+
listeners.forEach(({ node, event, handler }) => {
|
|
35
|
+
node.addEventListener(event, handler);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function removeListeners(listeners) {
|
|
39
|
+
listeners.forEach(({ node, event, handler }) => {
|
|
40
|
+
node.removeEventListener(event, handler);
|
|
41
|
+
});
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// src/dom/actions/prefer-horizontal-scroll.js
|
|
@@ -74,12 +74,14 @@ function useObserverMethodOnTarget(target, observer, method = "observe", options
|
|
|
74
74
|
function resizeObserver(target, options) {
|
|
75
75
|
const { callback, ...opts } = options;
|
|
76
76
|
const observer = new ResizeObserver(observerFn);
|
|
77
|
-
if (target === window
|
|
77
|
+
if (target === window || target === document)
|
|
78
|
+
target = document.documentElement;
|
|
78
79
|
useObserverMethodOnTarget(target, observer, "observe", opts);
|
|
79
80
|
function observerFn(entries) {
|
|
80
81
|
for (const entry of entries) {
|
|
81
82
|
if (callback) callback({ entry, entries, observer });
|
|
82
|
-
else
|
|
83
|
+
else
|
|
84
|
+
dispatchEvent(entry.target, "resize-obs", { entry, entries, observer });
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
return {
|
|
@@ -12,13 +12,17 @@ function getUnit(value) {
|
|
|
12
12
|
const [, unit] = splitUnit(value);
|
|
13
13
|
return unit;
|
|
14
14
|
}
|
|
15
|
+
function rem(multiple = 1) {
|
|
16
|
+
const value = parseFloat(getComputedStyle(document.body)["font-size"]);
|
|
17
|
+
return Math.round(value * multiple);
|
|
18
|
+
}
|
|
15
19
|
function em(element = document.body, multiple = 1) {
|
|
16
20
|
const value = parseFloat(getComputedStyle(element)["font-size"]);
|
|
17
21
|
return Math.round(value * multiple);
|
|
18
22
|
}
|
|
19
|
-
function
|
|
20
|
-
const
|
|
21
|
-
return Math.round(
|
|
23
|
+
function rlh(multiple = 1) {
|
|
24
|
+
const lineHeight = parseFloat(getComputedStyle(document.body)["line-height"]);
|
|
25
|
+
return Math.round(lineHeight * multiple);
|
|
22
26
|
}
|
|
23
27
|
function lh(element = document.body, multiple = 1) {
|
|
24
28
|
const lineHeight = getComputedStyle(element)["line-height"];
|
|
@@ -40,5 +44,6 @@ export {
|
|
|
40
44
|
getUnit,
|
|
41
45
|
lh,
|
|
42
46
|
rem,
|
|
47
|
+
rlh,
|
|
43
48
|
toPx
|
|
44
49
|
};
|
package/dist/esm/dom/index.js
CHANGED
|
@@ -152,12 +152,14 @@ function useObserverMethodOnTarget(target, observer, method = "observe", options
|
|
|
152
152
|
function resizeObserver(target, options) {
|
|
153
153
|
const { callback, ...opts } = options;
|
|
154
154
|
const observer = new ResizeObserver(observerFn);
|
|
155
|
-
if (target === window
|
|
155
|
+
if (target === window || target === document)
|
|
156
|
+
target = document.documentElement;
|
|
156
157
|
useObserverMethodOnTarget(target, observer, "observe", opts);
|
|
157
158
|
function observerFn(entries) {
|
|
158
159
|
for (const entry of entries) {
|
|
159
160
|
if (callback) callback({ entry, entries, observer });
|
|
160
|
-
else
|
|
161
|
+
else
|
|
162
|
+
dispatchEvent(entry.target, "resize-obs", { entry, entries, observer });
|
|
161
163
|
}
|
|
162
164
|
}
|
|
163
165
|
return {
|
|
@@ -205,36 +207,6 @@ function nativeMasonrySupport(node) {
|
|
|
205
207
|
return getComputedStyle(node).gridTemplateRows === "masonry";
|
|
206
208
|
}
|
|
207
209
|
|
|
208
|
-
// src/lib/numbers/index.js
|
|
209
|
-
function splitUnit(string) {
|
|
210
|
-
if (typeof string === "number") return [string, null];
|
|
211
|
-
const regex = /(-?\d*\.?\d+)\s*([a-z]+)/i;
|
|
212
|
-
const match = string.match(regex);
|
|
213
|
-
if (match) return [parseFloat(match[1]), match[2]];
|
|
214
|
-
return [parseFloat(string), null];
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// src/lib/form/sanitize.js
|
|
218
|
-
function sanitize(value, options = {}) {
|
|
219
|
-
const { sanitizer, ...rest } = options;
|
|
220
|
-
if (!sanitizer) throw new Error("sanitizer function is required");
|
|
221
|
-
if (typeof value === "string") return sanitizer(value, rest);
|
|
222
|
-
if (Array.isArray(value)) return sanitizeArray(value, { sanitizer, ...rest });
|
|
223
|
-
if (value && typeof value === "object") {
|
|
224
|
-
return Object.fromEntries(
|
|
225
|
-
Object.entries(value).map(([key, val]) => [
|
|
226
|
-
key,
|
|
227
|
-
sanitize(val, { sanitizer, ...rest })
|
|
228
|
-
])
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
return value;
|
|
232
|
-
}
|
|
233
|
-
function sanitizeArray(arr, { sanitizer, ...rest }) {
|
|
234
|
-
if (!sanitizer) throw new Error("sanitizer function is required");
|
|
235
|
-
return arr.map((item) => sanitize(item, { sanitizer, ...rest }));
|
|
236
|
-
}
|
|
237
|
-
|
|
238
210
|
// src/lib/objects/omit-empty.js
|
|
239
211
|
function omitEmpty(obj, shallow = false) {
|
|
240
212
|
if (typeof obj !== "object" || obj === null) return obj;
|
|
@@ -249,6 +221,22 @@ function omitEmpty(obj, shallow = false) {
|
|
|
249
221
|
return result;
|
|
250
222
|
}
|
|
251
223
|
|
|
224
|
+
// src/dom/css-vars.js
|
|
225
|
+
function getCSSValue(element, prop) {
|
|
226
|
+
return getCSSVar(element, prop);
|
|
227
|
+
}
|
|
228
|
+
function setCSSValue(element, prop, value) {
|
|
229
|
+
setCSSVar(element, prop, value);
|
|
230
|
+
}
|
|
231
|
+
function getCSSVar(element, prop) {
|
|
232
|
+
element = getElement(element);
|
|
233
|
+
return getComputedStyle(element).getPropertyValue(prop);
|
|
234
|
+
}
|
|
235
|
+
function setCSSVar(element, prop, value) {
|
|
236
|
+
element = getElement(element);
|
|
237
|
+
element.style.setProperty(prop, value);
|
|
238
|
+
}
|
|
239
|
+
|
|
252
240
|
// src/dom/actions/prefer-horizontal-scroll.js
|
|
253
241
|
var DEFAULT_OPTIONS = {
|
|
254
242
|
scrollSnapDelay: 1e3
|
|
@@ -504,22 +492,6 @@ function setCookie(name, value, days) {
|
|
|
504
492
|
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
|
505
493
|
}
|
|
506
494
|
|
|
507
|
-
// src/dom/css-vars.js
|
|
508
|
-
function getCSSValue(element, prop) {
|
|
509
|
-
return getCSSVar(element, prop);
|
|
510
|
-
}
|
|
511
|
-
function setCSSValue(element, prop, value) {
|
|
512
|
-
setCSSVar(element, prop, value);
|
|
513
|
-
}
|
|
514
|
-
function getCSSVar(element, prop) {
|
|
515
|
-
element = getElement(element);
|
|
516
|
-
return getComputedStyle(element).getPropertyValue(prop);
|
|
517
|
-
}
|
|
518
|
-
function setCSSVar(element, prop, value) {
|
|
519
|
-
element = getElement(element);
|
|
520
|
-
element.style.setProperty(prop, value);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
495
|
// src/dom/focusable.js
|
|
524
496
|
function getFocusableElements(container = document.body) {
|
|
525
497
|
return {
|
|
@@ -635,18 +607,31 @@ function Focusable(container = document.body) {
|
|
|
635
607
|
return getFocusableElements(container);
|
|
636
608
|
}
|
|
637
609
|
|
|
610
|
+
// src/lib/numbers/index.js
|
|
611
|
+
function splitUnit(string) {
|
|
612
|
+
if (typeof string === "number") return [string, null];
|
|
613
|
+
const regex = /(-?\d*\.?\d+)\s*([a-z]+)/i;
|
|
614
|
+
const match = string.match(regex);
|
|
615
|
+
if (match) return [parseFloat(match[1]), match[2]];
|
|
616
|
+
return [parseFloat(string), null];
|
|
617
|
+
}
|
|
618
|
+
|
|
638
619
|
// src/dom/font-size.js
|
|
639
620
|
function getUnit(value) {
|
|
640
621
|
const [, unit] = splitUnit(value);
|
|
641
622
|
return unit;
|
|
642
623
|
}
|
|
624
|
+
function rem(multiple = 1) {
|
|
625
|
+
const value = parseFloat(getComputedStyle(document.body)["font-size"]);
|
|
626
|
+
return Math.round(value * multiple);
|
|
627
|
+
}
|
|
643
628
|
function em(element = document.body, multiple = 1) {
|
|
644
629
|
const value = parseFloat(getComputedStyle(element)["font-size"]);
|
|
645
630
|
return Math.round(value * multiple);
|
|
646
631
|
}
|
|
647
|
-
function
|
|
648
|
-
const
|
|
649
|
-
return Math.round(
|
|
632
|
+
function rlh(multiple = 1) {
|
|
633
|
+
const lineHeight = parseFloat(getComputedStyle(document.body)["line-height"]);
|
|
634
|
+
return Math.round(lineHeight * multiple);
|
|
650
635
|
}
|
|
651
636
|
function lh(element = document.body, multiple = 1) {
|
|
652
637
|
const lineHeight = getComputedStyle(element)["line-height"];
|
|
@@ -819,40 +804,44 @@ var defaultOptions2 = {
|
|
|
819
804
|
// Float between 0 to 1.
|
|
820
805
|
tolerance: 0.1,
|
|
821
806
|
// Float between 0 to 1. Tolerance for event firing
|
|
822
|
-
throttle: 16,
|
|
823
|
-
// Throttle interval in ms (default: ~60fps)
|
|
824
807
|
once: false
|
|
825
808
|
// Only fire threshold callback once
|
|
826
809
|
};
|
|
810
|
+
function getScrollElement(node) {
|
|
811
|
+
if (node === document || node === window || node === document.documentElement) {
|
|
812
|
+
return document.documentElement;
|
|
813
|
+
}
|
|
814
|
+
return (
|
|
815
|
+
/** @type {Element} */
|
|
816
|
+
node
|
|
817
|
+
);
|
|
818
|
+
}
|
|
827
819
|
function scrollObserver(node, options = {}) {
|
|
828
820
|
const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
|
|
829
821
|
const opts = { ...defaultOptions2, ...userOpts };
|
|
830
|
-
const { threshold, tolerance,
|
|
831
|
-
|
|
822
|
+
const { threshold, tolerance, once } = opts;
|
|
823
|
+
let prevScrollDirection = null;
|
|
832
824
|
let prevScrollTop = 0;
|
|
833
825
|
let prevScrollPercent = 0;
|
|
834
|
-
let lastThrottleTime = 0;
|
|
835
826
|
let thresholdFired = false;
|
|
836
827
|
let rafId = null;
|
|
837
|
-
const isDocumentScroll = node === document || node === window;
|
|
838
|
-
const scrollElement =
|
|
828
|
+
const isDocumentScroll = node === document || node === window || node === document.documentElement;
|
|
829
|
+
const scrollElement = getScrollElement(node);
|
|
830
|
+
const eventTarget = isDocumentScroll ? window : node;
|
|
839
831
|
let cachedScrollHeight = 0;
|
|
840
832
|
let cachedClientHeight = 0;
|
|
841
833
|
updateCache();
|
|
842
834
|
const cacheObserver = resizeObserver(scrollElement, {
|
|
843
835
|
callback: updateCache
|
|
844
836
|
});
|
|
845
|
-
|
|
837
|
+
eventTarget.addEventListener("scroll", throttledObserve, { passive: true });
|
|
838
|
+
function throttledObserve() {
|
|
839
|
+
rafId = requestAnimationFrame(observe);
|
|
840
|
+
}
|
|
846
841
|
function updateCache() {
|
|
847
842
|
cachedScrollHeight = scrollElement.scrollHeight;
|
|
848
843
|
cachedClientHeight = scrollElement.clientHeight;
|
|
849
844
|
}
|
|
850
|
-
function throttledObserve() {
|
|
851
|
-
const now = Date.now();
|
|
852
|
-
if (now - lastThrottleTime < throttle) return;
|
|
853
|
-
lastThrottleTime = now;
|
|
854
|
-
rafId = requestAnimationFrame(observe);
|
|
855
|
-
}
|
|
856
845
|
function observe() {
|
|
857
846
|
const scrollTop = scrollElement.scrollTop;
|
|
858
847
|
if (Math.abs(scrollTop - prevScrollTop) < 1) return;
|
|
@@ -891,10 +880,11 @@ function scrollObserver(node, options = {}) {
|
|
|
891
880
|
}
|
|
892
881
|
prevScrollTop = scrollTop;
|
|
893
882
|
prevScrollPercent = scrollPercent;
|
|
883
|
+
prevScrollDirection = scrollDirection;
|
|
894
884
|
}
|
|
895
885
|
return {
|
|
896
886
|
destroy() {
|
|
897
|
-
|
|
887
|
+
eventTarget.removeEventListener("scroll", throttledObserve);
|
|
898
888
|
if (rafId) cancelAnimationFrame(rafId);
|
|
899
889
|
cacheObserver.destroy();
|
|
900
890
|
}
|
|
@@ -943,6 +933,29 @@ var queryParams = {
|
|
|
943
933
|
|
|
944
934
|
// src/dom/sanitize.js
|
|
945
935
|
import DOMPurify from "dompurify";
|
|
936
|
+
|
|
937
|
+
// src/lib/form/sanitize.js
|
|
938
|
+
function sanitize(value, options = {}) {
|
|
939
|
+
const { sanitizer, ...rest } = options;
|
|
940
|
+
if (!sanitizer) throw new Error("sanitizer function is required");
|
|
941
|
+
if (typeof value === "string") return sanitizer(value, rest);
|
|
942
|
+
if (Array.isArray(value)) return sanitizeArray(value, { sanitizer, ...rest });
|
|
943
|
+
if (value && typeof value === "object") {
|
|
944
|
+
return Object.fromEntries(
|
|
945
|
+
Object.entries(value).map(([key, val]) => [
|
|
946
|
+
key,
|
|
947
|
+
sanitize(val, { sanitizer, ...rest })
|
|
948
|
+
])
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
return value;
|
|
952
|
+
}
|
|
953
|
+
function sanitizeArray(arr, { sanitizer, ...rest }) {
|
|
954
|
+
if (!sanitizer) throw new Error("sanitizer function is required");
|
|
955
|
+
return arr.map((item) => sanitize(item, { sanitizer, ...rest }));
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
// src/dom/sanitize.js
|
|
946
959
|
function sanitize2(value, options = {}) {
|
|
947
960
|
return sanitize(value, { sanitizer: DOMPurify.sanitize, ...options });
|
|
948
961
|
}
|
|
@@ -1137,6 +1150,7 @@ export {
|
|
|
1137
1150
|
rem,
|
|
1138
1151
|
removeListeners,
|
|
1139
1152
|
resizeObserver,
|
|
1153
|
+
rlh,
|
|
1140
1154
|
sanitize2 as sanitize,
|
|
1141
1155
|
scrollObserver,
|
|
1142
1156
|
scrollToElement,
|