main repo

This commit is contained in:
Basilosaurusrex
2025-11-24 18:09:40 +01:00
parent b636ee5e70
commit f027651f9b
34146 changed files with 4436636 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
import { RemoveScrollType } from './types';
declare const ReactRemoveScroll: RemoveScrollType;
export default ReactRemoveScroll;

View File

@@ -0,0 +1,6 @@
import * as React from 'react';
import { RemoveScroll } from './UI';
import SideCar from './sidecar';
const ReactRemoveScroll = React.forwardRef((props, ref) => (React.createElement(RemoveScroll, { ...props, ref: ref, sideCar: SideCar })));
ReactRemoveScroll.classNames = RemoveScroll.classNames;
export default ReactRemoveScroll;

View File

@@ -0,0 +1,5 @@
import { TouchEvent } from 'react';
import { IRemoveScrollEffectProps } from './types';
export declare const getTouchXY: (event: TouchEvent | WheelEvent) => number[];
export declare const getDeltaXY: (event: WheelEvent) => number[];
export declare function RemoveScrollSideCar(props: IRemoveScrollEffectProps): JSX.Element;

View File

@@ -0,0 +1,155 @@
import * as React from 'react';
import { RemoveScrollBar } from 'react-remove-scroll-bar';
import { styleSingleton } from 'react-style-singleton';
import { nonPassive } from './aggresiveCapture';
import { handleScroll, locationCouldBeScrolled } from './handleScroll';
export const getTouchXY = (event) => 'changedTouches' in event ? [event.changedTouches[0].clientX, event.changedTouches[0].clientY] : [0, 0];
export const getDeltaXY = (event) => [event.deltaX, event.deltaY];
const extractRef = (ref) => ref && 'current' in ref ? ref.current : ref;
const deltaCompare = (x, y) => x[0] === y[0] && x[1] === y[1];
const generateStyle = (id) => `
.block-interactivity-${id} {pointer-events: none;}
.allow-interactivity-${id} {pointer-events: all;}
`;
let idCounter = 0;
let lockStack = [];
export function RemoveScrollSideCar(props) {
const shouldPreventQueue = React.useRef([]);
const touchStartRef = React.useRef([0, 0]);
const activeAxis = React.useRef();
const [id] = React.useState(idCounter++);
const [Style] = React.useState(styleSingleton);
const lastProps = React.useRef(props);
React.useEffect(() => {
lastProps.current = props;
}, [props]);
React.useEffect(() => {
if (props.inert) {
document.body.classList.add(`block-interactivity-${id}`);
const allow = [props.lockRef.current, ...(props.shards || []).map(extractRef)].filter(Boolean);
allow.forEach((el) => el.classList.add(`allow-interactivity-${id}`));
return () => {
document.body.classList.remove(`block-interactivity-${id}`);
allow.forEach((el) => el.classList.remove(`allow-interactivity-${id}`));
};
}
return;
}, [props.inert, props.lockRef.current, props.shards]);
const shouldCancelEvent = React.useCallback((event, parent) => {
if (('touches' in event && event.touches.length === 2) || (event.type === 'wheel' && event.ctrlKey)) {
return !lastProps.current.allowPinchZoom;
}
const touch = getTouchXY(event);
const touchStart = touchStartRef.current;
const deltaX = 'deltaX' in event ? event.deltaX : touchStart[0] - touch[0];
const deltaY = 'deltaY' in event ? event.deltaY : touchStart[1] - touch[1];
let currentAxis;
const target = event.target;
const moveDirection = Math.abs(deltaX) > Math.abs(deltaY) ? 'h' : 'v';
// allow horizontal touch move on Range inputs. They will not cause any scroll
if ('touches' in event && moveDirection === 'h' && target.type === 'range') {
return false;
}
let canBeScrolledInMainDirection = locationCouldBeScrolled(moveDirection, target);
if (!canBeScrolledInMainDirection) {
return true;
}
if (canBeScrolledInMainDirection) {
currentAxis = moveDirection;
}
else {
currentAxis = moveDirection === 'v' ? 'h' : 'v';
canBeScrolledInMainDirection = locationCouldBeScrolled(moveDirection, target);
// other axis might be not scrollable
}
if (!canBeScrolledInMainDirection) {
return false;
}
if (!activeAxis.current && 'changedTouches' in event && (deltaX || deltaY)) {
activeAxis.current = currentAxis;
}
if (!currentAxis) {
return true;
}
const cancelingAxis = activeAxis.current || currentAxis;
return handleScroll(cancelingAxis, parent, event, cancelingAxis === 'h' ? deltaX : deltaY, true);
}, []);
const shouldPrevent = React.useCallback((_event) => {
const event = _event;
if (!lockStack.length || lockStack[lockStack.length - 1] !== Style) {
// not the last active
return;
}
const delta = 'deltaY' in event ? getDeltaXY(event) : getTouchXY(event);
const sourceEvent = shouldPreventQueue.current.filter((e) => e.name === event.type && (e.target === event.target || event.target === e.shadowParent) && deltaCompare(e.delta, delta))[0];
// self event, and should be canceled
if (sourceEvent && sourceEvent.should) {
if (event.cancelable) {
event.preventDefault();
}
return;
}
// outside or shard event
if (!sourceEvent) {
const shardNodes = (lastProps.current.shards || [])
.map(extractRef)
.filter(Boolean)
.filter((node) => node.contains(event.target));
const shouldStop = shardNodes.length > 0 ? shouldCancelEvent(event, shardNodes[0]) : !lastProps.current.noIsolation;
if (shouldStop) {
if (event.cancelable) {
event.preventDefault();
}
}
}
}, []);
const shouldCancel = React.useCallback((name, delta, target, should) => {
const event = { name, delta, target, should, shadowParent: getOutermostShadowParent(target) };
shouldPreventQueue.current.push(event);
setTimeout(() => {
shouldPreventQueue.current = shouldPreventQueue.current.filter((e) => e !== event);
}, 1);
}, []);
const scrollTouchStart = React.useCallback((event) => {
touchStartRef.current = getTouchXY(event);
activeAxis.current = undefined;
}, []);
const scrollWheel = React.useCallback((event) => {
shouldCancel(event.type, getDeltaXY(event), event.target, shouldCancelEvent(event, props.lockRef.current));
}, []);
const scrollTouchMove = React.useCallback((event) => {
shouldCancel(event.type, getTouchXY(event), event.target, shouldCancelEvent(event, props.lockRef.current));
}, []);
React.useEffect(() => {
lockStack.push(Style);
props.setCallbacks({
onScrollCapture: scrollWheel,
onWheelCapture: scrollWheel,
onTouchMoveCapture: scrollTouchMove,
});
document.addEventListener('wheel', shouldPrevent, nonPassive);
document.addEventListener('touchmove', shouldPrevent, nonPassive);
document.addEventListener('touchstart', scrollTouchStart, nonPassive);
return () => {
lockStack = lockStack.filter((inst) => inst !== Style);
document.removeEventListener('wheel', shouldPrevent, nonPassive);
document.removeEventListener('touchmove', shouldPrevent, nonPassive);
document.removeEventListener('touchstart', scrollTouchStart, nonPassive);
};
}, []);
const { removeScrollBar, inert } = props;
return (React.createElement(React.Fragment, null,
inert ? React.createElement(Style, { styles: generateStyle(id) }) : null,
removeScrollBar ? React.createElement(RemoveScrollBar, { gapMode: props.gapMode }) : null));
}
function getOutermostShadowParent(node) {
let shadowParent = null;
while (node !== null) {
if (node instanceof ShadowRoot) {
shadowParent = node.host;
node = node.host;
}
node = node.parentNode;
}
return shadowParent;
}

7
node_modules/react-remove-scroll/dist/es2019/UI.d.ts generated vendored Normal file
View File

@@ -0,0 +1,7 @@
import { RemoveScrollUIType, IRemoveScrollSelfProps } from './types';
export type { IRemoveScrollSelfProps, RemoveScrollUIType };
/**
* Removes scrollbar from the page and contain the scroll within the Lock
*/
declare const RemoveScroll: RemoveScrollUIType;
export { RemoveScroll };

41
node_modules/react-remove-scroll/dist/es2019/UI.js generated vendored Normal file
View File

@@ -0,0 +1,41 @@
import * as React from 'react';
import { fullWidthClassName, zeroRightClassName } from 'react-remove-scroll-bar/constants';
import { useMergeRefs } from 'use-callback-ref';
import { effectCar } from './medium';
const nothing = () => {
return;
};
/**
* Removes scrollbar from the page and contain the scroll within the Lock
*/
const RemoveScroll = React.forwardRef((props, parentRef) => {
const ref = React.useRef(null);
const [callbacks, setCallbacks] = React.useState({
onScrollCapture: nothing,
onWheelCapture: nothing,
onTouchMoveCapture: nothing,
});
const { forwardProps, children, className, removeScrollBar, enabled, shards, sideCar, noIsolation, inert, allowPinchZoom, as: Container = 'div', gapMode, ...rest } = props;
const SideCar = sideCar;
const containerRef = useMergeRefs([ref, parentRef]);
const containerProps = {
...rest,
...callbacks,
};
return (React.createElement(React.Fragment, null,
enabled && (React.createElement(SideCar, { sideCar: effectCar, removeScrollBar: removeScrollBar, shards: shards, noIsolation: noIsolation, inert: inert, setCallbacks: setCallbacks, allowPinchZoom: !!allowPinchZoom, lockRef: ref, gapMode: gapMode })),
forwardProps ? (React.cloneElement(React.Children.only(children), {
...containerProps,
ref: containerRef,
})) : (React.createElement(Container, { ...containerProps, className: className, ref: containerRef }, children))));
});
RemoveScroll.defaultProps = {
enabled: true,
removeScrollBar: true,
inert: false,
};
RemoveScroll.classNames = {
fullWidth: fullWidthClassName,
zeroRight: zeroRightClassName,
};
export { RemoveScroll };

View File

@@ -0,0 +1,3 @@
export declare const nonPassive: boolean | {
passive: boolean;
};

View File

@@ -0,0 +1,19 @@
let passiveSupported = false;
if (typeof window !== 'undefined') {
try {
const options = Object.defineProperty({}, 'passive', {
get() {
passiveSupported = true;
return true;
},
});
// @ts-ignore
window.addEventListener('test', options, options);
// @ts-ignore
window.removeEventListener('test', options, options);
}
catch (err) {
passiveSupported = false;
}
}
export const nonPassive = passiveSupported ? { passive: false } : false;

View File

@@ -0,0 +1,3 @@
import { Axis } from './types';
export declare const locationCouldBeScrolled: (axis: Axis, node: HTMLElement) => boolean;
export declare const handleScroll: (axis: Axis, endTarget: HTMLElement, event: any, sourceDelta: number, noOverscroll: boolean) => boolean;

View File

@@ -0,0 +1,95 @@
const alwaysContainsScroll = (node) =>
// textarea will always _contain_ scroll inside self. It only can be hidden
node.tagName === 'TEXTAREA';
const elementCanBeScrolled = (node, overflow) => {
if (!(node instanceof Element)) {
return false;
}
const styles = window.getComputedStyle(node);
return (
// not-not-scrollable
styles[overflow] !== 'hidden' &&
// contains scroll inside self
!(styles.overflowY === styles.overflowX && !alwaysContainsScroll(node) && styles[overflow] === 'visible'));
};
const elementCouldBeVScrolled = (node) => elementCanBeScrolled(node, 'overflowY');
const elementCouldBeHScrolled = (node) => elementCanBeScrolled(node, 'overflowX');
export const locationCouldBeScrolled = (axis, node) => {
const ownerDocument = node.ownerDocument;
let current = node;
do {
// Skip over shadow root
if (typeof ShadowRoot !== 'undefined' && current instanceof ShadowRoot) {
current = current.host;
}
const isScrollable = elementCouldBeScrolled(axis, current);
if (isScrollable) {
const [, scrollHeight, clientHeight] = getScrollVariables(axis, current);
if (scrollHeight > clientHeight) {
return true;
}
}
current = current.parentNode;
} while (current && current !== ownerDocument.body);
return false;
};
const getVScrollVariables = ({ scrollTop, scrollHeight, clientHeight }) => [
scrollTop,
scrollHeight,
clientHeight,
];
const getHScrollVariables = ({ scrollLeft, scrollWidth, clientWidth }) => [
scrollLeft,
scrollWidth,
clientWidth,
];
const elementCouldBeScrolled = (axis, node) => axis === 'v' ? elementCouldBeVScrolled(node) : elementCouldBeHScrolled(node);
const getScrollVariables = (axis, node) => axis === 'v' ? getVScrollVariables(node) : getHScrollVariables(node);
const getDirectionFactor = (axis, direction) =>
/**
* If the element's direction is rtl (right-to-left), then scrollLeft is 0 when the scrollbar is at its rightmost position,
* and then increasingly negative as you scroll towards the end of the content.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft
*/
axis === 'h' && direction === 'rtl' ? -1 : 1;
export const handleScroll = (axis, endTarget, event, sourceDelta, noOverscroll) => {
const directionFactor = getDirectionFactor(axis, window.getComputedStyle(endTarget).direction);
const delta = directionFactor * sourceDelta;
// find scrollable target
let target = event.target;
const targetInLock = endTarget.contains(target);
let shouldCancelScroll = false;
const isDeltaPositive = delta > 0;
let availableScroll = 0;
let availableScrollTop = 0;
do {
const [position, scroll, capacity] = getScrollVariables(axis, target);
const elementScroll = scroll - capacity - directionFactor * position;
if (position || elementScroll) {
if (elementCouldBeScrolled(axis, target)) {
availableScroll += elementScroll;
availableScrollTop += position;
}
}
if (target instanceof ShadowRoot) {
target = target.host;
}
else {
target = target.parentNode;
}
} while (
// portaled content
(!targetInLock && target !== document.body) ||
// self content
(targetInLock && (endTarget.contains(target) || endTarget === target)));
// handle epsilon around 0 (non standard zoom levels)
if (isDeltaPositive &&
((noOverscroll && Math.abs(availableScroll) < 1) || (!noOverscroll && delta > availableScroll))) {
shouldCancelScroll = true;
}
else if (!isDeltaPositive &&
((noOverscroll && Math.abs(availableScrollTop) < 1) || (!noOverscroll && -delta > availableScrollTop))) {
shouldCancelScroll = true;
}
return shouldCancelScroll;
};

View File

@@ -0,0 +1,2 @@
import RemoveScroll from './Combination';
export { RemoveScroll };

View File

@@ -0,0 +1,2 @@
import RemoveScroll from './Combination';
export { RemoveScroll };

View File

@@ -0,0 +1,2 @@
import { IRemoveScrollEffectProps } from './types';
export declare const effectCar: Readonly<import("use-sidecar/dist/es5/types").SideCarMedium<IRemoveScrollEffectProps>>;

View File

@@ -0,0 +1,2 @@
import { createSidecarMedium } from 'use-sidecar';
export const effectCar = createSidecarMedium();

View File

@@ -0,0 +1,8 @@
import { Touch } from 'react';
export declare const pinchOrZoom: (event: TouchEvent, cache: Record<number, Touch>) => false | {
action: string;
coords?: undefined;
} | {
action: string;
coords: number[];
};

View File

@@ -0,0 +1,33 @@
const ds = (ab) => (ab[0] <= 0 && ab[1] >= 0) || (ab[0] >= 0 && ab[1] <= 0);
const sign = (x) => (x < 0 ? -1 : 1);
export const pinchOrZoom = (event, cache) => {
if (!event.changedTouches) {
return false;
}
if (event.touches.length === 2) {
const oldPoints = [cache[event.touches[0].identifier], cache[event.touches[1].identifier]];
const newPoints = [event.touches[0], event.touches[1]];
if (oldPoints[0] && oldPoints[1]) {
// Calculate the difference between the start and move coordinates
const diffx = [oldPoints[0].clientX - newPoints[0].clientX, oldPoints[1].clientX - newPoints[1].clientX];
const diffy = [oldPoints[0].clientY - newPoints[0].clientY, oldPoints[1].clientY - newPoints[1].clientY];
console.log(diffx, diffy);
if (ds(diffx) || ds(diffy)) {
return {
action: 'zoom',
};
}
const mx = Math.max(Math.abs(diffx[0]), Math.abs(diffx[1]));
const my = Math.max(Math.abs(diffy[0]), Math.abs(diffy[1]));
return {
action: 'pinch',
coords: [mx * sign(diffx[0]), my * sign(diffx[1])],
};
}
}
Array.from(event.changedTouches).forEach((touch) => (cache[touch.identifier] = touch));
return {
action: 'move',
coords: [event.changedTouches[0].clientX, event.changedTouches[0].clientY],
};
};

View File

@@ -0,0 +1,2 @@
declare const _default: import("use-sidecar").SideCarComponent<import("./types").IRemoveScrollEffectProps>;
export default _default;

View File

@@ -0,0 +1,4 @@
import { exportSidecar } from 'use-sidecar';
import { RemoveScrollSideCar } from './SideEffect';
import { effectCar } from './medium';
export default exportSidecar(effectCar, RemoveScrollSideCar);

View File

@@ -0,0 +1,98 @@
import * as React from 'react';
import { Ref, RefObject } from 'react';
import { ForwardRefExoticComponent } from 'react';
import { RefAttributes } from 'react';
export declare type Axis = 'v' | 'h';
export declare type GapMode = 'padding' | 'margin';
export interface RemoveScrollEffectCallbacks {
onScrollCapture(event: any): void;
onWheelCapture(event: any): void;
onTouchMoveCapture(event: any): void;
}
export interface ChildrenNode {
/**
* if forwardProps is false - children should be ReactNode
* and it would be wrapper with a div
* @see {@link IRemoveScrollSelfProps.as}
*/
forwardProps?: false;
children: React.ReactNode;
}
export interface ChildrenForward {
/**
* if forwardProps is true - everything will be forwarded to a single child node
* otherwise - a Container, controlled by `as` prop will be rendered in place
* @default false
* @see {@link IRemoveScrollSelfProps.as}
*/
forwardProps: true;
children: React.ReactElement;
}
export interface IRemoveScrollSelfProps {
ref?: Ref<HTMLElement>;
/**
* disables "event isolation" (suppressing of events happening outside of the Lock)
* @default false
*/
noIsolation?: boolean;
/**
* enabled complete Lock isolation using `pointer-events:none` for anything outside the Lock
* you probably don't need it, except you do
* @default false
* @see {IRemoveScrollSelfProps.noIsolation}
*/
inert?: boolean;
/**
* allows pinch-zoom, however might work not perfectly for normal scroll
*/
allowPinchZoom?: boolean;
/**
* switches on/off the behavior of the component
*/
enabled?: boolean;
/**
* Controls the body scroll bar removal
* @default false
*/
removeScrollBar?: boolean;
className?: string;
style?: React.CSSProperties;
/**
* array of refs to other Elements, which should be considered as a part of the Lock
*/
shards?: Array<React.RefObject<any> | HTMLElement>;
/**
* Control host node used for the lock.
* @default 'div'
*/
as?: string | React.ElementType;
/**
* controls the way "gap" is filled
* @default "margin"
*/
gapMode?: GapMode;
}
export declare type IRemoveScrollProps = IRemoveScrollSelfProps & (ChildrenForward | ChildrenNode);
export declare type IRemoveScrollUIProps = IRemoveScrollProps & {
sideCar: React.FC<any>;
};
export interface IRemoveScrollEffectProps {
noIsolation?: boolean;
removeScrollBar?: boolean;
allowPinchZoom: boolean;
inert?: boolean;
shards?: Array<React.RefObject<any> | HTMLElement>;
lockRef: RefObject<HTMLElement>;
gapMode?: GapMode;
setCallbacks(cb: RemoveScrollEffectCallbacks): void;
}
interface WithClassNames {
classNames: {
fullWidth: string;
zeroRight: string;
};
}
declare type RefForwarded<T> = ForwardRefExoticComponent<T & RefAttributes<HTMLElement>> & WithClassNames;
export declare type RemoveScrollType = RefForwarded<IRemoveScrollProps>;
export declare type RemoveScrollUIType = RefForwarded<IRemoveScrollUIProps>;
export {};

View File

@@ -0,0 +1 @@
export {};