UNPKG

ngx-doc-viewer

Version:
518 lines (513 loc) 37.6 kB
import * as i0 from '@angular/core'; import { EventEmitter, TemplateRef, ViewChildren, ContentChild, Input, Output, Component, NgModule } from '@angular/core'; import * as i2 from '@angular/common'; import { CommonModule } from '@angular/common'; import { getViewerDetails, isLocalFile, replaceLocalUrl, getDocxToHtml, googleCheckSubscription, getViewerRecoveryPlan, iframeIsLoaded } from 'docviewhelper'; export * from 'docviewhelper'; import * as i1 from '@angular/platform-browser'; class NgxDocViewerComponent { domSanitizer; ngZone; cdr; loaded = new EventEmitter(); loading = new EventEmitter(); error = new EventEmitter(); phaseChange = new EventEmitter(); url = ''; queryParams = ''; viewerUrl = ''; googleCheckInterval = 3000; googleMaxChecks = 5; googleFinalRetryDelay = 0; disableContent = 'none'; googleCheckContentLoaded = true; viewer = 'google'; overrideLocalhost = ''; loadingText = 'Loading document...'; errorTextOverride = ''; retryButtonText = 'Retry'; officeAutoRetry = false; officeRetryDelay = 3000; officeReloadButtonText = '↻'; officeReloadButtonTitle = 'Reload document'; secondaryActionText = ''; secondaryActionMode = 'open'; loadingTemplate; errorTemplate; errorActionsTemplate; officeReloadTemplate; iframes = undefined; fullUrl = undefined; externalViewer = false; docHtml = ''; configuredViewer = 'google'; showIframe = true; renderPhase = 'idle'; errorText = ''; failedUrl = ''; retryNonce = 0; loadingTemplateContext = this.createTemplateContext(); errorTemplateContext = this.createTemplateContext(); checkIFrameSubscription = undefined; loadVersion = 0; externalLoadTimeoutId = undefined; googleFinalRetryTimeoutId = undefined; googleFinalRetriedSourceKey = undefined; currentGoogleSourceKey = undefined; officeRetryTimeoutId = undefined; officeAutoRetriedSourceKey = undefined; currentOfficeSourceKey = undefined; lastEmittedPhase = undefined; constructor(domSanitizer, ngZone, cdr) { this.domSanitizer = domSanitizer; this.ngZone = ngZone; this.cdr = cdr; } ngOnDestroy() { this.clearExternalLoadTimeout(); this.clearGoogleFinalRetry(); this.clearOfficeRetry(); if (this.checkIFrameSubscription) { this.checkIFrameSubscription.unsubscribe(); } } async ngOnChanges(changes) { if (changes && changes['retryNonce'] && changes['retryNonce'].firstChange) { return; } if (changes && changes['viewer'] && (changes['viewer'].firstChange || changes['viewer'].currentValue !== changes['viewer'].previousValue)) { if (this.viewer !== 'google' && this.viewer !== 'office' && this.viewer !== 'mammoth' && this.viewer !== 'pdf' && this.viewer !== 'url') { console.error(`Unsupported viewer: '${this.viewer}'. Supported viewers: google, office, mammoth and pdf`); } this.configuredViewer = this.viewer; this.updateTemplateContexts(); } if ((changes['url'] && changes['url'].currentValue !== changes['url'].previousValue) || (changes['viewer'] && changes['viewer'].currentValue !== changes['viewer'].previousValue) || (changes['viewerUrl'] && changes['viewerUrl'].currentValue !== changes['viewerUrl'].previousValue)) { let viewerDetails = getViewerDetails(this.url, this.configuredViewer, this.queryParams, this.viewerUrl); const loadVersion = ++this.loadVersion; this.clearExternalLoadTimeout(); this.externalViewer = viewerDetails.externalViewer; if (viewerDetails.externalViewer && this.overrideLocalhost && isLocalFile(this.url)) { const newUrl = replaceLocalUrl(this.url, this.overrideLocalhost); viewerDetails = getViewerDetails(newUrl, this.configuredViewer, this.queryParams, this.viewerUrl); } const officeSourceKey = this.configuredViewer === 'office' ? viewerDetails.url : undefined; if (officeSourceKey !== this.currentOfficeSourceKey) { this.officeAutoRetriedSourceKey = undefined; } this.currentOfficeSourceKey = officeSourceKey; const googleSourceKey = this.configuredViewer === 'google' ? viewerDetails.url : undefined; if (googleSourceKey !== this.currentGoogleSourceKey) { this.googleFinalRetriedSourceKey = undefined; } this.currentGoogleSourceKey = googleSourceKey; this.docHtml = ''; this.errorText = ''; this.failedUrl = this.url; this.clearGoogleFinalRetry(); this.clearOfficeRetry(); this.updateTemplateContexts(); if (this.checkIFrameSubscription) { this.checkIFrameSubscription.unsubscribe(); } if (!this.url) { this.fullUrl = undefined; this.showIframe = false; this.externalViewer = false; this.setRenderPhase('idle'); this.updateTemplateContexts(); } else if (viewerDetails.externalViewer || this.configuredViewer === 'url' || this.configuredViewer === 'pdf') { this.setRenderPhase('loading'); const iframeUrl = this.domSanitizer.bypassSecurityTrustResourceUrl(viewerDetails.url); this.fullUrl = undefined; this.showIframe = false; this.cdr.detectChanges(); this.fullUrl = iframeUrl; this.showIframe = true; this.updateTemplateContexts(); this.scheduleExternalLoadTimeout(loadVersion); this.cdr.detectChanges(); this.scheduleViewerRecovery(); } else if (this.configuredViewer === 'mammoth') { this.setRenderPhase('loading'); this.externalViewer = false; this.fullUrl = undefined; this.showIframe = false; try { const docHtml = await getDocxToHtml(this.url); if (loadVersion !== this.loadVersion) { return; } this.ngZone.run(() => { this.docHtml = docHtml; this.setRenderPhase('ready'); this.updateTemplateContexts(); this.cdr.detectChanges(); }); } catch (error) { if (loadVersion !== this.loadVersion) { return; } this.ngZone.run(() => { this.errorText = error instanceof Error ? error.message : 'Unable to load document.'; this.setRenderPhase('error'); this.updateTemplateContexts(); this.cdr.detectChanges(); }); } } } } retryLoad() { this.retryNonce += 1; const retryVersion = ++this.loadVersion; this.clearExternalLoadTimeout(); this.clearGoogleFinalRetry(); this.clearOfficeRetry(); this.errorText = ''; this.setRenderPhase(this.url ? 'loading' : 'idle'); this.updateTemplateContexts(); if (!this.url) { return; } if (this.configuredViewer === 'mammoth') { this.docHtml = ''; void this.reloadMammoth(retryVersion); return; } if (this.configuredViewer === 'google' || this.configuredViewer === 'office' || this.configuredViewer === 'url' || this.configuredViewer === 'pdf') { const details = getViewerDetails(this.url, this.configuredViewer, this.queryParams, this.viewerUrl); const finalUrl = details.externalViewer && this.overrideLocalhost && isLocalFile(this.url) ? getViewerDetails(replaceLocalUrl(this.url, this.overrideLocalhost), this.configuredViewer, this.queryParams, this.viewerUrl).url : details.url; this.fullUrl = undefined; this.showIframe = false; this.cdr.detectChanges(); this.fullUrl = this.domSanitizer.bypassSecurityTrustResourceUrl(finalUrl); this.showIframe = true; this.scheduleExternalLoadTimeout(retryVersion); this.scheduleViewerRecovery(); this.updateTemplateContexts(); this.cdr.detectChanges(); } } reloadIframe(iframe) { this.checkIFrameSubscription = googleCheckSubscription(); this.checkIFrameSubscription.subscribe(iframe, this.googleCheckInterval, this.googleMaxChecks); } scheduleViewerRecovery() { const recoveryPlan = getViewerRecoveryPlan({ viewer: this.configuredViewer, googleCheckContentLoaded: this.googleCheckContentLoaded, googleFinalRetryDelay: this.googleFinalRetryDelay, officeAutoRetry: this.officeAutoRetry, }); for (const mode of recoveryPlan.modes) { if (mode === 'google-probe') { this.scheduleGoogleRecovery(); } if (mode === 'google-final-retry') { continue; } if (mode === 'office-auto-retry') { this.scheduleOfficeRetry(); } } } scheduleGoogleRecovery() { if (this.configuredViewer !== 'google' || !this.googleCheckContentLoaded) { return; } // see: // https://stackoverflow.com/questions/40414039/google-docs-viewer-returning-204-responses-no-longer-working-alternatives // hack to reload iframe if it's not loaded. this.ngZone.runOutsideAngular(() => { window.setTimeout(() => { const iframe = this.iframes?.first?.nativeElement; if (iframe) { this.reloadIframe(iframe); } }, 0); }); } iframeLoaded() { const iframe = this.iframes?.first?.nativeElement; if (iframe && iframeIsLoaded(iframe)) { this.clearExternalLoadTimeout(); this.clearGoogleFinalRetry(); this.clearOfficeRetry(); this.setRenderPhase('ready'); this.updateTemplateContexts(); this.loaded.emit(undefined); if (this.checkIFrameSubscription) { this.checkIFrameSubscription.unsubscribe(); } } } objectLoaded() { this.clearExternalLoadTimeout(); this.clearGoogleFinalRetry(); this.clearOfficeRetry(); this.setRenderPhase('ready'); this.updateTemplateContexts(); } async reloadMammoth(loadVersion) { this.externalViewer = false; this.fullUrl = undefined; this.showIframe = false; try { const docHtml = await getDocxToHtml(this.url); if (loadVersion !== this.loadVersion) { return; } this.ngZone.run(() => { this.docHtml = docHtml; this.setRenderPhase('ready'); this.updateTemplateContexts(); this.cdr.detectChanges(); }); } catch (error) { if (loadVersion !== this.loadVersion) { return; } this.ngZone.run(() => { this.errorText = error instanceof Error ? error.message : 'Unable to load document.'; this.setRenderPhase('error'); this.updateTemplateContexts(); this.cdr.detectChanges(); }); } } scheduleExternalLoadTimeout(loadVersion) { this.clearExternalLoadTimeout(); const timeoutMs = this.configuredViewer === 'google' ? Math.max(this.googleCheckInterval * this.googleMaxChecks + 2000, 15000) : 15000; this.externalLoadTimeoutId = window.setTimeout(() => { if (loadVersion !== this.loadVersion || this.renderPhase !== 'loading') { return; } if (this.scheduleGoogleFinalRetry()) { return; } this.ngZone.run(() => { this.errorText = `The ${this.configuredViewer} viewer did not finish loading in time.`; this.setRenderPhase('error'); this.updateTemplateContexts(); this.cdr.detectChanges(); }); }, timeoutMs); } clearExternalLoadTimeout() { if (this.externalLoadTimeoutId) { window.clearTimeout(this.externalLoadTimeoutId); this.externalLoadTimeoutId = undefined; } } clearGoogleFinalRetry() { if (this.googleFinalRetryTimeoutId) { window.clearTimeout(this.googleFinalRetryTimeoutId); this.googleFinalRetryTimeoutId = undefined; } } clearOfficeRetry() { if (this.officeRetryTimeoutId) { window.clearTimeout(this.officeRetryTimeoutId); this.officeRetryTimeoutId = undefined; } } scheduleOfficeRetry() { if (this.configuredViewer !== 'office' || !this.officeAutoRetry || !this.currentOfficeSourceKey || this.officeAutoRetriedSourceKey === this.currentOfficeSourceKey) { return; } this.clearOfficeRetry(); this.officeRetryTimeoutId = window.setTimeout(() => { if (!this.currentOfficeSourceKey || this.officeAutoRetriedSourceKey === this.currentOfficeSourceKey) { return; } this.officeAutoRetriedSourceKey = this.currentOfficeSourceKey; this.ngZone.run(() => this.retryLoad()); }, this.officeRetryDelay); } scheduleGoogleFinalRetry() { const recoveryPlan = getViewerRecoveryPlan({ viewer: this.configuredViewer, googleCheckContentLoaded: this.googleCheckContentLoaded, googleFinalRetryDelay: this.googleFinalRetryDelay, officeAutoRetry: this.officeAutoRetry, }); if (!recoveryPlan.modes.includes('google-final-retry') || !this.currentGoogleSourceKey || this.googleFinalRetriedSourceKey === this.currentGoogleSourceKey) { return false; } this.clearGoogleFinalRetry(); this.googleFinalRetryTimeoutId = window.setTimeout(() => { if (!this.currentGoogleSourceKey || this.googleFinalRetriedSourceKey === this.currentGoogleSourceKey) { return; } this.googleFinalRetriedSourceKey = this.currentGoogleSourceKey; this.ngZone.run(() => this.retryLoad()); }, this.googleFinalRetryDelay); return true; } get displayedErrorText() { return this.errorTextOverride || this.errorText || 'Unable to load document.'; } updateTemplateContexts() { const state = this.createStateContext(); this.loadingTemplateContext = { $implicit: state, state }; this.errorTemplateContext = { $implicit: state, state }; } createTemplateContext() { const state = this.createStateContext(); return { $implicit: state, state }; } createStateContext() { return { viewer: this.configuredViewer, url: this.failedUrl || this.url, phase: this.renderPhase, errorText: this.displayedErrorText, retry: () => this.retryLoad(), actionUrl: this.failedUrl || this.url, }; } setRenderPhase(phase) { this.renderPhase = phase; this.emitLifecycleIfNeeded(); } emitLifecycleIfNeeded() { if (this.lastEmittedPhase === this.renderPhase) { return; } this.lastEmittedPhase = this.renderPhase; const state = this.createStateContext(); this.phaseChange.emit(state); if (this.renderPhase === 'loading') { this.loading.emit(state); } if (this.renderPhase === 'error') { this.error.emit(state); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NgxDocViewerComponent, deps: [{ token: i1.DomSanitizer }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: NgxDocViewerComponent, isStandalone: true, selector: "ngx-doc-viewer", inputs: { url: "url", queryParams: "queryParams", viewerUrl: "viewerUrl", googleCheckInterval: "googleCheckInterval", googleMaxChecks: "googleMaxChecks", googleFinalRetryDelay: "googleFinalRetryDelay", disableContent: "disableContent", googleCheckContentLoaded: "googleCheckContentLoaded", viewer: "viewer", overrideLocalhost: "overrideLocalhost", loadingText: "loadingText", errorTextOverride: "errorTextOverride", retryButtonText: "retryButtonText", officeAutoRetry: "officeAutoRetry", officeRetryDelay: "officeRetryDelay", officeReloadButtonText: "officeReloadButtonText", officeReloadButtonTitle: "officeReloadButtonTitle", secondaryActionText: "secondaryActionText", secondaryActionMode: "secondaryActionMode" }, outputs: { loaded: "loaded", loading: "loading", error: "error", phaseChange: "phaseChange" }, queries: [{ propertyName: "loadingTemplate", first: true, predicate: ["loadingContent"], descendants: true, read: TemplateRef }, { propertyName: "errorTemplate", first: true, predicate: ["errorContent"], descendants: true, read: TemplateRef }, { propertyName: "errorActionsTemplate", first: true, predicate: ["errorActions"], descendants: true, read: TemplateRef }, { propertyName: "officeReloadTemplate", first: true, predicate: ["officeReloadContent"], descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "iframes", predicate: ["iframe"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"container\">\n <div *ngIf=\"renderPhase === 'loading'\" class=\"loading-overlay\">\n <ng-container *ngIf=\"loadingTemplate; else defaultLoadingTemplate\">\n <ng-container *ngTemplateOutlet=\"loadingTemplate; context: loadingTemplateContext\"></ng-container>\n </ng-container>\n <ng-template #defaultLoadingTemplate>{{ loadingText }}</ng-template>\n </div>\n <div *ngIf=\"renderPhase === 'error'\" class=\"error-overlay\">\n <ng-container *ngIf=\"errorTemplate; else defaultErrorTemplate\">\n <ng-container *ngTemplateOutlet=\"errorTemplate; context: errorTemplateContext\"></ng-container>\n </ng-container>\n <ng-template #defaultErrorTemplate>\n <div>\n <div>{{ displayedErrorText }}</div>\n <div *ngIf=\"configuredViewer\" style=\"margin-top: 8px; color: #475569;\">\n Viewer: {{ configuredViewer }}\n </div>\n <div *ngIf=\"failedUrl\" style=\"margin-top: 4px; color: #64748b; font-size: 12px; word-break: break-word;\">\n {{ failedUrl }}\n </div>\n <ng-container *ngIf=\"errorActionsTemplate; else defaultErrorActions\">\n <ng-container *ngTemplateOutlet=\"errorActionsTemplate; context: errorTemplateContext\"></ng-container>\n </ng-container>\n <ng-template #defaultErrorActions>\n <div style=\"margin-top: 14px; display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;\">\n <button\n type=\"button\"\n (click)=\"retryLoad()\"\n style=\"border: 1px solid #fecaca; background: #fff; color: #991b1b; border-radius: 999px; padding: 8px 14px; font: inherit; cursor: pointer;\"\n >\n {{ retryButtonText }}\n </button>\n <a\n *ngIf=\"secondaryActionText && failedUrl\"\n [href]=\"failedUrl\"\n [attr.target]=\"secondaryActionMode === 'open' ? '_blank' : null\"\n [attr.rel]=\"secondaryActionMode === 'open' ? 'noreferrer' : null\"\n [attr.download]=\"secondaryActionMode === 'download' ? '' : null\"\n style=\"border: 1px solid #cbd5e1; background: #fff; color: #334155; border-radius: 999px; padding: 8px 14px; text-decoration: none; font: inherit;\"\n >\n {{ secondaryActionText }}\n </a>\n </div>\n </ng-template>\n </div>\n </ng-template>\n </div>\n\n <ng-container *ngIf=\"!externalViewer\">\n <div *ngIf=\"configuredViewer !== 'pdf'\" class=\"inline-document-shell\">\n <div class=\"inline-document-page\" [innerHTML]=\"docHtml\"></div>\n </div>\n <object\n (load)=\"objectLoaded()\"\n *ngIf=\"fullUrl && configuredViewer === 'pdf'\"\n [data]=\"fullUrl\"\n type=\"application/pdf\"\n width=\"100%\"\n height=\"100%\"\n >\n <p>\n Your browser does not support PDFs.\n <a [href]=\"fullUrl\">Download the PDF</a>.\n </p>\n </object>\n </ng-container>\n\n <button\n *ngIf=\"configuredViewer === 'office' && renderPhase === 'ready'\"\n class=\"office-reload-btn\"\n type=\"button\"\n [attr.title]=\"officeReloadButtonTitle\"\n (click)=\"retryLoad()\"\n >\n <ng-container *ngIf=\"officeReloadTemplate; else defaultOfficeReloadTemplate\">\n <ng-container *ngTemplateOutlet=\"officeReloadTemplate; context: errorTemplateContext\"></ng-container>\n </ng-container>\n <ng-template #defaultOfficeReloadTemplate>{{ officeReloadButtonText }}</ng-template>\n </button>\n\n <ng-container *ngIf=\"externalViewer\">\n <iframe\n (load)=\"iframeLoaded()\"\n *ngIf=\"fullUrl && showIframe && disableContent === 'none'\"\n #iframe\n id=\"iframe-doc-viewer\"\n frameBorder=\"0\"\n allow=\"clipboard-read; clipboard-write\"\n [src]=\"fullUrl\"\n ></iframe>\n <div class=\"container\" *ngIf=\"disableContent !== 'none'\">\n <div\n [class.overlay-full]=\"disableContent === 'all'\"\n [class.overlay-popout-google]=\"\n configuredViewer === 'google' &&\n (disableContent === 'popout' || disableContent === 'popout-hide')\n \"\n [class.overlay-popout-office]=\"\n configuredViewer === 'office' &&\n (disableContent === 'popout' || disableContent === 'popout-hide')\n \"\n [style.background-color]=\"\n disableContent === 'popout-hide' ? '#fff' : 'transparent'\n \"\n ></div>\n <iframe\n (load)=\"iframeLoaded()\"\n *ngIf=\"fullUrl && showIframe\"\n #iframe\n id=\"iframe\"\n frameBorder=\"0\"\n allow=\"clipboard-read; clipboard-write\"\n [src]=\"fullUrl\"\n ></iframe>\n </div>\n </ng-container>\n</div>\n", styles: [":host{display:block}.container{width:100%;height:100%;position:relative}.inline-document-shell{width:100%;height:100%;overflow:auto;background:linear-gradient(180deg,#eef2f7,#f8fafc);padding:24px}.inline-document-page{max-width:900px;min-height:100%;margin:0 auto;background:#fff;border:1px solid #dbe4f0;border-radius:18px;box-shadow:0 18px 40px -24px #0f172a4d,0 6px 18px -10px #0f172a2e;padding:40px 48px}.inline-document-page,.inline-document-page *{box-sizing:border-box}.inline-document-page{color:#1e293b;font-family:Georgia,Cambria,Times New Roman,Times,serif;font-size:18px;line-height:1.7}.inline-document-page p,.inline-document-page ul,.inline-document-page ol,.inline-document-page blockquote,.inline-document-page table{margin:0 0 1.1em}.inline-document-page h1,.inline-document-page h2,.inline-document-page h3,.inline-document-page h4,.inline-document-page h5,.inline-document-page h6{margin:1.4em 0 .65em;color:#0f172a;line-height:1.25}.inline-document-page h1:first-child,.inline-document-page h2:first-child,.inline-document-page h3:first-child,.inline-document-page p:first-child{margin-top:0}.inline-document-page table{width:100%;border-collapse:collapse}.inline-document-page td,.inline-document-page th{padding:6px 10px;vertical-align:top}.inline-document-page img{max-width:100%;height:auto}.inline-document-page hr{border:0;border-top:1px solid #dbe4f0;margin:1.5em 0}.loading-overlay{position:absolute;inset:0;z-index:1001;display:flex;align-items:center;justify-content:center;background:#ffffffe0;color:#475569;font-size:14px;font-weight:600;letter-spacing:.02em;text-align:center;padding:16px}.error-overlay{position:absolute;inset:0;z-index:1001;display:flex;align-items:center;justify-content:center;background:#fffffff0;color:#991b1b;font-size:14px;font-weight:600;letter-spacing:.02em;text-align:center;padding:16px}.overlay-popout-google{width:40px;height:40px;right:26px;top:11.5px;position:absolute;z-index:1000}.overlay-popout-office{width:100px;height:20px;right:0;bottom:0;position:absolute;z-index:1000}.office-reload-btn{position:absolute;top:8px;right:8px;z-index:1001;width:32px;height:32px;border-radius:50%;border:1px solid rgba(0,0,0,.12);background:#ffffffd9;color:#475569;font-size:16px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;opacity:.5;transition:opacity .15s;padding:0}.office-reload-btn:hover{opacity:1}.overlay-full{width:100%;height:100%;right:0;top:0;position:absolute;z-index:1000}iframe{width:100%;height:100%}@media(max-width:768px){.inline-document-shell{padding:12px}.inline-document-page{border-radius:12px;padding:22px 18px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NgxDocViewerComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-doc-viewer', standalone: true, imports: [CommonModule], template: "<div class=\"container\">\n <div *ngIf=\"renderPhase === 'loading'\" class=\"loading-overlay\">\n <ng-container *ngIf=\"loadingTemplate; else defaultLoadingTemplate\">\n <ng-container *ngTemplateOutlet=\"loadingTemplate; context: loadingTemplateContext\"></ng-container>\n </ng-container>\n <ng-template #defaultLoadingTemplate>{{ loadingText }}</ng-template>\n </div>\n <div *ngIf=\"renderPhase === 'error'\" class=\"error-overlay\">\n <ng-container *ngIf=\"errorTemplate; else defaultErrorTemplate\">\n <ng-container *ngTemplateOutlet=\"errorTemplate; context: errorTemplateContext\"></ng-container>\n </ng-container>\n <ng-template #defaultErrorTemplate>\n <div>\n <div>{{ displayedErrorText }}</div>\n <div *ngIf=\"configuredViewer\" style=\"margin-top: 8px; color: #475569;\">\n Viewer: {{ configuredViewer }}\n </div>\n <div *ngIf=\"failedUrl\" style=\"margin-top: 4px; color: #64748b; font-size: 12px; word-break: break-word;\">\n {{ failedUrl }}\n </div>\n <ng-container *ngIf=\"errorActionsTemplate; else defaultErrorActions\">\n <ng-container *ngTemplateOutlet=\"errorActionsTemplate; context: errorTemplateContext\"></ng-container>\n </ng-container>\n <ng-template #defaultErrorActions>\n <div style=\"margin-top: 14px; display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;\">\n <button\n type=\"button\"\n (click)=\"retryLoad()\"\n style=\"border: 1px solid #fecaca; background: #fff; color: #991b1b; border-radius: 999px; padding: 8px 14px; font: inherit; cursor: pointer;\"\n >\n {{ retryButtonText }}\n </button>\n <a\n *ngIf=\"secondaryActionText && failedUrl\"\n [href]=\"failedUrl\"\n [attr.target]=\"secondaryActionMode === 'open' ? '_blank' : null\"\n [attr.rel]=\"secondaryActionMode === 'open' ? 'noreferrer' : null\"\n [attr.download]=\"secondaryActionMode === 'download' ? '' : null\"\n style=\"border: 1px solid #cbd5e1; background: #fff; color: #334155; border-radius: 999px; padding: 8px 14px; text-decoration: none; font: inherit;\"\n >\n {{ secondaryActionText }}\n </a>\n </div>\n </ng-template>\n </div>\n </ng-template>\n </div>\n\n <ng-container *ngIf=\"!externalViewer\">\n <div *ngIf=\"configuredViewer !== 'pdf'\" class=\"inline-document-shell\">\n <div class=\"inline-document-page\" [innerHTML]=\"docHtml\"></div>\n </div>\n <object\n (load)=\"objectLoaded()\"\n *ngIf=\"fullUrl && configuredViewer === 'pdf'\"\n [data]=\"fullUrl\"\n type=\"application/pdf\"\n width=\"100%\"\n height=\"100%\"\n >\n <p>\n Your browser does not support PDFs.\n <a [href]=\"fullUrl\">Download the PDF</a>.\n </p>\n </object>\n </ng-container>\n\n <button\n *ngIf=\"configuredViewer === 'office' && renderPhase === 'ready'\"\n class=\"office-reload-btn\"\n type=\"button\"\n [attr.title]=\"officeReloadButtonTitle\"\n (click)=\"retryLoad()\"\n >\n <ng-container *ngIf=\"officeReloadTemplate; else defaultOfficeReloadTemplate\">\n <ng-container *ngTemplateOutlet=\"officeReloadTemplate; context: errorTemplateContext\"></ng-container>\n </ng-container>\n <ng-template #defaultOfficeReloadTemplate>{{ officeReloadButtonText }}</ng-template>\n </button>\n\n <ng-container *ngIf=\"externalViewer\">\n <iframe\n (load)=\"iframeLoaded()\"\n *ngIf=\"fullUrl && showIframe && disableContent === 'none'\"\n #iframe\n id=\"iframe-doc-viewer\"\n frameBorder=\"0\"\n allow=\"clipboard-read; clipboard-write\"\n [src]=\"fullUrl\"\n ></iframe>\n <div class=\"container\" *ngIf=\"disableContent !== 'none'\">\n <div\n [class.overlay-full]=\"disableContent === 'all'\"\n [class.overlay-popout-google]=\"\n configuredViewer === 'google' &&\n (disableContent === 'popout' || disableContent === 'popout-hide')\n \"\n [class.overlay-popout-office]=\"\n configuredViewer === 'office' &&\n (disableContent === 'popout' || disableContent === 'popout-hide')\n \"\n [style.background-color]=\"\n disableContent === 'popout-hide' ? '#fff' : 'transparent'\n \"\n ></div>\n <iframe\n (load)=\"iframeLoaded()\"\n *ngIf=\"fullUrl && showIframe\"\n #iframe\n id=\"iframe\"\n frameBorder=\"0\"\n allow=\"clipboard-read; clipboard-write\"\n [src]=\"fullUrl\"\n ></iframe>\n </div>\n </ng-container>\n</div>\n", styles: [":host{display:block}.container{width:100%;height:100%;position:relative}.inline-document-shell{width:100%;height:100%;overflow:auto;background:linear-gradient(180deg,#eef2f7,#f8fafc);padding:24px}.inline-document-page{max-width:900px;min-height:100%;margin:0 auto;background:#fff;border:1px solid #dbe4f0;border-radius:18px;box-shadow:0 18px 40px -24px #0f172a4d,0 6px 18px -10px #0f172a2e;padding:40px 48px}.inline-document-page,.inline-document-page *{box-sizing:border-box}.inline-document-page{color:#1e293b;font-family:Georgia,Cambria,Times New Roman,Times,serif;font-size:18px;line-height:1.7}.inline-document-page p,.inline-document-page ul,.inline-document-page ol,.inline-document-page blockquote,.inline-document-page table{margin:0 0 1.1em}.inline-document-page h1,.inline-document-page h2,.inline-document-page h3,.inline-document-page h4,.inline-document-page h5,.inline-document-page h6{margin:1.4em 0 .65em;color:#0f172a;line-height:1.25}.inline-document-page h1:first-child,.inline-document-page h2:first-child,.inline-document-page h3:first-child,.inline-document-page p:first-child{margin-top:0}.inline-document-page table{width:100%;border-collapse:collapse}.inline-document-page td,.inline-document-page th{padding:6px 10px;vertical-align:top}.inline-document-page img{max-width:100%;height:auto}.inline-document-page hr{border:0;border-top:1px solid #dbe4f0;margin:1.5em 0}.loading-overlay{position:absolute;inset:0;z-index:1001;display:flex;align-items:center;justify-content:center;background:#ffffffe0;color:#475569;font-size:14px;font-weight:600;letter-spacing:.02em;text-align:center;padding:16px}.error-overlay{position:absolute;inset:0;z-index:1001;display:flex;align-items:center;justify-content:center;background:#fffffff0;color:#991b1b;font-size:14px;font-weight:600;letter-spacing:.02em;text-align:center;padding:16px}.overlay-popout-google{width:40px;height:40px;right:26px;top:11.5px;position:absolute;z-index:1000}.overlay-popout-office{width:100px;height:20px;right:0;bottom:0;position:absolute;z-index:1000}.office-reload-btn{position:absolute;top:8px;right:8px;z-index:1001;width:32px;height:32px;border-radius:50%;border:1px solid rgba(0,0,0,.12);background:#ffffffd9;color:#475569;font-size:16px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;opacity:.5;transition:opacity .15s;padding:0}.office-reload-btn:hover{opacity:1}.overlay-full{width:100%;height:100%;right:0;top:0;position:absolute;z-index:1000}iframe{width:100%;height:100%}@media(max-width:768px){.inline-document-shell{padding:12px}.inline-document-page{border-radius:12px;padding:22px 18px}}\n"] }] }], ctorParameters: () => [{ type: i1.DomSanitizer }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }], propDecorators: { loaded: [{ type: Output }], loading: [{ type: Output }], error: [{ type: Output }], phaseChange: [{ type: Output }], url: [{ type: Input }], queryParams: [{ type: Input }], viewerUrl: [{ type: Input }], googleCheckInterval: [{ type: Input }], googleMaxChecks: [{ type: Input }], googleFinalRetryDelay: [{ type: Input }], disableContent: [{ type: Input }], googleCheckContentLoaded: [{ type: Input }], viewer: [{ type: Input }], overrideLocalhost: [{ type: Input }], loadingText: [{ type: Input }], errorTextOverride: [{ type: Input }], retryButtonText: [{ type: Input }], officeAutoRetry: [{ type: Input }], officeRetryDelay: [{ type: Input }], officeReloadButtonText: [{ type: Input }], officeReloadButtonTitle: [{ type: Input }], secondaryActionText: [{ type: Input }], secondaryActionMode: [{ type: Input }], loadingTemplate: [{ type: ContentChild, args: ['loadingContent', { read: TemplateRef }] }], errorTemplate: [{ type: ContentChild, args: ['errorContent', { read: TemplateRef }] }], errorActionsTemplate: [{ type: ContentChild, args: ['errorActions', { read: TemplateRef }] }], officeReloadTemplate: [{ type: ContentChild, args: ['officeReloadContent', { read: TemplateRef }] }], iframes: [{ type: ViewChildren, args: ['iframe'] }] } }); class NgxDocViewerModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NgxDocViewerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.4", ngImport: i0, type: NgxDocViewerModule, imports: [CommonModule, NgxDocViewerComponent], exports: [NgxDocViewerComponent] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NgxDocViewerModule, imports: [CommonModule, NgxDocViewerComponent] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: NgxDocViewerModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule, NgxDocViewerComponent], exports: [NgxDocViewerComponent], }] }] }); /** * Generated bundle index. Do not edit. */ export { NgxDocViewerComponent, NgxDocViewerModule }; //# sourceMappingURL=ngx-doc-viewer.mjs.map