|
@@ -39,6 +39,14 @@ const isAtRight = ref(false);
|
|
|
const isAtBottom = ref(false);
|
|
|
const isAtLeft = ref(true);
|
|
|
|
|
|
+/**
|
|
|
+ * We have to check if the scroll amount is close enough to some threshold in order to
|
|
|
+ * more accurately calculate arrivedState. This is because scrollTop/scrollLeft are non-rounded
|
|
|
+ * numbers, while scrollHeight/scrollWidth and clientHeight/clientWidth are rounded.
|
|
|
+ * https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#determine_if_an_element_has_been_totally_scrolled
|
|
|
+ */
|
|
|
+const ARRIVED_STATE_THRESHOLD_PIXELS = 1;
|
|
|
+
|
|
|
const showShadowTop = computed(() => props.shadow && props.shadowTop);
|
|
|
const showShadowBottom = computed(() => props.shadow && props.shadowBottom);
|
|
|
const showShadowLeft = computed(() => props.shadow && props.shadowLeft);
|
|
@@ -60,14 +68,18 @@ function handleScroll(event: Event) {
|
|
|
const target = event.target as HTMLElement;
|
|
|
const scrollTop = target?.scrollTop ?? 0;
|
|
|
const scrollLeft = target?.scrollLeft ?? 0;
|
|
|
- const offsetHeight = target?.offsetHeight ?? 0;
|
|
|
- const offsetWidth = target?.offsetWidth ?? 0;
|
|
|
+ const clientHeight = target?.clientHeight ?? 0;
|
|
|
+ const clientWidth = target?.clientWidth ?? 0;
|
|
|
const scrollHeight = target?.scrollHeight ?? 0;
|
|
|
const scrollWidth = target?.scrollWidth ?? 0;
|
|
|
isAtTop.value = scrollTop <= 0;
|
|
|
isAtLeft.value = scrollLeft <= 0;
|
|
|
- isAtBottom.value = scrollTop + offsetHeight >= scrollHeight;
|
|
|
- isAtRight.value = scrollLeft + offsetWidth >= scrollWidth;
|
|
|
+ isAtBottom.value =
|
|
|
+ Math.abs(scrollTop) + clientHeight >=
|
|
|
+ scrollHeight - ARRIVED_STATE_THRESHOLD_PIXELS;
|
|
|
+ isAtRight.value =
|
|
|
+ Math.abs(scrollLeft) + clientWidth >=
|
|
|
+ scrollWidth - ARRIVED_STATE_THRESHOLD_PIXELS;
|
|
|
|
|
|
emit('scrollAt', {
|
|
|
bottom: isAtBottom.value,
|