mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-23 03:10:37 +03:00
overflow calc
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -61,6 +61,7 @@ export interface Environment {
|
|||||||
export interface State {
|
export interface State {
|
||||||
padding: TRBL;
|
padding: TRBL;
|
||||||
paddingAbsolute: boolean;
|
paddingAbsolute: boolean;
|
||||||
|
overflowEdge: XY<number>;
|
||||||
overflowAmount: XY<number>;
|
overflowAmount: XY<number>;
|
||||||
overflowStyle: XY<OverflowStyle>;
|
overflowStyle: XY<OverflowStyle>;
|
||||||
hasOverflow: XY<boolean>;
|
hasOverflow: XY<boolean>;
|
||||||
@@ -80,6 +81,7 @@ export interface OnUpdatedEventListenerArgs {
|
|||||||
sizeChanged: boolean;
|
sizeChanged: boolean;
|
||||||
directionChanged: boolean;
|
directionChanged: boolean;
|
||||||
heightIntrinsicChanged: boolean;
|
heightIntrinsicChanged: boolean;
|
||||||
|
overflowEdgeChanged: boolean;
|
||||||
overflowAmountChanged: boolean;
|
overflowAmountChanged: boolean;
|
||||||
overflowStyleChanged: boolean;
|
overflowStyleChanged: boolean;
|
||||||
hostMutation: boolean;
|
hostMutation: boolean;
|
||||||
@@ -212,11 +214,18 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
|||||||
name && listener && removeEvent(name, listener as any);
|
name && listener && removeEvent(name, listener as any);
|
||||||
},
|
},
|
||||||
state() {
|
state() {
|
||||||
const { _overflowAmount, _overflowStyle, _hasOverflow, _padding, _paddingAbsolute } =
|
const {
|
||||||
structureState();
|
_overflowEdge,
|
||||||
|
_overflowAmount,
|
||||||
|
_overflowStyle,
|
||||||
|
_hasOverflow,
|
||||||
|
_padding,
|
||||||
|
_paddingAbsolute,
|
||||||
|
} = structureState();
|
||||||
return assignDeep(
|
return assignDeep(
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
overflowEdge: _overflowEdge,
|
||||||
overflowAmount: _overflowAmount,
|
overflowAmount: _overflowAmount,
|
||||||
overflowStyle: _overflowStyle,
|
overflowStyle: _overflowStyle,
|
||||||
hasOverflow: _hasOverflow,
|
hasOverflow: _hasOverflow,
|
||||||
@@ -273,6 +282,7 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
|||||||
_sizeChanged,
|
_sizeChanged,
|
||||||
_directionChanged,
|
_directionChanged,
|
||||||
_heightIntrinsicChanged,
|
_heightIntrinsicChanged,
|
||||||
|
_overflowEdgeChanged,
|
||||||
_overflowAmountChanged,
|
_overflowAmountChanged,
|
||||||
_overflowStyleChanged,
|
_overflowStyleChanged,
|
||||||
_contentMutation,
|
_contentMutation,
|
||||||
@@ -286,6 +296,7 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
|
|||||||
sizeChanged: _sizeChanged,
|
sizeChanged: _sizeChanged,
|
||||||
directionChanged: _directionChanged,
|
directionChanged: _directionChanged,
|
||||||
heightIntrinsicChanged: _heightIntrinsicChanged,
|
heightIntrinsicChanged: _heightIntrinsicChanged,
|
||||||
|
overflowEdgeChanged: _overflowEdgeChanged,
|
||||||
overflowAmountChanged: _overflowAmountChanged,
|
overflowAmountChanged: _overflowAmountChanged,
|
||||||
overflowStyleChanged: _overflowStyleChanged,
|
overflowStyleChanged: _overflowStyleChanged,
|
||||||
contentMutation: _contentMutation,
|
contentMutation: _contentMutation,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export type ScrollbarsSetupElements = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const generateScrollbarDOM = (scrollbarClassName: string): ScrollbarStructure => {
|
const generateScrollbarDOM = (scrollbarClassName: string): ScrollbarStructure => {
|
||||||
const scrollbar = createDiv(`${classNameScrollbar} ${scrollbarClassName}`);
|
const scrollbar = createDiv(`${classNameScrollbar} ${scrollbarClassName} os-theme-dark`);
|
||||||
const track = createDiv(classNameScrollbarTrack);
|
const track = createDiv(classNameScrollbarTrack);
|
||||||
const handle = createDiv(classNameScrollbarHandle);
|
const handle = createDiv(classNameScrollbarHandle);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
import { each, isNumber, scrollLeft, scrollTop, assignDeep, keys } from 'support';
|
||||||
|
import { getEnvironment } from 'environment';
|
||||||
|
import {
|
||||||
|
createTrinsicUpdate,
|
||||||
|
createPaddingUpdate,
|
||||||
|
createOverflowUpdate,
|
||||||
|
} from 'setups/structureSetup/updateSegments';
|
||||||
|
import type { SetupState, SetupUpdateSegment, SetupUpdateCheckOption } from 'setups';
|
||||||
|
import type { StructureSetupState } from 'setups/structureSetup';
|
||||||
|
import type { StructureSetupElementsObj } from 'setups/structureSetup/structureSetup.elements';
|
||||||
|
|
||||||
|
export type CreateStructureUpdateSegment = (
|
||||||
|
structureSetupElements: StructureSetupElementsObj,
|
||||||
|
state: SetupState<StructureSetupState>
|
||||||
|
) => StructureSetupUpdateSegment;
|
||||||
|
|
||||||
|
export type StructureSetupUpdateSegment = SetupUpdateSegment<StructureSetupUpdateHints>;
|
||||||
|
|
||||||
|
export type StructureSetupUpdate = (
|
||||||
|
checkOption: SetupUpdateCheckOption,
|
||||||
|
updateHints: Partial<StructureSetupUpdateHints>,
|
||||||
|
force?: boolean
|
||||||
|
) => StructureSetupUpdateHints;
|
||||||
|
|
||||||
|
export interface StructureSetupUpdateHints {
|
||||||
|
_sizeChanged: boolean;
|
||||||
|
_directionChanged: boolean;
|
||||||
|
_heightIntrinsicChanged: boolean;
|
||||||
|
_overflowAmountChanged: boolean;
|
||||||
|
_overflowStyleChanged: boolean;
|
||||||
|
_paddingStyleChanged: boolean;
|
||||||
|
_hostMutation: boolean;
|
||||||
|
_contentMutation: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prepareUpdateHints = <T extends StructureSetupUpdateHints>(
|
||||||
|
leading: Required<T>,
|
||||||
|
adaptive?: Partial<T>,
|
||||||
|
force?: boolean
|
||||||
|
): Required<T> => {
|
||||||
|
const result = {};
|
||||||
|
const finalAdaptive = adaptive || {};
|
||||||
|
const objKeys = keys(leading).concat(keys(finalAdaptive));
|
||||||
|
|
||||||
|
each(objKeys, (key) => {
|
||||||
|
const leadingValue = leading[key];
|
||||||
|
const adaptiveValue = finalAdaptive[key];
|
||||||
|
result[key] = !!(force || leadingValue || adaptiveValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result as Required<T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createStructureSetupUpdate = (
|
||||||
|
structureSetupElements: StructureSetupElementsObj,
|
||||||
|
state: SetupState<StructureSetupState>
|
||||||
|
): StructureSetupUpdate => {
|
||||||
|
const { _viewport } = structureSetupElements;
|
||||||
|
const {
|
||||||
|
_nativeScrollbarsHiding: _nativeScrollbarStyling,
|
||||||
|
_nativeScrollbarsOverlaid: _nativeScrollbarIsOverlaid,
|
||||||
|
_flexboxGlue,
|
||||||
|
} = getEnvironment();
|
||||||
|
const doViewportArrange =
|
||||||
|
!_nativeScrollbarStyling && (_nativeScrollbarIsOverlaid.x || _nativeScrollbarIsOverlaid.y);
|
||||||
|
|
||||||
|
const updateSegments: StructureSetupUpdateSegment[] = [
|
||||||
|
createTrinsicUpdate(structureSetupElements, state),
|
||||||
|
createPaddingUpdate(structureSetupElements, state),
|
||||||
|
createOverflowUpdate(structureSetupElements, state),
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
checkOption: SetupUpdateCheckOption,
|
||||||
|
updateHints: Partial<StructureSetupUpdateHints>,
|
||||||
|
force?: boolean
|
||||||
|
) => {
|
||||||
|
const initialUpdateHints = prepareUpdateHints(
|
||||||
|
assignDeep(
|
||||||
|
{
|
||||||
|
_sizeChanged: false,
|
||||||
|
_paddingStyleChanged: false,
|
||||||
|
_directionChanged: false,
|
||||||
|
_heightIntrinsicChanged: false,
|
||||||
|
_overflowAmountChanged: false,
|
||||||
|
_overflowStyleChanged: false,
|
||||||
|
_hostMutation: false,
|
||||||
|
_contentMutation: false,
|
||||||
|
},
|
||||||
|
updateHints
|
||||||
|
),
|
||||||
|
{},
|
||||||
|
force
|
||||||
|
);
|
||||||
|
const adjustScrollOffset = doViewportArrange || !_flexboxGlue;
|
||||||
|
const scrollOffsetX = adjustScrollOffset && scrollLeft(_viewport);
|
||||||
|
const scrollOffsetY = adjustScrollOffset && scrollTop(_viewport);
|
||||||
|
|
||||||
|
let adaptivedUpdateHints: Required<StructureSetupUpdateHints> = initialUpdateHints;
|
||||||
|
each(updateSegments, (updateSegment) => {
|
||||||
|
adaptivedUpdateHints = prepareUpdateHints<StructureSetupUpdateHints>(
|
||||||
|
adaptivedUpdateHints,
|
||||||
|
updateSegment(adaptivedUpdateHints, checkOption, !!force) || {},
|
||||||
|
force
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isNumber(scrollOffsetX)) {
|
||||||
|
scrollLeft(_viewport, scrollOffsetX);
|
||||||
|
}
|
||||||
|
if (isNumber(scrollOffsetY)) {
|
||||||
|
scrollTop(_viewport, scrollOffsetY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return adaptivedUpdateHints;
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -15,6 +15,7 @@ export interface StructureSetupState {
|
|||||||
_padding: TRBL;
|
_padding: TRBL;
|
||||||
_paddingAbsolute: boolean;
|
_paddingAbsolute: boolean;
|
||||||
_viewportPaddingStyle: StyleObject;
|
_viewportPaddingStyle: StyleObject;
|
||||||
|
_overflowEdge: XY<number>;
|
||||||
_overflowAmount: XY<number>;
|
_overflowAmount: XY<number>;
|
||||||
_overflowStyle: XY<OverflowStyle>;
|
_overflowStyle: XY<OverflowStyle>;
|
||||||
_hasOverflow: XY<boolean>;
|
_hasOverflow: XY<boolean>;
|
||||||
@@ -36,6 +37,7 @@ type StructureSetupEventMap = {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const initialXYNumber = { x: 0, y: 0 };
|
||||||
const initialStructureSetupUpdateState: StructureSetupState = {
|
const initialStructureSetupUpdateState: StructureSetupState = {
|
||||||
_padding: {
|
_padding: {
|
||||||
t: 0,
|
t: 0,
|
||||||
@@ -53,10 +55,8 @@ const initialStructureSetupUpdateState: StructureSetupState = {
|
|||||||
paddingBottom: 0,
|
paddingBottom: 0,
|
||||||
paddingLeft: 0,
|
paddingLeft: 0,
|
||||||
},
|
},
|
||||||
_overflowAmount: {
|
_overflowEdge: initialXYNumber,
|
||||||
x: 0,
|
_overflowAmount: initialXYNumber,
|
||||||
y: 0,
|
|
||||||
},
|
|
||||||
_overflowStyle: {
|
_overflowStyle: {
|
||||||
x: 'hidden',
|
x: 'hidden',
|
||||||
y: 'hidden',
|
y: 'hidden',
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export interface StructureSetupUpdateHints {
|
|||||||
_sizeChanged: boolean;
|
_sizeChanged: boolean;
|
||||||
_directionChanged: boolean;
|
_directionChanged: boolean;
|
||||||
_heightIntrinsicChanged: boolean;
|
_heightIntrinsicChanged: boolean;
|
||||||
|
_overflowEdgeChanged: boolean;
|
||||||
_overflowAmountChanged: boolean;
|
_overflowAmountChanged: boolean;
|
||||||
_overflowStyleChanged: boolean;
|
_overflowStyleChanged: boolean;
|
||||||
_paddingStyleChanged: boolean;
|
_paddingStyleChanged: boolean;
|
||||||
@@ -82,6 +83,7 @@ export const createStructureSetupUpdate = (
|
|||||||
_paddingStyleChanged: false,
|
_paddingStyleChanged: false,
|
||||||
_directionChanged: false,
|
_directionChanged: false,
|
||||||
_heightIntrinsicChanged: false,
|
_heightIntrinsicChanged: false,
|
||||||
|
_overflowEdgeChanged: false,
|
||||||
_overflowAmountChanged: false,
|
_overflowAmountChanged: false,
|
||||||
_overflowStyleChanged: false,
|
_overflowStyleChanged: false,
|
||||||
_hostMutation: false,
|
_hostMutation: false,
|
||||||
|
|||||||
+30
-18
@@ -66,15 +66,11 @@ const xyCacheOptions = {
|
|||||||
_initialValue: { x: strHidden, y: strHidden } as XY<OverflowStyle>,
|
_initialValue: { x: strHidden, y: strHidden } as XY<OverflowStyle>,
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOverflowAmount = (
|
const getOverflowAmount = (viewportScrollSize: WH<number>, viewportClientSize: WH<number>) => {
|
||||||
viewportScrollSize: WH<number>,
|
|
||||||
viewportClientSize: WH<number>,
|
|
||||||
sizeFraction: WH<number>
|
|
||||||
) => {
|
|
||||||
const tollerance = window.devicePixelRatio % 1 !== 0 ? 1 : 0;
|
const tollerance = window.devicePixelRatio % 1 !== 0 ? 1 : 0;
|
||||||
const amount = {
|
const amount = {
|
||||||
w: max(0, viewportScrollSize.w - viewportClientSize.w - max(0, sizeFraction.w)),
|
w: max(0, viewportScrollSize.w - viewportClientSize.w),
|
||||||
h: max(0, viewportScrollSize.h - viewportClientSize.h - max(0, sizeFraction.h)),
|
h: max(0, viewportScrollSize.h - viewportClientSize.h),
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -135,6 +131,8 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
|||||||
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] =
|
const [updateOverflowAmountCache, getCurrentOverflowAmountCache] =
|
||||||
createCache<WH<number>>(whCacheOptions);
|
createCache<WH<number>>(whCacheOptions);
|
||||||
|
|
||||||
|
const [updateOverflowEdge, getCurrentOverflowEdgeCache] = createCache<WH<number>>(whCacheOptions);
|
||||||
|
|
||||||
const [updateOverflowStyleCache] = createCache<XY<OverflowStyle>>(xyCacheOptions);
|
const [updateOverflowStyleCache] = createCache<XY<OverflowStyle>>(xyCacheOptions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -350,6 +348,7 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
|||||||
let sizeFractionCache = getCurrentSizeFraction(force);
|
let sizeFractionCache = getCurrentSizeFraction(force);
|
||||||
let viewportScrollSizeCache = getCurrentViewportScrollSizeCache(force);
|
let viewportScrollSizeCache = getCurrentViewportScrollSizeCache(force);
|
||||||
let overflowAmuntCache = getCurrentOverflowAmountCache(force);
|
let overflowAmuntCache = getCurrentOverflowAmountCache(force);
|
||||||
|
let overflowEdgeCache = getCurrentOverflowEdgeCache(force);
|
||||||
|
|
||||||
let preMeasureViewportOverflowState: ViewportOverflowState | undefined;
|
let preMeasureViewportOverflowState: ViewportOverflowState | undefined;
|
||||||
|
|
||||||
@@ -407,22 +406,29 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
|||||||
arrangedViewportScrollSize = scrollSize(_viewport);
|
arrangedViewportScrollSize = scrollSize(_viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const overflowAmountScrollSize = {
|
||||||
|
w: max(viewportScrollSize.w, arrangedViewportScrollSize.w) + sizeFraction.w,
|
||||||
|
h: max(viewportScrollSize.h, arrangedViewportScrollSize.h) + sizeFraction.h,
|
||||||
|
};
|
||||||
|
const overflowAmountClientSize = {
|
||||||
|
w:
|
||||||
|
arrangedViewportClientSize.w +
|
||||||
|
max(0, viewportclientSize.w - viewportScrollSize.w) +
|
||||||
|
sizeFraction.w,
|
||||||
|
h:
|
||||||
|
arrangedViewportClientSize.h +
|
||||||
|
max(0, viewportclientSize.h - viewportScrollSize.h) +
|
||||||
|
sizeFraction.h,
|
||||||
|
};
|
||||||
|
|
||||||
|
overflowEdgeCache = updateOverflowEdge(overflowAmountClientSize);
|
||||||
overflowAmuntCache = updateOverflowAmountCache(
|
overflowAmuntCache = updateOverflowAmountCache(
|
||||||
getOverflowAmount(
|
getOverflowAmount(overflowAmountScrollSize, overflowAmountClientSize),
|
||||||
{
|
|
||||||
w: max(viewportScrollSize.w, arrangedViewportScrollSize.w),
|
|
||||||
h: max(viewportScrollSize.h, arrangedViewportScrollSize.h),
|
|
||||||
}, // scroll size
|
|
||||||
{
|
|
||||||
w: arrangedViewportClientSize.w + max(0, viewportclientSize.w - viewportScrollSize.w),
|
|
||||||
h: arrangedViewportClientSize.h + max(0, viewportclientSize.h - viewportScrollSize.h),
|
|
||||||
}, // client size
|
|
||||||
sizeFraction
|
|
||||||
),
|
|
||||||
force
|
force
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [overflowEdge, overflowEdgeChanged] = overflowEdgeCache;
|
||||||
const [overflowAmount, overflowAmountChanged] = overflowAmuntCache;
|
const [overflowAmount, overflowAmountChanged] = overflowAmuntCache;
|
||||||
const [viewportScrollSize, viewportScrollSizeChanged] = viewportScrollSizeCache;
|
const [viewportScrollSize, viewportScrollSizeChanged] = viewportScrollSizeCache;
|
||||||
const [sizeFraction, sizeFractionChanged] = sizeFractionCache;
|
const [sizeFraction, sizeFractionChanged] = sizeFractionCache;
|
||||||
@@ -440,6 +446,7 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
|||||||
_directionChanged ||
|
_directionChanged ||
|
||||||
sizeFractionChanged ||
|
sizeFractionChanged ||
|
||||||
viewportScrollSizeChanged ||
|
viewportScrollSizeChanged ||
|
||||||
|
overflowEdgeChanged ||
|
||||||
overflowAmountChanged ||
|
overflowAmountChanged ||
|
||||||
overflowChanged ||
|
overflowChanged ||
|
||||||
showNativeOverlaidScrollbarsChanged ||
|
showNativeOverlaidScrollbarsChanged ||
|
||||||
@@ -497,6 +504,10 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
|||||||
|
|
||||||
setState({
|
setState({
|
||||||
_overflowStyle: overflowStyle,
|
_overflowStyle: overflowStyle,
|
||||||
|
_overflowEdge: {
|
||||||
|
x: overflowEdge.w,
|
||||||
|
y: overflowEdge.h,
|
||||||
|
},
|
||||||
_overflowAmount: {
|
_overflowAmount: {
|
||||||
x: overflowAmount.w,
|
x: overflowAmount.w,
|
||||||
y: overflowAmount.h,
|
y: overflowAmount.h,
|
||||||
@@ -506,6 +517,7 @@ export const createOverflowUpdate: CreateStructureUpdateSegment = (
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
_overflowStyleChanged: overflowStyleChanged,
|
_overflowStyleChanged: overflowStyleChanged,
|
||||||
|
_overflowEdgeChanged: overflowEdgeChanged,
|
||||||
_overflowAmountChanged: overflowAmountChanged,
|
_overflowAmountChanged: overflowAmountChanged,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -9,9 +9,9 @@ module.exports = {
|
|||||||
workers: 4,
|
workers: 4,
|
||||||
projects: [
|
projects: [
|
||||||
{
|
{
|
||||||
name: 'Safari',
|
name: 'Chromium',
|
||||||
use: {
|
use: {
|
||||||
...devices['Desktop Safari'],
|
...devices['Desktop Chromium'],
|
||||||
headless: false,
|
headless: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user