Skip to content

Commit 1cd2c59

Browse files
committed
add shortRef
1 parent 533424d commit 1cd2c59

File tree

3 files changed

+107
-70
lines changed

3 files changed

+107
-70
lines changed

src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,7 @@ export declare function useActive(
2828
userIds: string[] | Ref<string[]>,
2929
options?: UseActiveOptions
3030
): UseActiveReturn
31+
32+
export interface ShortRef<T> extends Ref<T> {
33+
v: T
34+
}

src/useActive.ts

Lines changed: 67 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,50 @@
11
import {
2-
ref,
32
onMounted,
4-
computed,
53
unref,
64
watch,
75
isRef,
86
isReactive,
97
onBeforeUnmount,
108
reactive,
119
type Ref,
12-
type ComputedRef,
1310
} from 'vue'
14-
import { getEdges, useMediaRef, isSSR, FIXED_OFFSET, defaultOptions as _def } from './utils'
15-
import type { UseActiveOptions, UseActiveReturn } from './types'
11+
import {
12+
computed,
13+
ref,
14+
getEdges,
15+
useMediaRef,
16+
isSSR,
17+
FIXED_OFFSET,
18+
defaultOptions as def,
19+
} from './utils'
20+
import type { UseActiveOptions, UseActiveReturn, ShortRef } from './types'
1621

1722
export function useActive(
1823
userIds: string[] | Ref<string[]>,
1924
{
20-
root: _root = _def.root,
21-
jumpToFirst = _def.jumpToFirst,
22-
jumpToLast = _def.jumpToLast,
23-
overlayHeight = _def.overlayHeight,
24-
minWidth = _def.minWidth,
25-
replaceHash = _def.replaceHash,
25+
root: _root = def.root,
26+
jumpToFirst = def.jumpToFirst,
27+
jumpToLast = def.jumpToLast,
28+
overlayHeight = def.overlayHeight,
29+
minWidth = def.minWidth,
30+
replaceHash = def.replaceHash,
2631
boundaryOffset: {
27-
toTop = _def.boundaryOffset.toTop,
28-
toBottom = _def.boundaryOffset.toTop,
29-
} = _def.boundaryOffset,
32+
toTop = def.boundaryOffset.toTop,
33+
toBottom = def.boundaryOffset.toTop,
34+
} = def.boundaryOffset,
3035
edgeOffset: {
31-
first: firstOffset = _def.edgeOffset.first,
32-
last: lastOffset = _def.edgeOffset.last,
33-
} = _def.edgeOffset,
34-
}: UseActiveOptions = _def
36+
first: firstOffset = def.edgeOffset.first,
37+
last: lastOffset = def.edgeOffset.last,
38+
} = def.edgeOffset,
39+
}: UseActiveOptions = def
3540
): UseActiveReturn {
3641
// Reactivity - Internal - Root
3742

3843
const root = computed(() =>
3944
isSSR ? null : unref(_root) instanceof HTMLElement ? unref(_root) : document.documentElement
40-
) as ComputedRef<HTMLElement>
45+
) as ShortRef<HTMLElement>
4146

42-
const isWindow = computed(() => root.value === document.documentElement)
47+
const isWindow = computed(() => root.v === document.documentElement)
4348

4449
// Reactivity - Internal - Targets
4550

@@ -59,12 +64,12 @@ export function useActive(
5964

6065
// Reactivity - Internal - Coords
6166

62-
const clickStartY = computed(() => (isScrollFromClick.value ? getCurrentY() : 0))
67+
const clickStartY = computed(() => (isScrollFromClick.v ? getCurrentY() : 0))
6368

6469
// Reactivity - Returned
6570

6671
const activeId = useMediaRef(matchMedia, '')
67-
const activeIndex = computed(() => ids.value.indexOf(activeId.value))
72+
const activeIndex = computed(() => ids.v.indexOf(activeId.v))
6873

6974
// Non-reactive
7075

@@ -76,11 +81,11 @@ export function useActive(
7681
// Functions - Coords
7782

7883
function getCurrentY() {
79-
return isWindow.value ? window.scrollY : root.value.scrollTop
84+
return isWindow.v ? window.scrollY : root.v.scrollTop
8085
}
8186

8287
function getSentinel() {
83-
return isWindow.value ? root.value.getBoundingClientRect().top : -root.value.scrollTop
88+
return isWindow.v ? root.v.getBoundingClientRect().top : -root.v.scrollTop
8489
}
8590

8691
// Functions - Targets
@@ -98,8 +103,7 @@ export function useActive(
98103
_targets.sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top)
99104
targets.elements = _targets
100105

101-
const rootTop =
102-
root.value.getBoundingClientRect().top - (isWindow.value ? 0 : root.value.scrollTop)
106+
const rootTop = root.v.getBoundingClientRect().top - (isWindow.v ? 0 : root.v.scrollTop)
103107

104108
targets.top.clear()
105109
targets.bottom.clear()
@@ -118,19 +122,19 @@ export function useActive(
118122
return false
119123
}
120124

121-
const { isBottom, isTop } = getEdges(root.value)
125+
const { isBottom, isTop } = getEdges(root.v)
122126

123127
if (jumpToFirst && isTop) {
124-
return (activeId.value = ids.value[0]), true
128+
return (activeId.v = ids.v[0]), true
125129
}
126130
if (jumpToLast && isBottom) {
127-
return (activeId.value = ids.value[ids.value.length - 1]), true
131+
return (activeId.v = ids.v[ids.v.length - 1]), true
128132
}
129133
}
130134

131135
// Sets first target-top that LEFT the viewport
132136
function onScrollDown({ isCancel } = { isCancel: false }) {
133-
let firstOut = jumpToFirst ? ids.value[0] : ''
137+
let firstOut = jumpToFirst ? ids.v[0] : ''
134138

135139
const sentinel = getSentinel()
136140
const offset = FIXED_OFFSET + overlayHeight + toBottom
@@ -145,56 +149,53 @@ export function useActive(
145149
})
146150

147151
// Remove activeId once last target-bottom is out of view
148-
if (!jumpToLast && firstOut === ids.value[ids.value.length - 1]) {
149-
const lastBottom = Array.from(targets.bottom.values())[ids.value.length - 1]
152+
if (!jumpToLast && firstOut === ids.v[ids.v.length - 1]) {
153+
const lastBottom = Array.from(targets.bottom.values())[ids.v.length - 1]
150154

151155
if (sentinel + lastBottom < offset + lastOffset) {
152-
return (activeId.value = '')
156+
return (activeId.v = '')
153157
}
154158
}
155159

156160
// Highlight only next on smoothscroll/custom easings...
157-
if (
158-
ids.value.indexOf(firstOut) > ids.value.indexOf(activeId.value) ||
159-
(firstOut && !activeId.value)
160-
) {
161-
return (activeId.value = firstOut)
161+
if (ids.v.indexOf(firstOut) > ids.v.indexOf(activeId.v) || (firstOut && !activeId.v)) {
162+
return (activeId.v = firstOut)
162163
}
163164

164165
// ...but not on scroll cancel
165166
if (isCancel) {
166-
activeId.value = firstOut
167+
activeId.v = firstOut
167168
}
168169
}
169170

170171
// Sets first target-bottom that ENTERED the viewport
171172
function onScrollUp() {
172-
let firstIn = jumpToLast ? ids.value[ids.value.length - 1] : ''
173+
let firstIn = jumpToLast ? ids.v[ids.v.length - 1] : ''
173174

174175
const sentinel = getSentinel()
175176
const offset = FIXED_OFFSET + overlayHeight + toTop
176177

177178
Array.from(targets.bottom).some(([id, bottom], index) => {
178-
const _lastOffset = !jumpToLast && index === ids.value.length - 1 ? lastOffset : 0
179+
const _lastOffset = !jumpToLast && index === ids.v.length - 1 ? lastOffset : 0
179180

180181
if (sentinel + bottom > offset + _lastOffset) {
181182
return (firstIn = id), true // Return first
182183
}
183184
})
184185

185186
// Remove activeId once first target-top is in view
186-
if (!jumpToFirst && firstIn === ids.value[0]) {
187+
if (!jumpToFirst && firstIn === ids.v[0]) {
187188
if (sentinel + targets.top.values().next().value > offset + firstOffset) {
188-
return (activeId.value = '')
189+
return (activeId.v = '')
189190
}
190191
}
191192

192193
if (
193194
// Highlight only prev on smoothscroll/custom easings...
194-
ids.value.indexOf(firstIn) < ids.value.indexOf(activeId.value) ||
195-
(firstIn && !activeId.value)
195+
ids.v.indexOf(firstIn) < ids.v.indexOf(activeId.v) ||
196+
(firstIn && !activeId.v)
196197
) {
197-
return (activeId.value = firstIn)
198+
return (activeId.v = firstIn)
198199
}
199200
}
200201

@@ -211,7 +212,7 @@ export function useActive(
211212
}
212213

213214
function onScroll() {
214-
if (!isScrollFromClick.value) {
215+
if (!isScrollFromClick.v) {
215216
prevY = setActive({ prevY })
216217
onEdgeReached()
217218
}
@@ -235,8 +236,8 @@ export function useActive(
235236

236237
// Wait for n frames after scroll to make sure is idle
237238
if (frameCount === maxFrames) {
238-
isScrollIdle.value = true
239-
isScrollFromClick.value = false
239+
isScrollIdle.v = true
240+
isScrollFromClick.v = false
240241
cancelAnimationFrame(rafId as DOMHighResTimeStamp)
241242
} else {
242243
requestAnimationFrame(scrollEnd)
@@ -250,7 +251,7 @@ export function useActive(
250251
if (location.hash) {
251252
setIdleScroll(10)
252253
} else {
253-
isScrollIdle.value = true
254+
isScrollIdle.v = true
254255
}
255256
}
256257

@@ -260,14 +261,14 @@ export function useActive(
260261
const hashId = targets.elements.find(({ id }) => id === location.hash.slice(1))?.id
261262

262263
if (hashId) {
263-
return (activeId.value = hashId), true
264+
return (activeId.v = hashId), true
264265
}
265266
}
266267

267268
function onHashChange(event: HashChangeEvent) {
268269
// If scrolled back to top
269-
if (!event.newURL.includes('#') && activeId.value) {
270-
return (activeId.value = jumpToFirst ? ids.value[0] : '')
270+
if (!event.newURL.includes('#') && activeId.v) {
271+
return (activeId.v = jumpToFirst ? ids.v[0] : '')
271272
}
272273

273274
setFromHash()
@@ -284,7 +285,7 @@ export function useActive(
284285
// Functions - Resize
285286

286287
function onWindowResize() {
287-
matchMedia.value = window.matchMedia(`(min-width: ${minWidth}px)`).matches
288+
matchMedia.v = window.matchMedia(`(min-width: ${minWidth}px)`).matches
288289
}
289290

290291
function setResizeObserver() {
@@ -301,7 +302,7 @@ export function useActive(
301302
}
302303
})
303304

304-
resizeObserver.observe(root.value)
305+
resizeObserver.observe(root.v)
305306
}
306307

307308
function destroyResizeObserver() {
@@ -311,7 +312,7 @@ export function useActive(
311312
// Functions - Scroll cancel
312313

313314
function restoreHighlight() {
314-
isScrollFromClick.value = false
315+
isScrollFromClick.v = false
315316
}
316317

317318
function onSpaceBar(event: KeyboardEvent) {
@@ -324,24 +325,24 @@ export function useActive(
324325
const isAnchor = (event.target as HTMLElement).tagName === 'A'
325326

326327
if (CSS.supports('-moz-appearance', 'none') && !isAnchor) {
327-
const { isBottom, isTop } = getEdges(root.value)
328+
const { isBottom, isTop } = getEdges(root.v)
328329

329330
if (!isTop && !isBottom) {
330331
restoreHighlight()
331-
setActive({ prevY: clickStartY.value, isCancel: true })
332+
setActive({ prevY: clickStartY.v, isCancel: true })
332333
}
333334
}
334335
}
335336

336337
// Functions - Returned
337338

338339
function isActive(id: string) {
339-
return id === activeId.value
340+
return id === activeId.v
340341
}
341342

342343
function _setActive(id: string) {
343-
activeId.value = id
344-
isScrollFromClick.value = true
344+
activeId.v = id
345+
isScrollFromClick.v = true
345346
}
346347

347348
// Mount - Non-scroll listeners, targets and first highlight
@@ -352,7 +353,7 @@ export function useActive(
352353
// https://github.com/nuxt/content/issues/1799
353354
await new Promise((resolve) => setTimeout(resolve))
354355

355-
if (matchMedia.value) {
356+
if (matchMedia.v) {
356357
setTargets()
357358
setResizeObserver()
358359
setMountIdle()
@@ -386,7 +387,7 @@ export function useActive(
386387
onScrollDown()
387388
}
388389
} else {
389-
activeId.value = ''
390+
activeId.v = ''
390391
removeHashChangeListener()
391392
destroyResizeObserver()
392393
}
@@ -397,7 +398,7 @@ export function useActive(
397398
watch(
398399
[isScrollIdle, matchMedia, root, userIds],
399400
([_isScrollIdle, _matchMedia, _root, _userIds], _, onCleanup) => {
400-
const rootEl = isWindow.value ? document : _root
401+
const rootEl = isWindow.v ? document : _root
401402
const isActive = rootEl && _isScrollIdle && _matchMedia && unref(_userIds)?.length > 0
402403

403404
if (isActive) {
@@ -419,7 +420,7 @@ export function useActive(
419420
watch(
420421
isScrollFromClick,
421422
(_isScrollFromClick, _, onCleanup) => {
422-
const rootEl = isWindow.value ? document : root.value
423+
const rootEl = isWindow.v ? document : root.v
423424
const hasTargets = unref(userIds)?.length > 0
424425

425426
if (_isScrollFromClick && hasTargets) {
@@ -450,7 +451,7 @@ export function useActive(
450451
watch(activeId, (newId) => {
451452
if (replaceHash) {
452453
const start = jumpToFirst ? 0 : -1
453-
const newHash = `${location.pathname}${activeIndex.value > start ? `#${newId}` : ''}`
454+
const newHash = `${location.pathname}${activeIndex.v > start ? `#${newId}` : ''}`
454455
history.replaceState(history.state, '', newHash)
455456
}
456457
})

0 commit comments

Comments
 (0)