Fixed observable completion semantics

This commit is contained in:
squidfunk
2021-11-28 14:54:14 +01:00
parent abe475e151
commit c30c3d196e
55 changed files with 493 additions and 1347 deletions

View File

@@ -23,7 +23,6 @@
import {
Observable,
Subject,
animationFrameScheduler,
bufferCount,
combineLatest,
defer,
@@ -31,7 +30,6 @@ import {
distinctUntilKeyChanged,
finalize,
map,
observeOn,
of,
scan,
startWith,
@@ -40,12 +38,6 @@ import {
} from "rxjs"
import { feature } from "~/_"
import {
resetAnchorActive,
resetAnchorState,
setAnchorActive,
setAnchorState
} from "~/actions"
import {
Viewport,
getElements,
@@ -253,52 +245,55 @@ export function watchTableOfContents(
export function mountTableOfContents(
el: HTMLElement, options: MountOptions
): Observable<Component<TableOfContents>> {
const internal$ = new Subject<TableOfContents>()
internal$
.pipe(
observeOn(animationFrameScheduler),
)
.subscribe(({ prev, next }) => {
return defer(() => {
const push$ = new Subject<TableOfContents>()
push$.subscribe(({ prev, next }) => {
/* Look forward */
for (const [anchor] of next) {
resetAnchorActive(anchor)
resetAnchorState(anchor)
}
/* Look forward */
for (const [anchor] of next) {
anchor.removeAttribute("data-md-state")
anchor.classList.remove(
"md-nav__link--active"
)
}
/* Look backward */
for (const [index, [anchor]] of prev.entries()) {
setAnchorActive(anchor, index === prev.length - 1)
setAnchorState(anchor, "blur")
}
/* Look backward */
for (const [index, [anchor]] of prev.entries()) {
anchor.setAttribute("data-md-state", "blur")
anchor.classList.toggle(
"md-nav__link--active",
index === prev.length - 1
)
}
/* Set up anchor tracking, if enabled */
if (feature("navigation.tracking")) {
const url = getLocation()
/* Set up anchor tracking, if enabled */
if (feature("navigation.tracking")) {
const url = getLocation()
/* Set hash fragment to active anchor */
const anchor = prev[prev.length - 1]
if (anchor && anchor.length) {
const [active] = anchor
const { hash } = new URL(active.href)
if (url.hash !== hash) {
url.hash = hash
history.replaceState({}, "", `${url}`)
}
/* Reset anchor when at the top */
} else {
url.hash = ""
/* Set hash fragment to active anchor */
const anchor = prev[prev.length - 1]
if (anchor && anchor.length) {
const [active] = anchor
const { hash } = new URL(active.href)
if (url.hash !== hash) {
url.hash = hash
history.replaceState({}, "", `${url}`)
}
}
})
/* Create and return component */
return watchTableOfContents(el, options)
.pipe(
tap(state => internal$.next(state)),
finalize(() => internal$.complete()),
map(state => ({ ref: el, ...state }))
)
/* Reset anchor when at the top */
} else {
url.hash = ""
history.replaceState({}, "", `${url}`)
}
}
})
/* Create and return component */
return watchTableOfContents(el, options)
.pipe(
tap(state => push$.next(state)),
finalize(() => push$.complete()),
map(state => ({ ref: el, ...state }))
)
})
}