Skip to content

Commit

Permalink
internal: more work on synth scrolling
Browse files Browse the repository at this point in the history
  • Loading branch information
sashamilenkovic committed Dec 30, 2024
1 parent 203e65a commit 88d63cc
Show file tree
Hide file tree
Showing 13 changed files with 180 additions and 89 deletions.
40 changes: 25 additions & 15 deletions dist/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2293,6 +2293,10 @@ function handlePointercancel(data, state2) {
function handleEnd3(state2) {
if (state2.draggedNode) state2.draggedNode.el.draggable = false;
document.body.style.userSelect = state2.rootUserSelect || "";
if (isSynthDragState(state2)) {
document.documentElement.style.overscrollBehavior = state2.rootOverScrollBehavior || "";
document.documentElement.style.touchAction = state2.rootTouchAction || "";
}
if (isSynthDragState(state2)) cancelSynthScroll(state2);
if ("longPressTimeout" in state2 && state2.longPressTimeout)
clearTimeout(state2.longPressTimeout);
Expand Down Expand Up @@ -2344,8 +2348,6 @@ function handleNodePointerup(data, state2) {
config.handleEnd(state2);
}
function initSynthDrag(node, parent, e, _state, draggedNodes2) {
document.documentElement.style.overscrollBehavior = "none";
document.documentElement.style.touchAction = "none";
const config = parent.data.config;
let dragImage;
let display = node.el.style.display;
Expand Down Expand Up @@ -2409,8 +2411,12 @@ function initSynthDrag(node, parent, e, _state, draggedNodes2) {
synthDragScrolling: false,
synthDragging: true,
rootScrollWidth: document.scrollingElement?.scrollWidth,
rootScrollHeight: document.scrollingElement?.scrollHeight
rootScrollHeight: document.scrollingElement?.scrollHeight,
rootOverScrollBehavior: document.documentElement.style.overscrollBehavior,
rootTouchAction: document.documentElement.style.touchAction
};
document.documentElement.style.overscrollBehavior = "none";
document.documentElement.style.touchAction = "none";
const synthDragState = setDragState({
...dragStateProps(
node,
Expand Down Expand Up @@ -2777,30 +2783,34 @@ function isScrollX(el, e, style, rect, state2) {
};
}
if ((style.overflowX === "auto" || style.overflowX === "scroll") && el !== document.body && el !== document.documentElement) {
const scrollWidth = el.scrollWidth;
const offsetWidth = el.offsetWidth;
const scrollLeft = el.scrollLeft;
return {
right: e.clientX > rect.left + el.clientWidth * (1 - threshold),
left: e.clientX < rect.left + el.clientWidth * threshold
right: e.clientX > rect.left + offsetWidth * (1 - threshold) && scrollLeft < scrollWidth - offsetWidth,
left: e.clientX < rect.left + offsetWidth * threshold && scrollLeft > 0
};
}
return {
right: false,
left: false
};
}
function isScrollY(el, e, style, rect, state2) {
function isScrollY(el, e, style, rect) {
const threshold = 0.1;
if (el === document.scrollingElement) {
const canScrollUp = el.scrollTop > 0;
const canScrollDown = el.scrollTop + window.innerHeight < (state2.rootScrollHeight || 0);
return {
down: canScrollDown && e.clientY > el.clientHeight * (1 - threshold),
up: canScrollUp && e.clientY < el.clientHeight * threshold
down: e.clientY > el.clientHeight * (1 - threshold),
up: e.clientY < el.clientHeight * threshold
};
}
if ((style.overflowY === "auto" || style.overflowY === "scroll") && el !== document.body && el !== document.documentElement) {
const scrollHeight = el.scrollHeight;
const offsetHeight = el.offsetHeight;
const scrollTop = el.scrollTop;
return {
down: e.clientY > rect.top + el.clientHeight * (1 - threshold),
up: e.clientY < rect.top + el.clientHeight * threshold
down: e.clientY > rect.top + offsetHeight * (1 - threshold) && scrollTop < scrollHeight - offsetHeight,
up: e.clientY < rect.top + offsetHeight * threshold && scrollTop > 0
};
}
return {
Expand All @@ -2812,7 +2822,7 @@ function scrollX(el, e, state2, right = true) {
state2.preventEnter = true;
const incr = right ? 5 : -5;
function scroll(el2) {
el2.scrollTo({ left: el2.scrollLeft + incr });
el2.scrollBy({ left: incr });
moveNode(e, state2, incr, 0);
state2.animationFrameIdX = requestAnimationFrame(scroll.bind(null, el2));
}
Expand All @@ -2822,7 +2832,7 @@ function scrollY(el, e, state2, up = true) {
state2.preventEnter = true;
const incr = up ? -5 : 5;
function scroll() {
el.scrollTo({ top: el.scrollTop + incr });
el.scrollBy({ top: incr });
moveNode(e, state2, 0, incr);
state2.animationFrameIdY = requestAnimationFrame(scroll);
}
Expand All @@ -2848,7 +2858,7 @@ function handleSynthScroll(coordinates, e, state2) {
}
}
if (!scrollables.y) {
const { up, down } = isScrollY(el, e, style, rect, state2);
const { up, down } = isScrollY(el, e, style, rect);
if (up || down) {
scrollables.y = el;
scrollY(el, e, state2, up);
Expand Down
2 changes: 1 addition & 1 deletion dist/index.cjs.map

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions dist/index.d.cts
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,8 @@ interface SynthDragStateProps {
lastScrollY: HTMLElement | null;
rootScrollWidth: number | undefined;
rootScrollHeight: number | undefined;
rootOverScrollBehavior: string | undefined;
rootTouchAction: string | undefined;
}
type DragState<T> = DragStateProps<T> & BaseDragState<T>;
type BaseDragState<T> = {
Expand Down
2 changes: 2 additions & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,8 @@ interface SynthDragStateProps {
lastScrollY: HTMLElement | null;
rootScrollWidth: number | undefined;
rootScrollHeight: number | undefined;
rootOverScrollBehavior: string | undefined;
rootTouchAction: string | undefined;
}
type DragState<T> = DragStateProps<T> & BaseDragState<T>;
type BaseDragState<T> = {
Expand Down
40 changes: 25 additions & 15 deletions dist/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2203,6 +2203,10 @@ function handlePointercancel(data, state2) {
function handleEnd3(state2) {
if (state2.draggedNode) state2.draggedNode.el.draggable = false;
document.body.style.userSelect = state2.rootUserSelect || "";
if (isSynthDragState(state2)) {
document.documentElement.style.overscrollBehavior = state2.rootOverScrollBehavior || "";
document.documentElement.style.touchAction = state2.rootTouchAction || "";
}
if (isSynthDragState(state2)) cancelSynthScroll(state2);
if ("longPressTimeout" in state2 && state2.longPressTimeout)
clearTimeout(state2.longPressTimeout);
Expand Down Expand Up @@ -2254,8 +2258,6 @@ function handleNodePointerup(data, state2) {
config.handleEnd(state2);
}
function initSynthDrag(node, parent, e, _state, draggedNodes2) {
document.documentElement.style.overscrollBehavior = "none";
document.documentElement.style.touchAction = "none";
const config = parent.data.config;
let dragImage;
let display = node.el.style.display;
Expand Down Expand Up @@ -2319,8 +2321,12 @@ function initSynthDrag(node, parent, e, _state, draggedNodes2) {
synthDragScrolling: false,
synthDragging: true,
rootScrollWidth: document.scrollingElement?.scrollWidth,
rootScrollHeight: document.scrollingElement?.scrollHeight
rootScrollHeight: document.scrollingElement?.scrollHeight,
rootOverScrollBehavior: document.documentElement.style.overscrollBehavior,
rootTouchAction: document.documentElement.style.touchAction
};
document.documentElement.style.overscrollBehavior = "none";
document.documentElement.style.touchAction = "none";
const synthDragState = setDragState({
...dragStateProps(
node,
Expand Down Expand Up @@ -2687,30 +2693,34 @@ function isScrollX(el, e, style, rect, state2) {
};
}
if ((style.overflowX === "auto" || style.overflowX === "scroll") && el !== document.body && el !== document.documentElement) {
const scrollWidth = el.scrollWidth;
const offsetWidth = el.offsetWidth;
const scrollLeft = el.scrollLeft;
return {
right: e.clientX > rect.left + el.clientWidth * (1 - threshold),
left: e.clientX < rect.left + el.clientWidth * threshold
right: e.clientX > rect.left + offsetWidth * (1 - threshold) && scrollLeft < scrollWidth - offsetWidth,
left: e.clientX < rect.left + offsetWidth * threshold && scrollLeft > 0
};
}
return {
right: false,
left: false
};
}
function isScrollY(el, e, style, rect, state2) {
function isScrollY(el, e, style, rect) {
const threshold = 0.1;
if (el === document.scrollingElement) {
const canScrollUp = el.scrollTop > 0;
const canScrollDown = el.scrollTop + window.innerHeight < (state2.rootScrollHeight || 0);
return {
down: canScrollDown && e.clientY > el.clientHeight * (1 - threshold),
up: canScrollUp && e.clientY < el.clientHeight * threshold
down: e.clientY > el.clientHeight * (1 - threshold),
up: e.clientY < el.clientHeight * threshold
};
}
if ((style.overflowY === "auto" || style.overflowY === "scroll") && el !== document.body && el !== document.documentElement) {
const scrollHeight = el.scrollHeight;
const offsetHeight = el.offsetHeight;
const scrollTop = el.scrollTop;
return {
down: e.clientY > rect.top + el.clientHeight * (1 - threshold),
up: e.clientY < rect.top + el.clientHeight * threshold
down: e.clientY > rect.top + offsetHeight * (1 - threshold) && scrollTop < scrollHeight - offsetHeight,
up: e.clientY < rect.top + offsetHeight * threshold && scrollTop > 0
};
}
return {
Expand All @@ -2722,7 +2732,7 @@ function scrollX(el, e, state2, right = true) {
state2.preventEnter = true;
const incr = right ? 5 : -5;
function scroll(el2) {
el2.scrollTo({ left: el2.scrollLeft + incr });
el2.scrollBy({ left: incr });
moveNode(e, state2, incr, 0);
state2.animationFrameIdX = requestAnimationFrame(scroll.bind(null, el2));
}
Expand All @@ -2732,7 +2742,7 @@ function scrollY(el, e, state2, up = true) {
state2.preventEnter = true;
const incr = up ? -5 : 5;
function scroll() {
el.scrollTo({ top: el.scrollTop + incr });
el.scrollBy({ top: incr });
moveNode(e, state2, 0, incr);
state2.animationFrameIdY = requestAnimationFrame(scroll);
}
Expand All @@ -2758,7 +2768,7 @@ function handleSynthScroll(coordinates, e, state2) {
}
}
if (!scrollables.y) {
const { up, down } = isScrollY(el, e, style, rect, state2);
const { up, down } = isScrollY(el, e, style, rect);
if (up || down) {
scrollables.y = el;
scrollY(el, e, state2, up);
Expand Down
2 changes: 1 addition & 1 deletion dist/index.mjs.map

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions dist/react/index.d.cts
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,8 @@ interface SynthDragStateProps {
lastScrollY: HTMLElement | null;
rootScrollWidth: number | undefined;
rootScrollHeight: number | undefined;
rootOverScrollBehavior: string | undefined;
rootTouchAction: string | undefined;
}
type DragState<T> = DragStateProps<T> & BaseDragState<T>;
type BaseDragState<T> = {
Expand Down
2 changes: 2 additions & 0 deletions dist/react/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,8 @@ interface SynthDragStateProps {
lastScrollY: HTMLElement | null;
rootScrollWidth: number | undefined;
rootScrollHeight: number | undefined;
rootOverScrollBehavior: string | undefined;
rootTouchAction: string | undefined;
}
type DragState<T> = DragStateProps<T> & BaseDragState<T>;
type BaseDragState<T> = {
Expand Down
2 changes: 2 additions & 0 deletions dist/vue/index.d.cts
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,8 @@ interface SynthDragStateProps {
lastScrollY: HTMLElement | null;
rootScrollWidth: number | undefined;
rootScrollHeight: number | undefined;
rootOverScrollBehavior: string | undefined;
rootTouchAction: string | undefined;
}
type DragState<T> = DragStateProps<T> & BaseDragState<T>;
type BaseDragState<T> = {
Expand Down
2 changes: 2 additions & 0 deletions dist/vue/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,8 @@ interface SynthDragStateProps {
lastScrollY: HTMLElement | null;
rootScrollWidth: number | undefined;
rootScrollHeight: number | undefined;
rootOverScrollBehavior: string | undefined;
rootTouchAction: string | undefined;
}
type DragState<T> = DragStateProps<T> & BaseDragState<T>;
type BaseDragState<T> = {
Expand Down
47 changes: 27 additions & 20 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2969,7 +2969,7 @@ export function removeClass(
}

function isScrollX<T>(
el: Element,
el: HTMLElement,
e: PointerEvent,
style: CSSStyleDeclaration,
rect: DOMRect,
Expand All @@ -2993,9 +2993,15 @@ function isScrollX<T>(
el !== document.body &&
el !== document.documentElement
) {
const scrollWidth = el.scrollWidth;
const offsetWidth = el.offsetWidth;
const scrollLeft = el.scrollLeft;

return {
right: e.clientX > rect.left + el.clientWidth * (1 - threshold),
left: e.clientX < rect.left + el.clientWidth * threshold,
right:
e.clientX > rect.left + offsetWidth * (1 - threshold) &&
scrollLeft < scrollWidth - offsetWidth,
left: e.clientX < rect.left + offsetWidth * threshold && scrollLeft > 0,
};
}

Expand All @@ -3005,23 +3011,18 @@ function isScrollX<T>(
};
}

function isScrollY<T>(
el: Element,
function isScrollY(
el: HTMLElement,
e: PointerEvent,
style: CSSStyleDeclaration,
rect: DOMRect,
state: SynthDragState<T>
rect: DOMRect
): { up: boolean; down: boolean } {
const threshold = 0.1;

if (el === document.scrollingElement) {
const canScrollUp = el.scrollTop > 0;
const canScrollDown =
el.scrollTop + window.innerHeight < (state.rootScrollHeight || 0);

return {
down: canScrollDown && e.clientY > el.clientHeight * (1 - threshold),
up: canScrollUp && e.clientY < el.clientHeight * threshold,
down: e.clientY > el.clientHeight * (1 - threshold),
up: e.clientY < el.clientHeight * threshold,
};
}

Expand All @@ -3030,9 +3031,15 @@ function isScrollY<T>(
el !== document.body &&
el !== document.documentElement
) {
const scrollHeight = el.scrollHeight;
const offsetHeight = el.offsetHeight;
const scrollTop = el.scrollTop;

return {
down: e.clientY > rect.top + el.clientHeight * (1 - threshold),
up: e.clientY < rect.top + el.clientHeight * threshold,
down:
e.clientY > rect.top + offsetHeight * (1 - threshold) &&
scrollTop < scrollHeight - offsetHeight,
up: e.clientY < rect.top + offsetHeight * threshold && scrollTop > 0,
};
}

Expand All @@ -3043,7 +3050,7 @@ function isScrollY<T>(
}

function scrollX<T>(
el: Element,
el: HTMLElement,
e: PointerEvent,
state: SynthDragState<T>,
right = true
Expand All @@ -3052,8 +3059,8 @@ function scrollX<T>(

const incr = right ? 5 : -5;

function scroll(el: Element) {
el.scrollTo({ left: el.scrollLeft + incr });
function scroll(el: HTMLElement) {
el.scrollBy({ left: incr });

moveNode(e, state, incr, 0);

Expand All @@ -3074,7 +3081,7 @@ function scrollY<T>(
const incr = up ? -5 : 5;

function scroll() {
el.scrollTo({ top: el.scrollTop + incr });
el.scrollBy({ top: incr });

moveNode(e, state, 0, incr);

Expand Down Expand Up @@ -3127,7 +3134,7 @@ function handleSynthScroll<T>(
}

if (!scrollables.y) {
const { up, down } = isScrollY(el, e, style, rect, state);
const { up, down } = isScrollY(el, e, style, rect);

if (up || down) {
scrollables.y = el;
Expand Down
4 changes: 2 additions & 2 deletions tests/.nuxt/nuxt.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Generated by nuxi
/// <reference types="@nuxt/telemetry" />
/// <reference types="@nuxt/devtools" />
/// <reference types="@nuxtjs/tailwindcss" />
/// <reference types="@nuxt/devtools" />
/// <reference types="@nuxt/telemetry" />
/// <reference types="nuxt" />
/// <reference path="types/app-defaults.d.ts" />
/// <reference path="types/plugins.d.ts" />
Expand Down
Loading

0 comments on commit 88d63cc

Please sign in to comment.