[#3344, #2505] optimized records listing

This commit is contained in:
Gani Georgiev
2023-09-24 11:05:12 +03:00
parent 0f5dad7ede
commit 2550a9de54
48 changed files with 442 additions and 236 deletions
@@ -1,81 +0,0 @@
<script>
import { onMount } from "svelte";
let classes = "";
export { classes as class }; // export reserved keyword
let wrapper = null;
let scrollClasses = "";
let scrollTimeoutId = null;
let observer;
export function refresh() {
if (!wrapper) {
return;
}
clearTimeout(scrollTimeoutId);
scrollTimeoutId = setTimeout(() => {
const offsetWidth = wrapper.offsetWidth;
const scrollWidth = wrapper.scrollWidth;
if (scrollWidth - offsetWidth) {
scrollClasses = "scrollable";
if (wrapper.scrollLeft === 0) {
scrollClasses += " scroll-start";
} else if (wrapper.scrollLeft + offsetWidth == scrollWidth) {
scrollClasses += " scroll-end";
}
} else {
scrollClasses = "";
}
}, 100);
}
onMount(() => {
refresh();
observer = new MutationObserver(() => {
refresh();
});
observer.observe(wrapper, {
attributeFilter: ["width"],
childList: true,
subtree: true,
});
return () => {
observer?.disconnect();
clearTimeout(scrollTimeoutId);
};
});
</script>
<svelte:window on:resize={refresh} />
<div class="horizontal-scroller-wrapper">
<slot name="before" />
<div bind:this={wrapper} class="horizontal-scroller {classes} {scrollClasses}" on:scroll={refresh}>
<slot />
</div>
<slot name="after" />
</div>
<style>
.horizontal-scroller {
width: auto;
overflow-x: auto;
}
.horizontal-scroller-wrapper {
position: relative;
}
:global(.horizontal-scroller-wrapper .columns-dropdown) {
top: 40px;
z-index: 100;
max-height: 340px;
}
</style>
@@ -11,6 +11,8 @@
</main>
<footer class="page-footer">
<slot name="footer" />
<a href={import.meta.env.PB_DOCS_URL} target="_blank" rel="noopener noreferrer">
<i class="ri-book-open-line txt-sm" />
<span class="txt">Docs</span>
+151
View File
@@ -0,0 +1,151 @@
<script>
import { onMount, createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
let classes = "";
export { classes as class }; // export reserved keyword
export let vThreshold = 0;
export let hThreshold = 0;
export let dispatchOnNoScroll = true;
let wrapper = null;
let scrollClasses = "";
let throttleTimeoutId = null;
let hDiff;
let vDiff;
let wrapperWidth;
let wrapperHeight;
let observer;
export function resetVerticalScroll() {
if (!wrapper) {
return;
}
wrapper.scrollTop = 0;
}
export function resetHorizontalScroll() {
if (!wrapper) {
return;
}
wrapper.scrollLeft = 0;
}
export function refresh() {
if (!wrapper) {
return;
}
scrollClasses = "";
// +2 extra threshold as a workaround for the lack of subpixel precision
wrapperWidth = wrapper.clientWidth + 2;
wrapperHeight = wrapper.clientHeight + 2;
hDiff = wrapper.scrollWidth - wrapperWidth;
vDiff = wrapper.scrollHeight - wrapperHeight;
// vertical scroller
if (vDiff > 0) {
scrollClasses += " v-scroll";
if (vThreshold >= wrapperHeight) {
vThreshold = 0;
}
if (wrapper.scrollTop - vThreshold <= 0) {
scrollClasses += " v-scroll-start";
dispatch("vScrollStart");
}
if (wrapper.scrollTop + vThreshold >= vDiff) {
scrollClasses += " v-scroll-end";
dispatch("vScrollEnd");
}
} else if (dispatchOnNoScroll) {
dispatch("vScrollEnd");
}
// horizontal scroller
if (hDiff > 0) {
scrollClasses += " h-scroll";
if (hThreshold >= wrapperWidth) {
hThreshold = 0;
}
if (wrapper.scrollLeft - hThreshold <= 0) {
scrollClasses += " h-scroll-start";
dispatch("hScrollStart");
}
if (wrapper.scrollLeft + hThreshold >= hDiff) {
scrollClasses += " h-scroll-end";
dispatch("hScrollEnd");
}
} else if (dispatchOnNoScroll) {
dispatch("hScrollEnd");
}
}
export function throttleRefresh() {
if (throttleTimeoutId) {
return;
}
throttleTimeoutId = setTimeout(() => {
refresh();
throttleTimeoutId = null;
}, 150);
}
onMount(() => {
throttleRefresh();
observer = new MutationObserver(throttleRefresh);
observer.observe(wrapper, {
attributeFilter: ["width", "height"],
childList: true,
subtree: true,
});
return () => {
observer?.disconnect();
clearTimeout(throttleTimeoutId);
};
});
</script>
<svelte:window on:resize={throttleRefresh} />
<div class="scroller-wrapper">
<slot name="before" />
<div bind:this={wrapper} class="scroller {classes} {scrollClasses}" on:scroll={throttleRefresh}>
<slot />
</div>
<slot name="after" />
</div>
<style>
.scroller {
width: auto;
min-height: 0;
overflow: auto;
}
.scroller-wrapper {
position: relative;
min-height: 0;
}
:global(.scroller-wrapper .columns-dropdown) {
top: 40px;
z-index: 100;
max-height: 340px;
}
</style>