Packages
moon
2.90.4
2.90.5
retired
2.90.4
2.90.3
2.90.2
2.90.1
2.90.0
2.89.4
2.89.1
2.89.0
2.88.0
2.87.11
2.87.10
2.87.9
2.87.8
2.87.7
2.87.6
2.87.5
2.87.4
2.87.3
2.87.2
2.87.1
2.87.0
2.86.1
2.86.0
2.85.1
2.85.0
2.84.0
2.83.0
2.82.0
2.81.4
2.81.3
2.81.2
2.81.1
2.81.0
2.80.2
2.80.1
2.80.0
2.79.13
2.79.12
2.79.11
2.79.10
2.79.9
2.79.8
2.79.7
2.79.6
2.79.5
2.79.4
2.79.3
2.79.2
2.79.1
2.79.0
2.78.4
2.78.3
2.78.2
2.78.1
2.78.0
2.77.0
2.76.5
2.76.4
2.76.3
2.76.2
2.76.1
2.76.0
2.75.0
2.74.1
2.74.0
2.73.8
2.73.7
2.73.6
2.73.5
2.73.4
2.73.3
2.73.2
2.73.1
2.73.0
2.72.5
2.72.4
2.72.3
2.72.2
2.72.1
2.72.0
2.71.1
2.71.0
2.70.0
2.69.2
2.69.1
2.69.0
2.68.11
2.68.10
Components-based design system written in elixir
Current section
Files
Jump to
Current section
Files
assets/node_modules/scroll-into-view-if-needed/src/index.ts
import { compute } from 'compute-scroll-into-view'
import type {
Options as BaseOptions,
ScrollAction,
} from 'compute-scroll-into-view'
/** @public */
export type Options<T = unknown> =
| StandardBehaviorOptions
| CustomBehaviorOptions<T>
/**
* Only scrolls if the `node` is partially out of view:
* ```ts
* scrollIntoView(node, { scrollMode: 'if-needed' })
* ```
* Skips scrolling `overflow: hidden` elements:
* ```ts
* scrollIntoView(node, { skipOverflowHiddenElements: true })
* ```
* When scrolling is needed do the least and smoothest scrolling possible:
* ```ts
* scrollIntoView(node, {
* behavior: 'smooth',
* scrollMode: 'if-needed',
* block: 'nearest',
* inline: 'nearest',
* })
* ```
* @public
*/
export interface StandardBehaviorOptions extends BaseOptions {
/**
* @defaultValue 'auto
*/
behavior?: ScrollBehavior
}
/** @public */
export interface CustomBehaviorOptions<T = unknown> extends BaseOptions {
behavior: CustomScrollBehaviorCallback<T>
}
/** @public */
export type CustomScrollBehaviorCallback<T = unknown> = (
actions: ScrollAction[]
) => T
const isStandardScrollBehavior = (
options: any
): options is StandardBehaviorOptions =>
options === Object(options) && Object.keys(options).length !== 0
const isCustomScrollBehavior = <T = unknown>(
options: any
): options is CustomBehaviorOptions<T> =>
typeof options === 'object' ? typeof options.behavior === 'function' : false
const getOptions = (options: any): StandardBehaviorOptions => {
// Handle alignToTop for legacy reasons, to be compatible with the spec
if (options === false) {
return { block: 'end', inline: 'nearest' }
}
if (isStandardScrollBehavior(options)) {
// compute.ts ensures the defaults are block: 'center' and inline: 'nearest', to conform to the spec
return options
}
// if options = {}, options = true or options = null, based on w3c web platform test
return { block: 'start', inline: 'nearest' }
}
// Determine if the element is part of the document (including shadow dom)
// Derived from code of Andy Desmarais
// https://terodox.tech/how-to-tell-if-an-element-is-in-the-dom-including-the-shadow-dom/
const isInDocument = (element: Node) => {
let currentElement = element
while (currentElement && currentElement.parentNode) {
if (currentElement.parentNode === document) {
return true
} else if (currentElement.parentNode instanceof ShadowRoot) {
currentElement = (currentElement.parentNode as ShadowRoot).host
} else {
currentElement = currentElement.parentNode
}
}
return false
}
/**
* Scrolls the given element into view, with options for when, and how.
* Supports the same `options` as [`Element.prototype.scrollIntoView`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) with additions such as `scrollMode`, `behavior: Function` and `skipOverflowHiddenElements`.
* @public
*/
function scrollIntoView(
target: Element,
options?: StandardBehaviorOptions | boolean
): void
/**
* Scrolls the given element into view, with options for when, and how.
* Supports the same `options` as [`Element.prototype.scrollIntoView`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) with additions such as `scrollMode`, `behavior: Function` and `skipOverflowHiddenElements`.
*
* You can set the expected return type for `behavior: Function`:
* ```ts
* await scrollIntoView<Promise<boolean[]>>(node, {
* behavior: async actions => {
* return Promise.all(actions.map(
* // animate() resolves to `true` if anything was animated, `false` if the element already were in the end state
* ({ el, left, top }) => animate(el, {scroll: {left, top}})
* ))
* }
* })
* ```
* @public
*/
function scrollIntoView<T>(
target: Element,
options: CustomBehaviorOptions<T>
): T
function scrollIntoView<T = unknown>(
target: Element,
options?: StandardBehaviorOptions | CustomBehaviorOptions<T> | boolean
): T | void {
// Browsers treats targets that aren't in the dom as a no-op and so should we
if (!target.isConnected || !isInDocument(target)) {
return
}
if (isCustomScrollBehavior<T>(options)) {
return options.behavior(compute(target, options))
}
const behavior = typeof options === 'boolean' ? undefined : options?.behavior
for (const { el, top, left } of compute(target, getOptions(options))) {
el.scroll({ top, left, behavior })
}
}
export default scrollIntoView