Fixed header shadow appearing after document switch

This commit is contained in:
squidfunk
2020-02-21 11:36:32 +01:00
parent ff627c69e0
commit 1020953fa5
13 changed files with 52 additions and 46 deletions

View File

@@ -85,7 +85,7 @@ let components$: Observable<ComponentMap>
* ------------------------------------------------------------------------- */
/**
* Setup bindings to elements with given names
* Setup bindings to components with given names
*
* This function will maintain bindings to the elements identified by the given
* names in-between document switches and update the elements in-place.

View File

@@ -45,7 +45,7 @@ interface MountOptions {
*
* @param options - Options
*
* @return Header observable
* @return Operator function
*/
export function mountHeader(
{ viewport$ }: MountOptions

View File

@@ -54,7 +54,7 @@ interface MountOptions {
*
* @param options - Options
*
* @return Header title observable
* @return Operator function
*/
export function mountHeaderTitle(
{ header$, viewport$ }: MountOptions

View File

@@ -62,7 +62,7 @@ interface MountOptions {
*
* @param options - Options
*
* @return Hero observable
* @return Operator function
*/
export function mountHero(
{ header$, viewport$ }: MountOptions

View File

@@ -20,8 +20,8 @@
* IN THE SOFTWARE.
*/
import { Observable, OperatorFunction, pipe } from "rxjs"
import { distinctUntilKeyChanged, switchMap } from "rxjs/operators"
import { Observable, OperatorFunction, Subject, pipe } from "rxjs"
import { distinctUntilKeyChanged, switchMap, tap } from "rxjs/operators"
import {
Header,
@@ -52,31 +52,35 @@ interface MountOptions {
/**
* Mount main area from source observable
*
* The header must be connected to the main area observable outside of the
* operator function, as the header will persist in-between document switches
* while the main area is replaced. However, the header observable must be
* passed to this function, so we connect both via a long-living subject.
*
* @param options - Options
*
* @return Main area observable
* @return Operator function
*/
export function mountMain(
{ header$, viewport$ }: MountOptions
): OperatorFunction<HTMLElement, Main> {
return pipe(
switchMap(el => useComponent("header")
.pipe(
switchMap(header => {
const main$ = watchMain(el, { header$, viewport$ })
const main$ = new Subject<Main>()
/* Paint header shadow */
main$
.pipe(
distinctUntilKeyChanged("active"),
paintHeaderShadow(header)
)
.subscribe()
/* Return main area */
return main$
})
/* Connect to main area observable via long-living subject */
useComponent("header")
.pipe(
switchMap(header => main$
.pipe(
distinctUntilKeyChanged("active"),
paintHeaderShadow(header)
)
)
)
.subscribe()
/* Return operator */
return pipe(
switchMap(el => watchMain(el, { header$, viewport$ })),
tap(main => main$.next(main))
)
}

View File

@@ -60,7 +60,7 @@ interface MountOptions {
*
* @param options - Options
*
* @return Search observable
* @return Operator function
*/
export function mountSearch(
{ query$, reset$, result$ }: MountOptions
@@ -69,6 +69,7 @@ export function mountSearch(
switchMap(() => combineLatest([query$, result$, reset$])
.pipe(
map(([query, result]) => ({ query, result }))
))
)
)
)
}

View File

@@ -63,7 +63,7 @@ interface MountOptions {
*
* @param options - Options
*
* @return Tabs observable
* @return Operator function
*/
export function mountTabs(
{ header$, viewport$, screen$ }: MountOptions

View File

@@ -114,22 +114,17 @@ export function initialize(config: unknown) {
if (!isConfig(config))
throw new SyntaxError(`Invalid configuration: ${JSON.stringify(config)}`)
/* Setup user interface observables */
const location$ = watchLocation()
const document$ = watchDocument(
config.feature.instant ? { location$ } : {}
)
const hash$ = watchLocationHash()
const hash$ = watchLocationHash()
const viewport$ = watchViewport()
const tablet$ = watchMedia("(min-width: 960px)")
const screen$ = watchMedia("(min-width: 1220px)")
const tablet$ = watchMedia("(min-width: 960px)")
const screen$ = watchMedia("(min-width: 1220px)")
/* ----------------------------------------------------------------------- */
const worker = setupSearchWorker(config.worker.search, {
base: config.base
})
/* ----------------------------------------------------------------------- */
/* Setup document observable */
const document$ = config.feature.instant
? watchDocument({ location$ })
: watchDocument()
/* Setup toggle bindings */
setupToggles([
@@ -137,7 +132,7 @@ export function initialize(config: unknown) {
"search" /* Toggle for search */
], { document$ })
/* Setup components bindings */
/* Setup component bindings */
setupComponents([
"container", /* Container */
"header", /* Header */
@@ -155,6 +150,12 @@ export function initialize(config: unknown) {
/* ----------------------------------------------------------------------- */
const worker = setupSearchWorker(config.worker.search, {
base: config.base
})
/* ----------------------------------------------------------------------- */
/* Create header observable */
const header$ = useComponent("header")
.pipe(