mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-06-14 11:52:32 +03:00
Added support for variable sized header
This commit is contained in:
parent
a6bc272778
commit
b0ebcc8d5b
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
material/assets/javascripts/bundle.7cbaf05d.min.js.map
Normal file
1
material/assets/javascripts/bundle.7cbaf05d.min.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"assets/javascripts/bundle.js": "assets/javascripts/bundle.4a3df536.min.js",
|
||||
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.4a3df536.min.js.map",
|
||||
"assets/javascripts/bundle.js": "assets/javascripts/bundle.7cbaf05d.min.js",
|
||||
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.7cbaf05d.min.js.map",
|
||||
"assets/javascripts/worker/packer.js": "assets/javascripts/worker/packer.c14659e8.min.js",
|
||||
"assets/javascripts/worker/packer.js.map": "assets/javascripts/worker/packer.c14659e8.min.js.map",
|
||||
"assets/javascripts/worker/search.js": "assets/javascripts/worker/search.0a5433f7.min.js",
|
||||
|
@ -190,7 +190,7 @@
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% block scripts %}
|
||||
<script src="{{ 'assets/javascripts/bundle.4a3df536.min.js' | url }}"></script>
|
||||
<script src="{{ 'assets/javascripts/bundle.7cbaf05d.min.js' | url }}"></script>
|
||||
<script id="__lang" type="application/json">
|
||||
{%- set translations = {} -%}
|
||||
{%- for key in [
|
||||
|
@ -24,6 +24,31 @@
|
||||
* Functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Set sidebar offset
|
||||
*
|
||||
* @param el - Sidebar element
|
||||
* @param value - Sidebar offset
|
||||
*/
|
||||
export function setSidebarOffset(
|
||||
el: HTMLElement, value: number
|
||||
): void {
|
||||
el.style.top = `${value}px`
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset sidebar offset
|
||||
*
|
||||
* @param el - Sidebar element
|
||||
*/
|
||||
export function resetSidebarOffset(
|
||||
el: HTMLElement
|
||||
): void {
|
||||
el.style.top = ""
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Set sidebar height
|
||||
*
|
||||
|
@ -24,6 +24,7 @@ import { Observable, OperatorFunction, pipe } from "rxjs"
|
||||
import { map, shareReplay, switchMap } from "rxjs/operators"
|
||||
|
||||
import {
|
||||
Header,
|
||||
Main,
|
||||
NavigationLayer,
|
||||
Sidebar,
|
||||
@ -70,6 +71,7 @@ export type Navigation =
|
||||
* Mount options
|
||||
*/
|
||||
interface MountOptions {
|
||||
header$: Observable<Header> /* Header observable */
|
||||
main$: Observable<Main> /* Main area observable */
|
||||
viewport$: Observable<Viewport> /* Viewport observable */
|
||||
screen$: Observable<boolean> /* Screen media observable */
|
||||
@ -87,7 +89,7 @@ interface MountOptions {
|
||||
* @return Operator function
|
||||
*/
|
||||
export function mountNavigation(
|
||||
{ main$, viewport$, screen$ }: MountOptions
|
||||
{ header$, main$, viewport$, screen$ }: MountOptions
|
||||
): OperatorFunction<HTMLElement, Navigation> {
|
||||
return pipe(
|
||||
switchMap(el => screen$
|
||||
@ -98,7 +100,7 @@ export function mountNavigation(
|
||||
if (screen) {
|
||||
return watchSidebar(el, { main$, viewport$ })
|
||||
.pipe(
|
||||
paintSidebar(el),
|
||||
paintSidebar(el, { header$ }),
|
||||
map(sidebar => ({ sidebar }))
|
||||
)
|
||||
|
||||
|
@ -108,7 +108,7 @@ export function mountTableOfContents(
|
||||
/* Watch and paint sidebar */
|
||||
const sidebar$ = watchSidebar(el, { main$, viewport$ })
|
||||
.pipe(
|
||||
paintSidebar(el)
|
||||
paintSidebar(el, { header$ })
|
||||
)
|
||||
|
||||
/* Watch and paint anchor list (scroll spy) */
|
||||
|
@ -161,7 +161,7 @@ export function initialize(config: unknown) {
|
||||
|
||||
const navigation$ = useComponent("navigation")
|
||||
.pipe(
|
||||
mountNavigation({ main$, viewport$, screen$ })
|
||||
mountNavigation({ header$, main$, viewport$, screen$ })
|
||||
)
|
||||
|
||||
const toc$ = useComponent("toc")
|
||||
|
@ -88,9 +88,9 @@ export function watchViewport(): Observable<Viewport> {
|
||||
export function watchViewportAt(
|
||||
el: HTMLElement, { header$, viewport$ }: WatchRelativeOptions
|
||||
): Observable<Viewport> {
|
||||
return combineLatest([viewport$, header$])
|
||||
return combineLatest([header$, viewport$])
|
||||
.pipe(
|
||||
map(([{ offset, size }, { height }]) => ({
|
||||
map(([{ height }, { offset, size }]) => ({
|
||||
offset: {
|
||||
x: offset.x - el.offsetLeft,
|
||||
y: offset.y - el.offsetTop + height
|
||||
|
@ -149,9 +149,9 @@ export function watchAnchorList(
|
||||
}),
|
||||
|
||||
/* Re-compute partition when viewport offset changes */
|
||||
switchMap(index => combineLatest(viewport$, adjust$)
|
||||
switchMap(index => combineLatest(adjust$, viewport$)
|
||||
.pipe(
|
||||
scan(([prev, next], [{ offset: { y } }, adjust]) => {
|
||||
scan(([prev, next], [adjust, { offset: { y } }]) => {
|
||||
|
||||
/* Look forward */
|
||||
while (next.length) {
|
||||
|
@ -83,29 +83,30 @@ export function watchMain(
|
||||
)
|
||||
|
||||
/* Compute the main area's visible height */
|
||||
const height$ = combineLatest([viewport$, adjust$])
|
||||
const height$ = combineLatest([adjust$, viewport$])
|
||||
.pipe(
|
||||
map(([{ offset: { y }, size: { height } }, adjust]) => {
|
||||
map(([adjust, { offset: { y }, size: { height } }]) => {
|
||||
const top = el.offsetTop
|
||||
const bottom = el.offsetHeight + top
|
||||
return height
|
||||
- Math.max(0, top - y, adjust)
|
||||
- Math.max(0, height + y - bottom)
|
||||
}),
|
||||
map(height => Math.max(0, height)),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
|
||||
/* Compute whether the viewport offset is past the main area's top */
|
||||
const active$ = combineLatest([viewport$, adjust$])
|
||||
const active$ = combineLatest([adjust$, viewport$])
|
||||
.pipe(
|
||||
map(([{ offset: { y } }, adjust]) => y >= el.offsetTop - adjust),
|
||||
map(([adjust, { offset: { y } }]) => y >= el.offsetTop - adjust),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
|
||||
/* Combine into a single hot observable */
|
||||
return combineLatest([height$, adjust$, active$])
|
||||
return combineLatest([adjust$, height$, active$])
|
||||
.pipe(
|
||||
map(([height, adjust, active]) => ({
|
||||
map(([adjust, height, active]) => ({
|
||||
offset: el.offsetTop - adjust,
|
||||
height,
|
||||
active
|
||||
|
@ -20,7 +20,6 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { equals } from "ramda"
|
||||
import {
|
||||
MonoTypeOperatorFunction,
|
||||
Observable,
|
||||
@ -30,21 +29,26 @@ import {
|
||||
} from "rxjs"
|
||||
import {
|
||||
distinctUntilChanged,
|
||||
distinctUntilKeyChanged,
|
||||
finalize,
|
||||
map,
|
||||
observeOn,
|
||||
shareReplay,
|
||||
tap
|
||||
tap,
|
||||
withLatestFrom
|
||||
} from "rxjs/operators"
|
||||
|
||||
import {
|
||||
resetSidebarHeight,
|
||||
resetSidebarLock,
|
||||
resetSidebarOffset,
|
||||
setSidebarHeight,
|
||||
setSidebarLock
|
||||
setSidebarLock,
|
||||
setSidebarOffset
|
||||
} from "actions"
|
||||
|
||||
import { Viewport } from "../../agent"
|
||||
import { Header } from "../../header"
|
||||
import { Main } from "../_"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -71,6 +75,13 @@ interface WatchOptions {
|
||||
viewport$: Observable<Viewport> /* Viewport observable */
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint options
|
||||
*/
|
||||
interface PaintOptions {
|
||||
header$: Observable<Header> /* Header observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
@ -93,30 +104,42 @@ export function watchSidebar(
|
||||
): Observable<Sidebar> {
|
||||
|
||||
/* Adjust for internal main area offset */
|
||||
const adjust = parseFloat(
|
||||
const adjust$ = viewport$
|
||||
.pipe(
|
||||
distinctUntilKeyChanged("size"),
|
||||
map(() => parseFloat(
|
||||
getComputedStyle(el.parentElement!)
|
||||
.getPropertyValue("padding-top")
|
||||
)),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
|
||||
/* Compute the sidebar's available height */
|
||||
const height$ = combineLatest([viewport$, main$])
|
||||
const height$ = viewport$
|
||||
.pipe(
|
||||
map(([{ offset: { y } }, { offset, height }]) => {
|
||||
return height - adjust + Math.min(adjust, Math.max(0, y - offset))
|
||||
})
|
||||
withLatestFrom(adjust$, main$),
|
||||
map(([{ offset: { y } }, adjust, { offset, height }]) => (
|
||||
height
|
||||
+ Math.min(adjust, Math.max(0, y - offset))
|
||||
- adjust
|
||||
)),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
|
||||
/* Compute whether the sidebar should be locked */
|
||||
const lock$ = combineLatest([viewport$, main$])
|
||||
const lock$ = viewport$
|
||||
.pipe(
|
||||
map(([{ offset: { y } }, { offset }]) => y >= offset + adjust)
|
||||
withLatestFrom(adjust$, main$),
|
||||
map(([{ offset: { y } }, adjust, { offset }]) => (
|
||||
y >= offset + adjust
|
||||
)),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
|
||||
/* Combine into single hot observable */
|
||||
return combineLatest([height$, lock$])
|
||||
.pipe(
|
||||
map(([height, lock]) => ({ height, lock })),
|
||||
distinctUntilChanged<Sidebar>(equals),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
@ -127,23 +150,35 @@ export function watchSidebar(
|
||||
* Paint sidebar
|
||||
*
|
||||
* @param el - Sidebar element
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
*/
|
||||
export function paintSidebar(
|
||||
el: HTMLElement
|
||||
el: HTMLElement, { header$ }: PaintOptions
|
||||
): MonoTypeOperatorFunction<Sidebar> {
|
||||
return pipe(
|
||||
|
||||
/* Defer repaint to next animation frame */
|
||||
observeOn(animationFrameScheduler),
|
||||
tap(({ height, lock }) => {
|
||||
withLatestFrom(header$),
|
||||
tap(([{ height, lock }, { height: offset }]) => {
|
||||
setSidebarHeight(el, height)
|
||||
setSidebarLock(el, lock)
|
||||
|
||||
/* Set offset in locked state depending on header height */
|
||||
if (lock)
|
||||
setSidebarOffset(el, offset)
|
||||
else
|
||||
resetSidebarOffset(el)
|
||||
}),
|
||||
|
||||
/* Re-map to sidebar */
|
||||
map(([sidebar]) => sidebar),
|
||||
|
||||
/* Reset on complete or error */
|
||||
finalize(() => {
|
||||
resetSidebarOffset(el)
|
||||
resetSidebarHeight(el)
|
||||
resetSidebarLock(el)
|
||||
})
|
||||
|
@ -90,9 +90,9 @@ export function watchNavigationLayer(
|
||||
}
|
||||
|
||||
/* Determine topmost layer */
|
||||
const layer$ = merge(
|
||||
...[...table.keys()].map(input => fromEvent(input, "change"))
|
||||
)
|
||||
const layer$ = merge(...[...table.keys()].map(input => (
|
||||
fromEvent(input, "change")
|
||||
)))
|
||||
.pipe(
|
||||
map(() => getElementOrThrow(".md-nav__list", table.get(
|
||||
findLast(({ checked }) => checked, [...table.keys()])!
|
||||
|
Loading…
Reference in New Issue
Block a user