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

View File

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

View File

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

View File

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

View File

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