mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2025-02-25 21:58:40 +01:00
Fixed unmapped components
This commit is contained in:
parent
37b3870133
commit
f39c9f9e68
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -104,7 +104,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
||||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
||||||
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
|
<label class="md-overlay" for="__drawer"></label>
|
||||||
{% if page.toc | first is defined %}
|
{% if page.toc | first is defined %}
|
||||||
<a href="{{ (page.toc | first).url }}" tabindex="1" class="md-skip">
|
<a href="{{ (page.toc | first).url }}" tabindex="1" class="md-skip">
|
||||||
{{ lang.t('skip.link.title') }}
|
{{ lang.t('skip.link.title') }}
|
||||||
|
@ -101,7 +101,7 @@ export function watchComponentMap(
|
|||||||
switch (name) {
|
switch (name) {
|
||||||
|
|
||||||
/* Top-level components: update */
|
/* Top-level components: update */
|
||||||
case "title":
|
case "header-title":
|
||||||
case "container":
|
case "container":
|
||||||
if (name in prev && typeof prev[name] !== "undefined") {
|
if (name in prev && typeof prev[name] !== "undefined") {
|
||||||
prev[name]!.replaceWith(next[name]!)
|
prev[name]!.replaceWith(next[name]!)
|
||||||
|
@ -20,66 +20,56 @@
|
|||||||
* IN THE SOFTWARE.
|
* IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: remove this later on
|
// TODO: remove this after we finished refactoring
|
||||||
|
|
||||||
// tslint:disable
|
// tslint:disable
|
||||||
|
|
||||||
import { identity } from "ramda"
|
import { identity, values } from "ramda"
|
||||||
import {
|
import {
|
||||||
EMPTY,
|
EMPTY,
|
||||||
MonoTypeOperatorFunction,
|
|
||||||
NEVER,
|
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
defer,
|
|
||||||
forkJoin,
|
forkJoin,
|
||||||
fromEvent,
|
|
||||||
merge,
|
merge,
|
||||||
of,
|
of
|
||||||
pipe,
|
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
import { ajax } from "rxjs/ajax"
|
||||||
import {
|
import {
|
||||||
combineAll,
|
|
||||||
delay,
|
delay,
|
||||||
distinctUntilKeyChanged,
|
|
||||||
filter,
|
filter,
|
||||||
map,
|
map,
|
||||||
pluck,
|
pluck,
|
||||||
shareReplay,
|
|
||||||
switchMap,
|
switchMap,
|
||||||
switchMapTo,
|
switchMapTo,
|
||||||
take,
|
take,
|
||||||
tap,
|
tap,
|
||||||
} from "rxjs/operators"
|
} from "rxjs/operators"
|
||||||
|
|
||||||
import {} from "components"
|
|
||||||
import { AjaxResponse, ajax } from "rxjs/ajax"
|
|
||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
paintHeaderShadow,
|
paintHeaderShadow,
|
||||||
setupHero,
|
mountHero,
|
||||||
setupMain,
|
mountMain,
|
||||||
setupNavigation,
|
mountNavigation,
|
||||||
setupSearchResult,
|
mountSearchResult,
|
||||||
|
mountTableOfContents,
|
||||||
|
mountTabs,
|
||||||
switchComponent,
|
switchComponent,
|
||||||
watchComponentMap,
|
watchComponentMap,
|
||||||
watchHeader,
|
watchHeader,
|
||||||
watchSearchReset,
|
watchSearchQuery,
|
||||||
|
watchSearchReset
|
||||||
} from "./components"
|
} from "./components"
|
||||||
import { SearchIndex, SearchResult } from "./modules/search"
|
import { SearchIndexOptions } from "./modules"
|
||||||
import {
|
import {
|
||||||
getElement,
|
getElement,
|
||||||
setupAgent,
|
setupAgent,
|
||||||
watchDocument,
|
|
||||||
watchLocation,
|
|
||||||
watchLocationHash,
|
|
||||||
watchMedia,
|
|
||||||
watchToggle,
|
watchToggle,
|
||||||
watchViewportOffset,
|
watchWorker,
|
||||||
watchViewportSize,
|
setToggle
|
||||||
watchWorker
|
|
||||||
} from "./utilities"
|
} from "./utilities"
|
||||||
import {
|
import {
|
||||||
|
PackerMessage,
|
||||||
|
PackerMessageType,
|
||||||
SearchMessage,
|
SearchMessage,
|
||||||
SearchMessageType,
|
SearchMessageType,
|
||||||
SearchSetupMessage,
|
SearchSetupMessage,
|
||||||
@ -87,73 +77,71 @@ import {
|
|||||||
isSearchResultMessage
|
isSearchResultMessage
|
||||||
} from "./workers"
|
} from "./workers"
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Types
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration
|
* Configuration
|
||||||
*/
|
*/
|
||||||
export interface Config {
|
export interface Config {
|
||||||
base: string /* Base URL */
|
base: string /* Base URL */
|
||||||
worker: {
|
worker: {
|
||||||
search: string /* Web worker URL */
|
search: string /* Search worker URL */
|
||||||
packer: string /* Web worker URL */
|
packer: string /* Packer worker URL */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
import {
|
/* ----------------------------------------------------------------------------
|
||||||
PackerMessage,
|
* TODO: where do we put this stuff?
|
||||||
PackerMessageType
|
* ------------------------------------------------------------------------- */
|
||||||
} from "./workers/packer"
|
|
||||||
|
|
||||||
import { setupTabs } from "components/tabs"
|
document.documentElement.classList.remove("no-js")
|
||||||
import { setupTableOfContents } from "components/toc/_"
|
document.documentElement.classList.add("js")
|
||||||
|
|
||||||
|
const names: Component[] = [
|
||||||
|
"container", /* Container */
|
||||||
|
"header", /* Header */
|
||||||
|
"header-title", /* Header title */
|
||||||
|
"hero", /* Hero */
|
||||||
|
"main", /* Main area */
|
||||||
|
"navigation", /* Navigation */
|
||||||
|
"search", /* Search */
|
||||||
|
"search-query", /* Search input */
|
||||||
|
"search-reset", /* Search reset */
|
||||||
|
"search-result", /* Search results */
|
||||||
|
"tabs", /* Tabs */
|
||||||
|
"toc" /* Table of contents */
|
||||||
|
]
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Functions
|
* Helper functions
|
||||||
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that the given value is a valid configuration
|
* Ensure that the given value is a valid configuration
|
||||||
*
|
*
|
||||||
|
* We could use `jsonschema` or any other schema validation framework, but that
|
||||||
|
* would just add more bloat to the bundle, so we'll keep it plain and simple.
|
||||||
|
*
|
||||||
* @param config - Configuration
|
* @param config - Configuration
|
||||||
*
|
*
|
||||||
* @return Test result
|
* @return Test result
|
||||||
*/
|
*/
|
||||||
export function isConfig(config: any): config is Config {
|
function isConfig(config: any): config is Config {
|
||||||
return typeof config === "object"
|
return typeof config === "object"
|
||||||
&& typeof config.base === "string"
|
&& typeof config.base === "string"
|
||||||
|
&& typeof config.worker === "object"
|
||||||
|
&& typeof config.worker.search === "string"
|
||||||
|
&& typeof config.worker.packer === "string"
|
||||||
}
|
}
|
||||||
|
|
||||||
// TBD
|
|
||||||
|
|
||||||
// TODO: put this somewhere else... (merge with config!) JSON schema!?
|
|
||||||
const names: Component[] = [
|
|
||||||
"header", /* Header */
|
|
||||||
"title", /* Header title */
|
|
||||||
"search", /* Search */
|
|
||||||
"query", /* Search input */
|
|
||||||
"reset", /* Search reset */
|
|
||||||
"result", /* Search results */
|
|
||||||
"container", /* Container */
|
|
||||||
"main", /* Main area */
|
|
||||||
"hero", /* Hero */
|
|
||||||
"tabs", /* Tabs */
|
|
||||||
"navigation", /* Navigation */
|
|
||||||
"toc" /* Table of contents */
|
|
||||||
]
|
|
||||||
|
|
||||||
// modernizr for the poor
|
|
||||||
document.documentElement.classList.remove("no-js")
|
|
||||||
document.documentElement.classList.add("js")
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Rogue control characters must be filtered before handing the query to the
|
* Rogue control characters must be filtered before handing the query to the
|
||||||
* search index, as lunr will throw otherwise.
|
* search index, as lunr will throw otherwise.
|
||||||
*/
|
*/
|
||||||
function prepareQuery(value: string): string {
|
function prepare(value: string): string {
|
||||||
const newvalue = value
|
const newvalue = value
|
||||||
.replace(/(?:^|\s+)[*+-:^~]+(?=\s+|$)/g, "")
|
.replace(/(?:^|\s+)[*+-:^~]+(?=\s+|$)/g, "")
|
||||||
.trim()
|
.trim()
|
||||||
@ -161,29 +149,17 @@ function prepareQuery(value: string): string {
|
|||||||
return newvalue ? newvalue.replace(/\s+|$/g, "* ") : ""
|
return newvalue ? newvalue.replace(/\s+|$/g, "* ") : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function setupWorkers(config: Config) {
|
||||||
* Initialize Material for MkDocs
|
|
||||||
*
|
|
||||||
* @param config - Configuration
|
|
||||||
*/
|
|
||||||
export function initialize(config: unknown) {
|
|
||||||
if (!isConfig(config))
|
|
||||||
throw new SyntaxError(`Invalid configuration: ${JSON.stringify(config)}`)
|
|
||||||
|
|
||||||
const agent = setupAgent()
|
|
||||||
|
|
||||||
const worker = new Worker(config.worker.search)
|
const worker = new Worker(config.worker.search)
|
||||||
const packer = new Worker(config.worker.packer)
|
const packer = new Worker(config.worker.packer)
|
||||||
|
|
||||||
// const query = message.data.trim().replace(/\s+|$/g, "* ") // TODO: do this outside of the worker
|
|
||||||
|
|
||||||
const packerMessage$ = new Subject<PackerMessage>()
|
const packerMessage$ = new Subject<PackerMessage>()
|
||||||
const packer$ = watchWorker(packer, { send$: packerMessage$ })
|
const packer$ = watchWorker(packer, { send$: packerMessage$ })
|
||||||
|
|
||||||
// send a message, then switchMapTo worker!
|
// send a message, then switchMapTo worker!
|
||||||
|
|
||||||
packer$.subscribe(message => {
|
packer$.subscribe(message => {
|
||||||
console.log("PACKER.MSG", message.data.length)
|
// console.log("PACKER.MSG", message.data.length)
|
||||||
// is always packed!
|
// is always packed!
|
||||||
if (message.type === PackerMessageType.BINARY && message.data[0] !== "{")
|
if (message.type === PackerMessageType.BINARY && message.data[0] !== "{")
|
||||||
localStorage.setItem("index", message.data)
|
localStorage.setItem("index", message.data)
|
||||||
@ -195,25 +171,6 @@ export function initialize(config: unknown) {
|
|||||||
|
|
||||||
const search$ = watchWorker(worker, { send$: searchMessage$ })
|
const search$ = watchWorker(worker, { send$: searchMessage$ })
|
||||||
|
|
||||||
// paintSearchResult <-- must paint META AND LIST!
|
|
||||||
// list must be painted based on scroll offset...
|
|
||||||
|
|
||||||
/* Render search results */
|
|
||||||
// search$
|
|
||||||
// .pipe(
|
|
||||||
// filter(isSearchResultMessage),
|
|
||||||
// pluck("data")
|
|
||||||
// )
|
|
||||||
// .subscribe(result => {
|
|
||||||
// const list = getElement(".md-search-result__list")!
|
|
||||||
// list.innerHTML = ""
|
|
||||||
// for (const el of result.map(renderSearchResult)) // TODO: perform entire lazy render!!!!
|
|
||||||
// list.appendChild(el)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// scroll!
|
|
||||||
// watchSearchResult
|
|
||||||
|
|
||||||
/* Link search to packer */
|
/* Link search to packer */
|
||||||
search$
|
search$
|
||||||
.pipe(
|
.pipe(
|
||||||
@ -232,7 +189,7 @@ export function initialize(config: unknown) {
|
|||||||
responseType: "json",
|
responseType: "json",
|
||||||
withCredentials: true
|
withCredentials: true
|
||||||
})
|
})
|
||||||
.pipe<SearchIndex>(
|
.pipe<SearchIndexOptions>(
|
||||||
pluck("response")
|
pluck("response")
|
||||||
// take(1)
|
// take(1)
|
||||||
)
|
)
|
||||||
@ -264,48 +221,34 @@ export function initialize(config: unknown) {
|
|||||||
searchMessage$.next(message) // TODO: this shall not complete
|
searchMessage$.next(message) // TODO: this shall not complete
|
||||||
})
|
})
|
||||||
|
|
||||||
// filter singular "+" or "-",as it will result in a lunr.js error
|
return [search$, searchMessage$] as const
|
||||||
|
}
|
||||||
|
|
||||||
// data$
|
/* ----------------------------------------------------------------------------
|
||||||
// .pipe(
|
* Functions
|
||||||
// map<SearchIndex, SearchMessage>(data => ({
|
* ------------------------------------------------------------------------- */
|
||||||
// type: SearchMessageType.SETUP,
|
|
||||||
// data
|
|
||||||
// }))
|
|
||||||
// )
|
|
||||||
// .subscribe(message => {
|
|
||||||
// searchMessage$.next(message) // TODO: this shall not complete
|
|
||||||
// })
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/**
|
||||||
|
* Initialize Material for MkDocs
|
||||||
|
*
|
||||||
|
* @param config - Configuration
|
||||||
|
*/
|
||||||
|
export function initialize(config: unknown) {
|
||||||
|
if (!isConfig(config))
|
||||||
|
throw new SyntaxError(`Invalid configuration: ${JSON.stringify(config)}`)
|
||||||
|
|
||||||
/* Create viewport observables */
|
// pass config here!?
|
||||||
const offset$ = watchViewportOffset()
|
const agent = setupAgent() // TODO: add a config parameter here to configure media queries
|
||||||
const size$ = watchViewportSize()
|
|
||||||
|
|
||||||
/* Create media observables */
|
const [
|
||||||
const screen$ = watchMedia("(min-width: 1220px)")
|
searchWorkerRecv$,
|
||||||
const tablet$ = watchMedia("(min-width: 960px)")
|
searchMessage$
|
||||||
|
] = setupWorkers(config)
|
||||||
/* Create location observables */
|
|
||||||
const location$ = watchLocation()
|
|
||||||
const fragment$ = watchLocationHash()
|
|
||||||
|
|
||||||
/* Create document observables */
|
|
||||||
const load$ = watchDocument()
|
|
||||||
|
|
||||||
// Complete set of AgentObservables...
|
|
||||||
|
|
||||||
// component map!
|
|
||||||
//
|
|
||||||
|
|
||||||
// const switch$ = watchDocumentSwitch({ location$ })
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* Create component map observable */
|
/* Create component map observable */
|
||||||
const components$ = watchComponentMap(names, { document$: load$ })
|
const components$ = watchComponentMap(names, { document$: agent.document.load$ })
|
||||||
|
|
||||||
const component = <T extends HTMLElement>(name: Component): Observable<T> => {
|
const component = <T extends HTMLElement>(name: Component): Observable<T> => {
|
||||||
return components$
|
return components$
|
||||||
.pipe(
|
.pipe(
|
||||||
@ -319,233 +262,136 @@ export function initialize(config: unknown) {
|
|||||||
switchMap(watchHeader)
|
switchMap(watchHeader)
|
||||||
)
|
)
|
||||||
|
|
||||||
// DONE
|
|
||||||
const main$ = component("main")
|
|
||||||
.pipe(
|
|
||||||
setupMain(agent, { header$ })
|
|
||||||
)
|
|
||||||
|
|
||||||
// setupHeader(agent) ??
|
|
||||||
|
|
||||||
// setupSearch
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
/* Create header shadow toggle */
|
/* Create header shadow toggle */
|
||||||
component("header")
|
component("header")
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(el => main$
|
switchMap(el => main$
|
||||||
.pipe(
|
.pipe(
|
||||||
paintHeaderShadow(el)
|
paintHeaderShadow(el) // technically, this could be done in paintMain
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.subscribe()
|
.subscribe()
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// watchSearchResult // emit, if at bottom...
|
// watchSearchResult // emit, if at bottom...
|
||||||
// receive results as a second observable!? filter stuff, paint
|
// receive results as a second observable!? filter stuff, paint
|
||||||
|
|
||||||
const result$ = search$
|
const result$ = searchWorkerRecv$ // move worker initialization into mountSearch ?
|
||||||
.pipe(
|
.pipe(
|
||||||
|
tap(m => console.log("message from worker", m)),
|
||||||
filter(isSearchResultMessage),
|
filter(isSearchResultMessage),
|
||||||
pluck("data")
|
pluck("data")
|
||||||
)
|
)
|
||||||
|
|
||||||
const query$ = component<HTMLInputElement>("query")
|
// handleSearchResult <-- operator
|
||||||
|
|
||||||
|
const query$ = component<HTMLInputElement>("search-query")
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(el => fromEvent(el, "keyup")
|
switchMap(el => watchSearchQuery(el, { prepare }))
|
||||||
.pipe(
|
|
||||||
map(() => prepareQuery(el.value))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DONE
|
query$
|
||||||
component("result")
|
.pipe<SearchMessage>(
|
||||||
.pipe(
|
map(query => ({ // put this into some function...
|
||||||
setupSearchResult(agent, { result$, query$ })
|
type: SearchMessageType.QUERY,
|
||||||
|
data: query.value
|
||||||
|
})), // TODO. ugly...
|
||||||
|
// distinctUntilKeyChanged("data")
|
||||||
)
|
)
|
||||||
.subscribe()
|
.subscribe(searchMessage$)
|
||||||
|
|
||||||
|
// create the message subject internally... and link it to the worker...?
|
||||||
|
// watchSearchWorker(worker, agent, { query$ }) // message internally...
|
||||||
|
|
||||||
query$
|
query$
|
||||||
.pipe(
|
.pipe(
|
||||||
map(data => ({ // put this into some function...
|
tap(query => {
|
||||||
type: SearchMessageType.QUERY,
|
if (query.focus)
|
||||||
data
|
setToggle(search, true)
|
||||||
})), // TODO. ugly...
|
|
||||||
distinctUntilKeyChanged("data")
|
|
||||||
)
|
|
||||||
|
|
||||||
.subscribe(x => {
|
|
||||||
searchMessage$.next(x as any) // TODO
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Focus on search input
|
|
||||||
component("query")
|
|
||||||
.pipe(
|
|
||||||
switchMap(el => fromEvent(el, "focus")
|
|
||||||
.pipe(
|
|
||||||
tap(() => {
|
|
||||||
if (!search.checked)
|
|
||||||
search.click() // move this inside the search query stuff? not important...
|
|
||||||
})
|
|
||||||
)
|
|
||||||
) // not super nice...
|
|
||||||
)
|
)
|
||||||
.subscribe()
|
.subscribe()
|
||||||
|
|
||||||
// // WIP: instant loading
|
|
||||||
// load$
|
|
||||||
// .pipe(
|
|
||||||
// switchMap(({ body }) => fromEvent(body, "click")),
|
|
||||||
// switchMap(ev => {
|
|
||||||
// if (ev.target instanceof HTMLElement) {
|
|
||||||
// const el = ev.target.closest("a") || undefined
|
|
||||||
// if (el) {
|
|
||||||
// if (!/^(https?:|#)/.test(el.getAttribute("href")!)) {
|
|
||||||
// ev.preventDefault()
|
|
||||||
// }
|
|
||||||
// const href = el.href
|
|
||||||
// history.pushState({}, "", href) // TODO: reference necessary!?
|
|
||||||
// return of(href)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return EMPTY
|
|
||||||
// })
|
|
||||||
|
|
||||||
// // try to reduce the jiggle upon instant page load. ideally, the location
|
|
||||||
// // should directly be resolved and the respective document loaded, but
|
|
||||||
// // we must scroll to the top at first and wait at least 250ms.
|
|
||||||
// //
|
|
||||||
// // Furthermore, this doesn't include the back/next buttons of the browser
|
|
||||||
// // which must be delayed
|
|
||||||
// // tap(url => {
|
|
||||||
// // if (!/#/.test(url))
|
|
||||||
// // scrollTo({ top: 0 })
|
|
||||||
// // }) // only when loading something we havent loaded!
|
|
||||||
// // delay(250)
|
|
||||||
// )
|
|
||||||
// .subscribe(location$)
|
|
||||||
|
|
||||||
// location$.subscribe(x => {
|
|
||||||
// console.log("L", x)
|
|
||||||
// })
|
|
||||||
// switch$.subscribe(x => {
|
|
||||||
// console.log("S", x)
|
|
||||||
// })
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
component("navigation")
|
const main$ = component("main")
|
||||||
.pipe(
|
.pipe(
|
||||||
setupNavigation(agent, { main$ })
|
mountMain(agent, { header$ })
|
||||||
)
|
)
|
||||||
.subscribe()
|
|
||||||
|
|
||||||
component("toc")
|
const navigation$ = component("navigation")
|
||||||
.pipe(
|
.pipe(
|
||||||
setupTableOfContents(agent, { header$, main$ })
|
mountNavigation(agent, { main$ })
|
||||||
)
|
)
|
||||||
.subscribe()
|
|
||||||
|
|
||||||
component("tabs")
|
const toc$ = component("toc")
|
||||||
.pipe(
|
.pipe(
|
||||||
setupTabs(agent, { header$ })
|
mountTableOfContents(agent, { header$, main$ })
|
||||||
)
|
)
|
||||||
.subscribe()
|
|
||||||
|
|
||||||
component("hero")
|
// TODO: naming?
|
||||||
|
const resultComponent$ = component("search-result")
|
||||||
.pipe(
|
.pipe(
|
||||||
setupHero(agent, { header$ })
|
mountSearchResult(agent, { result$, query$: query$.pipe(pluck("value")) })
|
||||||
|
) // temporary fix
|
||||||
|
|
||||||
|
const tabs$ = component("tabs")
|
||||||
|
.pipe(
|
||||||
|
mountTabs(agent, { header$ })
|
||||||
)
|
)
|
||||||
.subscribe()
|
|
||||||
|
|
||||||
// /* Create header title toggle */
|
const hero$ = component("hero")
|
||||||
// component("main")
|
.pipe(
|
||||||
// .pipe(
|
mountHero(agent, { header$ })
|
||||||
// delay(1000), // initial delay
|
)
|
||||||
// switchMap(el => typeof getElement("h1", el) !== "undefined"
|
|
||||||
// ? watchBottomOffset(getElement("h1", el)!, { size$, offset$, header$ })
|
|
||||||
// .pipe(
|
|
||||||
// map(({ y }) => y >= 0),
|
|
||||||
// withLatestFrom(component("title")),
|
|
||||||
// tap(([active, title]) => {
|
|
||||||
// title.dataset.mdState = active ? "active" : ""
|
|
||||||
// })
|
|
||||||
// )
|
|
||||||
// : NEVER
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
// .subscribe()
|
|
||||||
|
|
||||||
// TODO: replace title as inner text
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
const drawer = getElement<HTMLInputElement>("[data-md-toggle=drawer]")!
|
const drawer = getElement<HTMLInputElement>("[data-md-toggle=drawer]")!
|
||||||
const search = getElement<HTMLInputElement>("[data-md-toggle=search]")!
|
const search = getElement<HTMLInputElement>("[data-md-toggle=search]")!
|
||||||
|
|
||||||
// watchToggle
|
|
||||||
|
|
||||||
// --> watchSearchQuery?
|
|
||||||
|
|
||||||
// watchSearch
|
|
||||||
// watchSearchReset
|
|
||||||
|
|
||||||
// toggles stay the same...
|
|
||||||
|
|
||||||
const a$ = watchToggle(search)
|
const a$ = watchToggle(search)
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(identity),
|
filter(identity),
|
||||||
delay(400)
|
delay(400)
|
||||||
)
|
)
|
||||||
|
|
||||||
// watchSearchReset()
|
const reset$ = component("search-reset")
|
||||||
|
|
||||||
const b$ = component("reset")
|
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(watchSearchReset)
|
switchMap(watchSearchReset)
|
||||||
)
|
)
|
||||||
|
|
||||||
function focusQuery(): MonoTypeOperatorFunction<HTMLElement> {
|
merge(a$, reset$)
|
||||||
return pipe(
|
|
||||||
tap(el => el.focus())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
merge(a$, b$)
|
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMapTo(component("query")),
|
switchMapTo(component<HTMLInputElement>("search-query")),
|
||||||
focusQuery()
|
tap(el => el.focus())
|
||||||
)
|
)
|
||||||
.subscribe()
|
.subscribe()
|
||||||
|
|
||||||
/* Wrap all data tables for better overflow scrolling */
|
/* ----------------------------------------------------------------------- */
|
||||||
// const tables = getElements<HTMLTableElement>("table:not([class])")
|
|
||||||
// tables.forEach(table => {
|
|
||||||
// console.log("x", table)
|
|
||||||
// table.parentNode!.insertBefore(renderTable(table), table)
|
|
||||||
// table.replaceWith(renderTable(table) as any)
|
|
||||||
// // table.parentElement!.replaceChild(, table)
|
|
||||||
// })
|
|
||||||
|
|
||||||
return {
|
const state = {
|
||||||
// agent, // agent.viewport.offset$
|
search: {
|
||||||
// component, // component.toc$
|
query$,
|
||||||
|
result$: resultComponent$,
|
||||||
|
reset$,
|
||||||
|
},
|
||||||
|
main$,
|
||||||
|
navigation$,
|
||||||
|
toc$,
|
||||||
|
tabs$,
|
||||||
|
hero$
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return observable factories */
|
const { search: temp, ...rest } = state
|
||||||
return {
|
merge(...values(rest), ...values(temp))
|
||||||
|
.subscribe() // potential memleak <-- use takeUntil
|
||||||
|
|
||||||
/* User interface */
|
return {
|
||||||
watchDocument: () => load$,
|
agent,
|
||||||
// watchDocumentSwitch: () => switch$,
|
state
|
||||||
watchLocation: () => location$,
|
|
||||||
watchLocationFragment: () => fragment$,
|
|
||||||
watchMediaScreen: () => screen$,
|
|
||||||
watchMediaTablet: () => tablet$,
|
|
||||||
watchViewportOffset: () => offset$,
|
|
||||||
watchViewportSize: () => size$
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,11 +238,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Overlay for expanded drawer -->
|
<!-- Overlay for expanded drawer -->
|
||||||
<label
|
<label class="md-overlay" for="__drawer"></label>
|
||||||
class="md-overlay"
|
|
||||||
data-md-component="overlay"
|
|
||||||
for="__drawer"
|
|
||||||
></label>
|
|
||||||
|
|
||||||
<!-- Link to skip to content -->
|
<!-- Link to skip to content -->
|
||||||
{% if page.toc | first is defined %}
|
{% if page.toc | first is defined %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user