@ngstarter-ui/components 21.0.34 → 21.0.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,16 @@
1
1
  import { NgTemplateOutlet, DOCUMENT, isPlatformBrowser } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { input, output, signal, computed, ChangeDetectionStrategy, Component, Directive, Injectable, effect, untracked, inject, DestroyRef, ElementRef, PLATFORM_ID, viewChild, contentChildren, numberAttribute, booleanAttribute } from '@angular/core';
4
- import { MatchFlag } from '@embedpdf/models';
3
+ import { input, output, signal, computed, ChangeDetectionStrategy, Component, Directive, Injectable, effect, untracked, inject, DestroyRef, ElementRef, PLATFORM_ID, viewChild, contentChildren, numberAttribute, booleanAttribute, afterNextRender } from '@angular/core';
4
+ import { Rotation, MatchFlag } from '@embedpdf/models';
5
5
  import { BlockLoader } from '@ngstarter-ui/components/block-loader';
6
6
  import { Button } from '@ngstarter-ui/components/button';
7
7
  import { Divider } from '@ngstarter-ui/components/divider';
8
8
  import { Icon } from '@ngstarter-ui/components/icon';
9
9
  import { ImagePlaceholder } from '@ngstarter-ui/components/image-placeholder';
10
10
  import { Menu, MenuDivider, MenuHeading, MenuItem, MenuTrigger } from '@ngstarter-ui/components/menu';
11
- import { Panel, PanelContent, PanelHeader, PanelAside, PanelSidebar } from '@ngstarter-ui/components/panel';
12
- import { Toolbar, ToolbarSpacer, ToolbarTitle, ToolbarItem } from '@ngstarter-ui/components/toolbar';
11
+ import { Panel, PanelContent, PanelHeader, PanelSubheader, PanelAside, PanelSidebar } from '@ngstarter-ui/components/panel';
12
+ import { Toolbar, ToolbarItem, ToolbarSpacer, ToolbarTitle } from '@ngstarter-ui/components/toolbar';
13
13
  import { isObservable } from 'rxjs';
14
- import { Avatar } from '@ngstarter-ui/components/avatar';
15
- import { Card, CardActions, CardAside, CardAvatar, CardContent, CardHeader, CardSubtitle, CardTitle } from '@ngstarter-ui/components/card';
16
- import { Chip } from '@ngstarter-ui/components/chips';
17
14
  import { FormField, IconButtonSuffix, IconPrefix } from '@ngstarter-ui/components/form-field';
18
15
  import { Input } from '@ngstarter-ui/components/input';
19
16
  import { PluginRegistry } from '@embedpdf/core';
@@ -92,22 +89,12 @@ class PdfViewerAnnotations {
92
89
  .some((value) => value.toLocaleLowerCase().includes(query));
93
90
  }
94
91
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PdfViewerAnnotations, deps: [], target: i0.ɵɵFactoryTarget.Component });
95
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: PdfViewerAnnotations, isStandalone: true, selector: "ngs-pdf-viewer-annotations", inputs: { annotations: { classPropertyName: "annotations", publicName: "annotations", isSignal: true, isRequired: false, transformFunction: null }, annotationDefs: { classPropertyName: "annotationDefs", publicName: "annotationDefs", isSignal: true, isRequired: false, transformFunction: null }, annotationTypeProperty: { classPropertyName: "annotationTypeProperty", publicName: "annotationTypeProperty", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", pageSelected: "pageSelected" }, host: { classAttribute: "ngs-pdf-viewer-annotations" }, ngImport: i0, template: "<ngs-panel class=\"pdf-viewer-annotations\" aria-label=\"PDF annotations\">\n <ngs-panel-header class=\"pdf-viewer-annotations__toolbar\">\n <h3>Annotations</h3>\n <button\n class=\"pdf-viewer-annotations__close\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Close annotations panel\"\n (click)=\"closed.emit()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n </ngs-panel-header>\n\n <ngs-panel-content>\n <div class=\"pdf-viewer-annotations__content\">\n <div class=\"pdf-viewer-annotations__filters\">\n <ngs-form-field subscriptHiddenIfEmpty>\n <ngs-icon ngsIconPrefix name=\"fluent:search-24-regular\" />\n <input\n ngsInput\n type=\"text\"\n aria-label=\"Filter annotations\"\n placeholder=\"Filter annotations...\"\n [value]=\"filterQuery()\"\n (input)=\"setFilterQuery($event)\" />\n @if (filterQuery()) {\n <button\n ngsIconButton\n ngsIconButtonSuffix\n type=\"button\"\n aria-label=\"Clear annotation filter\"\n (click)=\"clearFilterQuery()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n }\n </ngs-form-field>\n\n <button\n ngsIconButton\n type=\"button\"\n aria-label=\"Annotation filters\">\n <ngs-icon name=\"fluent:filter-24-regular\" />\n </button>\n </div>\n\n <div class=\"pdf-viewer-annotations__list\">\n <ng-template #defaultAnnotationTemplate let-annotation let-goToPage=\"goToPage\">\n <ngs-card class=\"pdf-viewer-annotation-card\">\n <ngs-card-header>\n <ngs-avatar\n ngsCardAvatar\n variant=\"tonal\"\n [image]=\"getAvatarImage(annotation)\"\n [label]=\"getAvatarLabel(annotation)\"\n [alt]=\"annotation.author\" />\n\n <ngs-card-title>{{ annotation.author }}</ngs-card-title>\n @if (annotation.time) {\n <ngs-card-subtitle>{{ annotation.time }}</ngs-card-subtitle>\n }\n\n <ngs-card-aside>\n <ngs-chip appearance=\"tonal\">{{ getAnnotationTypeLabel(annotation) }}</ngs-chip>\n </ngs-card-aside>\n </ngs-card-header>\n\n <ngs-card-content>\n <p>{{ annotation.text }}</p>\n </ngs-card-content>\n\n <ngs-card-actions align=\"between\">\n <button ngsButton=\"tonal\" type=\"button\" (click)=\"goToPage(annotation.pageNumber)\">\n Page {{ annotation.pageNumber }}\n </button>\n\n <button ngsButton=\"text\" type=\"button\">\n <ngs-icon name=\"fluent:arrow-reply-24-regular\" />\n {{ getReplyLabel(annotation) }}\n </button>\n </ngs-card-actions>\n </ngs-card>\n </ng-template>\n\n @for (annotation of filteredAnnotations(); track annotation.id ?? annotation.pageNumber + '-' + $index) {\n <ng-container\n [ngTemplateOutlet]=\"getAnnotationTemplate(annotation, $index) ?? defaultAnnotationTemplate\"\n [ngTemplateOutletContext]=\"getAnnotationTemplateContext(annotation, $index)\" />\n } @empty {\n <div class=\"pdf-viewer-annotations__empty\">No annotations found.</div>\n }\n </div>\n </div>\n </ngs-panel-content>\n</ngs-panel>\n", styles: [":host{display:block;min-height:0;height:100%}:host ngs-panel.pdf-viewer-annotations{background:var(--ngs-color-surface)}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__toolbar{display:flex;align-items:center;justify-content:space-between;padding:0 calc(var(--spacing, .25rem) * 4);border-bottom:1px solid var(--ngs-color-border)}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__toolbar h3{margin:0;color:var(--ngs-color-on-surface);font-size:var(--ngs-font-size-sm);font-weight:600;letter-spacing:0;text-transform:uppercase}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__content{display:flex;flex-direction:column;min-height:100%;background:var(--ngs-color-surface-container-lowest)}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__filters{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3) calc(var(--spacing, .25rem) * 4);border-bottom:1px solid var(--ngs-color-border)}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__list{display:flex;flex:1 1 auto;flex-direction:column;gap:calc(var(--spacing, .25rem) * 4);padding:calc(var(--spacing, .25rem) * 4)}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__empty{padding:calc(var(--spacing, .25rem) * 4);color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-sm);text-align:center}:host ngs-card.pdf-viewer-annotation-card{--ngs-card-bg: var(--ngs-color-surface);--ngs-card-radius: var(--ngs-radius-md);--ngs-card-padding: calc(var(--spacing, .25rem) * 4)}:host ngs-card.pdf-viewer-annotation-card ngs-card-header{align-items:flex-start}:host ngs-card.pdf-viewer-annotation-card ngs-card-title{font-weight:600}:host ngs-card.pdf-viewer-annotation-card ngs-card-subtitle{color:var(--ngs-color-on-surface-variant)}:host ngs-card.pdf-viewer-annotation-card ngs-card-content p{margin:0;color:var(--ngs-color-on-surface);font-size:var(--ngs-font-size-base);line-height:1.45}:host ngs-card.pdf-viewer-annotation-card ngs-card-actions{padding:0 calc(var(--spacing, .25rem) * 3) calc(var(--spacing, .25rem) * 3)}:host ngs-card.pdf-viewer-annotation-card ngs-chip{text-transform:uppercase}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: Avatar, selector: "ngs-avatar,[ngs-avatar]", inputs: ["image", "variant", "clickable", "label", "alt", "automaticColor", "presenceIndicator"], exportAs: ["ngsAvatar"] }, { kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: Card, selector: "ngs-card", inputs: ["appearance"], exportAs: ["ngsCard"] }, { kind: "component", type: CardActions, selector: "ngs-card-actions, [ngs-card-actions], [ngsCardActions]", inputs: ["align"] }, { kind: "component", type: CardAside, selector: "ngs-card-aside, [ngs-card-aside], ngsCardAside" }, { kind: "directive", type: CardAvatar, selector: "ngs-card-avatar, [ngs-card-avatar], [ngsCardAvatar]" }, { kind: "component", type: CardContent, selector: "ngs-card-content, [ngs-card-content], [ngsCardContent]", inputs: ["withoutPadding"], exportAs: ["ngsCardContent"] }, { kind: "component", type: CardHeader, selector: "ngs-card-header", exportAs: ["ngsCardHeader"] }, { kind: "component", type: CardSubtitle, selector: "ngs-card-subtitle, [ngs-card-subtitle], [ngsCardSubtitle]", exportAs: ["ngsCardSubtitle"] }, { kind: "component", type: CardTitle, selector: "ngs-card-title, [ngs-card-title], [ngsCardTitle]", exportAs: ["ngsCardTitle"] }, { kind: "component", type: Chip, selector: "ngs-chip", inputs: ["appearance", "disabled", "value"], outputs: ["destroyed", "removed"], exportAs: ["ngsChip"] }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty", "sameHeightAsButton"], exportAs: ["ngsFormField"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "directive", type: IconButtonSuffix, selector: "[ngsIconButtonSuffix]" }, { kind: "directive", type: IconPrefix, selector: "[ngsIconPrefix]" }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Panel, selector: "ngs-panel", inputs: ["absolute"], exportAs: ["ngsPanel"] }, { kind: "component", type: PanelContent, selector: "ngs-panel-content", exportAs: ["ngsPanelContent"] }, { kind: "component", type: PanelHeader, selector: "ngs-panel-header", inputs: ["flex", "autoHeight"], exportAs: ["ngsPanelHeader"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
92
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: PdfViewerAnnotations, isStandalone: true, selector: "ngs-pdf-viewer-annotations", inputs: { annotations: { classPropertyName: "annotations", publicName: "annotations", isSignal: true, isRequired: false, transformFunction: null }, annotationDefs: { classPropertyName: "annotationDefs", publicName: "annotationDefs", isSignal: true, isRequired: false, transformFunction: null }, annotationTypeProperty: { classPropertyName: "annotationTypeProperty", publicName: "annotationTypeProperty", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", pageSelected: "pageSelected" }, host: { classAttribute: "ngs-pdf-viewer-annotations" }, ngImport: i0, template: "<ngs-panel class=\"pdf-viewer-annotations bg-surface\" aria-label=\"PDF annotations\">\n <ngs-panel-header class=\"p-0\">\n <ngs-toolbar class=\"w-full py-0 pr-2 ps-4\" aria-label=\"PDF annotations toolbar\">\n <ngs-toolbar-title>\n Annotations\n </ngs-toolbar-title>\n <ngs-toolbar-spacer />\n <ngs-toolbar-item>\n <button\n class=\"pdf-viewer-annotations__close\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Close annotations panel\"\n (click)=\"closed.emit()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n </ngs-toolbar-item>\n </ngs-toolbar>\n </ngs-panel-header>\n\n <ngs-panel-subheader autoHeight class=\"px-4 pb-4\">\n <ngs-form-field subscriptHiddenIfEmpty>\n <ngs-icon ngsIconPrefix name=\"fluent:search-24-regular\" />\n <input\n ngsInput\n type=\"text\"\n aria-label=\"Filter annotations\"\n placeholder=\"Filter annotations...\"\n [value]=\"filterQuery()\"\n (input)=\"setFilterQuery($event)\" />\n @if (filterQuery()) {\n <button\n ngsIconButton\n ngsIconButtonSuffix\n type=\"button\"\n aria-label=\"Clear annotation filter\"\n (click)=\"clearFilterQuery()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n }\n </ngs-form-field>\n </ngs-panel-subheader>\n\n <ngs-panel-content>\n <div class=\"flex min-h-full flex-col\">\n <div class=\"flex flex-1 flex-col gap-4 pb-4 px-4\">\n <ng-template #defaultAnnotationTemplate let-annotation let-goToPage=\"goToPage\">\n <article class=\"rounded-2xl border border-border bg-surface p-4 shadow-xs\">\n <header class=\"flex items-start gap-3\">\n <span class=\"flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-full bg-primary-container text-xs font-semibold text-on-primary-container\">\n @if (getAvatarImage(annotation); as avatarImage) {\n <img\n class=\"h-full w-full object-cover\"\n [src]=\"avatarImage\"\n [alt]=\"annotation.author\" />\n } @else {\n {{ getAvatarLabel(annotation) }}\n }\n </span>\n\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate text-sm font-semibold text-on-surface\">{{ annotation.author }}</span>\n @if (annotation.time) {\n <span class=\"block truncate text-xs text-on-surface-variant\">{{ annotation.time }}</span>\n }\n </span>\n\n <span class=\"rounded-full bg-surface-container-high px-2 py-1 text-xs font-medium tracking-normal text-on-surface-variant uppercase\">\n {{ getAnnotationTypeLabel(annotation) }}\n </span>\n </header>\n\n <p class=\"mt-3 mb-0 text-base leading-relaxed text-on-surface\">{{ annotation.text }}</p>\n\n <footer class=\"mt-4 flex items-center justify-between gap-2\">\n <button\n ngsButton=\"tonal\"\n type=\"button\"\n (click)=\"goToPage(annotation.pageNumber)\">\n Page {{ annotation.pageNumber }}\n </button>\n\n <button ngsButton=\"text\" type=\"button\">\n {{ getReplyLabel(annotation) }}\n </button>\n </footer>\n </article>\n </ng-template>\n\n @for (annotation of filteredAnnotations(); track annotation.id ?? annotation.pageNumber + '-' + $index) {\n <ng-container\n [ngTemplateOutlet]=\"getAnnotationTemplate(annotation, $index) ?? defaultAnnotationTemplate\"\n [ngTemplateOutletContext]=\"getAnnotationTemplateContext(annotation, $index)\" />\n } @empty {\n <div class=\"p-4 text-center text-sm text-on-surface-variant\">No annotations found.</div>\n }\n </div>\n </div>\n </ngs-panel-content>\n</ngs-panel>\n", styles: [":host{display:block;min-height:0;height:100%}\n"], dependencies: [{ kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty", "sameHeightAsButton"], exportAs: ["ngsFormField"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "directive", type: IconButtonSuffix, selector: "[ngsIconButtonSuffix]" }, { kind: "directive", type: IconPrefix, selector: "[ngsIconPrefix]" }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Panel, selector: "ngs-panel", inputs: ["absolute"], exportAs: ["ngsPanel"] }, { kind: "component", type: PanelContent, selector: "ngs-panel-content", exportAs: ["ngsPanelContent"] }, { kind: "component", type: PanelHeader, selector: "ngs-panel-header", inputs: ["flex", "autoHeight"], exportAs: ["ngsPanelHeader"] }, { kind: "component", type: Toolbar, selector: "ngs-toolbar", exportAs: ["ngsToolbar"] }, { kind: "component", type: ToolbarItem, selector: "ngs-toolbar-item", inputs: ["hidden"], outputs: ["hiddenChange"] }, { kind: "component", type: ToolbarSpacer, selector: "ngs-toolbar-spacer" }, { kind: "component", type: ToolbarTitle, selector: "ngs-toolbar-title" }, { kind: "component", type: PanelSubheader, selector: "ngs-panel-subheader", inputs: ["flex", "autoHeight"], exportAs: ["ngsPanelSubheader"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
96
93
  }
97
94
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PdfViewerAnnotations, decorators: [{
98
95
  type: Component,
99
96
  args: [{ selector: 'ngs-pdf-viewer-annotations', standalone: true, imports: [
100
- Avatar,
101
97
  Button,
102
- Card,
103
- CardActions,
104
- CardAside,
105
- CardAvatar,
106
- CardContent,
107
- CardHeader,
108
- CardSubtitle,
109
- CardTitle,
110
- Chip,
111
98
  FormField,
112
99
  Icon,
113
100
  IconButtonSuffix,
@@ -117,9 +104,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
117
104
  Panel,
118
105
  PanelContent,
119
106
  PanelHeader,
107
+ Toolbar,
108
+ ToolbarItem,
109
+ ToolbarSpacer,
110
+ ToolbarTitle,
111
+ PanelSubheader,
120
112
  ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
121
113
  class: 'ngs-pdf-viewer-annotations',
122
- }, template: "<ngs-panel class=\"pdf-viewer-annotations\" aria-label=\"PDF annotations\">\n <ngs-panel-header class=\"pdf-viewer-annotations__toolbar\">\n <h3>Annotations</h3>\n <button\n class=\"pdf-viewer-annotations__close\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Close annotations panel\"\n (click)=\"closed.emit()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n </ngs-panel-header>\n\n <ngs-panel-content>\n <div class=\"pdf-viewer-annotations__content\">\n <div class=\"pdf-viewer-annotations__filters\">\n <ngs-form-field subscriptHiddenIfEmpty>\n <ngs-icon ngsIconPrefix name=\"fluent:search-24-regular\" />\n <input\n ngsInput\n type=\"text\"\n aria-label=\"Filter annotations\"\n placeholder=\"Filter annotations...\"\n [value]=\"filterQuery()\"\n (input)=\"setFilterQuery($event)\" />\n @if (filterQuery()) {\n <button\n ngsIconButton\n ngsIconButtonSuffix\n type=\"button\"\n aria-label=\"Clear annotation filter\"\n (click)=\"clearFilterQuery()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n }\n </ngs-form-field>\n\n <button\n ngsIconButton\n type=\"button\"\n aria-label=\"Annotation filters\">\n <ngs-icon name=\"fluent:filter-24-regular\" />\n </button>\n </div>\n\n <div class=\"pdf-viewer-annotations__list\">\n <ng-template #defaultAnnotationTemplate let-annotation let-goToPage=\"goToPage\">\n <ngs-card class=\"pdf-viewer-annotation-card\">\n <ngs-card-header>\n <ngs-avatar\n ngsCardAvatar\n variant=\"tonal\"\n [image]=\"getAvatarImage(annotation)\"\n [label]=\"getAvatarLabel(annotation)\"\n [alt]=\"annotation.author\" />\n\n <ngs-card-title>{{ annotation.author }}</ngs-card-title>\n @if (annotation.time) {\n <ngs-card-subtitle>{{ annotation.time }}</ngs-card-subtitle>\n }\n\n <ngs-card-aside>\n <ngs-chip appearance=\"tonal\">{{ getAnnotationTypeLabel(annotation) }}</ngs-chip>\n </ngs-card-aside>\n </ngs-card-header>\n\n <ngs-card-content>\n <p>{{ annotation.text }}</p>\n </ngs-card-content>\n\n <ngs-card-actions align=\"between\">\n <button ngsButton=\"tonal\" type=\"button\" (click)=\"goToPage(annotation.pageNumber)\">\n Page {{ annotation.pageNumber }}\n </button>\n\n <button ngsButton=\"text\" type=\"button\">\n <ngs-icon name=\"fluent:arrow-reply-24-regular\" />\n {{ getReplyLabel(annotation) }}\n </button>\n </ngs-card-actions>\n </ngs-card>\n </ng-template>\n\n @for (annotation of filteredAnnotations(); track annotation.id ?? annotation.pageNumber + '-' + $index) {\n <ng-container\n [ngTemplateOutlet]=\"getAnnotationTemplate(annotation, $index) ?? defaultAnnotationTemplate\"\n [ngTemplateOutletContext]=\"getAnnotationTemplateContext(annotation, $index)\" />\n } @empty {\n <div class=\"pdf-viewer-annotations__empty\">No annotations found.</div>\n }\n </div>\n </div>\n </ngs-panel-content>\n</ngs-panel>\n", styles: [":host{display:block;min-height:0;height:100%}:host ngs-panel.pdf-viewer-annotations{background:var(--ngs-color-surface)}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__toolbar{display:flex;align-items:center;justify-content:space-between;padding:0 calc(var(--spacing, .25rem) * 4);border-bottom:1px solid var(--ngs-color-border)}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__toolbar h3{margin:0;color:var(--ngs-color-on-surface);font-size:var(--ngs-font-size-sm);font-weight:600;letter-spacing:0;text-transform:uppercase}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__content{display:flex;flex-direction:column;min-height:100%;background:var(--ngs-color-surface-container-lowest)}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__filters{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3) calc(var(--spacing, .25rem) * 4);border-bottom:1px solid var(--ngs-color-border)}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__list{display:flex;flex:1 1 auto;flex-direction:column;gap:calc(var(--spacing, .25rem) * 4);padding:calc(var(--spacing, .25rem) * 4)}:host ngs-panel.pdf-viewer-annotations .pdf-viewer-annotations__empty{padding:calc(var(--spacing, .25rem) * 4);color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-sm);text-align:center}:host ngs-card.pdf-viewer-annotation-card{--ngs-card-bg: var(--ngs-color-surface);--ngs-card-radius: var(--ngs-radius-md);--ngs-card-padding: calc(var(--spacing, .25rem) * 4)}:host ngs-card.pdf-viewer-annotation-card ngs-card-header{align-items:flex-start}:host ngs-card.pdf-viewer-annotation-card ngs-card-title{font-weight:600}:host ngs-card.pdf-viewer-annotation-card ngs-card-subtitle{color:var(--ngs-color-on-surface-variant)}:host ngs-card.pdf-viewer-annotation-card ngs-card-content p{margin:0;color:var(--ngs-color-on-surface);font-size:var(--ngs-font-size-base);line-height:1.45}:host ngs-card.pdf-viewer-annotation-card ngs-card-actions{padding:0 calc(var(--spacing, .25rem) * 3) calc(var(--spacing, .25rem) * 3)}:host ngs-card.pdf-viewer-annotation-card ngs-chip{text-transform:uppercase}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
114
+ }, template: "<ngs-panel class=\"pdf-viewer-annotations bg-surface\" aria-label=\"PDF annotations\">\n <ngs-panel-header class=\"p-0\">\n <ngs-toolbar class=\"w-full py-0 pr-2 ps-4\" aria-label=\"PDF annotations toolbar\">\n <ngs-toolbar-title>\n Annotations\n </ngs-toolbar-title>\n <ngs-toolbar-spacer />\n <ngs-toolbar-item>\n <button\n class=\"pdf-viewer-annotations__close\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Close annotations panel\"\n (click)=\"closed.emit()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n </ngs-toolbar-item>\n </ngs-toolbar>\n </ngs-panel-header>\n\n <ngs-panel-subheader autoHeight class=\"px-4 pb-4\">\n <ngs-form-field subscriptHiddenIfEmpty>\n <ngs-icon ngsIconPrefix name=\"fluent:search-24-regular\" />\n <input\n ngsInput\n type=\"text\"\n aria-label=\"Filter annotations\"\n placeholder=\"Filter annotations...\"\n [value]=\"filterQuery()\"\n (input)=\"setFilterQuery($event)\" />\n @if (filterQuery()) {\n <button\n ngsIconButton\n ngsIconButtonSuffix\n type=\"button\"\n aria-label=\"Clear annotation filter\"\n (click)=\"clearFilterQuery()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n }\n </ngs-form-field>\n </ngs-panel-subheader>\n\n <ngs-panel-content>\n <div class=\"flex min-h-full flex-col\">\n <div class=\"flex flex-1 flex-col gap-4 pb-4 px-4\">\n <ng-template #defaultAnnotationTemplate let-annotation let-goToPage=\"goToPage\">\n <article class=\"rounded-2xl border border-border bg-surface p-4 shadow-xs\">\n <header class=\"flex items-start gap-3\">\n <span class=\"flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-full bg-primary-container text-xs font-semibold text-on-primary-container\">\n @if (getAvatarImage(annotation); as avatarImage) {\n <img\n class=\"h-full w-full object-cover\"\n [src]=\"avatarImage\"\n [alt]=\"annotation.author\" />\n } @else {\n {{ getAvatarLabel(annotation) }}\n }\n </span>\n\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate text-sm font-semibold text-on-surface\">{{ annotation.author }}</span>\n @if (annotation.time) {\n <span class=\"block truncate text-xs text-on-surface-variant\">{{ annotation.time }}</span>\n }\n </span>\n\n <span class=\"rounded-full bg-surface-container-high px-2 py-1 text-xs font-medium tracking-normal text-on-surface-variant uppercase\">\n {{ getAnnotationTypeLabel(annotation) }}\n </span>\n </header>\n\n <p class=\"mt-3 mb-0 text-base leading-relaxed text-on-surface\">{{ annotation.text }}</p>\n\n <footer class=\"mt-4 flex items-center justify-between gap-2\">\n <button\n ngsButton=\"tonal\"\n type=\"button\"\n (click)=\"goToPage(annotation.pageNumber)\">\n Page {{ annotation.pageNumber }}\n </button>\n\n <button ngsButton=\"text\" type=\"button\">\n {{ getReplyLabel(annotation) }}\n </button>\n </footer>\n </article>\n </ng-template>\n\n @for (annotation of filteredAnnotations(); track annotation.id ?? annotation.pageNumber + '-' + $index) {\n <ng-container\n [ngTemplateOutlet]=\"getAnnotationTemplate(annotation, $index) ?? defaultAnnotationTemplate\"\n [ngTemplateOutletContext]=\"getAnnotationTemplateContext(annotation, $index)\" />\n } @empty {\n <div class=\"p-4 text-center text-sm text-on-surface-variant\">No annotations found.</div>\n }\n </div>\n </div>\n </ngs-panel-content>\n</ngs-panel>\n", styles: [":host{display:block;min-height:0;height:100%}\n"] }]
123
115
  }], propDecorators: { annotations: [{ type: i0.Input, args: [{ isSignal: true, alias: "annotations", required: false }] }], annotationDefs: [{ type: i0.Input, args: [{ isSignal: true, alias: "annotationDefs", required: false }] }], annotationTypeProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "annotationTypeProperty", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], pageSelected: [{ type: i0.Output, args: ["pageSelected"] }] } });
124
116
 
125
117
  class PdfViewerAnnotationDef {
@@ -164,7 +156,10 @@ class PdfViewerEngineService {
164
156
  if (cachedEngine) {
165
157
  return cachedEngine;
166
158
  }
167
- const engine = this.createEngine(wasmUrl);
159
+ const engine = this.createEngine(wasmUrl).catch((error) => {
160
+ this.engines.delete(wasmUrl);
161
+ throw error;
162
+ });
168
163
  this.engines.set(wasmUrl, engine);
169
164
  return engine;
170
165
  }
@@ -301,14 +296,13 @@ class PdfViewerSearch {
301
296
  return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
302
297
  }
303
298
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PdfViewerSearch, deps: [], target: i0.ɵɵFactoryTarget.Component });
304
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: PdfViewerSearch, isStandalone: true, selector: "ngs-pdf-viewer-search", inputs: { results: { classPropertyName: "results", publicName: "results", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", resultSelected: "resultSelected", searchChanged: "searchChanged" }, host: { classAttribute: "ngs-pdf-viewer-search" }, ngImport: i0, template: "<ngs-panel class=\"pdf-viewer-search\" aria-label=\"PDF search\">\n <ngs-panel-header class=\"ps-5 pe-3\">\n <ngs-toolbar>\n <ngs-toolbar-title>Search</ngs-toolbar-title>\n <ngs-toolbar-spacer />\n <button ngsIconButton type=\"button\" aria-label=\"Close search panel\" (click)=\"closed.emit()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n </ngs-toolbar>\n </ngs-panel-header>\n\n <ngs-panel-content>\n <div class=\"pdf-viewer-search__content flex min-h-full flex-col gap-5 p-6\">\n <ngs-form-field class=\"pdf-viewer-search__field\" subscriptHiddenIfEmpty>\n <ngs-icon name=\"fluent:search-24-regular\" ngsIconPrefix />\n <input\n ngsInput\n type=\"text\"\n aria-label=\"Search PDF\"\n placeholder=\"Search\"\n [value]=\"queryValue()\"\n (input)=\"setQuery($event)\" />\n @if (queryValue()) {\n <button ngsIconButtonSuffix ngsIconButton type=\"button\" aria-label=\"Clear search\" (click)=\"clearQuery()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n }\n </ngs-form-field>\n\n <div class=\"pdf-viewer-search__options grid gap-3 text-base text-on-surface\">\n <ngs-checkbox [checked]=\"caseSensitive()\" (checkedChange)=\"setCaseSensitive($event)\">\n Case sensitive\n </ngs-checkbox>\n <ngs-checkbox [checked]=\"wholeWord()\" (checkedChange)=\"setWholeWord($event)\">\n Whole word\n </ngs-checkbox>\n </div>\n\n @if (hasQuery()) {\n <ngs-divider />\n\n <div class=\"pdf-viewer-search__summary flex items-center justify-between gap-4 text-base text-on-surface-variant\">\n <span>{{ resultCountLabel() }}</span>\n <div class=\"pdf-viewer-search__nav flex items-center gap-3\">\n <button\n class=\"text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Previous search result\"\n [disabled]=\"results().length === 0\"\n (click)=\"previousResult()\">\n <ngs-icon name=\"fluent:chevron-left-24-regular\" />\n </button>\n <button\n class=\"text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Next search result\"\n [disabled]=\"results().length === 0\"\n (click)=\"nextResult()\">\n <ngs-icon name=\"fluent:chevron-right-24-regular\" />\n </button>\n </div>\n </div>\n\n <div class=\"pdf-viewer-search__results grid min-h-0 gap-4\">\n @for (group of visibleResultGroups(); track group.pageNumber) {\n <section class=\"pdf-viewer-search__page-group grid gap-3\">\n <h3 class=\"m-0 text-base font-medium text-on-surface-variant\">Page {{ group.pageNumber }}</h3>\n @for (item of group.results; track item.result.id ?? item.result.pageNumber + '-' + item.index) {\n <button\n class=\"pdf-viewer-search__result w-full cursor-pointer rounded border border-border p-4 text-left text-base leading-snug text-on-surface\"\n type=\"button\"\n [class.bg-primary-container]=\"item.index === activeResultIndex()\"\n [class.bg-surface]=\"item.index !== activeResultIndex()\"\n (click)=\"selectResult(item.result, item.index)\">\n @for (part of resultParts(item.result); track part.text + '-' + $index) {\n <span\n [class.font-bold]=\"part.highlight\"\n [class.text-primary]=\"part.highlight\">{{ part.text }}</span>\n }\n </button>\n }\n </section>\n } @empty {\n <div class=\"pdf-viewer-search__empty p-4 text-center text-sm text-on-surface-variant\">No results.</div>\n }\n </div>\n }\n </div>\n </ngs-panel-content>\n</ngs-panel>\n", styles: [":host{display:block;min-height:0;height:100%}\n"], dependencies: [{ kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: Checkbox, selector: "ngs-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["checkedChange", "disabledChange", "indeterminateChange", "change"], exportAs: ["ngsCheckbox"] }, { kind: "component", type: Divider, selector: "ngs-divider", inputs: ["vertical", "inset", "fixedHeight"], exportAs: ["ngsDivider"] }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty", "sameHeightAsButton"], exportAs: ["ngsFormField"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "directive", type: IconButtonSuffix, selector: "[ngsIconButtonSuffix]" }, { kind: "directive", type: IconPrefix, selector: "[ngsIconPrefix]" }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "component", type: Panel, selector: "ngs-panel", inputs: ["absolute"], exportAs: ["ngsPanel"] }, { kind: "component", type: PanelContent, selector: "ngs-panel-content", exportAs: ["ngsPanelContent"] }, { kind: "component", type: PanelHeader, selector: "ngs-panel-header", inputs: ["flex", "autoHeight"], exportAs: ["ngsPanelHeader"] }, { kind: "component", type: Toolbar, selector: "ngs-toolbar", exportAs: ["ngsToolbar"] }, { kind: "component", type: ToolbarSpacer, selector: "ngs-toolbar-spacer" }, { kind: "component", type: ToolbarTitle, selector: "ngs-toolbar-title" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
299
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: PdfViewerSearch, isStandalone: true, selector: "ngs-pdf-viewer-search", inputs: { results: { classPropertyName: "results", publicName: "results", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", resultSelected: "resultSelected", searchChanged: "searchChanged" }, host: { classAttribute: "ngs-pdf-viewer-search" }, ngImport: i0, template: "<ngs-panel class=\"pdf-viewer-search\" aria-label=\"PDF search\">\n <ngs-panel-header class=\"ps-4 pe-3\">\n <ngs-toolbar>\n <ngs-toolbar-title>Search</ngs-toolbar-title>\n <ngs-toolbar-spacer />\n <button ngsIconButton type=\"button\" aria-label=\"Close search panel\" (click)=\"closed.emit()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n </ngs-toolbar>\n </ngs-panel-header>\n\n <ngs-panel-subheader autoHeight class=\"px-4 pb-4\">\n <ngs-form-field class=\"pdf-viewer-search__field\" subscriptHiddenIfEmpty>\n <ngs-icon name=\"fluent:search-24-regular\" ngsIconPrefix />\n <input\n ngsInput\n type=\"text\"\n aria-label=\"Search PDF\"\n placeholder=\"Search\"\n [value]=\"queryValue()\"\n (input)=\"setQuery($event)\" />\n @if (queryValue()) {\n <button ngsIconButtonSuffix ngsIconButton type=\"button\" aria-label=\"Clear search\" (click)=\"clearQuery()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n }\n </ngs-form-field>\n\n <div class=\"pdf-viewer-search__options mt-4 grid gap-3 text-base text-on-surface\">\n <ngs-checkbox [checked]=\"caseSensitive()\" (checkedChange)=\"setCaseSensitive($event)\">\n Case sensitive\n </ngs-checkbox>\n <ngs-checkbox [checked]=\"wholeWord()\" (checkedChange)=\"setWholeWord($event)\">\n Whole word\n </ngs-checkbox>\n </div>\n\n @if (hasQuery()) {\n <div class=\"pdf-viewer-search__summary mt-4 flex items-center justify-between gap-4 text-base text-on-surface-variant\">\n <span>{{ resultCountLabel() }}</span>\n <div class=\"pdf-viewer-search__nav flex items-center gap-3\">\n <button\n class=\"text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Previous search result\"\n [disabled]=\"results().length === 0\"\n (click)=\"previousResult()\">\n <ngs-icon name=\"fluent:chevron-left-24-regular\" />\n </button>\n <button\n class=\"text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Next search result\"\n [disabled]=\"results().length === 0\"\n (click)=\"nextResult()\">\n <ngs-icon name=\"fluent:chevron-right-24-regular\" />\n </button>\n </div>\n </div>\n }\n </ngs-panel-subheader>\n\n <ngs-panel-content>\n <div class=\"pdf-viewer-search__content flex min-h-full flex-col gap-4 px-4 pb-4\">\n @if (hasQuery()) {\n <div class=\"pdf-viewer-search__results grid min-h-0 gap-4\">\n @for (group of visibleResultGroups(); track group.pageNumber) {\n <section class=\"pdf-viewer-search__page-group grid gap-3 bg-surface\">\n <h3 class=\"m-0 text-base font-medium text-on-surface-variant\">Page {{ group.pageNumber }}</h3>\n @for (item of group.results; track item.result.id ?? item.result.pageNumber + '-' + item.index) {\n <button\n class=\"pdf-viewer-search__result w-full cursor-pointer rounded-2xl border border-border p-4 text-left text-base leading-snug text-on-surface\"\n type=\"button\"\n [class.bg-primary-container]=\"item.index === activeResultIndex()\"\n [class.bg-surface]=\"item.index !== activeResultIndex()\"\n (click)=\"selectResult(item.result, item.index)\">\n @for (part of resultParts(item.result); track part.text + '-' + $index) {\n <span\n [class.font-bold]=\"part.highlight\"\n [class.text-primary]=\"part.highlight\">{{ part.text }}</span>\n }\n </button>\n }\n </section>\n } @empty {\n <div class=\"pdf-viewer-search__empty p-4 text-center text-sm text-on-surface-variant\">No results.</div>\n }\n </div>\n }\n </div>\n </ngs-panel-content>\n</ngs-panel>\n", styles: [":host{display:block;min-height:0;height:100%}\n"], dependencies: [{ kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: Checkbox, selector: "ngs-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["checkedChange", "disabledChange", "indeterminateChange", "change"], exportAs: ["ngsCheckbox"] }, { kind: "component", type: FormField, selector: "ngs-form-field", inputs: ["subscriptHiddenIfEmpty", "sameHeightAsButton"], exportAs: ["ngsFormField"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "directive", type: IconButtonSuffix, selector: "[ngsIconButtonSuffix]" }, { kind: "directive", type: IconPrefix, selector: "[ngsIconPrefix]" }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "component", type: Panel, selector: "ngs-panel", inputs: ["absolute"], exportAs: ["ngsPanel"] }, { kind: "component", type: PanelContent, selector: "ngs-panel-content", exportAs: ["ngsPanelContent"] }, { kind: "component", type: PanelHeader, selector: "ngs-panel-header", inputs: ["flex", "autoHeight"], exportAs: ["ngsPanelHeader"] }, { kind: "component", type: Toolbar, selector: "ngs-toolbar", exportAs: ["ngsToolbar"] }, { kind: "component", type: ToolbarSpacer, selector: "ngs-toolbar-spacer" }, { kind: "component", type: ToolbarTitle, selector: "ngs-toolbar-title" }, { kind: "component", type: PanelSubheader, selector: "ngs-panel-subheader", inputs: ["flex", "autoHeight"], exportAs: ["ngsPanelSubheader"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
305
300
  }
306
301
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PdfViewerSearch, decorators: [{
307
302
  type: Component,
308
303
  args: [{ selector: 'ngs-pdf-viewer-search', standalone: true, imports: [
309
304
  Button,
310
305
  Checkbox,
311
- Divider,
312
306
  FormField,
313
307
  Icon,
314
308
  IconButtonSuffix,
@@ -320,9 +314,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
320
314
  Toolbar,
321
315
  ToolbarSpacer,
322
316
  ToolbarTitle,
317
+ PanelSubheader,
323
318
  ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
324
319
  class: 'ngs-pdf-viewer-search',
325
- }, template: "<ngs-panel class=\"pdf-viewer-search\" aria-label=\"PDF search\">\n <ngs-panel-header class=\"ps-5 pe-3\">\n <ngs-toolbar>\n <ngs-toolbar-title>Search</ngs-toolbar-title>\n <ngs-toolbar-spacer />\n <button ngsIconButton type=\"button\" aria-label=\"Close search panel\" (click)=\"closed.emit()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n </ngs-toolbar>\n </ngs-panel-header>\n\n <ngs-panel-content>\n <div class=\"pdf-viewer-search__content flex min-h-full flex-col gap-5 p-6\">\n <ngs-form-field class=\"pdf-viewer-search__field\" subscriptHiddenIfEmpty>\n <ngs-icon name=\"fluent:search-24-regular\" ngsIconPrefix />\n <input\n ngsInput\n type=\"text\"\n aria-label=\"Search PDF\"\n placeholder=\"Search\"\n [value]=\"queryValue()\"\n (input)=\"setQuery($event)\" />\n @if (queryValue()) {\n <button ngsIconButtonSuffix ngsIconButton type=\"button\" aria-label=\"Clear search\" (click)=\"clearQuery()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n }\n </ngs-form-field>\n\n <div class=\"pdf-viewer-search__options grid gap-3 text-base text-on-surface\">\n <ngs-checkbox [checked]=\"caseSensitive()\" (checkedChange)=\"setCaseSensitive($event)\">\n Case sensitive\n </ngs-checkbox>\n <ngs-checkbox [checked]=\"wholeWord()\" (checkedChange)=\"setWholeWord($event)\">\n Whole word\n </ngs-checkbox>\n </div>\n\n @if (hasQuery()) {\n <ngs-divider />\n\n <div class=\"pdf-viewer-search__summary flex items-center justify-between gap-4 text-base text-on-surface-variant\">\n <span>{{ resultCountLabel() }}</span>\n <div class=\"pdf-viewer-search__nav flex items-center gap-3\">\n <button\n class=\"text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Previous search result\"\n [disabled]=\"results().length === 0\"\n (click)=\"previousResult()\">\n <ngs-icon name=\"fluent:chevron-left-24-regular\" />\n </button>\n <button\n class=\"text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Next search result\"\n [disabled]=\"results().length === 0\"\n (click)=\"nextResult()\">\n <ngs-icon name=\"fluent:chevron-right-24-regular\" />\n </button>\n </div>\n </div>\n\n <div class=\"pdf-viewer-search__results grid min-h-0 gap-4\">\n @for (group of visibleResultGroups(); track group.pageNumber) {\n <section class=\"pdf-viewer-search__page-group grid gap-3\">\n <h3 class=\"m-0 text-base font-medium text-on-surface-variant\">Page {{ group.pageNumber }}</h3>\n @for (item of group.results; track item.result.id ?? item.result.pageNumber + '-' + item.index) {\n <button\n class=\"pdf-viewer-search__result w-full cursor-pointer rounded border border-border p-4 text-left text-base leading-snug text-on-surface\"\n type=\"button\"\n [class.bg-primary-container]=\"item.index === activeResultIndex()\"\n [class.bg-surface]=\"item.index !== activeResultIndex()\"\n (click)=\"selectResult(item.result, item.index)\">\n @for (part of resultParts(item.result); track part.text + '-' + $index) {\n <span\n [class.font-bold]=\"part.highlight\"\n [class.text-primary]=\"part.highlight\">{{ part.text }}</span>\n }\n </button>\n }\n </section>\n } @empty {\n <div class=\"pdf-viewer-search__empty p-4 text-center text-sm text-on-surface-variant\">No results.</div>\n }\n </div>\n }\n </div>\n </ngs-panel-content>\n</ngs-panel>\n", styles: [":host{display:block;min-height:0;height:100%}\n"] }]
320
+ }, template: "<ngs-panel class=\"pdf-viewer-search\" aria-label=\"PDF search\">\n <ngs-panel-header class=\"ps-4 pe-3\">\n <ngs-toolbar>\n <ngs-toolbar-title>Search</ngs-toolbar-title>\n <ngs-toolbar-spacer />\n <button ngsIconButton type=\"button\" aria-label=\"Close search panel\" (click)=\"closed.emit()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n </ngs-toolbar>\n </ngs-panel-header>\n\n <ngs-panel-subheader autoHeight class=\"px-4 pb-4\">\n <ngs-form-field class=\"pdf-viewer-search__field\" subscriptHiddenIfEmpty>\n <ngs-icon name=\"fluent:search-24-regular\" ngsIconPrefix />\n <input\n ngsInput\n type=\"text\"\n aria-label=\"Search PDF\"\n placeholder=\"Search\"\n [value]=\"queryValue()\"\n (input)=\"setQuery($event)\" />\n @if (queryValue()) {\n <button ngsIconButtonSuffix ngsIconButton type=\"button\" aria-label=\"Clear search\" (click)=\"clearQuery()\">\n <ngs-icon name=\"fluent:dismiss-24-regular\" />\n </button>\n }\n </ngs-form-field>\n\n <div class=\"pdf-viewer-search__options mt-4 grid gap-3 text-base text-on-surface\">\n <ngs-checkbox [checked]=\"caseSensitive()\" (checkedChange)=\"setCaseSensitive($event)\">\n Case sensitive\n </ngs-checkbox>\n <ngs-checkbox [checked]=\"wholeWord()\" (checkedChange)=\"setWholeWord($event)\">\n Whole word\n </ngs-checkbox>\n </div>\n\n @if (hasQuery()) {\n <div class=\"pdf-viewer-search__summary mt-4 flex items-center justify-between gap-4 text-base text-on-surface-variant\">\n <span>{{ resultCountLabel() }}</span>\n <div class=\"pdf-viewer-search__nav flex items-center gap-3\">\n <button\n class=\"text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Previous search result\"\n [disabled]=\"results().length === 0\"\n (click)=\"previousResult()\">\n <ngs-icon name=\"fluent:chevron-left-24-regular\" />\n </button>\n <button\n class=\"text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Next search result\"\n [disabled]=\"results().length === 0\"\n (click)=\"nextResult()\">\n <ngs-icon name=\"fluent:chevron-right-24-regular\" />\n </button>\n </div>\n </div>\n }\n </ngs-panel-subheader>\n\n <ngs-panel-content>\n <div class=\"pdf-viewer-search__content flex min-h-full flex-col gap-4 px-4 pb-4\">\n @if (hasQuery()) {\n <div class=\"pdf-viewer-search__results grid min-h-0 gap-4\">\n @for (group of visibleResultGroups(); track group.pageNumber) {\n <section class=\"pdf-viewer-search__page-group grid gap-3 bg-surface\">\n <h3 class=\"m-0 text-base font-medium text-on-surface-variant\">Page {{ group.pageNumber }}</h3>\n @for (item of group.results; track item.result.id ?? item.result.pageNumber + '-' + item.index) {\n <button\n class=\"pdf-viewer-search__result w-full cursor-pointer rounded-2xl border border-border p-4 text-left text-base leading-snug text-on-surface\"\n type=\"button\"\n [class.bg-primary-container]=\"item.index === activeResultIndex()\"\n [class.bg-surface]=\"item.index !== activeResultIndex()\"\n (click)=\"selectResult(item.result, item.index)\">\n @for (part of resultParts(item.result); track part.text + '-' + $index) {\n <span\n [class.font-bold]=\"part.highlight\"\n [class.text-primary]=\"part.highlight\">{{ part.text }}</span>\n }\n </button>\n }\n </section>\n } @empty {\n <div class=\"pdf-viewer-search__empty p-4 text-center text-sm text-on-surface-variant\">No results.</div>\n }\n </div>\n }\n </div>\n </ngs-panel-content>\n</ngs-panel>\n", styles: [":host{display:block;min-height:0;height:100%}\n"] }]
326
321
  }], ctorParameters: () => [], propDecorators: { results: [{ type: i0.Input, args: [{ isSignal: true, alias: "results", required: false }] }], query: [{ type: i0.Input, args: [{ isSignal: true, alias: "query", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], resultSelected: [{ type: i0.Output, args: ["resultSelected"] }], searchChanged: [{ type: i0.Output, args: ["searchChanged"] }] } });
327
322
 
328
323
  class PdfViewer {
@@ -346,7 +341,7 @@ class PdfViewer {
346
341
  maxScale = input(60, { ...(ngDevMode ? { debugName: "maxScale" } : /* istanbul ignore next */ {}), transform: numberAttribute });
347
342
  zoomStep = input(0.1, { ...(ngDevMode ? { debugName: "zoomStep" } : /* istanbul ignore next */ {}), transform: numberAttribute });
348
343
  maxRenderPixels = input(128_000_000, { ...(ngDevMode ? { debugName: "maxRenderPixels" } : /* istanbul ignore next */ {}), transform: numberAttribute });
349
- maxRenderDimension = input(12_000, { ...(ngDevMode ? { debugName: "maxRenderDimension" } : /* istanbul ignore next */ {}), transform: numberAttribute });
344
+ maxRenderDimension = input(13_000, { ...(ngDevMode ? { debugName: "maxRenderDimension" } : /* istanbul ignore next */ {}), transform: numberAttribute });
350
345
  renderAll = input(true, { ...(ngDevMode ? { debugName: "renderAll" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
351
346
  showToolbar = input(true, { ...(ngDevMode ? { debugName: "showToolbar" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
352
347
  showPageList = input(true, { ...(ngDevMode ? { debugName: "showPageList" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -372,8 +367,10 @@ class PdfViewer {
372
367
  pageListVisible = signal(false, ...(ngDevMode ? [{ debugName: "pageListVisible" }] : /* istanbul ignore next */ []));
373
368
  searchPanelVisible = signal(false, ...(ngDevMode ? [{ debugName: "searchPanelVisible" }] : /* istanbul ignore next */ []));
374
369
  annotationsPanelVisible = signal(false, ...(ngDevMode ? [{ debugName: "annotationsPanelVisible" }] : /* istanbul ignore next */ []));
370
+ asidePanelInteractive = signal(false, ...(ngDevMode ? [{ debugName: "asidePanelInteractive" }] : /* istanbul ignore next */ []));
375
371
  spreadMode = signal('single', ...(ngDevMode ? [{ debugName: "spreadMode" }] : /* istanbul ignore next */ []));
376
- scrollLayout = signal('horizontal', ...(ngDevMode ? [{ debugName: "scrollLayout" }] : /* istanbul ignore next */ []));
372
+ scrollLayout = signal('vertical', ...(ngDevMode ? [{ debugName: "scrollLayout" }] : /* istanbul ignore next */ []));
373
+ pageRotation = signal(Rotation.Degree0, ...(ngDevMode ? [{ debugName: "pageRotation" }] : /* istanbul ignore next */ []));
377
374
  zoomMode = signal('custom', ...(ngDevMode ? [{ debugName: "zoomMode" }] : /* istanbul ignore next */ []));
378
375
  annotationItems = signal([], ...(ngDevMode ? [{ debugName: "annotationItems" }] : /* istanbul ignore next */ []));
379
376
  activeSearchQuery = signal('', ...(ngDevMode ? [{ debugName: "activeSearchQuery" }] : /* istanbul ignore next */ []));
@@ -397,6 +394,7 @@ class PdfViewer {
397
394
  canZoomIn = computed(() => this.zoom() < this.getScaleBounds().max, ...(ngDevMode ? [{ debugName: "canZoomIn" }] : /* istanbul ignore next */ []));
398
395
  zoomLabel = computed(() => `${Math.round(this.zoom() * 100)}%`, ...(ngDevMode ? [{ debugName: "zoomLabel" }] : /* istanbul ignore next */ []));
399
396
  displayDocumentName = computed(() => this.documentName() || this.getSourceName(this.src()), ...(ngDevMode ? [{ debugName: "displayDocumentName" }] : /* istanbul ignore next */ []));
397
+ pageSpreads = computed(() => this.groupPagesIntoSpreads(this.renderedPages(), this.spreadMode()), ...(ngDevMode ? [{ debugName: "pageSpreads" }] : /* istanbul ignore next */ []));
400
398
  zoomPresets = [0.25, 0.5, 1, 1.25, 1.5, 2, 4, 8, 16];
401
399
  engine = null;
402
400
  pdfDocument = null;
@@ -422,7 +420,13 @@ class PdfViewer {
422
420
  programmaticScrollMinDuration = 900;
423
421
  programmaticScrollMaxDuration = 6000;
424
422
  qualityRenderZoomIdleDelay = 160;
423
+ documentOpenTimeoutMs = 15000;
425
424
  constructor() {
425
+ afterNextRender(() => {
426
+ if (this.isBrowser) {
427
+ this.asidePanelInteractive.set(true);
428
+ }
429
+ });
426
430
  this.destroyRef.onDestroy(() => {
427
431
  this.loadToken++;
428
432
  this.renderToken++;
@@ -498,11 +502,15 @@ class PdfViewer {
498
502
  const activePage = renderAll ? untracked(() => this.activePage()) : this.activePage();
499
503
  const withAnnotations = this.withAnnotations();
500
504
  const withForms = this.withForms();
505
+ this.pageRotation();
506
+ this.spreadMode();
507
+ this.scrollLayout();
501
508
  if (!this.pdfDocument || !this.engine || this.isLoading()) {
502
509
  return;
503
510
  }
504
511
  untracked(() => {
505
512
  this.applyInstantZoom(zoom);
513
+ this.schedulePageObserverRefresh();
506
514
  this.scheduleVisiblePagesRender({ zoom, activePage, renderAll, withAnnotations, withForms });
507
515
  });
508
516
  });
@@ -510,6 +518,7 @@ class PdfViewer {
510
518
  const withAnnotations = this.withAnnotations();
511
519
  const isLoading = this.isLoading();
512
520
  const pageCount = this.pageCount();
521
+ this.pageRotation();
513
522
  if (isLoading || pageCount === 0 || !this.pdfDocument || !this.engine) {
514
523
  return;
515
524
  }
@@ -603,15 +612,68 @@ class PdfViewer {
603
612
  }
604
613
  setSpreadMode(mode) {
605
614
  this.spreadMode.set(mode);
615
+ this.refreshLayoutAfterModeChange();
606
616
  }
607
617
  setScrollLayout(layout) {
608
618
  this.scrollLayout.set(layout);
619
+ this.refreshLayoutAfterModeChange();
609
620
  }
610
621
  rotateClockwise() {
611
- this.renderedPages.update((pages) => [...pages]);
622
+ this.setPageRotation(this.rotatePageBy(1));
612
623
  }
613
624
  rotateCounterClockwise() {
614
- this.renderedPages.update((pages) => [...pages]);
625
+ this.setPageRotation(this.rotatePageBy(-1));
626
+ }
627
+ groupPagesIntoSpreads(pages, mode) {
628
+ if (mode === 'single') {
629
+ return pages.map((page) => ({
630
+ id: `single-${page.pageNumber}`,
631
+ leadingPlaceholder: false,
632
+ leadingPlaceholderPage: null,
633
+ pages: [page],
634
+ }));
635
+ }
636
+ const spreads = [];
637
+ let pageIndex = 0;
638
+ if (mode === 'two-even' && pages.length > 0) {
639
+ spreads.push({
640
+ id: 'two-even-cover',
641
+ leadingPlaceholder: true,
642
+ leadingPlaceholderPage: pages[0],
643
+ pages: [pages[0]],
644
+ });
645
+ pageIndex = 1;
646
+ }
647
+ while (pageIndex < pages.length) {
648
+ const spreadPages = pages.slice(pageIndex, pageIndex + 2);
649
+ spreads.push({
650
+ id: `${mode}-${spreadPages.map((page) => page.pageNumber).join('-')}`,
651
+ leadingPlaceholder: false,
652
+ leadingPlaceholderPage: null,
653
+ pages: spreadPages,
654
+ });
655
+ pageIndex += 2;
656
+ }
657
+ return spreads;
658
+ }
659
+ setPageRotation(rotation) {
660
+ this.pageRotation.set(rotation);
661
+ this.applyInstantZoom(this.zoom());
662
+ this.refreshLayoutAfterModeChange();
663
+ }
664
+ rotatePageBy(delta) {
665
+ return this.normalizeRotation(this.pageRotation() + delta);
666
+ }
667
+ refreshLayoutAfterModeChange() {
668
+ this.selectionStart = null;
669
+ this.selectionRects.set([]);
670
+ this.schedulePageObserverRefresh();
671
+ const targetWindow = this.document.defaultView;
672
+ if (!targetWindow) {
673
+ this.scrollToPage(this.activePage());
674
+ return;
675
+ }
676
+ targetWindow.requestAnimationFrame(() => this.scrollToPage(this.activePage()));
615
677
  }
616
678
  toggleFullscreen() {
617
679
  if (!this.isBrowser) {
@@ -923,12 +985,17 @@ class PdfViewer {
923
985
  const pdfPage = pdfDocument.pages[pageNumber - 1];
924
986
  const previousPage = previousPageMap.get(pageNumber);
925
987
  const displaySize = this.getPageDisplaySize(pdfPage, nextScale);
926
- const isFresh = previousPage?.url && Math.abs((previousPage.renderedScale ?? 0) - nextScale) < 0.0001;
988
+ const displayRotation = this.getPageDisplayRotation(pdfPage);
989
+ const isFresh = previousPage?.url
990
+ && Math.abs((previousPage.renderedScale ?? 0) - nextScale) < 0.0001
991
+ && previousPage.renderedRotation === displayRotation;
927
992
  return {
928
993
  pageNumber,
929
994
  url: isFresh ? previousPage.url : null,
930
995
  scale: nextScale,
931
996
  renderedScale: isFresh ? previousPage.renderedScale : null,
997
+ rotation: displayRotation,
998
+ renderedRotation: isFresh ? previousPage.renderedRotation : null,
932
999
  width: displaySize.width,
933
1000
  height: displaySize.height,
934
1001
  isRendering: false,
@@ -1001,17 +1068,21 @@ class PdfViewer {
1001
1068
  return;
1002
1069
  }
1003
1070
  const currentPage = this.renderedPages().find((page) => page.pageNumber === pageNumber);
1071
+ const page = pdfDocument.pages[pageNumber - 1];
1072
+ const renderRotation = this.getPageDisplayRotation(page);
1004
1073
  if (!currentPage || Math.abs(currentPage.scale - renderScale) > 0.0001) {
1005
1074
  continue;
1006
1075
  }
1007
- if (currentPage.url && Math.abs((currentPage.renderedScale ?? 0) - renderScale) < 0.0001) {
1076
+ if (currentPage.url
1077
+ && Math.abs((currentPage.renderedScale ?? 0) - renderScale) < 0.0001
1078
+ && currentPage.renderedRotation === renderRotation) {
1008
1079
  continue;
1009
1080
  }
1010
1081
  this.patchRenderedPage(pageNumber, { isRendering: !currentPage.url });
1011
- const page = pdfDocument.pages[pageNumber - 1];
1012
1082
  const rasterOptions = this.getPageRasterRenderOptions(page, renderScale);
1013
1083
  const blob = await this.engine.renderPage(pdfDocument, page, {
1014
1084
  scaleFactor: rasterOptions.scaleFactor,
1085
+ rotation: renderRotation,
1015
1086
  dpr: rasterOptions.dpr,
1016
1087
  withAnnotations: options.withAnnotations,
1017
1088
  withForms: options.withForms,
@@ -1020,7 +1091,9 @@ class PdfViewer {
1020
1091
  return;
1021
1092
  }
1022
1093
  const displaySize = this.getPageDisplaySize(page, renderScale);
1023
- const textGlyphs = await this.getPageTextGlyphs(pdfDocument, page, renderScale);
1094
+ const textGlyphs = this.pageRotation() === Rotation.Degree0
1095
+ ? await this.getPageTextGlyphs(pdfDocument, page, renderScale)
1096
+ : [];
1024
1097
  if (!this.isRenderCurrent(token, renderToken)) {
1025
1098
  return;
1026
1099
  }
@@ -1030,6 +1103,8 @@ class PdfViewer {
1030
1103
  url,
1031
1104
  scale: renderScale,
1032
1105
  renderedScale: renderScale,
1106
+ rotation: renderRotation,
1107
+ renderedRotation: renderRotation,
1033
1108
  width: displaySize.width,
1034
1109
  height: displaySize.height,
1035
1110
  isRendering: false,
@@ -1057,16 +1132,27 @@ class PdfViewer {
1057
1132
  return;
1058
1133
  }
1059
1134
  let hasChanges = false;
1135
+ const urlsToRevoke = [];
1060
1136
  const nextPages = pages.map((page) => {
1061
- if (Math.abs(page.scale - nextScale) < 0.0001) {
1137
+ const pdfPage = pdfDocument.pages[page.pageNumber - 1];
1138
+ const displaySize = this.getPageDisplaySize(pdfPage, nextScale);
1139
+ const displayRotation = this.getPageDisplayRotation(pdfPage);
1140
+ const scaleChanged = Math.abs(page.scale - nextScale) >= 0.0001;
1141
+ const rotationChanged = page.rotation !== displayRotation || page.renderedRotation !== displayRotation;
1142
+ if (!scaleChanged && !rotationChanged && page.width === displaySize.width && page.height === displaySize.height) {
1062
1143
  return page;
1063
1144
  }
1064
1145
  hasChanges = true;
1065
- const pdfPage = pdfDocument.pages[page.pageNumber - 1];
1066
- const displaySize = this.getPageDisplaySize(pdfPage, nextScale);
1146
+ if (rotationChanged && page.url) {
1147
+ urlsToRevoke.push(page.url);
1148
+ }
1067
1149
  return {
1068
1150
  ...page,
1151
+ url: rotationChanged ? null : page.url,
1069
1152
  scale: nextScale,
1153
+ renderedScale: rotationChanged ? null : page.renderedScale,
1154
+ rotation: displayRotation,
1155
+ renderedRotation: rotationChanged ? null : page.renderedRotation,
1070
1156
  width: displaySize.width,
1071
1157
  height: displaySize.height,
1072
1158
  isRendering: false,
@@ -1079,6 +1165,9 @@ class PdfViewer {
1079
1165
  this.selectionStart = null;
1080
1166
  this.selectionRects.set([]);
1081
1167
  this.renderedPages.set(nextPages);
1168
+ for (const url of urlsToRevoke) {
1169
+ this.revokeObjectUrl(url);
1170
+ }
1082
1171
  this.schedulePageObserverRefresh();
1083
1172
  }
1084
1173
  getPriorityPageNumbers(activePage, renderAll) {
@@ -1109,15 +1198,18 @@ class PdfViewer {
1109
1198
  return [];
1110
1199
  }
1111
1200
  const containerRect = container.getBoundingClientRect();
1112
- const prefetchMargin = containerRect.height;
1201
+ const verticalPrefetchMargin = containerRect.height;
1202
+ const horizontalPrefetchMargin = containerRect.width;
1113
1203
  const pages = Array.from(container.querySelectorAll('[data-ngs-pdf-page]'));
1114
1204
  const visiblePageNumbers = [];
1115
1205
  for (const page of pages) {
1116
1206
  const rect = page.getBoundingClientRect();
1117
1207
  const pageNumber = Number(page.dataset['ngsPdfPage']);
1118
1208
  if (Number.isFinite(pageNumber) &&
1119
- rect.bottom >= containerRect.top - prefetchMargin &&
1120
- rect.top <= containerRect.bottom + prefetchMargin) {
1209
+ rect.bottom >= containerRect.top - verticalPrefetchMargin &&
1210
+ rect.top <= containerRect.bottom + verticalPrefetchMargin &&
1211
+ rect.right >= containerRect.left - horizontalPrefetchMargin &&
1212
+ rect.left <= containerRect.right + horizontalPrefetchMargin) {
1121
1213
  visiblePageNumbers.push(pageNumber);
1122
1214
  }
1123
1215
  }
@@ -1137,6 +1229,7 @@ class PdfViewer {
1137
1229
  for (const page of pdfDocument.pages) {
1138
1230
  const blob = await this.engine.renderThumbnail(pdfDocument, page, {
1139
1231
  scaleFactor: thumbnailScale,
1232
+ rotation: this.getPageDisplayRotation(page),
1140
1233
  dpr: this.getDevicePixelRatio(),
1141
1234
  withAnnotations: options.withAnnotations,
1142
1235
  }).toPromise();
@@ -1323,16 +1416,39 @@ class PdfViewer {
1323
1416
  }
1324
1417
  async openSource(engine, documentId, source) {
1325
1418
  if (typeof source === 'string') {
1326
- return engine.openDocumentUrl({ id: documentId, url: source }).toPromise();
1419
+ const content = await this.fetchPdfSource(source);
1420
+ return this.openDocumentBuffer(engine, documentId, content);
1327
1421
  }
1328
1422
  if (source instanceof Blob) {
1329
- return engine.openDocumentBuffer({ id: documentId, content: await source.arrayBuffer() }).toPromise();
1423
+ return this.openDocumentBuffer(engine, documentId, await source.arrayBuffer());
1330
1424
  }
1331
1425
  if (source instanceof Uint8Array) {
1332
1426
  const content = new Uint8Array(source).buffer;
1333
- return engine.openDocumentBuffer({ id: documentId, content }).toPromise();
1427
+ return this.openDocumentBuffer(engine, documentId, content);
1428
+ }
1429
+ return this.openDocumentBuffer(engine, documentId, source);
1430
+ }
1431
+ async fetchPdfSource(source) {
1432
+ const response = await fetch(source);
1433
+ if (!response.ok) {
1434
+ throw new Error(`PDF request failed with status ${response.status}`);
1334
1435
  }
1335
- return engine.openDocumentBuffer({ id: documentId, content: source }).toPromise();
1436
+ return response.arrayBuffer();
1437
+ }
1438
+ openDocumentBuffer(engine, documentId, content) {
1439
+ return this.withTimeout(engine.openDocumentBuffer({ id: documentId, content }).toPromise(), this.documentOpenTimeoutMs, 'PDF document opening timed out');
1440
+ }
1441
+ withTimeout(promise, timeoutMs, message) {
1442
+ return new Promise((resolve, reject) => {
1443
+ const timeoutId = setTimeout(() => reject(new Error(message)), timeoutMs);
1444
+ promise.then((value) => {
1445
+ clearTimeout(timeoutId);
1446
+ resolve(value);
1447
+ }, (error) => {
1448
+ clearTimeout(timeoutId);
1449
+ reject(error);
1450
+ });
1451
+ });
1336
1452
  }
1337
1453
  async closeDocument() {
1338
1454
  if (!this.engine || !this.pdfDocument) {
@@ -1419,7 +1535,7 @@ class PdfViewer {
1419
1535
  const devicePixelRatio = Math.max(1, this.getDevicePixelRatio());
1420
1536
  const pageSize = this.getPageBaseSize(page);
1421
1537
  const maxRenderPixels = this.sanitizePositiveNumber(this.maxRenderPixels(), 128_000_000);
1422
- const maxRenderDimension = this.sanitizePositiveNumber(this.maxRenderDimension(), 12_000);
1538
+ const maxRenderDimension = this.sanitizePositiveNumber(this.maxRenderDimension(), 13_000);
1423
1539
  const targetEffectiveScale = scale * devicePixelRatio;
1424
1540
  const dimensionEffectiveScale = maxRenderDimension / Math.max(pageSize.width, pageSize.height);
1425
1541
  const pixelEffectiveScale = Math.sqrt(maxRenderPixels / (pageSize.width * pageSize.height));
@@ -1651,7 +1767,8 @@ class PdfViewer {
1651
1767
  };
1652
1768
  }
1653
1769
  getPageBaseSize(page) {
1654
- const isRotatedSideways = page.rotation === 1 || page.rotation === 3;
1770
+ const rotation = this.getPageDisplayRotation(page);
1771
+ const isRotatedSideways = rotation === Rotation.Degree90 || rotation === Rotation.Degree270;
1655
1772
  const width = isRotatedSideways ? page.size.height : page.size.width;
1656
1773
  const height = isRotatedSideways ? page.size.width : page.size.height;
1657
1774
  return {
@@ -1659,6 +1776,12 @@ class PdfViewer {
1659
1776
  height: Math.max(1, height),
1660
1777
  };
1661
1778
  }
1779
+ getPageDisplayRotation(page) {
1780
+ return this.normalizeRotation(page.rotation + this.pageRotation());
1781
+ }
1782
+ normalizeRotation(rotation) {
1783
+ return (((rotation % 4) + 4) % 4);
1784
+ }
1662
1785
  scrollToPage(pageNumber) {
1663
1786
  if (!this.renderAll()) {
1664
1787
  return;
@@ -1669,11 +1792,12 @@ class PdfViewer {
1669
1792
  return;
1670
1793
  }
1671
1794
  const nextScrollTop = this.getPageScrollTop(container, target);
1672
- const scrollDistance = Math.abs(container.scrollTop - nextScrollTop);
1795
+ const nextScrollLeft = this.getPageScrollLeft(container, target);
1796
+ const scrollDistance = Math.hypot(container.scrollTop - nextScrollTop, container.scrollLeft - nextScrollLeft);
1673
1797
  this.startProgrammaticScrollLock(pageNumber, scrollDistance);
1674
1798
  container.scrollTo({
1675
1799
  top: nextScrollTop,
1676
- left: this.getPageScrollLeft(container, target),
1800
+ left: nextScrollLeft,
1677
1801
  behavior: 'smooth',
1678
1802
  });
1679
1803
  }
@@ -1713,27 +1837,35 @@ class PdfViewer {
1713
1837
  return null;
1714
1838
  }
1715
1839
  const containerRect = container.getBoundingClientRect();
1716
- const viewportCenter = containerRect.top + containerRect.height / 2;
1840
+ const viewportCenterX = containerRect.left + containerRect.width / 2;
1841
+ const viewportCenterY = containerRect.top + containerRect.height / 2;
1717
1842
  const pages = Array.from(container.querySelectorAll('[data-ngs-pdf-page]'));
1718
1843
  let closestPage = null;
1719
1844
  let closestDistance = Number.POSITIVE_INFINITY;
1720
1845
  let mostVisiblePage = null;
1721
- let mostVisibleHeight = 0;
1846
+ let mostVisibleArea = 0;
1722
1847
  for (const page of pages) {
1723
1848
  const rect = page.getBoundingClientRect();
1724
1849
  const pageNumber = Number(page.dataset['ngsPdfPage']);
1725
1850
  if (!Number.isFinite(pageNumber)) {
1726
1851
  continue;
1727
1852
  }
1728
- if (rect.top <= viewportCenter && rect.bottom >= viewportCenter) {
1853
+ if (rect.left <= viewportCenterX &&
1854
+ rect.right >= viewportCenterX &&
1855
+ rect.top <= viewportCenterY &&
1856
+ rect.bottom >= viewportCenterY) {
1729
1857
  return pageNumber;
1730
1858
  }
1859
+ const visibleWidth = Math.max(0, Math.min(rect.right, containerRect.right) - Math.max(rect.left, containerRect.left));
1731
1860
  const visibleHeight = Math.max(0, Math.min(rect.bottom, containerRect.bottom) - Math.max(rect.top, containerRect.top));
1732
- if (visibleHeight > mostVisibleHeight) {
1733
- mostVisibleHeight = visibleHeight;
1861
+ const visibleArea = visibleWidth * visibleHeight;
1862
+ if (visibleArea > mostVisibleArea) {
1863
+ mostVisibleArea = visibleArea;
1734
1864
  mostVisiblePage = pageNumber;
1735
1865
  }
1736
- const distance = Math.min(Math.abs(rect.top - viewportCenter), Math.abs(rect.bottom - viewportCenter));
1866
+ const pageCenterX = rect.left + rect.width / 2;
1867
+ const pageCenterY = rect.top + rect.height / 2;
1868
+ const distance = Math.hypot(pageCenterX - viewportCenterX, pageCenterY - viewportCenterY);
1737
1869
  if (distance < closestDistance) {
1738
1870
  closestDistance = distance;
1739
1871
  closestPage = pageNumber;
@@ -1806,7 +1938,8 @@ class PdfViewer {
1806
1938
  this.completeProgrammaticScroll();
1807
1939
  return;
1808
1940
  }
1809
- if (Math.abs(container.scrollTop - this.getPageScrollTop(container, target)) <= 2) {
1941
+ if (Math.abs(container.scrollTop - this.getPageScrollTop(container, target)) <= 2 &&
1942
+ Math.abs(container.scrollLeft - this.getPageScrollLeft(container, target)) <= 2) {
1810
1943
  this.completeProgrammaticScroll();
1811
1944
  }
1812
1945
  }
@@ -1830,7 +1963,7 @@ class PdfViewer {
1830
1963
  this.programmaticScrollTargetPage = null;
1831
1964
  }
1832
1965
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PdfViewer, deps: [], target: i0.ɵɵFactoryTarget.Component });
1833
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: PdfViewer, isStandalone: true, selector: "ngs-pdf-viewer", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, documentName: { classPropertyName: "documentName", publicName: "documentName", isSignal: true, isRequired: false, transformFunction: null }, wasmUrl: { classPropertyName: "wasmUrl", publicName: "wasmUrl", isSignal: true, isRequired: false, transformFunction: null }, page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, minScale: { classPropertyName: "minScale", publicName: "minScale", isSignal: true, isRequired: false, transformFunction: null }, maxScale: { classPropertyName: "maxScale", publicName: "maxScale", isSignal: true, isRequired: false, transformFunction: null }, zoomStep: { classPropertyName: "zoomStep", publicName: "zoomStep", isSignal: true, isRequired: false, transformFunction: null }, maxRenderPixels: { classPropertyName: "maxRenderPixels", publicName: "maxRenderPixels", isSignal: true, isRequired: false, transformFunction: null }, maxRenderDimension: { classPropertyName: "maxRenderDimension", publicName: "maxRenderDimension", isSignal: true, isRequired: false, transformFunction: null }, renderAll: { classPropertyName: "renderAll", publicName: "renderAll", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showPageList: { classPropertyName: "showPageList", publicName: "showPageList", isSignal: true, isRequired: false, transformFunction: null }, showSearchPanel: { classPropertyName: "showSearchPanel", publicName: "showSearchPanel", isSignal: true, isRequired: false, transformFunction: null }, showAnnotationsPanel: { classPropertyName: "showAnnotationsPanel", publicName: "showAnnotationsPanel", isSignal: true, isRequired: false, transformFunction: null }, annotations: { classPropertyName: "annotations", publicName: "annotations", isSignal: true, isRequired: false, transformFunction: null }, annotationsDataSource: { classPropertyName: "annotationsDataSource", publicName: "annotationsDataSource", isSignal: true, isRequired: false, transformFunction: null }, annotationTypeProperty: { classPropertyName: "annotationTypeProperty", publicName: "annotationTypeProperty", isSignal: true, isRequired: false, transformFunction: null }, searchQuery: { classPropertyName: "searchQuery", publicName: "searchQuery", isSignal: true, isRequired: false, transformFunction: null }, withAnnotations: { classPropertyName: "withAnnotations", publicName: "withAnnotations", isSignal: true, isRequired: false, transformFunction: null }, withForms: { classPropertyName: "withForms", publicName: "withForms", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loaded: "loaded", pageChanged: "pageChanged", pageRendered: "pageRendered", error: "error" }, host: { properties: { "class.is-loading": "isLoading()", "class.has-toolbar": "showToolbar()", "class.has-page-list": "isPageListVisible()", "class.has-error": "errorState()" }, classAttribute: "ngs-pdf-viewer not-prose" }, queries: [{ propertyName: "annotationDefs", predicate: PdfViewerAnnotationDef, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "viewerBody", first: true, predicate: ["viewerBody"], descendants: true, isSignal: true }, { propertyName: "pageList", first: true, predicate: ["pageList"], descendants: true, isSignal: true }], exportAs: ["ngsPdfViewer"], ngImport: i0, template: "<ngs-panel class=\"pdf-viewer-panel h-full overflow-hidden rounded-lg border border-border bg-surface-container-low text-on-surface\">\n @if (showToolbar()) {\n <ngs-panel-header class=\"min-w-0 border-b border-border bg-surface\" flex>\n <ngs-toolbar class=\"pdf-viewer-toolbar flex h-14 w-full min-w-0 items-center gap-4 overflow-visible px-2 text-on-surface-variant\" aria-label=\"PDF viewer controls\">\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__start flex min-w-0 flex-none items-center gap-2\">\n @if (showPageList()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-label]=\"pageListVisible() ? 'Hide pages panel' : 'Show pages panel'\"\n [attr.aria-pressed]=\"pageListVisible()\"\n (click)=\"togglePageList()\">\n <ngs-icon\n class=\"text-2xl\"\n [name]=\"pageListVisible() ? 'fluent:panel-left-contract-24-regular' : 'fluent:panel-left-expand-24-regular'\" />\n </button>\n }\n <ngs-divider vertical />\n </ngs-toolbar-item>\n <ngs-toolbar-title class=\"min-w-0 flex-1 truncate text-sm! font-semibold! text-on-surface-variant\" [title]=\"displayDocumentName()\">\n {{ displayDocumentName() }}\n </ngs-toolbar-title>\n\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__center flex flex-none items-center gap-5\">\n <div class=\"pdf-viewer-toolbar__cluster flex min-w-0 items-center gap-2\" aria-label=\"Zoom controls\">\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Zoom out\"\n [disabled]=\"!canZoomOut()\"\n (click)=\"zoomOut()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:zoom-out-24-regular\" />\n </button>\n <button\n class=\"pdf-viewer-toolbar__zoom min-w-16 cursor-pointer border-0 bg-transparent p-0 text-center text-sm font-bold text-on-surface hover:text-primary\"\n type=\"button\"\n aria-label=\"Zoom presets\"\n [ngsMenuTriggerFor]=\"zoomMenu\">\n {{ zoomLabel() }}\n </button>\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Zoom in\"\n [disabled]=\"!canZoomIn()\"\n (click)=\"zoomIn()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:zoom-in-24-regular\" />\n </button>\n </div>\n\n <ngs-divider vertical />\n\n <div class=\"pdf-viewer-toolbar__cluster flex min-w-0 items-center gap-2\" aria-label=\"Page navigation\">\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Previous page\"\n [disabled]=\"!canGoPrevious()\"\n (click)=\"previousPage()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:chevron-left-24-regular\" />\n </button>\n <span class=\"pdf-viewer-toolbar__page inline-flex h-9 min-w-24 items-center justify-center gap-2 rounded bg-surface-container-low text-sm font-bold text-on-surface\">\n <span>{{ activePage() }}</span>\n <span>/</span>\n <span>{{ pageCount() || 1 }}</span>\n </span>\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Next page\"\n [disabled]=\"!canGoNext()\"\n (click)=\"nextPage()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:chevron-right-24-regular\" />\n </button>\n </div>\n </ngs-toolbar-item>\n\n <ngs-toolbar-spacer />\n\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__end flex min-w-0 flex-1 items-center justify-end gap-2\" aria-label=\"PDF tools\">\n @if (showSearchPanel()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-pressed]=\"isSearchPanelVisible()\"\n aria-label=\"Search\"\n (click)=\"toggleSearchPanel()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:search-24-regular\" />\n </button>\n }\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"PDF viewer settings\"\n [ngsMenuTriggerFor]=\"settingsMenu\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:settings-24-regular\" />\n </button>\n @if (showAnnotationsPanel()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-pressed]=\"isAnnotationsPanelVisible()\"\n aria-label=\"Toggle annotations panel\"\n (click)=\"toggleAnnotationsPanel()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:text-bullet-list-square-edit-24-regular\" />\n </button>\n }\n </ngs-toolbar-item>\n </ngs-toolbar>\n\n <ngs-menu #zoomMenu=\"ngsMenu\">\n @for (zoomPreset of zoomPresets; track zoomPreset) {\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"isZoomPresetSelected(zoomPreset)\"\n (click)=\"setZoomPreset(zoomPreset)\">\n <span>{{ zoomPreset * 100 }}%</span>\n </button>\n }\n\n <ngs-menu-divider />\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"zoomMode() === 'fit-page'\"\n (click)=\"fitToPage()\">\n <ngs-icon name=\"fluent:resize-large-24-regular\" />\n <span>Fit to Page</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"zoomMode() === 'fit-width'\"\n (click)=\"fitToWidth()\">\n <ngs-icon name=\"fluent:resize-24-regular\" />\n <span>Fit to Width</span>\n </button>\n </ngs-menu>\n\n <ngs-menu #settingsMenu=\"ngsMenu\" xPosition=\"before\">\n <ngs-menu-heading>SPREAD MODE</ngs-menu-heading>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'single'\"\n (click)=\"setSpreadMode('single')\">\n <ngs-icon name=\"fluent:document-24-regular\" />\n <span>Single Page</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'two-odd'\"\n (click)=\"setSpreadMode('two-odd')\">\n <ngs-icon name=\"fluent:book-open-24-regular\" />\n <span>Two Page (Odd)</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'two-even'\"\n (click)=\"setSpreadMode('two-even')\">\n <ngs-icon name=\"fluent:document-text-24-regular\" />\n <span>Two Page (Even)</span>\n </button>\n\n <ngs-menu-divider />\n <ngs-menu-heading>SCROLL LAYOUT</ngs-menu-heading>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"scrollLayout() === 'vertical'\"\n (click)=\"setScrollLayout('vertical')\">\n <ngs-icon name=\"fluent:arrow-sort-24-regular\" />\n <span>Vertical</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"scrollLayout() === 'horizontal'\"\n (click)=\"setScrollLayout('horizontal')\">\n <ngs-icon name=\"fluent:arrow-swap-24-regular\" />\n <span>Horizontal</span>\n </button>\n\n <ngs-menu-divider />\n <ngs-menu-heading>PAGE ROTATION</ngs-menu-heading>\n <button ngs-menu-item type=\"button\" (click)=\"rotateClockwise()\">\n <ngs-icon name=\"fluent:arrow-clockwise-24-regular\" />\n <span>Rotate Clockwise</span>\n </button>\n <button ngs-menu-item type=\"button\" (click)=\"rotateCounterClockwise()\">\n <ngs-icon name=\"fluent:arrow-counterclockwise-24-regular\" />\n <span>Rotate Counter-Clockwise</span>\n </button>\n\n <ngs-menu-divider />\n <button ngs-menu-item type=\"button\" (click)=\"toggleFullscreen()\">\n <ngs-icon name=\"fluent:arrow-maximize-24-regular\" />\n <span>Fullscreen</span>\n </button>\n </ngs-menu>\n </ngs-panel-header>\n }\n\n @if (isPageListVisible()) {\n <ngs-panel-sidebar class=\"w-[var(--ngs-pdf-viewer-sidebar-width)] min-w-[var(--ngs-pdf-viewer-sidebar-width)] border-r border-border bg-surface\">\n <div class=\"pdf-viewer-sidebar flex h-full min-h-0 flex-col gap-2 overflow-auto p-3\" #pageList>\n <div class=\"pdf-viewer-sidebar__title px-1 text-xs font-semibold text-on-surface-variant\">Pages</div>\n <div class=\"pdf-viewer-sidebar__pages flex min-h-0 flex-col gap-2\" aria-label=\"PDF pages\">\n @for (pageItem of pageItems(); track pageItem.pageNumber) {\n <button\n class=\"pdf-viewer-sidebar__page group flex w-full cursor-pointer flex-col items-stretch gap-1 rounded border border-transparent bg-transparent p-1 text-left text-on-surface-variant focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary [&.is-active]:text-on-surface\"\n type=\"button\"\n [class.is-active]=\"pageItem.pageNumber === activePage()\"\n [attr.aria-current]=\"pageItem.pageNumber === activePage() ? 'page' : null\"\n [attr.aria-label]=\"'Open page ' + pageItem.pageNumber\"\n [attr.data-ngs-pdf-page-button]=\"pageItem.pageNumber\"\n (click)=\"setPage(pageItem.pageNumber)\">\n <span class=\"pdf-viewer-sidebar__thumb flex aspect-[3/4] w-full items-center justify-center overflow-hidden rounded border border-border bg-surface shadow-xs group-hover:border-border group-[.is-active]:border-border group-[.is-active]:bg-primary-container group-[.is-active]:shadow-xs group-[.is-active]:ring-2 group-[.is-active]:ring-primary-container\" aria-hidden=\"true\">\n @if (pageItem.thumbnail; as thumbnail) {\n <img\n class=\"block h-full w-full select-none object-contain\"\n [src]=\"thumbnail.url\"\n [attr.width]=\"thumbnail.width\"\n [attr.height]=\"thumbnail.height\"\n alt=\"\"\n draggable=\"false\" />\n } @else {\n <ngs-image-placeholder class=\"h-full w-full\" />\n }\n </span>\n <span class=\"pdf-viewer-sidebar__label block truncate text-center text-xs font-medium leading-tight\">Page {{ pageItem.pageNumber }}</span>\n </button>\n }\n </div>\n </div>\n </ngs-panel-sidebar>\n }\n\n <ngs-panel-content class=\"min-h-0 min-w-0 overflow-hidden bg-surface-container-low\">\n <div class=\"pdf-viewer-body absolute inset-0 overflow-auto\" #viewerBody (scroll)=\"onViewerScroll()\" (wheel)=\"onViewerWheel($event)\">\n <ngs-block-loader [loading]=\"isLoading()\">Loading PDF...</ngs-block-loader>\n @if (errorState()) {\n <div class=\"pdf-viewer-state pdf-viewer-state--error absolute inset-0 flex flex-col items-center justify-center gap-3 p-6 text-center text-danger\">\n <ngs-icon class=\"text-3xl\" name=\"fluent:error-circle-24-regular\" />\n <span>PDF could not be loaded.</span>\n </div>\n } @else if (!src()) {\n <div class=\"pdf-viewer-state absolute inset-0 flex flex-col items-center justify-center gap-3 p-6 text-center text-on-surface-variant\">\n <ngs-icon class=\"text-3xl\" name=\"fluent:document-pdf-24-regular\" />\n <span>No PDF selected.</span>\n </div>\n } @else {\n <div class=\"pdf-viewer-pages grid min-h-full min-w-full w-max content-start grid-flow-row box-border justify-items-center gap-6 p-6\">\n @for (pdfPage of renderedPages(); track pdfPage.pageNumber) {\n <article\n class=\"pdf-viewer-page w-max max-w-none\"\n [attr.aria-label]=\"'PDF page ' + pdfPage.pageNumber\"\n [attr.data-ngs-pdf-page]=\"pdfPage.pageNumber\">\n <div\n class=\"pdf-viewer-page__surface relative cursor-text overflow-hidden rounded bg-surface shadow-md select-none touch-none\"\n [style.width.px]=\"pdfPage.width\"\n [style.height.px]=\"pdfPage.height\"\n (pointerdown)=\"startTextSelection($event, pdfPage)\"\n (pointermove)=\"updateTextSelection($event, pdfPage)\"\n (pointerup)=\"finishTextSelection($event, pdfPage)\"\n (pointercancel)=\"cancelTextSelection()\"\n (mousedown)=\"startTextSelection($event, pdfPage)\"\n (mousemove)=\"updateTextSelection($event, pdfPage)\"\n (mouseup)=\"finishTextSelection($event, pdfPage)\">\n @if (pdfPage.url; as pageUrl) {\n <img\n class=\"block h-full w-full max-w-none select-none pointer-events-none\"\n [src]=\"pageUrl\"\n [alt]=\"'PDF page ' + pdfPage.pageNumber\"\n [attr.width]=\"pdfPage.width\"\n [attr.height]=\"pdfPage.height\"\n draggable=\"false\" />\n } @else {\n <div class=\"pdf-viewer-page__placeholder pointer-events-none absolute inset-0 flex items-center justify-center bg-surface\" aria-hidden=\"true\">\n @if (pdfPage.isRendering) {\n <span class=\"size-8 animate-spin rounded-full border-2 border-border border-t-primary\"></span>\n }\n </div>\n }\n @if (selectionRectsForPage(pdfPage.pageNumber); as selectionRects) {\n @if (selectionRects.length > 0) {\n <div class=\"pdf-viewer-page__selection-layer pointer-events-none absolute inset-0 z-[1] isolate overflow-hidden mix-blend-multiply\" aria-hidden=\"true\">\n @for (selectionRect of selectionRects; track selectionRect.left + '-' + selectionRect.top + '-' + $index) {\n <div\n class=\"pdf-viewer-page__selection-rect pointer-events-none absolute bg-primary/30\"\n [style.left.px]=\"selectionRect.left\"\n [style.top.px]=\"selectionRect.top\"\n [style.width.px]=\"selectionRect.width\"\n [style.height.px]=\"selectionRect.height\"></div>\n }\n </div>\n }\n }\n </div>\n </article>\n }\n </div>\n }\n </div>\n </ngs-panel-content>\n\n @if (isSearchPanelVisible() || isAnnotationsPanelVisible()) {\n <ngs-panel-aside class=\"w-[var(--ngs-pdf-viewer-aside-width)] min-w-[var(--ngs-pdf-viewer-aside-width)] border-l border-border bg-surface\">\n @if (isSearchPanelVisible()) {\n <ngs-pdf-viewer-search\n [query]=\"activeSearchQuery()\"\n [results]=\"pdfSearchResults()\"\n (closed)=\"closeAsidePanel()\"\n (searchChanged)=\"updatePdfSearch($event)\"\n (resultSelected)=\"selectSearchResult($event)\" />\n } @else {\n <ngs-pdf-viewer-annotations\n [annotations]=\"annotationItems()\"\n [annotationDefs]=\"annotationDefs()\"\n [annotationTypeProperty]=\"annotationTypeProperty()\"\n (closed)=\"closeAsidePanel()\"\n (pageSelected)=\"setPage($event)\" />\n }\n </ngs-panel-aside>\n }\n</ngs-panel>\n", styles: [":host{--ngs-pdf-viewer-height: 720px;--ngs-pdf-viewer-min-height: 720px;--ngs-pdf-viewer-sidebar-width: 152px;--ngs-pdf-viewer-aside-width: 360px;display:block;height:var(--ngs-pdf-viewer-height);min-height:var(--ngs-pdf-viewer-min-height);overflow:hidden}:host .pdf-viewer-page__selection-layer{forced-color-adjust:none}\n"], dependencies: [{ kind: "component", type: BlockLoader, selector: "ngs-block-loader", inputs: ["loading", "spinnerDiameter", "spinnerStrokeWidth"], exportAs: ["ngsBlockLoader"] }, { kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: Divider, selector: "ngs-divider", inputs: ["vertical", "inset", "fixedHeight"], exportAs: ["ngsDivider"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: ImagePlaceholder, selector: "ngs-image-placeholder", exportAs: ["ngsImagePlaceholder"] }, { kind: "component", type: Menu, selector: "ngs-menu", inputs: ["role", "classList", "xPosition", "yPosition"], outputs: ["closed"], exportAs: ["ngsMenu"] }, { kind: "component", type: MenuDivider, selector: "ngs-menu-divider" }, { kind: "component", type: MenuHeading, selector: "ngs-menu-heading" }, { kind: "component", type: MenuItem, selector: "ngs-menu-item, [ngs-menu-item]", inputs: ["disabled", "role", "selected"], outputs: ["_triggered"], exportAs: ["ngsMenuItem"] }, { kind: "directive", type: MenuTrigger, selector: "[ngsMenuTriggerFor]", inputs: ["ngsMenuTriggerFor", "ngsMenuTriggerData", "ngsMenuDisabled", "xPosition", "yPosition", "ngsMenuTriggerRestoreFocus"], outputs: ["menuOpened", "menuClosed"], exportAs: ["ngsMenuTrigger"] }, { kind: "component", type: Panel, selector: "ngs-panel", inputs: ["absolute"], exportAs: ["ngsPanel"] }, { kind: "component", type: PanelAside, selector: "ngs-panel-aside" }, { kind: "component", type: PanelContent, selector: "ngs-panel-content", exportAs: ["ngsPanelContent"] }, { kind: "component", type: PanelHeader, selector: "ngs-panel-header", inputs: ["flex", "autoHeight"], exportAs: ["ngsPanelHeader"] }, { kind: "component", type: PanelSidebar, selector: "ngs-panel-sidebar" }, { kind: "component", type: Toolbar, selector: "ngs-toolbar", exportAs: ["ngsToolbar"] }, { kind: "component", type: ToolbarItem, selector: "ngs-toolbar-item", inputs: ["hidden"], outputs: ["hiddenChange"] }, { kind: "component", type: ToolbarSpacer, selector: "ngs-toolbar-spacer" }, { kind: "component", type: ToolbarTitle, selector: "ngs-toolbar-title" }, { kind: "component", type: PdfViewerAnnotations, selector: "ngs-pdf-viewer-annotations", inputs: ["annotations", "annotationDefs", "annotationTypeProperty"], outputs: ["closed", "pageSelected"] }, { kind: "component", type: PdfViewerSearch, selector: "ngs-pdf-viewer-search", inputs: ["results", "query"], outputs: ["closed", "resultSelected", "searchChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1966
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: PdfViewer, isStandalone: true, selector: "ngs-pdf-viewer", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, documentName: { classPropertyName: "documentName", publicName: "documentName", isSignal: true, isRequired: false, transformFunction: null }, wasmUrl: { classPropertyName: "wasmUrl", publicName: "wasmUrl", isSignal: true, isRequired: false, transformFunction: null }, page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, minScale: { classPropertyName: "minScale", publicName: "minScale", isSignal: true, isRequired: false, transformFunction: null }, maxScale: { classPropertyName: "maxScale", publicName: "maxScale", isSignal: true, isRequired: false, transformFunction: null }, zoomStep: { classPropertyName: "zoomStep", publicName: "zoomStep", isSignal: true, isRequired: false, transformFunction: null }, maxRenderPixels: { classPropertyName: "maxRenderPixels", publicName: "maxRenderPixels", isSignal: true, isRequired: false, transformFunction: null }, maxRenderDimension: { classPropertyName: "maxRenderDimension", publicName: "maxRenderDimension", isSignal: true, isRequired: false, transformFunction: null }, renderAll: { classPropertyName: "renderAll", publicName: "renderAll", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showPageList: { classPropertyName: "showPageList", publicName: "showPageList", isSignal: true, isRequired: false, transformFunction: null }, showSearchPanel: { classPropertyName: "showSearchPanel", publicName: "showSearchPanel", isSignal: true, isRequired: false, transformFunction: null }, showAnnotationsPanel: { classPropertyName: "showAnnotationsPanel", publicName: "showAnnotationsPanel", isSignal: true, isRequired: false, transformFunction: null }, annotations: { classPropertyName: "annotations", publicName: "annotations", isSignal: true, isRequired: false, transformFunction: null }, annotationsDataSource: { classPropertyName: "annotationsDataSource", publicName: "annotationsDataSource", isSignal: true, isRequired: false, transformFunction: null }, annotationTypeProperty: { classPropertyName: "annotationTypeProperty", publicName: "annotationTypeProperty", isSignal: true, isRequired: false, transformFunction: null }, searchQuery: { classPropertyName: "searchQuery", publicName: "searchQuery", isSignal: true, isRequired: false, transformFunction: null }, withAnnotations: { classPropertyName: "withAnnotations", publicName: "withAnnotations", isSignal: true, isRequired: false, transformFunction: null }, withForms: { classPropertyName: "withForms", publicName: "withForms", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loaded: "loaded", pageChanged: "pageChanged", pageRendered: "pageRendered", error: "error" }, host: { properties: { "class.is-loading": "isLoading()", "class.has-toolbar": "showToolbar()", "class.has-page-list": "isPageListVisible()", "class.has-error": "errorState()" }, classAttribute: "ngs-pdf-viewer not-prose" }, queries: [{ propertyName: "annotationDefs", predicate: PdfViewerAnnotationDef, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "viewerBody", first: true, predicate: ["viewerBody"], descendants: true, isSignal: true }, { propertyName: "pageList", first: true, predicate: ["pageList"], descendants: true, isSignal: true }], exportAs: ["ngsPdfViewer"], ngImport: i0, template: "<ngs-panel class=\"pdf-viewer-panel h-full overflow-hidden rounded-lg border border-border bg-surface-container-low text-on-surface\">\n @if (showToolbar()) {\n <ngs-panel-header class=\"min-w-0 border-b border-border bg-surface\" flex>\n <ngs-toolbar class=\"pdf-viewer-toolbar flex h-14 w-full min-w-0 items-center gap-4 overflow-visible px-2 text-on-surface-variant\" aria-label=\"PDF viewer controls\">\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__start flex min-w-0 flex-none items-center gap-2\">\n @if (showPageList()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-label]=\"pageListVisible() ? 'Hide pages panel' : 'Show pages panel'\"\n [attr.aria-pressed]=\"pageListVisible()\"\n (click)=\"togglePageList()\">\n <ngs-icon\n class=\"text-2xl\"\n [name]=\"pageListVisible() ? 'fluent:panel-left-contract-24-regular' : 'fluent:panel-left-expand-24-regular'\" />\n </button>\n }\n <ngs-divider vertical fixedHeight />\n </ngs-toolbar-item>\n <ngs-toolbar-title class=\"min-w-0 flex-1 truncate text-sm! max-w-[20%] font-semibold! text-on-surface-variant\" [title]=\"displayDocumentName()\">\n {{ displayDocumentName() }}\n </ngs-toolbar-title>\n\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__center flex flex-none items-center gap-3\">\n <div class=\"pdf-viewer-toolbar__cluster flex min-w-0 items-center gap-2\" aria-label=\"Zoom controls\">\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Zoom out\"\n [disabled]=\"!canZoomOut()\"\n (click)=\"zoomOut()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:zoom-out-24-regular\" />\n </button>\n <button\n class=\"pdf-viewer-toolbar__zoom min-w-12 cursor-pointer border-0 bg-transparent p-0 text-center text-sm text-on-surface hover:text-primary\"\n type=\"button\"\n aria-label=\"Zoom presets\"\n [ngsMenuTriggerFor]=\"zoomMenu\">\n {{ zoomLabel() }}\n </button>\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Zoom in\"\n [disabled]=\"!canZoomIn()\"\n (click)=\"zoomIn()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:zoom-in-24-regular\" />\n </button>\n </div>\n\n <ngs-divider vertical fixedHeight />\n\n <div class=\"pdf-viewer-toolbar__cluster flex min-w-0 items-center gap-2\" aria-label=\"Page navigation\">\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Previous page\"\n [disabled]=\"!canGoPrevious()\"\n (click)=\"previousPage()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:chevron-left-24-regular\" />\n </button>\n <span class=\"pdf-viewer-toolbar__page inline-flex h-9 min-w-16 items-center justify-center gap-2 rounded bg-surface-container-low text-sm font-bold text-on-surface\">\n <span>{{ activePage() }}</span>\n <span>/</span>\n <span>{{ pageCount() || 1 }}</span>\n </span>\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Next page\"\n [disabled]=\"!canGoNext()\"\n (click)=\"nextPage()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:chevron-right-24-regular\" />\n </button>\n </div>\n </ngs-toolbar-item>\n\n <ngs-toolbar-spacer />\n\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__end flex min-w-0 flex-1 items-center justify-end gap-2\" aria-label=\"PDF tools\">\n @if (showSearchPanel()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-pressed]=\"isSearchPanelVisible()\"\n aria-label=\"Search\"\n [disabled]=\"!asidePanelInteractive()\"\n (click)=\"toggleSearchPanel()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:search-24-regular\" />\n </button>\n }\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"PDF viewer settings\"\n [ngsMenuTriggerFor]=\"settingsMenu\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:settings-24-regular\" />\n </button>\n @if (showAnnotationsPanel()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-pressed]=\"isAnnotationsPanelVisible()\"\n aria-label=\"Toggle annotations panel\"\n [disabled]=\"!asidePanelInteractive()\"\n (click)=\"toggleAnnotationsPanel()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:text-bullet-list-square-edit-24-regular\" />\n </button>\n }\n </ngs-toolbar-item>\n </ngs-toolbar>\n\n <ngs-menu #zoomMenu=\"ngsMenu\">\n @for (zoomPreset of zoomPresets; track zoomPreset) {\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"isZoomPresetSelected(zoomPreset)\"\n (click)=\"setZoomPreset(zoomPreset)\">\n <span>{{ zoomPreset * 100 }}%</span>\n </button>\n }\n\n <ngs-menu-divider />\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"zoomMode() === 'fit-page'\"\n (click)=\"fitToPage()\">\n <ngs-icon name=\"fluent:resize-large-24-regular\" />\n <span>Fit to Page</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"zoomMode() === 'fit-width'\"\n (click)=\"fitToWidth()\">\n <ngs-icon name=\"fluent:resize-24-regular\" />\n <span>Fit to Width</span>\n </button>\n </ngs-menu>\n\n <ngs-menu #settingsMenu=\"ngsMenu\" xPosition=\"before\">\n <ngs-menu-heading>SPREAD MODE</ngs-menu-heading>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'single'\"\n (click)=\"setSpreadMode('single')\">\n <ngs-icon name=\"fluent:document-24-regular\" />\n <span>Single Page</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'two-odd'\"\n (click)=\"setSpreadMode('two-odd')\">\n <ngs-icon name=\"fluent:book-open-24-regular\" />\n <span>Two Page (Odd)</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'two-even'\"\n (click)=\"setSpreadMode('two-even')\">\n <ngs-icon name=\"fluent:document-text-24-regular\" />\n <span>Two Page (Even)</span>\n </button>\n\n <ngs-menu-divider />\n <ngs-menu-heading>SCROLL LAYOUT</ngs-menu-heading>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"scrollLayout() === 'vertical'\"\n (click)=\"setScrollLayout('vertical')\">\n <ngs-icon name=\"fluent:arrow-sort-24-regular\" />\n <span>Vertical</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"scrollLayout() === 'horizontal'\"\n (click)=\"setScrollLayout('horizontal')\">\n <ngs-icon name=\"fluent:arrow-swap-24-regular\" />\n <span>Horizontal</span>\n </button>\n\n <ngs-menu-divider />\n <ngs-menu-heading>PAGE ROTATION</ngs-menu-heading>\n <button ngs-menu-item type=\"button\" (click)=\"rotateClockwise()\">\n <ngs-icon name=\"fluent:arrow-clockwise-24-regular\" />\n <span>Rotate Clockwise</span>\n </button>\n <button ngs-menu-item type=\"button\" (click)=\"rotateCounterClockwise()\">\n <ngs-icon name=\"fluent:arrow-counterclockwise-24-regular\" />\n <span>Rotate Counter-Clockwise</span>\n </button>\n\n <ngs-menu-divider />\n <button ngs-menu-item type=\"button\" (click)=\"toggleFullscreen()\">\n <ngs-icon name=\"fluent:arrow-maximize-24-regular\" />\n <span>Fullscreen</span>\n </button>\n </ngs-menu>\n </ngs-panel-header>\n }\n\n @if (isPageListVisible()) {\n <ngs-panel-sidebar class=\"w-[var(--ngs-pdf-viewer-sidebar-width)] min-w-[var(--ngs-pdf-viewer-sidebar-width)] border-r border-border bg-surface\">\n <div class=\"pdf-viewer-sidebar flex h-full min-h-0 flex-col gap-2 overflow-auto p-3\" #pageList>\n <div class=\"pdf-viewer-sidebar__title px-1 text-xs font-semibold text-on-surface-variant\">Pages</div>\n <div class=\"pdf-viewer-sidebar__pages flex min-h-0 flex-col gap-2\" aria-label=\"PDF pages\">\n @for (pageItem of pageItems(); track pageItem.pageNumber) {\n <button\n class=\"pdf-viewer-sidebar__page group flex w-full cursor-pointer flex-col items-stretch gap-1 rounded border border-transparent bg-transparent p-1 text-left text-on-surface-variant focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary [&.is-active]:text-on-surface\"\n type=\"button\"\n [class.is-active]=\"pageItem.pageNumber === activePage()\"\n [attr.aria-current]=\"pageItem.pageNumber === activePage() ? 'page' : null\"\n [attr.aria-label]=\"'Open page ' + pageItem.pageNumber\"\n [attr.data-ngs-pdf-page-button]=\"pageItem.pageNumber\"\n (click)=\"setPage(pageItem.pageNumber)\">\n <span class=\"pdf-viewer-sidebar__thumb flex aspect-[3/4] w-full items-center justify-center overflow-hidden rounded border border-border bg-surface shadow-xs group-hover:border-border\" aria-hidden=\"true\">\n @if (pageItem.thumbnail; as thumbnail) {\n <img\n class=\"block h-full w-full select-none object-contain\"\n [src]=\"thumbnail.url\"\n [attr.width]=\"thumbnail.width\"\n [attr.height]=\"thumbnail.height\"\n alt=\"\"\n draggable=\"false\" />\n } @else {\n <ngs-image-placeholder class=\"h-full w-full\" />\n }\n </span>\n <span class=\"pdf-viewer-sidebar__label block truncate text-center text-xs font-medium leading-tight\">Page {{ pageItem.pageNumber }}</span>\n </button>\n }\n </div>\n </div>\n </ngs-panel-sidebar>\n }\n\n <ngs-panel-content class=\"min-h-0 min-w-0 overflow-hidden bg-surface-container-low\">\n <div class=\"pdf-viewer-body absolute inset-0 overflow-auto\" #viewerBody (scroll)=\"onViewerScroll()\" (wheel)=\"onViewerWheel($event)\">\n <ngs-block-loader [loading]=\"isLoading()\">Loading PDF...</ngs-block-loader>\n @if (errorState()) {\n <div class=\"pdf-viewer-state pdf-viewer-state--error absolute inset-0 flex flex-col items-center justify-center gap-3 p-6 text-center text-danger\">\n <ngs-icon class=\"text-3xl\" name=\"fluent:error-circle-24-regular\" />\n <span>PDF could not be loaded.</span>\n </div>\n } @else if (!src()) {\n <div class=\"pdf-viewer-state absolute inset-0 flex flex-col items-center justify-center gap-3 p-6 text-center text-on-surface-variant\">\n <ngs-icon class=\"text-3xl\" name=\"fluent:document-pdf-24-regular\" />\n <span>No PDF selected.</span>\n </div>\n } @else {\n <div\n class=\"pdf-viewer-pages\"\n [class.is-horizontal]=\"scrollLayout() === 'horizontal'\"\n [class.is-vertical]=\"scrollLayout() === 'vertical'\"\n [class.is-spread]=\"spreadMode() !== 'single'\">\n @for (spread of pageSpreads(); track spread.id) {\n <div class=\"pdf-viewer-spread\" [attr.data-ngs-pdf-spread]=\"spread.id\">\n @if (spread.leadingPlaceholder) {\n @if (spread.leadingPlaceholderPage; as placeholderPage) {\n <div\n class=\"pdf-viewer-spread__placeholder\"\n [style.width.px]=\"placeholderPage.width\"\n [style.height.px]=\"placeholderPage.height\"\n aria-hidden=\"true\"></div>\n }\n }\n @for (pdfPage of spread.pages; track pdfPage.pageNumber) {\n <article\n class=\"pdf-viewer-page w-max max-w-none\"\n [attr.aria-label]=\"'PDF page ' + pdfPage.pageNumber\"\n [attr.data-ngs-pdf-page]=\"pdfPage.pageNumber\">\n <div\n class=\"pdf-viewer-page__surface relative cursor-text overflow-hidden rounded bg-surface shadow-md select-none touch-none\"\n [style.width.px]=\"pdfPage.width\"\n [style.height.px]=\"pdfPage.height\"\n (pointerdown)=\"startTextSelection($event, pdfPage)\"\n (pointermove)=\"updateTextSelection($event, pdfPage)\"\n (pointerup)=\"finishTextSelection($event, pdfPage)\"\n (pointercancel)=\"cancelTextSelection()\"\n (mousedown)=\"startTextSelection($event, pdfPage)\"\n (mousemove)=\"updateTextSelection($event, pdfPage)\"\n (mouseup)=\"finishTextSelection($event, pdfPage)\">\n @if (pdfPage.url; as pageUrl) {\n <img\n class=\"block h-full w-full max-w-none select-none pointer-events-none\"\n [src]=\"pageUrl\"\n [alt]=\"'PDF page ' + pdfPage.pageNumber\"\n [attr.width]=\"pdfPage.width\"\n [attr.height]=\"pdfPage.height\"\n draggable=\"false\" />\n } @else {\n <div class=\"pdf-viewer-page__placeholder pointer-events-none absolute inset-0 flex items-center justify-center bg-surface\" aria-hidden=\"true\">\n @if (pdfPage.isRendering) {\n <span class=\"size-8 animate-spin rounded-full border-2 border-border border-t-primary\"></span>\n }\n </div>\n }\n @if (selectionRectsForPage(pdfPage.pageNumber); as selectionRects) {\n @if (selectionRects.length > 0) {\n <div class=\"pdf-viewer-page__selection-layer pointer-events-none absolute inset-0 z-[1] isolate overflow-hidden mix-blend-multiply\" aria-hidden=\"true\">\n @for (selectionRect of selectionRects; track selectionRect.left + '-' + selectionRect.top + '-' + $index) {\n <div\n class=\"pdf-viewer-page__selection-rect pointer-events-none absolute bg-primary/30\"\n [style.left.px]=\"selectionRect.left\"\n [style.top.px]=\"selectionRect.top\"\n [style.width.px]=\"selectionRect.width\"\n [style.height.px]=\"selectionRect.height\"></div>\n }\n </div>\n }\n }\n </div>\n </article>\n }\n </div>\n }\n </div>\n }\n </div>\n </ngs-panel-content>\n\n @if (isSearchPanelVisible() || isAnnotationsPanelVisible()) {\n <ngs-panel-aside class=\"w-[var(--ngs-pdf-viewer-aside-width)] min-w-[var(--ngs-pdf-viewer-aside-width)] border-l border-border bg-surface\">\n @if (isSearchPanelVisible()) {\n <ngs-pdf-viewer-search\n [query]=\"activeSearchQuery()\"\n [results]=\"pdfSearchResults()\"\n (closed)=\"closeAsidePanel()\"\n (searchChanged)=\"updatePdfSearch($event)\"\n (resultSelected)=\"selectSearchResult($event)\" />\n } @else {\n <ngs-pdf-viewer-annotations\n [annotations]=\"annotationItems()\"\n [annotationDefs]=\"annotationDefs()\"\n [annotationTypeProperty]=\"annotationTypeProperty()\"\n (closed)=\"closeAsidePanel()\"\n (pageSelected)=\"setPage($event)\" />\n }\n </ngs-panel-aside>\n }\n</ngs-panel>\n", styles: [":host{--ngs-pdf-viewer-height: 720px;--ngs-pdf-viewer-min-height: 720px;--ngs-pdf-viewer-sidebar-width: 152px;--ngs-pdf-viewer-aside-width: 360px;--ngs-pdf-viewer-page-gap: 24px;--ngs-pdf-viewer-spread-gap: 16px;--ngs-pdf-viewer-page-padding: 24px;display:block;height:var(--ngs-pdf-viewer-height);min-height:var(--ngs-pdf-viewer-min-height);overflow:hidden}:host .pdf-viewer-pages{box-sizing:border-box;display:grid;gap:var(--ngs-pdf-viewer-page-gap);min-height:100%;min-width:100%;padding:var(--ngs-pdf-viewer-page-padding)}:host .pdf-viewer-pages.is-vertical{align-content:start;grid-auto-flow:row;grid-auto-rows:max-content;justify-items:center}:host .pdf-viewer-pages.is-horizontal{align-content:center;align-items:center;grid-auto-columns:max-content;grid-auto-flow:column;justify-content:start;width:max-content}:host .pdf-viewer-spread{align-items:start;display:grid;gap:var(--ngs-pdf-viewer-spread-gap);grid-auto-columns:max-content;grid-auto-flow:column;justify-content:center}:host .pdf-viewer-spread__placeholder{pointer-events:none;visibility:hidden}:host .pdf-viewer-toolbar{position:relative}:host .pdf-viewer-toolbar__center{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:1}:host .pdf-viewer-toolbar__start,:host .pdf-viewer-toolbar__end{position:relative;z-index:2}:host .pdf-viewer-sidebar__page.is-active .pdf-viewer-sidebar__thumb{outline:2px solid var(--ngs-color-primary)}:host .pdf-viewer-page__selection-layer{forced-color-adjust:none}\n"], dependencies: [{ kind: "component", type: BlockLoader, selector: "ngs-block-loader", inputs: ["loading", "spinnerDiameter", "spinnerStrokeWidth"], exportAs: ["ngsBlockLoader"] }, { kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: Divider, selector: "ngs-divider", inputs: ["vertical", "inset", "fixedHeight"], exportAs: ["ngsDivider"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: ImagePlaceholder, selector: "ngs-image-placeholder", exportAs: ["ngsImagePlaceholder"] }, { kind: "component", type: Menu, selector: "ngs-menu", inputs: ["role", "classList", "xPosition", "yPosition"], outputs: ["closed"], exportAs: ["ngsMenu"] }, { kind: "component", type: MenuDivider, selector: "ngs-menu-divider" }, { kind: "component", type: MenuHeading, selector: "ngs-menu-heading" }, { kind: "component", type: MenuItem, selector: "ngs-menu-item, [ngs-menu-item]", inputs: ["disabled", "role", "selected"], outputs: ["_triggered"], exportAs: ["ngsMenuItem"] }, { kind: "directive", type: MenuTrigger, selector: "[ngsMenuTriggerFor]", inputs: ["ngsMenuTriggerFor", "ngsMenuTriggerData", "ngsMenuDisabled", "xPosition", "yPosition", "ngsMenuTriggerRestoreFocus"], outputs: ["menuOpened", "menuClosed"], exportAs: ["ngsMenuTrigger"] }, { kind: "component", type: Panel, selector: "ngs-panel", inputs: ["absolute"], exportAs: ["ngsPanel"] }, { kind: "component", type: PanelAside, selector: "ngs-panel-aside" }, { kind: "component", type: PanelContent, selector: "ngs-panel-content", exportAs: ["ngsPanelContent"] }, { kind: "component", type: PanelHeader, selector: "ngs-panel-header", inputs: ["flex", "autoHeight"], exportAs: ["ngsPanelHeader"] }, { kind: "component", type: PanelSidebar, selector: "ngs-panel-sidebar" }, { kind: "component", type: Toolbar, selector: "ngs-toolbar", exportAs: ["ngsToolbar"] }, { kind: "component", type: ToolbarItem, selector: "ngs-toolbar-item", inputs: ["hidden"], outputs: ["hiddenChange"] }, { kind: "component", type: ToolbarSpacer, selector: "ngs-toolbar-spacer" }, { kind: "component", type: ToolbarTitle, selector: "ngs-toolbar-title" }, { kind: "component", type: PdfViewerAnnotations, selector: "ngs-pdf-viewer-annotations", inputs: ["annotations", "annotationDefs", "annotationTypeProperty"], outputs: ["closed", "pageSelected"] }, { kind: "component", type: PdfViewerSearch, selector: "ngs-pdf-viewer-search", inputs: ["results", "query"], outputs: ["closed", "resultSelected", "searchChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1834
1967
  }
1835
1968
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PdfViewer, decorators: [{
1836
1969
  type: Component,
@@ -1862,7 +1995,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
1862
1995
  '[class.has-toolbar]': 'showToolbar()',
1863
1996
  '[class.has-page-list]': 'isPageListVisible()',
1864
1997
  '[class.has-error]': 'errorState()',
1865
- }, template: "<ngs-panel class=\"pdf-viewer-panel h-full overflow-hidden rounded-lg border border-border bg-surface-container-low text-on-surface\">\n @if (showToolbar()) {\n <ngs-panel-header class=\"min-w-0 border-b border-border bg-surface\" flex>\n <ngs-toolbar class=\"pdf-viewer-toolbar flex h-14 w-full min-w-0 items-center gap-4 overflow-visible px-2 text-on-surface-variant\" aria-label=\"PDF viewer controls\">\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__start flex min-w-0 flex-none items-center gap-2\">\n @if (showPageList()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-label]=\"pageListVisible() ? 'Hide pages panel' : 'Show pages panel'\"\n [attr.aria-pressed]=\"pageListVisible()\"\n (click)=\"togglePageList()\">\n <ngs-icon\n class=\"text-2xl\"\n [name]=\"pageListVisible() ? 'fluent:panel-left-contract-24-regular' : 'fluent:panel-left-expand-24-regular'\" />\n </button>\n }\n <ngs-divider vertical />\n </ngs-toolbar-item>\n <ngs-toolbar-title class=\"min-w-0 flex-1 truncate text-sm! font-semibold! text-on-surface-variant\" [title]=\"displayDocumentName()\">\n {{ displayDocumentName() }}\n </ngs-toolbar-title>\n\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__center flex flex-none items-center gap-5\">\n <div class=\"pdf-viewer-toolbar__cluster flex min-w-0 items-center gap-2\" aria-label=\"Zoom controls\">\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Zoom out\"\n [disabled]=\"!canZoomOut()\"\n (click)=\"zoomOut()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:zoom-out-24-regular\" />\n </button>\n <button\n class=\"pdf-viewer-toolbar__zoom min-w-16 cursor-pointer border-0 bg-transparent p-0 text-center text-sm font-bold text-on-surface hover:text-primary\"\n type=\"button\"\n aria-label=\"Zoom presets\"\n [ngsMenuTriggerFor]=\"zoomMenu\">\n {{ zoomLabel() }}\n </button>\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Zoom in\"\n [disabled]=\"!canZoomIn()\"\n (click)=\"zoomIn()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:zoom-in-24-regular\" />\n </button>\n </div>\n\n <ngs-divider vertical />\n\n <div class=\"pdf-viewer-toolbar__cluster flex min-w-0 items-center gap-2\" aria-label=\"Page navigation\">\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Previous page\"\n [disabled]=\"!canGoPrevious()\"\n (click)=\"previousPage()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:chevron-left-24-regular\" />\n </button>\n <span class=\"pdf-viewer-toolbar__page inline-flex h-9 min-w-24 items-center justify-center gap-2 rounded bg-surface-container-low text-sm font-bold text-on-surface\">\n <span>{{ activePage() }}</span>\n <span>/</span>\n <span>{{ pageCount() || 1 }}</span>\n </span>\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Next page\"\n [disabled]=\"!canGoNext()\"\n (click)=\"nextPage()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:chevron-right-24-regular\" />\n </button>\n </div>\n </ngs-toolbar-item>\n\n <ngs-toolbar-spacer />\n\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__end flex min-w-0 flex-1 items-center justify-end gap-2\" aria-label=\"PDF tools\">\n @if (showSearchPanel()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-pressed]=\"isSearchPanelVisible()\"\n aria-label=\"Search\"\n (click)=\"toggleSearchPanel()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:search-24-regular\" />\n </button>\n }\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"PDF viewer settings\"\n [ngsMenuTriggerFor]=\"settingsMenu\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:settings-24-regular\" />\n </button>\n @if (showAnnotationsPanel()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-pressed]=\"isAnnotationsPanelVisible()\"\n aria-label=\"Toggle annotations panel\"\n (click)=\"toggleAnnotationsPanel()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:text-bullet-list-square-edit-24-regular\" />\n </button>\n }\n </ngs-toolbar-item>\n </ngs-toolbar>\n\n <ngs-menu #zoomMenu=\"ngsMenu\">\n @for (zoomPreset of zoomPresets; track zoomPreset) {\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"isZoomPresetSelected(zoomPreset)\"\n (click)=\"setZoomPreset(zoomPreset)\">\n <span>{{ zoomPreset * 100 }}%</span>\n </button>\n }\n\n <ngs-menu-divider />\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"zoomMode() === 'fit-page'\"\n (click)=\"fitToPage()\">\n <ngs-icon name=\"fluent:resize-large-24-regular\" />\n <span>Fit to Page</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"zoomMode() === 'fit-width'\"\n (click)=\"fitToWidth()\">\n <ngs-icon name=\"fluent:resize-24-regular\" />\n <span>Fit to Width</span>\n </button>\n </ngs-menu>\n\n <ngs-menu #settingsMenu=\"ngsMenu\" xPosition=\"before\">\n <ngs-menu-heading>SPREAD MODE</ngs-menu-heading>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'single'\"\n (click)=\"setSpreadMode('single')\">\n <ngs-icon name=\"fluent:document-24-regular\" />\n <span>Single Page</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'two-odd'\"\n (click)=\"setSpreadMode('two-odd')\">\n <ngs-icon name=\"fluent:book-open-24-regular\" />\n <span>Two Page (Odd)</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'two-even'\"\n (click)=\"setSpreadMode('two-even')\">\n <ngs-icon name=\"fluent:document-text-24-regular\" />\n <span>Two Page (Even)</span>\n </button>\n\n <ngs-menu-divider />\n <ngs-menu-heading>SCROLL LAYOUT</ngs-menu-heading>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"scrollLayout() === 'vertical'\"\n (click)=\"setScrollLayout('vertical')\">\n <ngs-icon name=\"fluent:arrow-sort-24-regular\" />\n <span>Vertical</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"scrollLayout() === 'horizontal'\"\n (click)=\"setScrollLayout('horizontal')\">\n <ngs-icon name=\"fluent:arrow-swap-24-regular\" />\n <span>Horizontal</span>\n </button>\n\n <ngs-menu-divider />\n <ngs-menu-heading>PAGE ROTATION</ngs-menu-heading>\n <button ngs-menu-item type=\"button\" (click)=\"rotateClockwise()\">\n <ngs-icon name=\"fluent:arrow-clockwise-24-regular\" />\n <span>Rotate Clockwise</span>\n </button>\n <button ngs-menu-item type=\"button\" (click)=\"rotateCounterClockwise()\">\n <ngs-icon name=\"fluent:arrow-counterclockwise-24-regular\" />\n <span>Rotate Counter-Clockwise</span>\n </button>\n\n <ngs-menu-divider />\n <button ngs-menu-item type=\"button\" (click)=\"toggleFullscreen()\">\n <ngs-icon name=\"fluent:arrow-maximize-24-regular\" />\n <span>Fullscreen</span>\n </button>\n </ngs-menu>\n </ngs-panel-header>\n }\n\n @if (isPageListVisible()) {\n <ngs-panel-sidebar class=\"w-[var(--ngs-pdf-viewer-sidebar-width)] min-w-[var(--ngs-pdf-viewer-sidebar-width)] border-r border-border bg-surface\">\n <div class=\"pdf-viewer-sidebar flex h-full min-h-0 flex-col gap-2 overflow-auto p-3\" #pageList>\n <div class=\"pdf-viewer-sidebar__title px-1 text-xs font-semibold text-on-surface-variant\">Pages</div>\n <div class=\"pdf-viewer-sidebar__pages flex min-h-0 flex-col gap-2\" aria-label=\"PDF pages\">\n @for (pageItem of pageItems(); track pageItem.pageNumber) {\n <button\n class=\"pdf-viewer-sidebar__page group flex w-full cursor-pointer flex-col items-stretch gap-1 rounded border border-transparent bg-transparent p-1 text-left text-on-surface-variant focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary [&.is-active]:text-on-surface\"\n type=\"button\"\n [class.is-active]=\"pageItem.pageNumber === activePage()\"\n [attr.aria-current]=\"pageItem.pageNumber === activePage() ? 'page' : null\"\n [attr.aria-label]=\"'Open page ' + pageItem.pageNumber\"\n [attr.data-ngs-pdf-page-button]=\"pageItem.pageNumber\"\n (click)=\"setPage(pageItem.pageNumber)\">\n <span class=\"pdf-viewer-sidebar__thumb flex aspect-[3/4] w-full items-center justify-center overflow-hidden rounded border border-border bg-surface shadow-xs group-hover:border-border group-[.is-active]:border-border group-[.is-active]:bg-primary-container group-[.is-active]:shadow-xs group-[.is-active]:ring-2 group-[.is-active]:ring-primary-container\" aria-hidden=\"true\">\n @if (pageItem.thumbnail; as thumbnail) {\n <img\n class=\"block h-full w-full select-none object-contain\"\n [src]=\"thumbnail.url\"\n [attr.width]=\"thumbnail.width\"\n [attr.height]=\"thumbnail.height\"\n alt=\"\"\n draggable=\"false\" />\n } @else {\n <ngs-image-placeholder class=\"h-full w-full\" />\n }\n </span>\n <span class=\"pdf-viewer-sidebar__label block truncate text-center text-xs font-medium leading-tight\">Page {{ pageItem.pageNumber }}</span>\n </button>\n }\n </div>\n </div>\n </ngs-panel-sidebar>\n }\n\n <ngs-panel-content class=\"min-h-0 min-w-0 overflow-hidden bg-surface-container-low\">\n <div class=\"pdf-viewer-body absolute inset-0 overflow-auto\" #viewerBody (scroll)=\"onViewerScroll()\" (wheel)=\"onViewerWheel($event)\">\n <ngs-block-loader [loading]=\"isLoading()\">Loading PDF...</ngs-block-loader>\n @if (errorState()) {\n <div class=\"pdf-viewer-state pdf-viewer-state--error absolute inset-0 flex flex-col items-center justify-center gap-3 p-6 text-center text-danger\">\n <ngs-icon class=\"text-3xl\" name=\"fluent:error-circle-24-regular\" />\n <span>PDF could not be loaded.</span>\n </div>\n } @else if (!src()) {\n <div class=\"pdf-viewer-state absolute inset-0 flex flex-col items-center justify-center gap-3 p-6 text-center text-on-surface-variant\">\n <ngs-icon class=\"text-3xl\" name=\"fluent:document-pdf-24-regular\" />\n <span>No PDF selected.</span>\n </div>\n } @else {\n <div class=\"pdf-viewer-pages grid min-h-full min-w-full w-max content-start grid-flow-row box-border justify-items-center gap-6 p-6\">\n @for (pdfPage of renderedPages(); track pdfPage.pageNumber) {\n <article\n class=\"pdf-viewer-page w-max max-w-none\"\n [attr.aria-label]=\"'PDF page ' + pdfPage.pageNumber\"\n [attr.data-ngs-pdf-page]=\"pdfPage.pageNumber\">\n <div\n class=\"pdf-viewer-page__surface relative cursor-text overflow-hidden rounded bg-surface shadow-md select-none touch-none\"\n [style.width.px]=\"pdfPage.width\"\n [style.height.px]=\"pdfPage.height\"\n (pointerdown)=\"startTextSelection($event, pdfPage)\"\n (pointermove)=\"updateTextSelection($event, pdfPage)\"\n (pointerup)=\"finishTextSelection($event, pdfPage)\"\n (pointercancel)=\"cancelTextSelection()\"\n (mousedown)=\"startTextSelection($event, pdfPage)\"\n (mousemove)=\"updateTextSelection($event, pdfPage)\"\n (mouseup)=\"finishTextSelection($event, pdfPage)\">\n @if (pdfPage.url; as pageUrl) {\n <img\n class=\"block h-full w-full max-w-none select-none pointer-events-none\"\n [src]=\"pageUrl\"\n [alt]=\"'PDF page ' + pdfPage.pageNumber\"\n [attr.width]=\"pdfPage.width\"\n [attr.height]=\"pdfPage.height\"\n draggable=\"false\" />\n } @else {\n <div class=\"pdf-viewer-page__placeholder pointer-events-none absolute inset-0 flex items-center justify-center bg-surface\" aria-hidden=\"true\">\n @if (pdfPage.isRendering) {\n <span class=\"size-8 animate-spin rounded-full border-2 border-border border-t-primary\"></span>\n }\n </div>\n }\n @if (selectionRectsForPage(pdfPage.pageNumber); as selectionRects) {\n @if (selectionRects.length > 0) {\n <div class=\"pdf-viewer-page__selection-layer pointer-events-none absolute inset-0 z-[1] isolate overflow-hidden mix-blend-multiply\" aria-hidden=\"true\">\n @for (selectionRect of selectionRects; track selectionRect.left + '-' + selectionRect.top + '-' + $index) {\n <div\n class=\"pdf-viewer-page__selection-rect pointer-events-none absolute bg-primary/30\"\n [style.left.px]=\"selectionRect.left\"\n [style.top.px]=\"selectionRect.top\"\n [style.width.px]=\"selectionRect.width\"\n [style.height.px]=\"selectionRect.height\"></div>\n }\n </div>\n }\n }\n </div>\n </article>\n }\n </div>\n }\n </div>\n </ngs-panel-content>\n\n @if (isSearchPanelVisible() || isAnnotationsPanelVisible()) {\n <ngs-panel-aside class=\"w-[var(--ngs-pdf-viewer-aside-width)] min-w-[var(--ngs-pdf-viewer-aside-width)] border-l border-border bg-surface\">\n @if (isSearchPanelVisible()) {\n <ngs-pdf-viewer-search\n [query]=\"activeSearchQuery()\"\n [results]=\"pdfSearchResults()\"\n (closed)=\"closeAsidePanel()\"\n (searchChanged)=\"updatePdfSearch($event)\"\n (resultSelected)=\"selectSearchResult($event)\" />\n } @else {\n <ngs-pdf-viewer-annotations\n [annotations]=\"annotationItems()\"\n [annotationDefs]=\"annotationDefs()\"\n [annotationTypeProperty]=\"annotationTypeProperty()\"\n (closed)=\"closeAsidePanel()\"\n (pageSelected)=\"setPage($event)\" />\n }\n </ngs-panel-aside>\n }\n</ngs-panel>\n", styles: [":host{--ngs-pdf-viewer-height: 720px;--ngs-pdf-viewer-min-height: 720px;--ngs-pdf-viewer-sidebar-width: 152px;--ngs-pdf-viewer-aside-width: 360px;display:block;height:var(--ngs-pdf-viewer-height);min-height:var(--ngs-pdf-viewer-min-height);overflow:hidden}:host .pdf-viewer-page__selection-layer{forced-color-adjust:none}\n"] }]
1998
+ }, template: "<ngs-panel class=\"pdf-viewer-panel h-full overflow-hidden rounded-lg border border-border bg-surface-container-low text-on-surface\">\n @if (showToolbar()) {\n <ngs-panel-header class=\"min-w-0 border-b border-border bg-surface\" flex>\n <ngs-toolbar class=\"pdf-viewer-toolbar flex h-14 w-full min-w-0 items-center gap-4 overflow-visible px-2 text-on-surface-variant\" aria-label=\"PDF viewer controls\">\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__start flex min-w-0 flex-none items-center gap-2\">\n @if (showPageList()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-label]=\"pageListVisible() ? 'Hide pages panel' : 'Show pages panel'\"\n [attr.aria-pressed]=\"pageListVisible()\"\n (click)=\"togglePageList()\">\n <ngs-icon\n class=\"text-2xl\"\n [name]=\"pageListVisible() ? 'fluent:panel-left-contract-24-regular' : 'fluent:panel-left-expand-24-regular'\" />\n </button>\n }\n <ngs-divider vertical fixedHeight />\n </ngs-toolbar-item>\n <ngs-toolbar-title class=\"min-w-0 flex-1 truncate text-sm! max-w-[20%] font-semibold! text-on-surface-variant\" [title]=\"displayDocumentName()\">\n {{ displayDocumentName() }}\n </ngs-toolbar-title>\n\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__center flex flex-none items-center gap-3\">\n <div class=\"pdf-viewer-toolbar__cluster flex min-w-0 items-center gap-2\" aria-label=\"Zoom controls\">\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Zoom out\"\n [disabled]=\"!canZoomOut()\"\n (click)=\"zoomOut()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:zoom-out-24-regular\" />\n </button>\n <button\n class=\"pdf-viewer-toolbar__zoom min-w-12 cursor-pointer border-0 bg-transparent p-0 text-center text-sm text-on-surface hover:text-primary\"\n type=\"button\"\n aria-label=\"Zoom presets\"\n [ngsMenuTriggerFor]=\"zoomMenu\">\n {{ zoomLabel() }}\n </button>\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Zoom in\"\n [disabled]=\"!canZoomIn()\"\n (click)=\"zoomIn()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:zoom-in-24-regular\" />\n </button>\n </div>\n\n <ngs-divider vertical fixedHeight />\n\n <div class=\"pdf-viewer-toolbar__cluster flex min-w-0 items-center gap-2\" aria-label=\"Page navigation\">\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Previous page\"\n [disabled]=\"!canGoPrevious()\"\n (click)=\"previousPage()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:chevron-left-24-regular\" />\n </button>\n <span class=\"pdf-viewer-toolbar__page inline-flex h-9 min-w-16 items-center justify-center gap-2 rounded bg-surface-container-low text-sm font-bold text-on-surface\">\n <span>{{ activePage() }}</span>\n <span>/</span>\n <span>{{ pageCount() || 1 }}</span>\n </span>\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"Next page\"\n [disabled]=\"!canGoNext()\"\n (click)=\"nextPage()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:chevron-right-24-regular\" />\n </button>\n </div>\n </ngs-toolbar-item>\n\n <ngs-toolbar-spacer />\n\n <ngs-toolbar-item class=\"pdf-viewer-toolbar__end flex min-w-0 flex-1 items-center justify-end gap-2\" aria-label=\"PDF tools\">\n @if (showSearchPanel()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-pressed]=\"isSearchPanelVisible()\"\n aria-label=\"Search\"\n [disabled]=\"!asidePanelInteractive()\"\n (click)=\"toggleSearchPanel()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:search-24-regular\" />\n </button>\n }\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n aria-label=\"PDF viewer settings\"\n [ngsMenuTriggerFor]=\"settingsMenu\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:settings-24-regular\" />\n </button>\n @if (showAnnotationsPanel()) {\n <button\n class=\"pdf-viewer-toolbar__button size-10 text-on-surface-variant hover:bg-surface-container-low hover:text-on-surface\"\n ngsIconButton\n type=\"button\"\n [attr.aria-pressed]=\"isAnnotationsPanelVisible()\"\n aria-label=\"Toggle annotations panel\"\n [disabled]=\"!asidePanelInteractive()\"\n (click)=\"toggleAnnotationsPanel()\">\n <ngs-icon class=\"text-2xl\" name=\"fluent:text-bullet-list-square-edit-24-regular\" />\n </button>\n }\n </ngs-toolbar-item>\n </ngs-toolbar>\n\n <ngs-menu #zoomMenu=\"ngsMenu\">\n @for (zoomPreset of zoomPresets; track zoomPreset) {\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"isZoomPresetSelected(zoomPreset)\"\n (click)=\"setZoomPreset(zoomPreset)\">\n <span>{{ zoomPreset * 100 }}%</span>\n </button>\n }\n\n <ngs-menu-divider />\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"zoomMode() === 'fit-page'\"\n (click)=\"fitToPage()\">\n <ngs-icon name=\"fluent:resize-large-24-regular\" />\n <span>Fit to Page</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"zoomMode() === 'fit-width'\"\n (click)=\"fitToWidth()\">\n <ngs-icon name=\"fluent:resize-24-regular\" />\n <span>Fit to Width</span>\n </button>\n </ngs-menu>\n\n <ngs-menu #settingsMenu=\"ngsMenu\" xPosition=\"before\">\n <ngs-menu-heading>SPREAD MODE</ngs-menu-heading>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'single'\"\n (click)=\"setSpreadMode('single')\">\n <ngs-icon name=\"fluent:document-24-regular\" />\n <span>Single Page</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'two-odd'\"\n (click)=\"setSpreadMode('two-odd')\">\n <ngs-icon name=\"fluent:book-open-24-regular\" />\n <span>Two Page (Odd)</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"spreadMode() === 'two-even'\"\n (click)=\"setSpreadMode('two-even')\">\n <ngs-icon name=\"fluent:document-text-24-regular\" />\n <span>Two Page (Even)</span>\n </button>\n\n <ngs-menu-divider />\n <ngs-menu-heading>SCROLL LAYOUT</ngs-menu-heading>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"scrollLayout() === 'vertical'\"\n (click)=\"setScrollLayout('vertical')\">\n <ngs-icon name=\"fluent:arrow-sort-24-regular\" />\n <span>Vertical</span>\n </button>\n <button\n ngs-menu-item\n type=\"button\"\n [selected]=\"scrollLayout() === 'horizontal'\"\n (click)=\"setScrollLayout('horizontal')\">\n <ngs-icon name=\"fluent:arrow-swap-24-regular\" />\n <span>Horizontal</span>\n </button>\n\n <ngs-menu-divider />\n <ngs-menu-heading>PAGE ROTATION</ngs-menu-heading>\n <button ngs-menu-item type=\"button\" (click)=\"rotateClockwise()\">\n <ngs-icon name=\"fluent:arrow-clockwise-24-regular\" />\n <span>Rotate Clockwise</span>\n </button>\n <button ngs-menu-item type=\"button\" (click)=\"rotateCounterClockwise()\">\n <ngs-icon name=\"fluent:arrow-counterclockwise-24-regular\" />\n <span>Rotate Counter-Clockwise</span>\n </button>\n\n <ngs-menu-divider />\n <button ngs-menu-item type=\"button\" (click)=\"toggleFullscreen()\">\n <ngs-icon name=\"fluent:arrow-maximize-24-regular\" />\n <span>Fullscreen</span>\n </button>\n </ngs-menu>\n </ngs-panel-header>\n }\n\n @if (isPageListVisible()) {\n <ngs-panel-sidebar class=\"w-[var(--ngs-pdf-viewer-sidebar-width)] min-w-[var(--ngs-pdf-viewer-sidebar-width)] border-r border-border bg-surface\">\n <div class=\"pdf-viewer-sidebar flex h-full min-h-0 flex-col gap-2 overflow-auto p-3\" #pageList>\n <div class=\"pdf-viewer-sidebar__title px-1 text-xs font-semibold text-on-surface-variant\">Pages</div>\n <div class=\"pdf-viewer-sidebar__pages flex min-h-0 flex-col gap-2\" aria-label=\"PDF pages\">\n @for (pageItem of pageItems(); track pageItem.pageNumber) {\n <button\n class=\"pdf-viewer-sidebar__page group flex w-full cursor-pointer flex-col items-stretch gap-1 rounded border border-transparent bg-transparent p-1 text-left text-on-surface-variant focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary [&.is-active]:text-on-surface\"\n type=\"button\"\n [class.is-active]=\"pageItem.pageNumber === activePage()\"\n [attr.aria-current]=\"pageItem.pageNumber === activePage() ? 'page' : null\"\n [attr.aria-label]=\"'Open page ' + pageItem.pageNumber\"\n [attr.data-ngs-pdf-page-button]=\"pageItem.pageNumber\"\n (click)=\"setPage(pageItem.pageNumber)\">\n <span class=\"pdf-viewer-sidebar__thumb flex aspect-[3/4] w-full items-center justify-center overflow-hidden rounded border border-border bg-surface shadow-xs group-hover:border-border\" aria-hidden=\"true\">\n @if (pageItem.thumbnail; as thumbnail) {\n <img\n class=\"block h-full w-full select-none object-contain\"\n [src]=\"thumbnail.url\"\n [attr.width]=\"thumbnail.width\"\n [attr.height]=\"thumbnail.height\"\n alt=\"\"\n draggable=\"false\" />\n } @else {\n <ngs-image-placeholder class=\"h-full w-full\" />\n }\n </span>\n <span class=\"pdf-viewer-sidebar__label block truncate text-center text-xs font-medium leading-tight\">Page {{ pageItem.pageNumber }}</span>\n </button>\n }\n </div>\n </div>\n </ngs-panel-sidebar>\n }\n\n <ngs-panel-content class=\"min-h-0 min-w-0 overflow-hidden bg-surface-container-low\">\n <div class=\"pdf-viewer-body absolute inset-0 overflow-auto\" #viewerBody (scroll)=\"onViewerScroll()\" (wheel)=\"onViewerWheel($event)\">\n <ngs-block-loader [loading]=\"isLoading()\">Loading PDF...</ngs-block-loader>\n @if (errorState()) {\n <div class=\"pdf-viewer-state pdf-viewer-state--error absolute inset-0 flex flex-col items-center justify-center gap-3 p-6 text-center text-danger\">\n <ngs-icon class=\"text-3xl\" name=\"fluent:error-circle-24-regular\" />\n <span>PDF could not be loaded.</span>\n </div>\n } @else if (!src()) {\n <div class=\"pdf-viewer-state absolute inset-0 flex flex-col items-center justify-center gap-3 p-6 text-center text-on-surface-variant\">\n <ngs-icon class=\"text-3xl\" name=\"fluent:document-pdf-24-regular\" />\n <span>No PDF selected.</span>\n </div>\n } @else {\n <div\n class=\"pdf-viewer-pages\"\n [class.is-horizontal]=\"scrollLayout() === 'horizontal'\"\n [class.is-vertical]=\"scrollLayout() === 'vertical'\"\n [class.is-spread]=\"spreadMode() !== 'single'\">\n @for (spread of pageSpreads(); track spread.id) {\n <div class=\"pdf-viewer-spread\" [attr.data-ngs-pdf-spread]=\"spread.id\">\n @if (spread.leadingPlaceholder) {\n @if (spread.leadingPlaceholderPage; as placeholderPage) {\n <div\n class=\"pdf-viewer-spread__placeholder\"\n [style.width.px]=\"placeholderPage.width\"\n [style.height.px]=\"placeholderPage.height\"\n aria-hidden=\"true\"></div>\n }\n }\n @for (pdfPage of spread.pages; track pdfPage.pageNumber) {\n <article\n class=\"pdf-viewer-page w-max max-w-none\"\n [attr.aria-label]=\"'PDF page ' + pdfPage.pageNumber\"\n [attr.data-ngs-pdf-page]=\"pdfPage.pageNumber\">\n <div\n class=\"pdf-viewer-page__surface relative cursor-text overflow-hidden rounded bg-surface shadow-md select-none touch-none\"\n [style.width.px]=\"pdfPage.width\"\n [style.height.px]=\"pdfPage.height\"\n (pointerdown)=\"startTextSelection($event, pdfPage)\"\n (pointermove)=\"updateTextSelection($event, pdfPage)\"\n (pointerup)=\"finishTextSelection($event, pdfPage)\"\n (pointercancel)=\"cancelTextSelection()\"\n (mousedown)=\"startTextSelection($event, pdfPage)\"\n (mousemove)=\"updateTextSelection($event, pdfPage)\"\n (mouseup)=\"finishTextSelection($event, pdfPage)\">\n @if (pdfPage.url; as pageUrl) {\n <img\n class=\"block h-full w-full max-w-none select-none pointer-events-none\"\n [src]=\"pageUrl\"\n [alt]=\"'PDF page ' + pdfPage.pageNumber\"\n [attr.width]=\"pdfPage.width\"\n [attr.height]=\"pdfPage.height\"\n draggable=\"false\" />\n } @else {\n <div class=\"pdf-viewer-page__placeholder pointer-events-none absolute inset-0 flex items-center justify-center bg-surface\" aria-hidden=\"true\">\n @if (pdfPage.isRendering) {\n <span class=\"size-8 animate-spin rounded-full border-2 border-border border-t-primary\"></span>\n }\n </div>\n }\n @if (selectionRectsForPage(pdfPage.pageNumber); as selectionRects) {\n @if (selectionRects.length > 0) {\n <div class=\"pdf-viewer-page__selection-layer pointer-events-none absolute inset-0 z-[1] isolate overflow-hidden mix-blend-multiply\" aria-hidden=\"true\">\n @for (selectionRect of selectionRects; track selectionRect.left + '-' + selectionRect.top + '-' + $index) {\n <div\n class=\"pdf-viewer-page__selection-rect pointer-events-none absolute bg-primary/30\"\n [style.left.px]=\"selectionRect.left\"\n [style.top.px]=\"selectionRect.top\"\n [style.width.px]=\"selectionRect.width\"\n [style.height.px]=\"selectionRect.height\"></div>\n }\n </div>\n }\n }\n </div>\n </article>\n }\n </div>\n }\n </div>\n }\n </div>\n </ngs-panel-content>\n\n @if (isSearchPanelVisible() || isAnnotationsPanelVisible()) {\n <ngs-panel-aside class=\"w-[var(--ngs-pdf-viewer-aside-width)] min-w-[var(--ngs-pdf-viewer-aside-width)] border-l border-border bg-surface\">\n @if (isSearchPanelVisible()) {\n <ngs-pdf-viewer-search\n [query]=\"activeSearchQuery()\"\n [results]=\"pdfSearchResults()\"\n (closed)=\"closeAsidePanel()\"\n (searchChanged)=\"updatePdfSearch($event)\"\n (resultSelected)=\"selectSearchResult($event)\" />\n } @else {\n <ngs-pdf-viewer-annotations\n [annotations]=\"annotationItems()\"\n [annotationDefs]=\"annotationDefs()\"\n [annotationTypeProperty]=\"annotationTypeProperty()\"\n (closed)=\"closeAsidePanel()\"\n (pageSelected)=\"setPage($event)\" />\n }\n </ngs-panel-aside>\n }\n</ngs-panel>\n", styles: [":host{--ngs-pdf-viewer-height: 720px;--ngs-pdf-viewer-min-height: 720px;--ngs-pdf-viewer-sidebar-width: 152px;--ngs-pdf-viewer-aside-width: 360px;--ngs-pdf-viewer-page-gap: 24px;--ngs-pdf-viewer-spread-gap: 16px;--ngs-pdf-viewer-page-padding: 24px;display:block;height:var(--ngs-pdf-viewer-height);min-height:var(--ngs-pdf-viewer-min-height);overflow:hidden}:host .pdf-viewer-pages{box-sizing:border-box;display:grid;gap:var(--ngs-pdf-viewer-page-gap);min-height:100%;min-width:100%;padding:var(--ngs-pdf-viewer-page-padding)}:host .pdf-viewer-pages.is-vertical{align-content:start;grid-auto-flow:row;grid-auto-rows:max-content;justify-items:center}:host .pdf-viewer-pages.is-horizontal{align-content:center;align-items:center;grid-auto-columns:max-content;grid-auto-flow:column;justify-content:start;width:max-content}:host .pdf-viewer-spread{align-items:start;display:grid;gap:var(--ngs-pdf-viewer-spread-gap);grid-auto-columns:max-content;grid-auto-flow:column;justify-content:center}:host .pdf-viewer-spread__placeholder{pointer-events:none;visibility:hidden}:host .pdf-viewer-toolbar{position:relative}:host .pdf-viewer-toolbar__center{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:1}:host .pdf-viewer-toolbar__start,:host .pdf-viewer-toolbar__end{position:relative;z-index:2}:host .pdf-viewer-sidebar__page.is-active .pdf-viewer-sidebar__thumb{outline:2px solid var(--ngs-color-primary)}:host .pdf-viewer-page__selection-layer{forced-color-adjust:none}\n"] }]
1866
1999
  }], ctorParameters: () => [], propDecorators: { viewerBody: [{ type: i0.ViewChild, args: ['viewerBody', { isSignal: true }] }], pageList: [{ type: i0.ViewChild, args: ['pageList', { isSignal: true }] }], annotationDefs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => PdfViewerAnnotationDef), { ...{ descendants: true }, isSignal: true }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], documentName: [{ type: i0.Input, args: [{ isSignal: true, alias: "documentName", required: false }] }], wasmUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "wasmUrl", required: false }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }], scale: [{ type: i0.Input, args: [{ isSignal: true, alias: "scale", required: false }] }], minScale: [{ type: i0.Input, args: [{ isSignal: true, alias: "minScale", required: false }] }], maxScale: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxScale", required: false }] }], zoomStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoomStep", required: false }] }], maxRenderPixels: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRenderPixels", required: false }] }], maxRenderDimension: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRenderDimension", required: false }] }], renderAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderAll", required: false }] }], showToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToolbar", required: false }] }], showPageList: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageList", required: false }] }], showSearchPanel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearchPanel", required: false }] }], showAnnotationsPanel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAnnotationsPanel", required: false }] }], annotations: [{ type: i0.Input, args: [{ isSignal: true, alias: "annotations", required: false }] }], annotationsDataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "annotationsDataSource", required: false }] }], annotationTypeProperty: [{ type: i0.Input, args: [{ isSignal: true, alias: "annotationTypeProperty", required: false }] }], searchQuery: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchQuery", required: false }] }], withAnnotations: [{ type: i0.Input, args: [{ isSignal: true, alias: "withAnnotations", required: false }] }], withForms: [{ type: i0.Input, args: [{ isSignal: true, alias: "withForms", required: false }] }], loaded: [{ type: i0.Output, args: ["loaded"] }], pageChanged: [{ type: i0.Output, args: ["pageChanged"] }], pageRendered: [{ type: i0.Output, args: ["pageRendered"] }], error: [{ type: i0.Output, args: ["error"] }] } });
1867
2000
 
1868
2001
  /**