@marianmeres/stuic 2.0.0-next.2 → 2.0.0-next.4
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.
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare type Subscribe<T> = (value: T) => void;
|
|
2
|
+
declare type Unsubscribe = () => void;
|
|
3
|
+
declare type Update<T> = (value: T) => T;
|
|
4
|
+
interface StoreReadable<T> {
|
|
5
|
+
subscribe(cb: Subscribe<T>): Unsubscribe;
|
|
6
|
+
}
|
|
7
|
+
interface StoreLike<T> extends StoreReadable<T> {
|
|
8
|
+
set(value: T): void;
|
|
9
|
+
update(cb: Update<T>): void;
|
|
10
|
+
}
|
|
11
|
+
export type AutoscrollOptions = ScrollOptions & {
|
|
12
|
+
dependencies?: StoreReadable<any>[];
|
|
13
|
+
logger?: (...args: any[]) => void;
|
|
14
|
+
newScrollableContentSignal?: StoreLike<boolean>;
|
|
15
|
+
shouldScrollThresholdPx?: number;
|
|
16
|
+
startScrollTimeout?: number;
|
|
17
|
+
};
|
|
18
|
+
export declare function autoscroll(node: HTMLElement, options?: AutoscrollOptions): {
|
|
19
|
+
destroy(): void;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const DEFAULTS = {
|
|
2
|
+
shouldScrollThresholdPx: 100,
|
|
3
|
+
startScrollTimeout: 300,
|
|
4
|
+
};
|
|
5
|
+
export function autoscroll(node, options = {
|
|
6
|
+
shouldScrollThresholdPx: DEFAULTS.shouldScrollThresholdPx,
|
|
7
|
+
startScrollTimeout: DEFAULTS.startScrollTimeout,
|
|
8
|
+
}) {
|
|
9
|
+
// use "smooth" by default
|
|
10
|
+
options.behavior ??= 'smooth';
|
|
11
|
+
options.shouldScrollThresholdPx ??= DEFAULTS.shouldScrollThresholdPx;
|
|
12
|
+
options.startScrollTimeout ??= DEFAULTS.startScrollTimeout;
|
|
13
|
+
const { behavior, shouldScrollThresholdPx, dependencies, logger, newScrollableContentSignal, startScrollTimeout, } = options || {};
|
|
14
|
+
let origScrollHeight = 0;
|
|
15
|
+
const log = (...args) => typeof logger === 'function' && logger.apply(null, [...args]);
|
|
16
|
+
const shouldScroll = () => {
|
|
17
|
+
const { scrollTop, clientHeight } = node;
|
|
18
|
+
const result = origScrollHeight - scrollTop - clientHeight < shouldScrollThresholdPx;
|
|
19
|
+
log('shouldScroll?', result, { scrollTop, origScrollHeight, clientHeight });
|
|
20
|
+
return result;
|
|
21
|
+
};
|
|
22
|
+
const scroll = () => {
|
|
23
|
+
const opts = { top: node.scrollHeight, left: node.scrollWidth, behavior };
|
|
24
|
+
log(`scrollTo(${JSON.stringify(opts)})`);
|
|
25
|
+
node.scrollTo(opts);
|
|
26
|
+
};
|
|
27
|
+
// for when children change sizes
|
|
28
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
29
|
+
log('observed resize...');
|
|
30
|
+
shouldScroll() && scroll();
|
|
31
|
+
});
|
|
32
|
+
// for when children
|
|
33
|
+
const mutationObserver = new MutationObserver(() => {
|
|
34
|
+
log('observed mutation...');
|
|
35
|
+
shouldScroll() ? scroll() : newScrollableContentSignal?.set(true);
|
|
36
|
+
origScrollHeight = node.scrollHeight;
|
|
37
|
+
});
|
|
38
|
+
const unsubs = dependencies?.map((dep) => dep.subscribe((v) => {
|
|
39
|
+
log('dependency update...', v);
|
|
40
|
+
setTimeout(scroll, startScrollTimeout);
|
|
41
|
+
})) ?? [];
|
|
42
|
+
// observe size of all children
|
|
43
|
+
for (const child of node.children) {
|
|
44
|
+
resizeObserver.observe(child);
|
|
45
|
+
}
|
|
46
|
+
mutationObserver.observe(node, { childList: true, subtree: true });
|
|
47
|
+
return {
|
|
48
|
+
destroy() {
|
|
49
|
+
if (mutationObserver) {
|
|
50
|
+
mutationObserver.disconnect();
|
|
51
|
+
}
|
|
52
|
+
if (resizeObserver) {
|
|
53
|
+
resizeObserver.disconnect();
|
|
54
|
+
}
|
|
55
|
+
for (const unsubscribe of unsubs) {
|
|
56
|
+
unsubscribe();
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
package/dist/actions/index.d.ts
CHANGED
package/dist/actions/index.js
CHANGED