Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Receivers are non-deterministic #175

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build/DraxContext.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/// <reference types="react" />
import { DraxContextValue } from './types';
export declare const DraxContext: import("react").Context<DraxContextValue | undefined>;
6 changes: 6 additions & 0 deletions build/DraxContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DraxContext = void 0;
const react_1 = require("react");
exports.DraxContext = (0, react_1.createContext)(undefined);
exports.DraxContext.displayName = 'Drax';
8 changes: 8 additions & 0 deletions build/DraxList.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { PropsWithChildren, Ref } from 'react';
import { FlatList } from 'react-native';
import { DraxListProps } from './types';
declare type DraxListType = <T extends unknown>(props: PropsWithChildren<DraxListProps<T>> & {
ref?: Ref<FlatList>;
}) => JSX.Element;
export declare const DraxList: DraxListType;
export {};
497 changes: 497 additions & 0 deletions build/DraxList.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions build/DraxProvider.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// <reference types="react" />
/// <reference types="react" />
import { DraxProviderProps } from './types';
export declare const DraxProvider: ({ debug, style, children, }: DraxProviderProps) => JSX.Element;
641 changes: 641 additions & 0 deletions build/DraxProvider.js

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions build/DraxScrollView.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react';
import { ScrollView } from 'react-native';
import { DraxScrollViewProps } from './types';
export declare const DraxScrollView: React.ForwardRefExoticComponent<DraxScrollViewProps & {
children?: React.ReactNode;
} & React.RefAttributes<ScrollView>>;
197 changes: 197 additions & 0 deletions build/DraxScrollView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DraxScrollView = void 0;
const react_1 = __importStar(require("react"));
const react_native_1 = require("react-native");
const DraxView_1 = require("./DraxView");
const DraxSubprovider_1 = require("./DraxSubprovider");
const hooks_1 = require("./hooks");
const types_1 = require("./types");
const params_1 = require("./params");
const DraxScrollViewUnforwarded = (props, forwardedRef) => {
const { children, style, onScroll: onScrollProp, onContentSizeChange: onContentSizeChangeProp, scrollEventThrottle = params_1.defaultScrollEventThrottle, autoScrollIntervalLength = params_1.defaultAutoScrollIntervalLength, autoScrollJumpRatio = params_1.defaultAutoScrollJumpRatio, autoScrollBackThreshold = params_1.defaultAutoScrollBackThreshold, autoScrollForwardThreshold = params_1.defaultAutoScrollForwardThreshold, id: idProp, ...scrollViewProps } = props;
// The unique identifer for this view.
const id = (0, hooks_1.useDraxId)(idProp);
// Scrollable view, used for scrolling.
const scrollRef = (0, react_1.useRef)(null);
// ScrollView node handle, used for measuring children.
const nodeHandleRef = (0, react_1.useRef)(null);
// Container view measurements, for scrolling by percentage.
const containerMeasurementsRef = (0, react_1.useRef)(undefined);
// Content size, for scrolling by percentage.
const contentSizeRef = (0, react_1.useRef)(undefined);
// Scroll position, for Drax bounds checking and auto-scrolling.
const scrollPositionRef = (0, react_1.useRef)({ x: 0, y: 0 });
// Auto-scroll state.
const autoScrollStateRef = (0, react_1.useRef)({
x: types_1.AutoScrollDirection.None,
y: types_1.AutoScrollDirection.None,
});
// Auto-scroll interval.
const autoScrollIntervalRef = (0, react_1.useRef)(undefined);
// Handle auto-scrolling on interval.
const doScroll = (0, react_1.useCallback)(() => {
const scroll = scrollRef.current;
const containerMeasurements = containerMeasurementsRef.current;
const contentSize = contentSizeRef.current;
if (!scroll || !containerMeasurements || !contentSize) {
return;
}
const scrollPosition = scrollPositionRef.current;
const autoScrollState = autoScrollStateRef.current;
const jump = {
x: containerMeasurements.width * autoScrollJumpRatio,
y: containerMeasurements.height * autoScrollJumpRatio,
};
let xNew;
let yNew;
if (autoScrollState.x === types_1.AutoScrollDirection.Forward) {
const xMax = contentSize.x - containerMeasurements.width;
if (scrollPosition.x < xMax) {
xNew = Math.min(scrollPosition.x + jump.x, xMax);
}
}
else if (autoScrollState.x === types_1.AutoScrollDirection.Back) {
if (scrollPosition.x > 0) {
xNew = Math.max(scrollPosition.x - jump.x, 0);
}
}
if (autoScrollState.y === types_1.AutoScrollDirection.Forward) {
const yMax = contentSize.y - containerMeasurements.height;
if (scrollPosition.y < yMax) {
yNew = Math.min(scrollPosition.y + jump.y, yMax);
}
}
else if (autoScrollState.y === types_1.AutoScrollDirection.Back) {
if (scrollPosition.y > 0) {
yNew = Math.max(scrollPosition.y - jump.y, 0);
}
}
if (xNew !== undefined || yNew !== undefined) {
scroll.scrollTo({
x: xNew ?? scrollPosition.x,
y: yNew ?? scrollPosition.y,
});
scroll.flashScrollIndicators(); // ScrollView typing is missing this method
}
}, [autoScrollJumpRatio]);
// Start the auto-scrolling interval.
const startScroll = (0, react_1.useCallback)(() => {
if (autoScrollIntervalRef.current) {
return;
}
doScroll();
autoScrollIntervalRef.current = setInterval(doScroll, autoScrollIntervalLength);
}, [doScroll, autoScrollIntervalLength]);
// Stop the auto-scrolling interval.
const stopScroll = (0, react_1.useCallback)(() => {
if (autoScrollIntervalRef.current) {
clearInterval(autoScrollIntervalRef.current);
autoScrollIntervalRef.current = undefined;
}
}, []);
// If startScroll changes, refresh our interval.
(0, react_1.useEffect)(() => {
if (autoScrollIntervalRef.current) {
stopScroll();
startScroll();
}
}, [stopScroll, startScroll]);
// Clear auto-scroll direction and stop the auto-scrolling interval.
const resetScroll = (0, react_1.useCallback)(() => {
const autoScrollState = autoScrollStateRef.current;
autoScrollState.x = types_1.AutoScrollDirection.None;
autoScrollState.y = types_1.AutoScrollDirection.None;
stopScroll();
}, [stopScroll]);
// Track the size of the container view.
const onMeasureContainer = (0, react_1.useCallback)((measurements) => {
containerMeasurementsRef.current = measurements;
}, []);
// Monitor drag-over events to react with auto-scrolling.
const onMonitorDragOver = (0, react_1.useCallback)((event) => {
const { monitorOffsetRatio } = event;
const autoScrollState = autoScrollStateRef.current;
if (monitorOffsetRatio.x >= autoScrollForwardThreshold) {
autoScrollState.x = types_1.AutoScrollDirection.Forward;
}
else if (monitorOffsetRatio.x <= autoScrollBackThreshold) {
autoScrollState.x = types_1.AutoScrollDirection.Back;
}
else {
autoScrollState.x = types_1.AutoScrollDirection.None;
}
if (monitorOffsetRatio.y >= autoScrollForwardThreshold) {
autoScrollState.y = types_1.AutoScrollDirection.Forward;
}
else if (monitorOffsetRatio.y <= autoScrollBackThreshold) {
autoScrollState.y = types_1.AutoScrollDirection.Back;
}
else {
autoScrollState.y = types_1.AutoScrollDirection.None;
}
if (autoScrollState.x === types_1.AutoScrollDirection.None && autoScrollState.y === types_1.AutoScrollDirection.None) {
stopScroll();
}
else {
startScroll();
}
}, [
stopScroll,
startScroll,
autoScrollBackThreshold,
autoScrollForwardThreshold,
]);
// Set the ScrollView and node handle refs.
const setScrollViewRefs = (0, react_1.useCallback)((ref) => {
scrollRef.current = ref;
nodeHandleRef.current = ref && (0, react_native_1.findNodeHandle)(ref);
if (forwardedRef) {
if (typeof forwardedRef === 'function') {
forwardedRef(ref);
}
else {
// eslint-disable-next-line no-param-reassign
forwardedRef.current = ref;
}
}
}, [forwardedRef]);
// Track content size.
const onContentSizeChange = (0, react_1.useCallback)((width, height) => {
contentSizeRef.current = { x: width, y: height };
return onContentSizeChangeProp?.(width, height);
}, [onContentSizeChangeProp]);
// Update tracked scroll position when list is scrolled.
const onScroll = (0, react_1.useCallback)((event) => {
const { nativeEvent: { contentOffset } } = event;
scrollPositionRef.current = { ...contentOffset };
return onScrollProp?.(event);
}, [onScrollProp]);
return id ? (react_1.default.createElement(DraxView_1.DraxView, { id: id, style: style, scrollPositionRef: scrollPositionRef, onMeasure: onMeasureContainer, onMonitorDragOver: onMonitorDragOver, onMonitorDragExit: resetScroll, onMonitorDragEnd: resetScroll, onMonitorDragDrop: resetScroll },
react_1.default.createElement(DraxSubprovider_1.DraxSubprovider, { parent: { id, nodeHandleRef } },
react_1.default.createElement(react_native_1.ScrollView, { ...scrollViewProps, ref: setScrollViewRefs, onContentSizeChange: onContentSizeChange, onScroll: onScroll, scrollEventThrottle: scrollEventThrottle }, children)))) : null;
};
exports.DraxScrollView = (0, react_1.forwardRef)(DraxScrollViewUnforwarded);
3 changes: 3 additions & 0 deletions build/DraxSubprovider.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { FunctionComponent } from 'react';
import { DraxSubproviderProps } from './types';
export declare const DraxSubprovider: FunctionComponent<DraxSubproviderProps>;
18 changes: 18 additions & 0 deletions build/DraxSubprovider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DraxSubprovider = void 0;
const react_1 = __importDefault(require("react"));
const DraxContext_1 = require("./DraxContext");
const hooks_1 = require("./hooks");
const DraxSubprovider = ({ parent, children }) => {
const contextValue = (0, hooks_1.useDraxContext)();
const subContextValue = {
...contextValue,
parent,
};
return (react_1.default.createElement(DraxContext_1.DraxContext.Provider, { value: subContextValue }, children));
};
exports.DraxSubprovider = DraxSubprovider;
3 changes: 3 additions & 0 deletions build/DraxView.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { PropsWithChildren } from 'react';
import { DraxViewProps } from './types';
export declare const DraxView: ({ onDragStart, onDrag, onDragEnter, onDragOver, onDragExit, onDragEnd, onDragDrop, onSnapbackEnd, onReceiveDragEnter, onReceiveDragOver, onReceiveDragExit, onReceiveDragDrop, onMonitorDragStart, onMonitorDragEnter, onMonitorDragOver, onMonitorDragExit, onMonitorDragEnd, onMonitorDragDrop, animateSnapback, snapbackDelay, snapbackDuration, snapbackAnimator, payload, dragPayload, receiverPayload, style, dragInactiveStyle, draggingStyle, draggingWithReceiverStyle, draggingWithoutReceiverStyle, dragReleasedStyle, hoverStyle, hoverDraggingStyle, hoverDraggingWithReceiverStyle, hoverDraggingWithoutReceiverStyle, hoverDragReleasedStyle, receiverInactiveStyle, receivingStyle, otherDraggingStyle, otherDraggingWithReceiverStyle, otherDraggingWithoutReceiverStyle, renderContent, renderHoverContent, registration, onMeasure, scrollPositionRef, lockDragXPosition, lockDragYPosition, children, viewRef: inputViewRef, noHover, isParent, longPressDelay, id: idProp, parent: parentProp, draggable: draggableProp, receptive: receptiveProp, monitoring: monitoringProp, ...props }: PropsWithChildren<DraxViewProps>) => JSX.Element;
Loading