mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2026-07-23 22:33:42 -04:00
Improved flow of observables/emissions
This commit is contained in:
@@ -93,9 +93,11 @@ export function watchViewport(): Observable<Viewport> {
|
||||
export function watchViewportAt(
|
||||
el: HTMLElement, { header$, viewport$ }: WatchAtOptions
|
||||
): Observable<Viewport> {
|
||||
const offset$ = viewport$
|
||||
const offset$ = combineLatest([
|
||||
viewport$.pipe(distinctUntilKeyChanged("size")),
|
||||
header$
|
||||
])
|
||||
.pipe(
|
||||
distinctUntilKeyChanged("size"),
|
||||
map((): ViewportOffset => ({
|
||||
x: el.offsetLeft,
|
||||
y: el.offsetTop
|
||||
|
||||
@@ -92,7 +92,7 @@ export function mountHeader(
|
||||
): OperatorFunction<HTMLElement, Header> {
|
||||
return pipe(
|
||||
switchMap(el => {
|
||||
const header$ = watchHeader(el, { viewport$ })
|
||||
const header$ = watchHeader(el)
|
||||
|
||||
/* Compute whether the header should switch to page header */
|
||||
const type$ = useComponent("main")
|
||||
|
||||
@@ -28,14 +28,14 @@ import {
|
||||
pipe
|
||||
} from "rxjs"
|
||||
import {
|
||||
distinctUntilKeyChanged,
|
||||
finalize,
|
||||
map,
|
||||
observeOn,
|
||||
switchMap,
|
||||
shareReplay,
|
||||
tap
|
||||
} from "rxjs/operators"
|
||||
|
||||
import { Viewport } from "browser"
|
||||
import { watchElementSize } from "browser"
|
||||
|
||||
import { Header, HeaderType } from "../_"
|
||||
import {
|
||||
@@ -43,17 +43,6 @@ import {
|
||||
setHeaderTitleActive
|
||||
} from "../set"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Helper types
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Watch options
|
||||
*/
|
||||
interface WatchOptions {
|
||||
viewport$: Observable<Viewport> /* Viewport observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
@@ -61,32 +50,32 @@ interface WatchOptions {
|
||||
/**
|
||||
* Watch header
|
||||
*
|
||||
* The header is wrapped in an observable to pave the way for auto-hiding or
|
||||
* other dynamic behaviors that may be implemented later on.
|
||||
*
|
||||
* @param el - Header element
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Header observable
|
||||
*/
|
||||
export function watchHeader(
|
||||
el: HTMLElement, { viewport$ }: WatchOptions
|
||||
el: HTMLElement
|
||||
): Observable<Omit<Header, "type">> {
|
||||
return viewport$
|
||||
.pipe(
|
||||
distinctUntilKeyChanged("size"),
|
||||
switchMap(() => {
|
||||
const styles = getComputedStyle(el)
|
||||
const sticky = [
|
||||
"sticky", /* Modern browsers */
|
||||
"-webkit-sticky" /* Safari */
|
||||
].includes(styles.position)
|
||||
return of({
|
||||
sticky,
|
||||
height: sticky ? el.offsetHeight : 0
|
||||
})
|
||||
})
|
||||
)
|
||||
const styles = getComputedStyle(el)
|
||||
if ([
|
||||
"sticky", /* Modern browsers */
|
||||
"-webkit-sticky" /* Safari */
|
||||
].includes(styles.position)) {
|
||||
return watchElementSize(el)
|
||||
.pipe(
|
||||
map(({ height }) => ({
|
||||
sticky: true,
|
||||
height
|
||||
})),
|
||||
shareReplay(1)
|
||||
)
|
||||
} else {
|
||||
return of({
|
||||
sticky: false,
|
||||
height: 0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
@@ -29,11 +29,13 @@ import {
|
||||
} from "rxjs"
|
||||
import {
|
||||
distinctUntilChanged,
|
||||
distinctUntilKeyChanged,
|
||||
finalize,
|
||||
map,
|
||||
observeOn,
|
||||
pluck,
|
||||
shareReplay,
|
||||
switchMap,
|
||||
tap
|
||||
} from "rxjs/operators"
|
||||
|
||||
@@ -81,17 +83,23 @@ export function watchMain(
|
||||
/* Compute necessary adjustment for header */
|
||||
const adjust$ = header$
|
||||
.pipe(
|
||||
pluck("height")
|
||||
pluck("height"),
|
||||
distinctUntilChanged(),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
/* Compute the main area's top and bottom markers */
|
||||
const marker$ = watchElementSize(el)
|
||||
const marker$ = adjust$
|
||||
.pipe(
|
||||
map(({ height }) => ({
|
||||
top: el.offsetTop,
|
||||
bottom: el.offsetTop + height
|
||||
})),
|
||||
distinctUntilChanged(),
|
||||
switchMap(() => watchElementSize(el)
|
||||
.pipe(
|
||||
map(({ height }) => ({
|
||||
top: el.offsetTop,
|
||||
bottom: el.offsetTop + height
|
||||
}))
|
||||
)
|
||||
),
|
||||
distinctUntilKeyChanged("top"),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ import {
|
||||
Observable,
|
||||
animationFrameScheduler,
|
||||
combineLatest,
|
||||
of,
|
||||
pipe
|
||||
} from "rxjs"
|
||||
import {
|
||||
@@ -90,15 +89,13 @@ interface ApplyOptions {
|
||||
export function watchSidebar(
|
||||
el: HTMLElement, { main$, viewport$ }: WatchOptions
|
||||
): Observable<Sidebar> {
|
||||
const inner = el.parentElement!
|
||||
const outer = inner.parentElement!
|
||||
const adjust = el.parentElement!.offsetTop
|
||||
- el.parentElement!.parentElement!.offsetTop
|
||||
|
||||
/* Compute the sidebar's available height */
|
||||
const adjust$ = of(inner.offsetTop - outer.offsetTop)
|
||||
const height$ = viewport$
|
||||
const height$ = combineLatest([main$, viewport$])
|
||||
.pipe(
|
||||
withLatestFrom(adjust$, main$),
|
||||
map(([{ offset: { y } }, adjust, { offset, height }]) => (
|
||||
map(([{ offset, height }, { offset: { y } }]) => (
|
||||
height
|
||||
+ Math.min(adjust, Math.max(0, y - offset))
|
||||
- adjust
|
||||
@@ -107,12 +104,9 @@ export function watchSidebar(
|
||||
)
|
||||
|
||||
/* Compute whether the sidebar should be locked */
|
||||
const lock$ = viewport$
|
||||
const lock$ = combineLatest([main$, viewport$])
|
||||
.pipe(
|
||||
withLatestFrom(adjust$, main$),
|
||||
map(([{ offset: { y } }, adjust, { offset }]) => (
|
||||
y >= offset + adjust
|
||||
)),
|
||||
map(([{ offset }, { offset: { y } }]) => y >= offset + adjust),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user