Added prerequisites for instand loading

This commit is contained in:
squidfunk 2019-11-22 17:55:00 +01:00
parent 4fc4876fc8
commit f422c8f90e
5 changed files with 42 additions and 33 deletions

View File

@ -20,8 +20,9 @@
* IN THE SOFTWARE.
*/
import { keys } from "ramda"
import { MonoTypeOperatorFunction, Observable, of, pipe } from "rxjs"
import { scan, shareReplay, tap } from "rxjs/operators"
import { scan, shareReplay } from "rxjs/operators"
import { getElement } from "../../ui"
@ -40,10 +41,11 @@ export type Component =
| "reset" /* Search reset */
| "result" /* Search results */
| "container" /* Container */
| "main" /* Main area */
| "hero" /* Hero */
| "tabs" /* Tabs */
| "navigation" /* Navigation */
| "toc" /* Table of contents */
| "footer" /* Footer */
/**
* Component map
@ -79,10 +81,11 @@ export function watchComponentMap(
"reset", /* Search reset */
"result", /* Search results */
"container", /* Container */
"main", /* Main area */
"hero", /* Hero */
"tabs", /* Tabs */
"navigation", /* Navigation */
"toc", /* Table of contents */
"footer" /* Footer */
"toc" /* Table of contents */
].reduce<ComponentMap>((map, name) => {
const el = getElement(`[data-md-component=${name}]`, document)
return {
@ -104,21 +107,30 @@ export function watchComponentMap(
* Paint component map from source observable
*
* This operator function will swap the components in the previous component
* map with the new components identified by the given names.
* map with the new components identified by the given names and rebind all
* remaining components, as they may be children of swapped components.
*
* @param names - Components to paint
*
* @return Operator function
*/
export function paintComponentMap(
names: Component[] = ["title", "tabs", "container", "footer"]
names: Component[] = ["title", "container"]
): MonoTypeOperatorFunction<ComponentMap> {
return pipe(
scan<ComponentMap>((prev, next) => {
for (const name of names) {
if (name in prev && typeof prev[name] !== "undefined") {
prev[name]!.replaceWith(next[name]!)
prev[name] = next[name]
for (const name of keys(prev)) {
/* Swap component */
if (names.includes(name)) {
if (name in prev && typeof prev[name] !== "undefined") {
prev[name]!.replaceWith(next[name]!)
prev[name] = next[name]
}
/* Bind component */
} else {
prev[name] = getElement(`[data-md-component=${name}]`)
}
}
return prev

View File

@ -28,7 +28,7 @@ import {
tap
} from "rxjs/operators"
import { Container } from "../../container"
import { Main } from "../../main"
import {
resetHeaderShadow,
setHeaderShadow
@ -87,7 +87,7 @@ export function watchHeader(
*/
export function paintHeaderShadow(
el: HTMLElement
): MonoTypeOperatorFunction<Container> {
): MonoTypeOperatorFunction<Main> {
return pipe(
distinctUntilKeyChanged("active"),
tap(({ active }) => {

View File

@ -22,7 +22,7 @@
export * from "./_"
export * from "./anchor"
export * from "./container"
export * from "./header"
export * from "./main"
export * from "./navigation"
export * from "./sidebar"

View File

@ -36,11 +36,11 @@ import { Header } from "../header"
* ------------------------------------------------------------------------- */
/**
* Container
* Main area
*/
export interface Container {
offset: number /* Container top offset */
height: number /* Container visible height */
export interface Main {
offset: number /* Main area top offset */
height: number /* Main area visible height */
active: boolean /* Scrolled past top offset */
}
@ -62,19 +62,16 @@ interface WatchOptions {
* ------------------------------------------------------------------------- */
/**
* Create an observable to watch the container
* Create an observable to watch the main area
*
* The container represents the main content area including the sidebars (table
* of contents and navigation), as well as the actual page content.
*
* @param el - Container element
* @param el - Main area element
* @param options - Options
*
* @return Container observable
* @return Main area observable
*/
export function watchContainer(
export function watchMain(
el: HTMLElement, { size$, offset$, header$ }: WatchOptions
): Observable<Container> {
): Observable<Main> {
/* Compute necessary adjustment for header */
const adjust$ = header$
@ -82,7 +79,7 @@ export function watchContainer(
pluck("height")
)
/* Compute the container's visible height */
/* Compute the main area's visible height */
const height$ = combineLatest(offset$, size$, adjust$)
.pipe(
map(([{ y }, { height }, adjust]) => {
@ -95,7 +92,7 @@ export function watchContainer(
distinctUntilChanged()
)
/* Compute whether the viewport offset is past the container's top */
/* Compute whether the viewport offset is past the main area's top */
const active$ = combineLatest(offset$, adjust$)
.pipe(
map(([{ y }, adjust]) => y >= el.offsetTop - adjust),

View File

@ -38,7 +38,7 @@ import {
} from "rxjs/operators"
import { ViewportOffset } from "../../../ui"
import { Container } from "../../container"
import { Main } from "../../main"
import {
resetSidebarHeight,
resetSidebarLock,
@ -67,7 +67,7 @@ export interface Sidebar {
*/
interface WatchOptions {
offset$: Observable<ViewportOffset> /* Viewport offset observable */
container$: Observable<Container> /* Container observable */
main$: Observable<Main> /* Main area observable */
}
/* ----------------------------------------------------------------------------
@ -83,17 +83,17 @@ interface WatchOptions {
* @return Sidebar observable
*/
export function watchSidebar(
el: HTMLElement, { offset$, container$ }: WatchOptions
el: HTMLElement, { offset$, main$ }: WatchOptions
): Observable<Sidebar> {
/* Adjust for internal container offset */
/* Adjust for internal main area offset */
const adjust = parseFloat(
getComputedStyle(el.parentElement!)
.getPropertyValue("padding-top")
)
/* Compute the sidebar's available height */
const height$ = combineLatest(offset$, container$)
const height$ = combineLatest(offset$, main$)
.pipe(
map(([{ y }, { offset, height }]) => {
return height - adjust + Math.min(adjust, Math.max(0, y - offset))
@ -101,7 +101,7 @@ export function watchSidebar(
)
/* Compute whether the sidebar should be locked */
const lock$ = combineLatest(offset$, container$)
const lock$ = combineLatest(offset$, main$)
.pipe(
map(([{ y }, { offset }]) => y >= offset + adjust)
)