Skip to content

Commit 9925680

Browse files
authored
Merge pull request #10 from Yrobot/master
Version release
2 parents 8b14b11 + ca573bd commit 9925680

File tree

11 files changed

+3283
-1173
lines changed

11 files changed

+3283
-1173
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,12 @@ docs
88

99
# Generated by MacOS
1010
.DS_Store
11+
12+
# yarn4
13+
.pnp.*
14+
.yarn/*
15+
!.yarn/patches
16+
!.yarn/plugins
17+
!.yarn/releases
18+
!.yarn/sdks
19+
!.yarn/versions

.npmignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,9 @@ CHANGELOG.md
2727

2828
## build
2929
build_website
30+
31+
## dev files
32+
.yarn
33+
.yarnrc.yml
34+
postcss.config.js
35+
tailwind.config.js

.yarnrc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodeLinker: node-modules

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!DOCTYPE html>
2-
<html lang="en">
2+
<html lang="en" data-theme="light">
33
<head>
44
<meta charset="UTF-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,12 @@
2626
"@types/node": "^20.10.6",
2727
"@types/react": "^18.2.46",
2828
"@types/react-dom": "^18.2.18",
29+
"autoprefixer": "^10.4.19",
30+
"daisyui": "^4.10.1",
31+
"postcss": "^8.4.38",
2932
"react": "^18.2.0",
3033
"react-dom": "^18.2.0",
34+
"tailwindcss": "^3.4.3",
3135
"typescript": "^5.3.3",
3236
"vite": "^5.0.11",
3337
"vite-plugin-dts": "^3.7.0"

package/index.ts

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
type unObserverCallback = () => void;
2-
32
const throttle = <R, A extends any[]>(
43
fn: (...args: A) => R,
54
delay: number
6-
): [(...args: A) => R | null, () => void] => {
7-
let wait = false;
5+
): [(...args: A) => null, () => void] => {
6+
let lastCall = -Infinity;
87
let timeout: undefined | number;
98
let cancelled = false;
109
return [
1110
(...args: A) => {
1211
if (cancelled) return null;
13-
if (wait) return null;
14-
const val = fn(...args);
15-
wait = true;
12+
let wait = lastCall + delay - Date.now();
13+
clearTimeout(timeout);
1614
timeout = window.setTimeout(() => {
17-
wait = false;
18-
}, delay);
19-
return val;
15+
lastCall = Date.now();
16+
fn(...args);
17+
}, Math.max(0, wait));
18+
return null;
2019
},
2120
() => {
2221
cancelled = true;
@@ -50,13 +49,24 @@ export const escapeWhenUpPlugin: Plugin<{
5049
}> = ({ threshold = 24, throttleTime = 100 } = {}) => {
5150
const context: Context = {};
5251
let isEscape = false;
52+
let lastScrollTop = -Infinity;
5353
const [onScroll] = throttle((evt: Event) => {
5454
const target = evt.target as Element;
55-
const scrollUpDistance =
56-
target.scrollHeight - target.scrollTop - target.clientHeight;
57-
isEscape = scrollUpDistance > threshold;
55+
// when isEscape=false and user scroll up, escape auto scroll
56+
if (!isEscape && target.scrollTop < lastScrollTop) {
57+
isEscape = true;
58+
}
59+
// when isEscape=true and user scroll down to $threshold, active auto scroll
60+
if (
61+
isEscape &&
62+
target.scrollHeight - target.scrollTop - target.clientHeight <= threshold
63+
) {
64+
isEscape = false;
65+
}
66+
lastScrollTop = target.scrollTop;
5867
}, throttleTime);
5968
context.onMount = (elm) => {
69+
lastScrollTop = elm.scrollTop;
6070
elm.addEventListener("scroll", onScroll);
6171
};
6272
context.onUnmount = (elm) => {
@@ -72,7 +82,7 @@ export const escapeWhenUpPlugin: Plugin<{
7282
* @param {Object} options - The config options for the autoScroll function.
7383
* @param {string} options.selector - The selector for the container element. (example: '#container')
7484
* @param {Context[]} [options.plugins] - The plugins for the life cycle hooks of the autoScroll function. [escapeHook,onMount,onUnmount]
75-
* @param {number} [options.throttleTime=100] - The throttle time in milliseconds.
85+
* @param {number} [options.throttleTime=100] - The throttle time in milliseconds. default is 100. 0 for no throttle.
7686
* @param {number} [options.offset=0] - The offset for the scroll position based on the container.scrollHeight.
7787
*
7888
* @return {function} The unObserverCallback function.
@@ -102,32 +112,45 @@ export default function autoScroll({
102112
.filter((result) => typeof result === "function") as OnUnmount[];
103113

104114
// main auto down scroll hook
105-
const [scrollHook] = throttle(() => {
115+
const onResize = () => {
106116
if (!!plugins.find((plugin) => plugin?.escapeHook?.(container) === true))
107117
return false;
108118
// use requestAnimationFrame for escape ResizeObserver loop
109119
requestAnimationFrame(() => {
110-
container.scrollTop = container.scrollHeight + offset;
120+
// console.log("scrollHook", container.scrollHeight - offset);
121+
container.scrollTo({
122+
top: container.scrollHeight - offset,
123+
// behavior: "smooth", // will effect escapeWhenUpPlugin user scroll up detection
124+
});
111125
});
112126
return true;
113-
}, throttleTime);
127+
};
128+
const [scrollHook] =
129+
throttleTime > 0 ? throttle(onResize, throttleTime) : [onResize];
114130

115131
// observers
116132
const resizeObserver = new ResizeObserver(() => {
133+
// console.log("ResizeObserver");
117134
scrollHook();
118135
});
136+
119137
const mutationObserver = new MutationObserver(() => {
138+
// console.log("MutationObserver");
139+
observeChildren(); // re-observe the children when the child is new added or removed
120140
scrollHook();
121141
});
122142

123143
// observe the children size change
124-
for (const child of container.children) {
125-
resizeObserver.observe(child);
126-
}
144+
const observeChildren = () => {
145+
resizeObserver.disconnect(); // clean the previous observer
146+
for (const child of container.children) {
147+
resizeObserver.observe(child);
148+
}
149+
};
150+
observeChildren();
127151

128152
// observe the subtree child list length change
129153
mutationObserver.observe(container, {
130-
subtree: true,
131154
childList: true,
132155
});
133156

postcss.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
plugins: {
3+
tailwindcss: {},
4+
autoprefixer: {},
5+
},
6+
};

tailwind.config.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/** @type {import('tailwindcss').Config} */
2+
module.exports = {
3+
content: ["./website/**/*.{ts,tsx,js,jsx}"],
4+
theme: {
5+
extend: {},
6+
},
7+
plugins: [require("daisyui")],
8+
daisyui: {
9+
themes: ["light"],
10+
},
11+
};

website/index.css

Lines changed: 33 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,37 @@
1-
body {
2-
margin: 0;
3-
padding: 0;
4-
display: flex;
5-
justify-content: center;
6-
align-items: flex-start;
7-
}
8-
.panel {
9-
width: 400px;
10-
}
11-
.list-container {
12-
box-sizing: border-box;
13-
border: 1px solid #000;
14-
padding: 8px;
15-
width: 100%;
16-
height: 600px;
17-
overflow: scroll;
18-
display: flex;
19-
flex-direction: column;
20-
justify-content: flex-start;
21-
gap: 16px;
22-
}
23-
.loading {
24-
flex: none;
25-
display: flex;
26-
justify-content: center;
27-
align-items: center;
28-
height: 64px;
29-
font-size: large;
30-
font-weight: 800;
31-
}
32-
.item {
33-
flex: none;
34-
width: 100%;
35-
height: 100px;
36-
border-radius: 8px;
37-
display: flex;
38-
justify-content: center;
39-
align-items: center;
40-
background-color: black;
41-
color: #fff;
42-
}
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
434

44-
.grid-table {
45-
display: grid;
46-
grid-template-columns: 1fr 1fr;
47-
gap: 64px;
5+
@layer base {
6+
body {
7+
@apply flex justify-center items-start m-0 p-0;
8+
}
9+
h3 {
10+
@apply my-4 font-bold;
11+
}
4812
}
4913

50-
code {
51-
white-space: pre-wrap;
14+
@layer components {
15+
.panel {
16+
@apply w-[400px] flex flex-col items-center justify-start;
17+
}
18+
.list-container {
19+
@apply overflow-scroll p-2 pt-6;
20+
}
21+
.item {
22+
@apply flex-none w-full h-[100px] flex justify-center items-center bg-[black] text-white rounded-lg;
23+
}
24+
.grid-table {
25+
@apply grid grid-cols-[1fr_1fr] gap-16;
26+
}
27+
.code-block {
28+
@apply p-3 rounded-lg;
29+
--tw-bg-opacity: 1;
30+
background-color: var(--fallback-n, oklch(var(--n) / var(--tw-bg-opacity)));
31+
--tw-text-opacity: 1;
32+
color: var(--fallback-nc, oklch(var(--nc) / var(--tw-text-opacity)));
33+
}
34+
.code-block code {
35+
@apply whitespace-pre-wrap;
36+
}
5237
}

0 commit comments

Comments
 (0)