ng2-pdfjs-viewer 25.0.10 → 25.0.12

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.
package/README.md CHANGED
@@ -219,16 +219,32 @@ Add PDF.js assets to your `angular.json`:
219
219
 
220
220
  #### Nginx Configuration
221
221
 
222
- For production deployments using nginx, you may need to configure MIME types for PDF.js ES modules (`.mjs` files):
222
+ For production deployments using nginx, configure MIME types for PDF.js ES modules:
223
223
 
224
224
  ```nginx
225
225
  # Add to your nginx.conf or site configuration
226
226
  types {
227
227
  application/javascript js mjs;
228
+ text/plain ftl;
228
229
  }
229
230
  ```
230
231
 
231
- **Why this is needed**: PDF.js v5+ uses `.mjs` files (ES modules). Without proper MIME type configuration, nginx serves these files with incorrect content-type headers, causing the PDF viewer to crash during loading in production environments.
232
+ #### IIS Configuration (Windows Server)
233
+
234
+ For production deployments using IIS, add to your `web.config`:
235
+
236
+ ```xml
237
+ <configuration>
238
+ <system.webServer>
239
+ <staticContent>
240
+ <mimeMap fileExtension=".mjs" mimeType="application/javascript" />
241
+ <mimeMap fileExtension=".ftl" mimeType="text/plain" />
242
+ </staticContent>
243
+ </system.webServer>
244
+ </configuration>
245
+ ```
246
+
247
+ **Why this is needed**: PDF.js v5+ uses `.mjs` files (ES modules) and `.ftl` files (localization). Without proper MIME type configuration, web servers serve these files with incorrect content-type headers, causing the PDF viewer to crash during loading in production environments.
232
248
 
233
249
  ### Angular Version Support
234
250
 
@@ -861,6 +861,10 @@ class PdfJsViewerComponent {
861
861
  if (changes['pdfSrc'] && !changes['pdfSrc'].firstChange) {
862
862
  // pdfSrc changed after initialization - reload the PDF
863
863
  if (!this.externalWindow) {
864
+ // Show spinner immediately when PDF source changes (Issue #275)
865
+ this.isLoading = true;
866
+ this.hasError = false;
867
+ this.currentErrorMessage = "";
864
868
  // Reset configuration queuing since iframe will reload fresh
865
869
  this.initialConfigQueued = false;
866
870
  this.isPostMessageReady = false;
@@ -1605,6 +1609,10 @@ class PdfJsViewerComponent {
1605
1609
  loadPdf() {
1606
1610
  if (!this.validatePdfSource())
1607
1611
  return;
1612
+ // Show spinner immediately when PDF loading starts (Issue #275)
1613
+ this.isLoading = true;
1614
+ this.hasError = false;
1615
+ this.currentErrorMessage = "";
1608
1616
  this.setupExternalWindow();
1609
1617
  const fileUrl = this.createFileUrl();
1610
1618
  const viewerUrl = this.buildViewerUrl(fileUrl);
@@ -1877,10 +1885,7 @@ class PdfJsViewerComponent {
1877
1885
  }
1878
1886
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: PdfJsViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1879
1887
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.6", type: PdfJsViewerComponent, isStandalone: false, selector: "ng2-pdfjs-viewer", inputs: { viewerId: "viewerId", viewerFolder: "viewerFolder", externalWindow: "externalWindow", target: "target", showSpinner: "showSpinner", downloadFileName: "downloadFileName", locale: "locale", useOnlyCssZoom: "useOnlyCssZoom", diagnosticLogs: "diagnosticLogs", showOpenFile: "showOpenFile", showAnnotations: "showAnnotations", showDownload: "showDownload", showViewBookmark: "showViewBookmark", showPrint: "showPrint", showFullScreen: "showFullScreen", showFind: "showFind", downloadOnLoad: "downloadOnLoad", printOnLoad: "printOnLoad", rotateCW: "rotateCW", rotateCCW: "rotateCCW", showLastPageOnLoad: "showLastPageOnLoad", namedDest: "namedDest", errorOverride: "errorOverride", errorAppend: "errorAppend", errorMessage: "errorMessage", urlValidation: "urlValidation", customSecurityTpl: "customSecurityTpl", theme: "theme", primaryColor: "primaryColor", backgroundColor: "backgroundColor", pageBorderColor: "pageBorderColor", pageSpacing: "pageSpacing", toolbarColor: "toolbarColor", textColor: "textColor", borderRadius: "borderRadius", customCSS: "customCSS", cspNonce: "cspNonce", iframeTitle: "iframeTitle", customSpinnerTpl: "customSpinnerTpl", spinnerClass: "spinnerClass", customErrorTpl: "customErrorTpl", errorClass: "errorClass", showToolbarLeft: "showToolbarLeft", showToolbarMiddle: "showToolbarMiddle", showToolbarRight: "showToolbarRight", showSecondaryToolbarToggle: "showSecondaryToolbarToggle", showSidebar: "showSidebar", showSidebarLeft: "showSidebarLeft", showSidebarRight: "showSidebarRight", toolbarDensity: "toolbarDensity", sidebarWidth: "sidebarWidth", toolbarPosition: "toolbarPosition", sidebarPosition: "sidebarPosition", responsiveBreakpoint: "responsiveBreakpoint", controlVisibility: "controlVisibility", autoActions: "autoActions", errorHandling: "errorHandling", viewerConfig: "viewerConfig", themeConfig: "themeConfig", groupVisibility: "groupVisibility", layoutConfig: "layoutConfig", startDownload: "startDownload", startPrint: "startPrint", openFile: "openFile", download: "download", print: "print", fullScreen: "fullScreen", find: "find", viewBookmark: "viewBookmark", lastPage: "lastPage", externalWindowOptions: "externalWindowOptions", iframeBorder: "iframeBorder", zoom: "zoom", rotation: "rotation", cursor: "cursor", scroll: "scroll", spread: "spread", pageMode: "pageMode", page: "page", pdfSrc: "pdfSrc" }, outputs: { onBeforePrint: "onBeforePrint", onAfterPrint: "onAfterPrint", onDocumentLoad: "onDocumentLoad", onPageChange: "onPageChange", onScaleChange: "onScaleChange", onRotationChange: "onRotationChange", onDocumentError: "onDocumentError", onDocumentInit: "onDocumentInit", onPagesInit: "onPagesInit", onPresentationModeChanged: "onPresentationModeChanged", onOpenFile: "onOpenFile", onFind: "onFind", onUpdateFindMatchesCount: "onUpdateFindMatchesCount", onMetadataLoaded: "onMetadataLoaded", onOutlineLoaded: "onOutlineLoaded", onPageRendered: "onPageRendered", onAnnotationLayerRendered: "onAnnotationLayerRendered", onBookmarkClick: "onBookmarkClick", onIdle: "onIdle", zoomChange: "zoomChange", cursorChange: "cursorChange", scrollChange: "scrollChange", spreadChange: "spreadChange", pageModeChange: "pageModeChange" }, viewQueries: [{ propertyName: "iframe", first: true, predicate: ["iframe"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `
1880
- <div
1881
- class="ng2-pdfjs-viewer-container"
1882
- style="position:relative;width:100%;height:100%;"
1883
- >
1888
+ <div class="ng2-pdfjs-viewer-container">
1884
1889
  <iframe
1885
1890
  [title]="iframeTitle || 'PDF document viewer'"
1886
1891
  [hidden]="externalWindow || (!externalWindow && !pdfSrc)"
@@ -1895,18 +1900,15 @@ class PdfJsViewerComponent {
1895
1900
  class="ng2-pdfjs-loading-overlay"
1896
1901
  *ngIf="showSpinner && isLoading && !externalWindow"
1897
1902
  [ngClass]="spinnerClass"
1898
- style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.6);backdrop-filter:saturate(120%) blur(1px);"
1899
1903
  >
1900
1904
  <ng-container
1901
1905
  *ngIf="customSpinnerTpl; else defaultSpinner"
1902
1906
  [ngTemplateOutlet]="customSpinnerTpl"
1903
1907
  ></ng-container>
1904
1908
  <ng-template #defaultSpinner>
1905
- <div style="text-align:center;">
1906
- <div
1907
- style="display:inline-block;width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #2196F3;border-radius:50%;animation:spin 1s linear infinite;"
1908
- ></div>
1909
- <div style="margin-top:16px;color:#666;font-size:16px;">
1909
+ <div class="ng2-pdfjs-spinner-content">
1910
+ <div class="ng2-pdfjs-spinner-icon"></div>
1911
+ <div class="ng2-pdfjs-spinner-text">
1910
1912
  Loading PDF...
1911
1913
  </div>
1912
1914
  </div>
@@ -1917,7 +1919,6 @@ class PdfJsViewerComponent {
1917
1919
  class="ng2-pdfjs-error-overlay"
1918
1920
  *ngIf="errorOverride && hasError && !externalWindow"
1919
1921
  [ngClass]="errorClass"
1920
- style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.9);backdrop-filter:saturate(120%) blur(1px);"
1921
1922
  >
1922
1923
  <ng-container
1923
1924
  *ngIf="customErrorTpl; else defaultError"
@@ -1925,31 +1926,26 @@ class PdfJsViewerComponent {
1925
1926
  [ngTemplateOutletContext]="getErrorTemplateData()"
1926
1927
  ></ng-container>
1927
1928
  <ng-template #defaultError>
1928
- <div style="text-align:center;max-width:400px;padding:20px;">
1929
- <div style="font-size:48px;color:#f44336;margin-bottom:16px;">
1929
+ <div class="ng2-pdfjs-error-content">
1930
+ <div class="ng2-pdfjs-error-icon">
1930
1931
  ⚠️
1931
1932
  </div>
1932
- <div
1933
- style="color:#333;font-size:18px;font-weight:500;margin-bottom:8px;"
1934
- >
1933
+ <div class="ng2-pdfjs-error-title">
1935
1934
  Error Loading PDF
1936
1935
  </div>
1937
- <div style="color:#666;font-size:14px;line-height:1.4;">
1936
+ <div class="ng2-pdfjs-error-message">
1938
1937
  {{ currentErrorMessage }}
1939
1938
  </div>
1940
1939
  </div>
1941
1940
  </ng-template>
1942
1941
  </div>
1943
1942
  </div>
1944
- `, isInline: true, styles: [".ng2-pdfjs-loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#fff9;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-error-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffe6;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
1943
+ `, isInline: true, styles: [".ng2-pdfjs-viewer-container{position:relative;width:100%;height:100%}.ng2-pdfjs-loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#fff9;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-spinner-content{text-align:center}.ng2-pdfjs-spinner-icon{display:inline-block;width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #2196F3;border-radius:50%;animation:spin 1s linear infinite}.ng2-pdfjs-spinner-text{margin-top:16px;color:#666;font-size:16px}.ng2-pdfjs-error-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffe6;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-error-content{text-align:center;max-width:400px;padding:20px}.ng2-pdfjs-error-icon{font-size:48px;color:#f44336;margin-bottom:16px}.ng2-pdfjs-error-title{color:#333;font-size:18px;font-weight:500;margin-bottom:8px}.ng2-pdfjs-error-message{color:#666;font-size:14px;line-height:1.4}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
1945
1944
  }
1946
1945
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: PdfJsViewerComponent, decorators: [{
1947
1946
  type: Component,
1948
1947
  args: [{ selector: "ng2-pdfjs-viewer", standalone: false, template: `
1949
- <div
1950
- class="ng2-pdfjs-viewer-container"
1951
- style="position:relative;width:100%;height:100%;"
1952
- >
1948
+ <div class="ng2-pdfjs-viewer-container">
1953
1949
  <iframe
1954
1950
  [title]="iframeTitle || 'PDF document viewer'"
1955
1951
  [hidden]="externalWindow || (!externalWindow && !pdfSrc)"
@@ -1964,18 +1960,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
1964
1960
  class="ng2-pdfjs-loading-overlay"
1965
1961
  *ngIf="showSpinner && isLoading && !externalWindow"
1966
1962
  [ngClass]="spinnerClass"
1967
- style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.6);backdrop-filter:saturate(120%) blur(1px);"
1968
1963
  >
1969
1964
  <ng-container
1970
1965
  *ngIf="customSpinnerTpl; else defaultSpinner"
1971
1966
  [ngTemplateOutlet]="customSpinnerTpl"
1972
1967
  ></ng-container>
1973
1968
  <ng-template #defaultSpinner>
1974
- <div style="text-align:center;">
1975
- <div
1976
- style="display:inline-block;width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #2196F3;border-radius:50%;animation:spin 1s linear infinite;"
1977
- ></div>
1978
- <div style="margin-top:16px;color:#666;font-size:16px;">
1969
+ <div class="ng2-pdfjs-spinner-content">
1970
+ <div class="ng2-pdfjs-spinner-icon"></div>
1971
+ <div class="ng2-pdfjs-spinner-text">
1979
1972
  Loading PDF...
1980
1973
  </div>
1981
1974
  </div>
@@ -1986,7 +1979,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
1986
1979
  class="ng2-pdfjs-error-overlay"
1987
1980
  *ngIf="errorOverride && hasError && !externalWindow"
1988
1981
  [ngClass]="errorClass"
1989
- style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.9);backdrop-filter:saturate(120%) blur(1px);"
1990
1982
  >
1991
1983
  <ng-container
1992
1984
  *ngIf="customErrorTpl; else defaultError"
@@ -1994,23 +1986,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
1994
1986
  [ngTemplateOutletContext]="getErrorTemplateData()"
1995
1987
  ></ng-container>
1996
1988
  <ng-template #defaultError>
1997
- <div style="text-align:center;max-width:400px;padding:20px;">
1998
- <div style="font-size:48px;color:#f44336;margin-bottom:16px;">
1989
+ <div class="ng2-pdfjs-error-content">
1990
+ <div class="ng2-pdfjs-error-icon">
1999
1991
  ⚠️
2000
1992
  </div>
2001
- <div
2002
- style="color:#333;font-size:18px;font-weight:500;margin-bottom:8px;"
2003
- >
1993
+ <div class="ng2-pdfjs-error-title">
2004
1994
  Error Loading PDF
2005
1995
  </div>
2006
- <div style="color:#666;font-size:14px;line-height:1.4;">
1996
+ <div class="ng2-pdfjs-error-message">
2007
1997
  {{ currentErrorMessage }}
2008
1998
  </div>
2009
1999
  </div>
2010
2000
  </ng-template>
2011
2001
  </div>
2012
2002
  </div>
2013
- `, styles: [".ng2-pdfjs-loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#fff9;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-error-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffe6;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
2003
+ `, styles: [".ng2-pdfjs-viewer-container{position:relative;width:100%;height:100%}.ng2-pdfjs-loading-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#fff9;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-spinner-content{text-align:center}.ng2-pdfjs-spinner-icon{display:inline-block;width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #2196F3;border-radius:50%;animation:spin 1s linear infinite}.ng2-pdfjs-spinner-text{margin-top:16px;color:#666;font-size:16px}.ng2-pdfjs-error-overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffe6;-webkit-backdrop-filter:saturate(120%) blur(1px);backdrop-filter:saturate(120%) blur(1px)}.ng2-pdfjs-error-content{text-align:center;max-width:400px;padding:20px}.ng2-pdfjs-error-icon{font-size:48px;color:#f44336;margin-bottom:16px}.ng2-pdfjs-error-title{color:#333;font-size:18px;font-weight:500;margin-bottom:8px}.ng2-pdfjs-error-message{color:#666;font-size:14px;line-height:1.4}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
2014
2004
  }], propDecorators: { iframe: [{
2015
2005
  type: ViewChild,
2016
2006
  args: ["iframe", { static: true }]