implement scroll restoration and scroll focus

This commit is contained in:
Rene Haas
2022-08-03 11:38:46 +02:00
parent ea76610bab
commit fa989cabb7
4 changed files with 31 additions and 4 deletions
@@ -20,6 +20,7 @@ import {
attrClass,
hasAttrClass,
noop,
on,
} from 'support';
import {
dataAttributeHost,
@@ -73,6 +74,7 @@ export interface StructureSetupElementsObj {
_viewportAddRemoveClass: (className: string, attributeClassName: string, add?: boolean) => void;
}
const tabIndexStr = 'tabindex';
const createNewDiv = createDiv.bind(0, '');
const unwrap = (elm: HTMLElement | false | null | undefined) => {
@@ -130,6 +132,8 @@ export const createStructureSetupElements = (
);
const viewportIsTarget = viewportElement === targetElement;
const viewportIsTargetBody = viewportIsTarget && isBody;
const setFocus =
!viewportIsTarget && wnd.top === wnd && ownerDocument.activeElement === targetElement;
const evaluatedTargetObj: StructureSetupElementsObj = {
_target: targetElement,
_host: isTextarea
@@ -240,6 +244,17 @@ export const createStructureSetupElements = (
insertBefore(_viewport, _viewportArrange);
push(destroyFns, removeElements.bind(0, _viewportArrange));
}
if (setFocus) {
const ogTabindex = attr(_viewport, tabIndexStr);
attr(_viewport, tabIndexStr, '-1');
_viewport.focus();
const off = on(ownerDocument, 'pointerdown keydown', () => {
ogTabindex ? attr(_viewport, tabIndexStr, ogTabindex) : removeAttr(_viewport, tabIndexStr);
off();
});
}
// @ts-ignore
targetContents = 0;
@@ -1,4 +1,4 @@
import { createEventListenerHub, isEmptyObject, keys } from 'support';
import { createEventListenerHub, isEmptyObject, keys, scrollLeft, scrollTop } from 'support';
import { createState, createOptionCheck } from 'setups/setups';
import { createStructureSetupElements } from 'setups/structureSetup/structureSetup.elements';
import { createStructureSetupUpdate } from 'setups/structureSetup/structureSetup.update';
@@ -97,8 +97,15 @@ export const createStructureSetup = (
addEvent('u', listener);
};
structureSetupState._appendElements = () => {
const { _target, _viewport } = elements;
const initialScrollLeft = scrollLeft(_target);
const initialScrollTop = scrollTop(_target);
appendObserverElements();
appendStructureElements();
scrollLeft(_viewport, initialScrollLeft);
scrollTop(_viewport, initialScrollTop);
};
structureSetupState._elements = elements;
@@ -57,7 +57,7 @@ export const createStructureSetupUpdate = (
structureSetupElements: StructureSetupElementsObj,
state: SetupState<StructureSetupState>
): StructureSetupUpdate => {
const { _viewport, _viewportAddRemoveClass } = structureSetupElements;
const { _target, _viewport, _viewportAddRemoveClass, _viewportIsTarget } = structureSetupElements;
const { _nativeScrollbarsHiding, _nativeScrollbarsOverlaid, _flexboxGlue } = getEnvironment();
const doViewportArrange =
!_nativeScrollbarsHiding && (_nativeScrollbarsOverlaid.x || _nativeScrollbarsOverlaid.y);
@@ -109,6 +109,11 @@ export const createStructureSetupUpdate = (
scrollTop(_viewport, scrollOffsetY);
_viewportAddRemoveClass('', dataValueHostUpdating);
if (!_viewportIsTarget) {
scrollLeft(_target, 0);
scrollTop(_target, 0);
}
return adaptivedUpdateHints;
};
};
@@ -1,5 +1,5 @@
import { from } from 'support/utils/array';
import { isNull, isUndefined } from 'support/utils/types';
import { isNumber, isString, isUndefined } from 'support/utils/types';
type GetSetPropName = 'scrollLeft' | 'scrollTop' | 'value';
@@ -27,7 +27,7 @@ const getSetProp = (
if (isUndefined(value)) {
return elm ? elm[topLeft] : fallback;
}
elm && !isNull(value) && value !== false && (elm[topLeft] = value);
elm && (isString(value) || isNumber(value)) && (elm[topLeft] = value);
};
/**