MCPcopy
hub / github.com/adobe/react-spectrum / scrollIntoViewport

Function scrollIntoViewport

packages/react-aria/src/utils/scrollIntoView.ts:142–187  ·  view source on GitHub ↗
(
  targetElement: Element | null,
  opts: ScrollIntoViewportOpts = {}
)

Source from the content-addressed store, hash-verified

140 * the body itself.
141 */
142export function scrollIntoViewport(
143 targetElement: Element | null,
144 opts: ScrollIntoViewportOpts = {}
145): void {
146 let {containingElement} = opts;
147 if (targetElement && targetElement.isConnected) {
148 let root = document.scrollingElement || document.documentElement;
149 let isScrollPrevented = window.getComputedStyle(root).overflow === 'hidden';
150 if (!isScrollPrevented) {
151 let {left: originalLeft, top: originalTop} = targetElement.getBoundingClientRect();
152
153 // use scrollIntoView({block: 'nearest'}) instead of .focus to check if the element is fully in view or not since .focus()
154 // won't cause a scroll if the element is already focused and doesn't behave consistently when an element is partially out of view horizontally vs vertically
155 targetElement?.scrollIntoView?.({block: 'nearest'});
156 let {left: newLeft, top: newTop} = targetElement.getBoundingClientRect();
157 // Account for sub pixel differences from rounding
158 if (Math.abs(originalLeft - newLeft) > 1 || Math.abs(originalTop - newTop) > 1) {
159 containingElement?.scrollIntoView?.({block: 'center', inline: 'center'});
160 targetElement.scrollIntoView?.({block: 'nearest'});
161 }
162 } else {
163 let {left: originalLeft, top: originalTop} = targetElement.getBoundingClientRect();
164
165 // If scrolling is prevented, we don't want to scroll the body since it might move the overlay partially offscreen and the user can't scroll it back into view.
166 let scrollParents = getScrollParents(targetElement, true);
167 for (let scrollParent of scrollParents) {
168 scrollIntoView(scrollParent as HTMLElement, targetElement as HTMLElement);
169 }
170 let {left: newLeft, top: newTop} = targetElement.getBoundingClientRect();
171 // Account for sub pixel differences from rounding
172 if (Math.abs(originalLeft - newLeft) > 1 || Math.abs(originalTop - newTop) > 1) {
173 scrollParents = containingElement ? getScrollParents(containingElement, true) : [];
174 // scroll containing element into view first, then rescroll target element into view like the non chrome flow above
175 for (let scrollParent of scrollParents) {
176 scrollIntoView(scrollParent as HTMLElement, containingElement as HTMLElement, {
177 block: 'center',
178 inline: 'center'
179 });
180 }
181 for (let scrollParent of getScrollParents(targetElement, true)) {
182 scrollIntoView(scrollParent as HTMLElement, targetElement as HTMLElement);
183 }
184 }
185 }
186 }
187}

Callers 7

useCalendarCellFunction · 0.90
onKeyDownCaptureFunction · 0.90
onFocusFunction · 0.90
useSelectableCollectionFunction · 0.90
onKeyDownCaptureFunction · 0.90
onFocusFunction · 0.90
TableVirtualizerFunction · 0.90

Calls 2

getScrollParentsFunction · 0.90
scrollIntoViewFunction · 0.70

Tested by

no test coverage detected