β¬ οΈ Back to Table of Contents
π useScroll¶
π Analysis Summary¶
| Metric | Count |
|---|---|
| π§ Functions | 5 |
| π¦ Imports | 16 |
| π Variables & Constants | 1 |
| π’ Vue Composition API | 4 |
| π Interfaces | 2 |
π Table of Contents¶
π οΈ File Location:¶
π packages/core/useScroll/index.ts
π¦ Imports¶
| Name | Source |
|---|---|
MaybeRefOrGetter |
vue |
ShallowRef |
vue |
WritableComputedRef |
vue |
ConfigurableWindow |
../_configurable |
noop |
@vueuse/shared |
tryOnMounted |
@vueuse/shared |
useDebounceFn |
@vueuse/shared |
useThrottleFn |
@vueuse/shared |
computed |
vue |
reactive |
vue |
shallowRef |
vue |
toValue |
vue |
defaultWindow |
../_configurable |
unrefElement |
../unrefElement |
useEventListener |
../useEventListener |
useMutationObserver |
../useMutationObserver |
Variables & Constants¶
| Name | Type | Kind | Value | Exported |
|---|---|---|---|---|
ARRIVED_STATE_THRESHOLD_PIXELS |
1 |
const | 1 |
β |
Vue Composition API¶
| Name | Type | Reactive Variables | Composables |
|---|---|---|---|
computed |
computed | none | none |
computed |
computed | none | none |
reactive |
reactive | none | none |
reactive |
reactive | none | none |
Functions¶
useScroll(element: MaybeRefOrGetter<HTMLElement | SVGElemeβ¦, options: UseScrollOptions): UseScrollReturn¶
Reactive scroll.
Parameters:
elementany: No descriptionoptionsany: No description
See: https://vueuse.org/useScroll
Raw JSDoc
Calls:
console.errorshallowRef (from vue)computed (from vue)scrollTotoValue (from vue)(_element instanceof Document ? window.document.body : _element)?.scrollToreactive (from vue)onStopuseDebounceFn (from @vueuse/shared)unrefElement (from ../unrefElement)window.getComputedStyleMath.abssetArrivedStateonScrollEndDebouncedonScrolluseEventListener (from ../useEventListener)useThrottleFn (from @vueuse/shared)tryOnMounted (from @vueuse/shared)onErroruseMutationObserver (from ../useMutationObserver)
Internal Comments:
// Use a computed for x and y because we want to write the value to the refs (x2)
// during a `scrollTo()` without firing additional `scrollTo()`s in the process. (x2)
// dedupe if support native scrollend event
// patch for mobile compatible
/**
* reverse columns and rows behave exactly the other way around,
* bottom is treated as top and top is treated as the negative version of bottom
*/
Code
export function useScroll(
element: MaybeRefOrGetter<HTMLElement | SVGElement | Window | Document | null | undefined>,
options: UseScrollOptions = {},
): UseScrollReturn {
const {
throttle = 0,
idle = 200,
onStop = noop,
onScroll = noop,
offset = {
left: 0,
right: 0,
top: 0,
bottom: 0,
},
observe: _observe = {
mutation: false,
},
eventListenerOptions = {
capture: false,
passive: true,
},
behavior = 'auto',
window = defaultWindow,
onError = (e) => { console.error(e) },
} = options
const observe = typeof _observe === 'boolean'
? {
mutation: _observe,
}
: _observe
const internalX = shallowRef(0)
const internalY = shallowRef(0)
// Use a computed for x and y because we want to write the value to the refs
// during a `scrollTo()` without firing additional `scrollTo()`s in the process.
const x = computed({
get() {
return internalX.value
},
set(x) {
scrollTo(x, undefined)
},
})
const y = computed({
get() {
return internalY.value
},
set(y) {
scrollTo(undefined, y)
},
})
function scrollTo(_x: number | undefined, _y: number | undefined) {
if (!window)
return
const _element = toValue(element)
if (!_element)
return
(_element instanceof Document ? window.document.body : _element)?.scrollTo({
top: toValue(_y) ?? y.value,
left: toValue(_x) ?? x.value,
behavior: toValue(behavior),
})
const scrollContainer
= (_element as Window)?.document?.documentElement
|| (_element as Document)?.documentElement
|| (_element as Element)
if (x != null)
internalX.value = scrollContainer.scrollLeft
if (y != null)
internalY.value = scrollContainer.scrollTop
}
const isScrolling = shallowRef(false)
const arrivedState = reactive({
left: true,
right: false,
top: true,
bottom: false,
})
const directions = reactive({
left: false,
right: false,
top: false,
bottom: false,
})
const onScrollEnd = (e: Event) => {
// dedupe if support native scrollend event
if (!isScrolling.value)
return
isScrolling.value = false
directions.left = false
directions.right = false
directions.top = false
directions.bottom = false
onStop(e)
}
const onScrollEndDebounced = useDebounceFn(onScrollEnd, throttle + idle)
const setArrivedState = (target: HTMLElement | SVGElement | Window | Document | null | undefined) => {
if (!window)
return
const el: Element = (
(target as Window)?.document?.documentElement
|| (target as Document)?.documentElement
|| unrefElement(target as HTMLElement | SVGElement)
) as Element
const { display, flexDirection, direction } = window.getComputedStyle(el)
const directionMultipler = direction === 'rtl' ? -1 : 1
const scrollLeft = el.scrollLeft
directions.left = scrollLeft < internalX.value
directions.right = scrollLeft > internalX.value
const left = Math.abs(scrollLeft * directionMultipler) <= (offset.left || 0)
const right = Math.abs(scrollLeft * directionMultipler)
+ el.clientWidth >= el.scrollWidth
- (offset.right || 0)
- ARRIVED_STATE_THRESHOLD_PIXELS
if (display === 'flex' && flexDirection === 'row-reverse') {
arrivedState.left = right
arrivedState.right = left
}
else {
arrivedState.left = left
arrivedState.right = right
}
internalX.value = scrollLeft
let scrollTop = el.scrollTop
// patch for mobile compatible
if (target === window.document && !scrollTop)
scrollTop = window.document.body.scrollTop
directions.top = scrollTop < internalY.value
directions.bottom = scrollTop > internalY.value
const top = Math.abs(scrollTop) <= (offset.top || 0)
const bottom = Math.abs(scrollTop)
+ el.clientHeight >= el.scrollHeight
- (offset.bottom || 0)
- ARRIVED_STATE_THRESHOLD_PIXELS
/**
* reverse columns and rows behave exactly the other way around,
* bottom is treated as top and top is treated as the negative version of bottom
*/
if (display === 'flex' && flexDirection === 'column-reverse') {
arrivedState.top = bottom
arrivedState.bottom = top
}
else {
arrivedState.top = top
arrivedState.bottom = bottom
}
internalY.value = scrollTop
}
const onScrollHandler = (e: Event) => {
if (!window)
return
const eventTarget = (
(e.target as Document).documentElement ?? e.target
) as HTMLElement
setArrivedState(eventTarget)
isScrolling.value = true
onScrollEndDebounced(e)
onScroll(e)
}
useEventListener(
element,
'scroll',
throttle ? useThrottleFn(onScrollHandler, throttle, true, false) : onScrollHandler,
eventListenerOptions,
)
tryOnMounted(() => {
try {
const _element = toValue(element)
if (!_element)
return
setArrivedState(_element)
}
catch (e) {
onError(e)
}
})
if (observe?.mutation && element != null && element !== window && element !== document) {
useMutationObserver(
element as MaybeRefOrGetter<HTMLElement | SVGElement>,
() => {
const _element = toValue(element)
if (!_element)
return
setArrivedState(_element)
},
{
attributes: true,
childList: true,
subtree: true,
},
)
}
useEventListener(
element,
'scrollend',
onScrollEnd,
eventListenerOptions,
)
return {
x,
y,
isScrolling,
arrivedState,
directions,
measure() {
const _element = toValue(element)
if (window && _element)
setArrivedState(_element)
},
}
}
Internal helpers¶
Declared inside another function in this file.
scrollTo(_x: number | undefined, _y: number | undefined): void¶
Parameters:
_xnumber | undefined_ynumber | undefined
Returns: void
Calls:
toValue (from vue)(_element instanceof Document ? window.document.body : _element)?.scrollTo
Code
function scrollTo(_x: number | undefined, _y: number | undefined) {
if (!window)
return
const _element = toValue(element)
if (!_element)
return
(_element instanceof Document ? window.document.body : _element)?.scrollTo({
top: toValue(_y) ?? y.value,
left: toValue(_x) ?? x.value,
behavior: toValue(behavior),
})
const scrollContainer
= (_element as Window)?.document?.documentElement
|| (_element as Document)?.documentElement
|| (_element as Element)
if (x != null)
internalX.value = scrollContainer.scrollLeft
if (y != null)
internalY.value = scrollContainer.scrollTop
}
onScrollEnd(e: Event): void¶
Parameters:
eEvent
Returns: void
Calls:
onStop
Internal Comments:
Code
setArrivedState(target: HTMLElement | SVGElement | Window | Docβ¦): void¶
Parameters:
targetHTMLElement | SVGElement | Window | Document | null | undefined
Returns: void
Calls:
unrefElement (from ../unrefElement)window.getComputedStyleMath.abs
Internal Comments:
// patch for mobile compatible
/**
* reverse columns and rows behave exactly the other way around,
* bottom is treated as top and top is treated as the negative version of bottom
*/
Code
(target: HTMLElement | SVGElement | Window | Document | null | undefined) => {
if (!window)
return
const el: Element = (
(target as Window)?.document?.documentElement
|| (target as Document)?.documentElement
|| unrefElement(target as HTMLElement | SVGElement)
) as Element
const { display, flexDirection, direction } = window.getComputedStyle(el)
const directionMultipler = direction === 'rtl' ? -1 : 1
const scrollLeft = el.scrollLeft
directions.left = scrollLeft < internalX.value
directions.right = scrollLeft > internalX.value
const left = Math.abs(scrollLeft * directionMultipler) <= (offset.left || 0)
const right = Math.abs(scrollLeft * directionMultipler)
+ el.clientWidth >= el.scrollWidth
- (offset.right || 0)
- ARRIVED_STATE_THRESHOLD_PIXELS
if (display === 'flex' && flexDirection === 'row-reverse') {
arrivedState.left = right
arrivedState.right = left
}
else {
arrivedState.left = left
arrivedState.right = right
}
internalX.value = scrollLeft
let scrollTop = el.scrollTop
// patch for mobile compatible
if (target === window.document && !scrollTop)
scrollTop = window.document.body.scrollTop
directions.top = scrollTop < internalY.value
directions.bottom = scrollTop > internalY.value
const top = Math.abs(scrollTop) <= (offset.top || 0)
const bottom = Math.abs(scrollTop)
+ el.clientHeight >= el.scrollHeight
- (offset.bottom || 0)
- ARRIVED_STATE_THRESHOLD_PIXELS
/**
* reverse columns and rows behave exactly the other way around,
* bottom is treated as top and top is treated as the negative version of bottom
*/
if (display === 'flex' && flexDirection === 'column-reverse') {
arrivedState.top = bottom
arrivedState.bottom = top
}
else {
arrivedState.top = top
arrivedState.bottom = bottom
}
internalY.value = scrollTop
}
onScrollHandler(e: Event): void¶
Parameters:
eEvent
Returns: void
Calls:
setArrivedStateonScrollEndDebouncedonScroll
Code
Interfaces¶
UseScrollOptions¶
Interface Code
export interface UseScrollOptions extends ConfigurableWindow {
/**
* Throttle time for scroll event, itβs disabled by default.
*
* @default 0
*/
throttle?: number
/**
* The check time when scrolling ends.
* This configuration will be setting to (throttle + idle) when the `throttle` is configured.
*
* @default 200
*/
idle?: number
/**
* Offset arrived states by x pixels
*
*/
offset?: {
left?: number
right?: number
top?: number
bottom?: number
}
/**
* Use MutationObserver to monitor specific DOM changes,
* such as attribute modifications, child node additions or removals, or subtree changes.
* @default { mutation: boolean }
*/
observe?: boolean | {
mutation?: boolean
}
/**
* Trigger it when scrolling.
*
*/
onScroll?: (e: Event) => void
/**
* Trigger it when scrolling ends.
*
*/
onStop?: (e: Event) => void
/**
* Listener options for scroll event.
*
* @default {capture: false, passive: true}
*/
eventListenerOptions?: boolean | AddEventListenerOptions
/**
* Optionally specify a scroll behavior of `auto` (default, not smooth scrolling) or
* `smooth` (for smooth scrolling) which takes effect when changing the `x` or `y` refs.
*
* @default 'auto'
*/
behavior?: MaybeRefOrGetter<ScrollBehavior>
/**
* On error callback
*
* Default log error to `console.error`
*/
onError?: (error: unknown) => void
}
Properties¶
| Name | Type | Optional | Description |
|---|---|---|---|
throttle |
number |
β | not shown |
idle |
number |
β | not shown |
offset |
{ left?: number right?: number top?: number bottom?: number } |
β | not shown |
observe |
boolean \| { mutation?: boolean } |
β | not shown |
onScroll |
(e: Event) => void |
β | not shown |
onStop |
(e: Event) => void |
β | not shown |
eventListenerOptions |
boolean \| AddEventListenerOptions |
β | not shown |
behavior |
MaybeRefOrGetter<ScrollBehavior> |
β | not shown |
onError |
(error: unknown) => void |
β | not shown |
UseScrollReturn¶
Interface Code
export interface UseScrollReturn {
x: WritableComputedRef<number>
y: WritableComputedRef<number>
isScrolling: ShallowRef<boolean>
arrivedState: {
left: boolean
right: boolean
top: boolean
bottom: boolean
}
directions: {
left: boolean
right: boolean
top: boolean
bottom: boolean
}
measure: () => void
}
Properties¶
| Name | Type | Optional | Description |
|---|---|---|---|
x |
WritableComputedRef<number> |
β | not shown |
y |
WritableComputedRef<number> |
β | not shown |
isScrolling |
ShallowRef<boolean> |
β | not shown |
arrivedState |
{ left: boolean right: boolean top: boolean bottom: boolean } |
β | not shown |
directions |
{ left: boolean right: boolean top: boolean bottom: boolean } |
β | not shown |
measure |
() => void |
β | not shown |
Generated by Syntax Scribe