11import { shallowRef , ref , unref , watch , computed , readonly , type CSSProperties as CSS } from 'vue'
22
33import { isSSR , useReducedMotion } from './utils'
4- import { defaultOptions , TRANSITION_STYLES } from './constants'
4+ import { TRANSITION_STYLES } from './constants'
55
66import type { UseFixedHeaderOptions , MaybeTemplateRef } from './types'
77
@@ -17,17 +17,18 @@ export function useFixedHeader(
1717) {
1818 // Config
1919
20- const config = { ...defaultOptions , ...options }
21-
2220 const { enterStyles, leaveStyles } = TRANSITION_STYLES
2321
24- let resizeObserver : ResizeObserver | undefined = undefined
22+ const root = ( ) => ( options . root || options . root === null ? unref ( options . root ) : null )
23+ const transitionOpacity = ( ) =>
24+ options . transitionOpacity === undefined ? false : unref ( options . transitionOpacity )
2525
2626 const isReduced = useReducedMotion ( )
2727
28- // Internal state
28+ // State
2929
30- const internals = {
30+ const internal = {
31+ resizeObserver : undefined as ResizeObserver | undefined ,
3132 skipInitialObserverCb : true ,
3233 isListeningScroll : false ,
3334 isHovering : false ,
@@ -44,8 +45,8 @@ export function useFixedHeader(
4445 // Utils
4546
4647 function getRoot ( ) {
47- const root = unref ( config . root )
48- if ( root != null ) return root
48+ const _root = root ( )
49+ if ( _root != null ) return _root
4950
5051 return document . documentElement
5152 }
@@ -86,24 +87,24 @@ export function useFixedHeader(
8687 */
8788 function onScrollRestoration ( ) {
8889 requestAnimationFrame ( ( ) => {
89- if ( ! internals . isMount || ! isFixed ( ) ) return
90+ if ( ! internal . isMount || ! isFixed ( ) ) return
9091
9192 const isInstant = getScrollTop ( ) > getHeaderHeight ( ) * 1.2 // Resolves to false if scroll is smooth
9293
9394 if ( isInstant ) {
9495 setStyles ( {
9596 transform : leaveStyles . transform ,
96- ...( config . transitionOpacity ? { opacity : 0 } : { } ) ,
97+ ...( transitionOpacity ( ) ? { opacity : 0 } : { } ) ,
9798 visibility : 'hidden' ,
9899 } )
99100 } else {
100101 setStyles ( {
101102 transform : enterStyles . transform ,
102- ...( config . transitionOpacity ? { opacity : 1 } : { } ) ,
103+ ...( transitionOpacity ( ) ? { opacity : 1 } : { } ) ,
103104 } )
104105 }
105106
106- internals . isMount = false
107+ internal . isMount = false
107108 } )
108109 }
109110
@@ -113,13 +114,13 @@ export function useFixedHeader(
113114 * turns from fixed/sticky to something else and vice-versa.
114115 */
115116 function addResizeObserver ( ) {
116- resizeObserver = new ResizeObserver ( ( ) => {
117- if ( internals . skipInitialObserverCb ) return ( internals . skipInitialObserverCb = false )
117+ internal . resizeObserver = new ResizeObserver ( ( ) => {
118+ if ( internal . skipInitialObserverCb ) return ( internal . skipInitialObserverCb = false )
118119 toggleListeners ( )
119120 } )
120121
121122 const root = getRoot ( )
122- if ( root ) resizeObserver . observe ( root )
123+ if ( root ) internal . resizeObserver . observe ( root )
123124 }
124125
125126 function onVisible ( ) {
@@ -129,7 +130,7 @@ export function useFixedHeader(
129130
130131 setStyles ( {
131132 ...enterStyles ,
132- ...( config . transitionOpacity ? { opacity : 1 } : { } ) ,
133+ ...( transitionOpacity ( ) ? { opacity : 1 } : { } ) ,
133134 visibility : '' as CSS [ 'visibility' ] ,
134135 } )
135136
@@ -139,7 +140,7 @@ export function useFixedHeader(
139140 function onHidden ( ) {
140141 if ( state . value === State . LEAVE ) return
141142
142- setStyles ( { ...leaveStyles , ...( config . transitionOpacity ? { opacity : 0 } : { } ) } )
143+ setStyles ( { ...leaveStyles , ...( transitionOpacity ( ) ? { opacity : 0 } : { } ) } )
143144
144145 setState ( State . LEAVE )
145146
@@ -198,7 +199,7 @@ export function useFixedHeader(
198199 if ( isTopReached ) return onVisible ( )
199200 if ( step < 10 ) return
200201
201- if ( ! internals . isHovering ) {
202+ if ( ! internal . isHovering ) {
202203 if ( isScrollingUp ) {
203204 onVisible ( )
204205 } else if ( isScrollingDown ) {
@@ -219,7 +220,7 @@ export function useFixedHeader(
219220 const scrollRoot = root === document . documentElement ? document : root
220221
221222 scrollRoot . addEventListener ( 'scroll' , onScroll , { passive : true } )
222- internals . isListeningScroll = true
223+ internal . isListeningScroll = true
223224 }
224225
225226 function removeScrollListener ( ) {
@@ -229,13 +230,13 @@ export function useFixedHeader(
229230 const scrollRoot = root === document . documentElement ? document : root
230231
231232 scrollRoot . removeEventListener ( 'scroll' , onScroll )
232- internals . isListeningScroll = false
233+ internal . isListeningScroll = false
233234 }
234235
235236 // Pointer Events
236237
237238 function onPointerMove ( e : PointerEvent ) {
238- internals . isHovering = unref ( target ) ?. contains ( e . target as Node ) ?? false
239+ internal . isHovering = unref ( target ) ?. contains ( e . target as Node ) ?? false
239240 }
240241
241242 function addPointerListener ( ) {
@@ -251,7 +252,7 @@ export function useFixedHeader(
251252 function toggleListeners ( ) {
252253 const isValid = isFixed ( )
253254
254- if ( internals . isListeningScroll ) {
255+ if ( internal . isListeningScroll ) {
255256 // If the header is not anymore fixed or sticky
256257 if ( ! isValid ) {
257258 removeListeners ( )
@@ -272,7 +273,7 @@ export function useFixedHeader(
272273 }
273274
274275 watch (
275- ( ) => [ unref ( target ) , unref ( config . root ) , isReduced . value , config . watch ] ,
276+ ( ) => [ unref ( target ) , getRoot ( ) , isReduced . value , unref ( options . watch ) ] ,
276277 ( [ headerEl , rootEl , isReduced ] , _ , onCleanup ) => {
277278 const shouldInit = ! isReduced && ! isSSR && headerEl && ( rootEl || rootEl === null )
278279
@@ -284,7 +285,7 @@ export function useFixedHeader(
284285
285286 onCleanup ( ( ) => {
286287 removeListeners ( )
287- resizeObserver ?. disconnect ( )
288+ internal . resizeObserver ?. disconnect ( )
288289 removeStyles ( )
289290 } )
290291 } ,
0 commit comments