UNPKG

@ng-doc/app

Version:

<!-- PROJECT LOGO --> <br /> <div align="center"> <a href="https://github.com/ng-doc/ng-doc"> <img src="https://ng-doc.com/assets/images/ng-doc.svg?raw=true" alt="Logo" height="150px"> </a>

130 lines (125 loc) 12 kB
import { __decorate, __metadata } from 'tslib'; import { DOCUMENT, NgFor } from '@angular/common'; import * as i0 from '@angular/core'; import { inject, ElementRef, Component, ChangeDetectionStrategy, Input, HostBinding, QueryList, signal, NgZone, ChangeDetectorRef, Renderer2, afterNextRender, ViewChild, ViewChildren } from '@angular/core'; import { RouterLink, Router, Scroll } from '@angular/router'; import { isPresent } from '@ng-doc/core/helpers/is-present'; import { ngDocZoneOptimize } from '@ng-doc/ui-kit'; import { untilDestroyed, UntilDestroy } from '@ngneat/until-destroy'; import { fromEvent, merge } from 'rxjs'; import { filter, map, startWith, debounceTime, distinctUntilChanged } from 'rxjs/operators'; import { NgDocDecodeUriComponentPipe } from '@ng-doc/app/pipes/decode-uri-component'; class NgDocTocElementComponent { constructor() { this.path = ''; this.hash = ''; this.selected = false; this.level = 1; this.elementRef = inject(ElementRef); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocTocElementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: NgDocTocElementComponent, isStandalone: true, selector: "li[ng-doc-toc-element]", inputs: { path: "path", hash: "hash", selected: "selected", level: "level" }, host: { properties: { "attr.data-ng-doc-selected": "this.selected", "attr.data-ng-doc-level": "this.level" } }, ngImport: i0, template: "<a\n [routerLink]=\"[]\"\n [fragment]=\"hash | decodeUriComponent\"\n [style.padding-left]=\"'calc(var(--ng-doc-toc-indent) * ' + level + ')'\">\n <ng-content></ng-content>\n</a>\n", styles: [":host{display:flex;margin:0;color:var(--ng-doc-text)}:host[data-ng-doc-level=\"1\"] a{padding-left:var(--ng-doc-base-gutter)}:host[data-ng-doc-selected=true]{color:var(--ng-doc-primary)}:host:hover{cursor:pointer;color:var(--ng-doc-primary)}:host a{font-family:var(--ng-doc-font-family);font-variant:no-contextual;color:var(--ng-doc-text);line-height:var(--ng-doc-line-height);font-size:var(--ng-doc-font-size);font-weight:var(--ng-doc-font-weight);padding:calc(var(--ng-doc-base-gutter) / 2);color:inherit;width:100%;text-decoration:none;word-break:break-word;--ng-doc-font-size: 14px}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: NgDocDecodeUriComponentPipe, name: "decodeUriComponent" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocTocElementComponent, decorators: [{ type: Component, args: [{ selector: 'li[ng-doc-toc-element]', changeDetection: ChangeDetectionStrategy.OnPush, imports: [RouterLink, NgDocDecodeUriComponentPipe], template: "<a\n [routerLink]=\"[]\"\n [fragment]=\"hash | decodeUriComponent\"\n [style.padding-left]=\"'calc(var(--ng-doc-toc-indent) * ' + level + ')'\">\n <ng-content></ng-content>\n</a>\n", styles: [":host{display:flex;margin:0;color:var(--ng-doc-text)}:host[data-ng-doc-level=\"1\"] a{padding-left:var(--ng-doc-base-gutter)}:host[data-ng-doc-selected=true]{color:var(--ng-doc-primary)}:host:hover{cursor:pointer;color:var(--ng-doc-primary)}:host a{font-family:var(--ng-doc-font-family);font-variant:no-contextual;color:var(--ng-doc-text);line-height:var(--ng-doc-line-height);font-size:var(--ng-doc-font-size);font-weight:var(--ng-doc-font-weight);padding:calc(var(--ng-doc-base-gutter) / 2);color:inherit;width:100%;text-decoration:none;word-break:break-word;--ng-doc-font-size: 14px}\n"] }] }], propDecorators: { path: [{ type: Input }], hash: [{ type: Input }], selected: [{ type: Input }, { type: HostBinding, args: ['attr.data-ng-doc-selected'] }], level: [{ type: Input }, { type: HostBinding, args: ['attr.data-ng-doc-level'] }] } }); let NgDocTocComponent = class NgDocTocComponent { constructor() { this.tableOfContent = []; this.elements = new QueryList(); this.activeItem = signal(undefined); this.document = inject(DOCUMENT); this.ngZone = inject(NgZone); this.changeDetectorRef = inject(ChangeDetectorRef); this.renderer = inject(Renderer2); this.router = inject(Router); afterNextRender({ write: () => { const scrollSelection = fromEvent(this.document, 'scroll').pipe(filter(() => !!this.tableOfContent.length), map((event) => event.target.scrollingElement), startWith(this.document.scrollingElement), map((target) => { const percentage = (target.scrollTop * 100) / (target.scrollHeight - target.offsetHeight); const selectionLine = target.scrollTop + (target.offsetHeight * percentage) / 100; if (!this.tableOfContent.length) { return null; } return this.tableOfContent.reduce((pTarget, cTarget) => { const pTop = pTarget.element.getBoundingClientRect().top + target.scrollTop; const cTop = cTarget.element.getBoundingClientRect().top + target.scrollTop; return Math.abs(cTop - selectionLine) < Math.abs(pTop - selectionLine) ? cTarget : pTarget; }); }), filter(isPresent)); const routerSelection = this.router.events.pipe(map((event) => { if (event instanceof Scroll) { const item = this.tableOfContent.find((item) => item.path.includes(event.routerEvent.url)); if (item) { return item; } } return null; }), filter(isPresent), debounceTime(20)); const elementsChanges = this.elements.changes.pipe(map(() => this.activeItem()), filter(isPresent)); merge(merge(scrollSelection, routerSelection).pipe(distinctUntilChanged()), elementsChanges) .pipe(debounceTime(0), ngDocZoneOptimize(this.ngZone), untilDestroyed(this)) .subscribe(this.select.bind(this)); }, }); } ngOnInit() { this.activeItem.set(this.tableOfContent[0]); } /** * Selects the item in the table of content. * @param item - Item to select. */ select(item) { const index = this.tableOfContent.indexOf(item); if (this.selection) { const element = this.elements.toArray()[index]?.elementRef.nativeElement; if (element) { this.renderer.setStyle(this.selection.nativeElement, 'top', `${element.offsetTop}px`); this.renderer.setStyle(this.selection.nativeElement, 'height', `${element.offsetHeight}px`); element.scrollIntoView({ block: 'nearest' }); } } this.activeItem.set(item); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocTocComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: NgDocTocComponent, isStandalone: true, selector: "ng-doc-toc", inputs: { tableOfContent: "tableOfContent" }, viewQueries: [{ propertyName: "selection", first: true, predicate: ["selection"], descendants: true, read: ElementRef }, { propertyName: "elements", predicate: NgDocTocElementComponent, descendants: true }], ngImport: i0, template: "<div class=\"ng-doc-toc-wrapper\">\n <div class=\"ng-doc-toc-container\">\n <div class=\"ng-doc-toc-selection\" #selection></div>\n <ul class=\"ng-doc-toc\">\n @for (item of tableOfContent; track item) {\n <li\n ng-doc-toc-element\n [path]=\"item.path\"\n [hash]=\"item.hash\"\n [level]=\"item.level\"\n [selected]=\"item === activeItem()\">\n {{ item.title }}\n </li>\n }\n </ul>\n </div>\n</div>\n", styles: [":host .ng-doc-toc-wrapper{position:relative;width:var(--ng-doc-toc-width)}:host .ng-doc-toc-wrapper .ng-doc-toc-container{position:fixed;top:calc(var(--ng-doc-navbar-height) + var(--ng-doc-toc-top-padding));overflow-y:auto;height:calc(100% - var(--ng-doc-navbar-height) - var(--ng-doc-base-gutter) * 5);width:var(--ng-doc-toc-width)}:host .ng-doc-toc-wrapper .ng-doc-toc-selection{position:absolute;transform:translate(-50%);width:3px;border-radius:calc(var(--ng-doc-base-gutter) / 2);background-color:var(--ng-doc-primary);left:calc(var(--ng-doc-toc-margin) + 1px);transition:var(--ng-doc-transition)}:host .ng-doc-toc-wrapper .ng-doc-toc{list-style:none;margin:0 0 0 var(--ng-doc-toc-margin);border-left:1px solid var(--ng-doc-base-3);padding:0 0 0 var(--ng-doc-base-gutter)}@media (max-width: 1200px){:host .ng-doc-toc-wrapper{display:none}}\n"], dependencies: [{ kind: "component", type: NgDocTocElementComponent, selector: "li[ng-doc-toc-element]", inputs: ["path", "hash", "selected", "level"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } }; NgDocTocComponent = __decorate([ UntilDestroy(), __metadata("design:paramtypes", []) ], NgDocTocComponent); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocTocComponent, decorators: [{ type: Component, args: [{ selector: 'ng-doc-toc', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgFor, NgDocTocElementComponent], template: "<div class=\"ng-doc-toc-wrapper\">\n <div class=\"ng-doc-toc-container\">\n <div class=\"ng-doc-toc-selection\" #selection></div>\n <ul class=\"ng-doc-toc\">\n @for (item of tableOfContent; track item) {\n <li\n ng-doc-toc-element\n [path]=\"item.path\"\n [hash]=\"item.hash\"\n [level]=\"item.level\"\n [selected]=\"item === activeItem()\">\n {{ item.title }}\n </li>\n }\n </ul>\n </div>\n</div>\n", styles: [":host .ng-doc-toc-wrapper{position:relative;width:var(--ng-doc-toc-width)}:host .ng-doc-toc-wrapper .ng-doc-toc-container{position:fixed;top:calc(var(--ng-doc-navbar-height) + var(--ng-doc-toc-top-padding));overflow-y:auto;height:calc(100% - var(--ng-doc-navbar-height) - var(--ng-doc-base-gutter) * 5);width:var(--ng-doc-toc-width)}:host .ng-doc-toc-wrapper .ng-doc-toc-selection{position:absolute;transform:translate(-50%);width:3px;border-radius:calc(var(--ng-doc-base-gutter) / 2);background-color:var(--ng-doc-primary);left:calc(var(--ng-doc-toc-margin) + 1px);transition:var(--ng-doc-transition)}:host .ng-doc-toc-wrapper .ng-doc-toc{list-style:none;margin:0 0 0 var(--ng-doc-toc-margin);border-left:1px solid var(--ng-doc-base-3);padding:0 0 0 var(--ng-doc-base-gutter)}@media (max-width: 1200px){:host .ng-doc-toc-wrapper{display:none}}\n"] }] }], ctorParameters: () => [], propDecorators: { tableOfContent: [{ type: Input }], selection: [{ type: ViewChild, args: ['selection', { read: ElementRef }] }], elements: [{ type: ViewChildren, args: [NgDocTocElementComponent] }] } }); /** * Generated bundle index. Do not edit. */ export { NgDocTocComponent, NgDocTocElementComponent }; //# sourceMappingURL=ng-doc-app-components-toc.mjs.map