@yoozsoft/yoozsoft-ng 5.3.5 → 7.1.1

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.
Files changed (113) hide show
  1. package/README.md +143 -24
  2. package/assets/js/UTIF.js-master/LICENSE +21 -21
  3. package/assets/js/UTIF.js-master/README.md +72 -72
  4. package/assets/js/UTIF.js-master/UTIF.js +1762 -1762
  5. package/assets/js/UTIF.js-master/package-lock.json +13 -13
  6. package/assets/js/UTIF.js-master/package.json +24 -0
  7. package/assets/styles/components/_ys-navbar.scss +22 -0
  8. package/assets/styles/components/_ys-pagination.scss +10 -0
  9. package/assets/styles/{ys-layout.scss → utilities/ys-layout.scss} +1 -1
  10. package/assets/styles/ys-styles.scss +2 -0
  11. package/autocomplete/package.json +4 -0
  12. package/date/package.json +4 -0
  13. package/datepicker/package.json +4 -0
  14. package/dropdown/package.json +4 -0
  15. package/fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs +257 -197
  16. package/fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs.map +1 -1
  17. package/fesm2022/yoozsoft-yoozsoft-ng-date.mjs +562 -0
  18. package/fesm2022/yoozsoft-yoozsoft-ng-date.mjs.map +1 -0
  19. package/fesm2022/yoozsoft-yoozsoft-ng-datepicker.mjs +600 -837
  20. package/fesm2022/yoozsoft-yoozsoft-ng-datepicker.mjs.map +1 -1
  21. package/fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs +161 -151
  22. package/fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs.map +1 -1
  23. package/fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs +93 -103
  24. package/fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs.map +1 -1
  25. package/fesm2022/yoozsoft-yoozsoft-ng-footer.mjs +16 -21
  26. package/fesm2022/yoozsoft-yoozsoft-ng-footer.mjs.map +1 -1
  27. package/fesm2022/yoozsoft-yoozsoft-ng-loading.mjs +20 -24
  28. package/fesm2022/yoozsoft-yoozsoft-ng-loading.mjs.map +1 -1
  29. package/fesm2022/yoozsoft-yoozsoft-ng-navbar.mjs +60 -76
  30. package/fesm2022/yoozsoft-yoozsoft-ng-navbar.mjs.map +1 -1
  31. package/fesm2022/yoozsoft-yoozsoft-ng-overlay.mjs +11 -15
  32. package/fesm2022/yoozsoft-yoozsoft-ng-overlay.mjs.map +1 -1
  33. package/fesm2022/yoozsoft-yoozsoft-ng-pagination.mjs +61 -55
  34. package/fesm2022/yoozsoft-yoozsoft-ng-pagination.mjs.map +1 -1
  35. package/fesm2022/yoozsoft-yoozsoft-ng-password-strength.mjs +142 -130
  36. package/fesm2022/yoozsoft-yoozsoft-ng-password-strength.mjs.map +1 -1
  37. package/fesm2022/yoozsoft-yoozsoft-ng-pipes.mjs +44 -0
  38. package/fesm2022/yoozsoft-yoozsoft-ng-pipes.mjs.map +1 -0
  39. package/fesm2022/yoozsoft-yoozsoft-ng-progress.mjs +51 -34
  40. package/fesm2022/yoozsoft-yoozsoft-ng-progress.mjs.map +1 -1
  41. package/fesm2022/yoozsoft-yoozsoft-ng-rating.mjs +155 -0
  42. package/fesm2022/yoozsoft-yoozsoft-ng-rating.mjs.map +1 -0
  43. package/fesm2022/yoozsoft-yoozsoft-ng-select.mjs +78 -80
  44. package/fesm2022/yoozsoft-yoozsoft-ng-select.mjs.map +1 -1
  45. package/fesm2022/yoozsoft-yoozsoft-ng-sidebar.mjs +99 -99
  46. package/fesm2022/yoozsoft-yoozsoft-ng-sidebar.mjs.map +1 -1
  47. package/fesm2022/yoozsoft-yoozsoft-ng-table.mjs +316 -0
  48. package/fesm2022/yoozsoft-yoozsoft-ng-table.mjs.map +1 -0
  49. package/fesm2022/yoozsoft-yoozsoft-ng-tiff-viewer.mjs +128 -114
  50. package/fesm2022/yoozsoft-yoozsoft-ng-tiff-viewer.mjs.map +1 -1
  51. package/fesm2022/yoozsoft-yoozsoft-ng-toast.mjs +112 -62
  52. package/fesm2022/yoozsoft-yoozsoft-ng-toast.mjs.map +1 -1
  53. package/fesm2022/yoozsoft-yoozsoft-ng-validators.mjs +37 -0
  54. package/fesm2022/yoozsoft-yoozsoft-ng-validators.mjs.map +1 -0
  55. package/fesm2022/yoozsoft-yoozsoft-ng.mjs.map +1 -1
  56. package/file-upload/package.json +4 -0
  57. package/footer/package.json +4 -0
  58. package/loading/package.json +4 -0
  59. package/navbar/package.json +4 -0
  60. package/overlay/package.json +4 -0
  61. package/package.json +61 -38
  62. package/pagination/package.json +4 -0
  63. package/password-strength/package.json +4 -0
  64. package/pipes/package.json +4 -0
  65. package/progress/package.json +4 -0
  66. package/rating/package.json +4 -0
  67. package/select/package.json +4 -0
  68. package/sidebar/package.json +4 -0
  69. package/table/package.json +4 -0
  70. package/tiff-viewer/package.json +4 -0
  71. package/toast/package.json +4 -0
  72. package/types/yoozsoft-yoozsoft-ng-autocomplete.d.ts +79 -0
  73. package/types/yoozsoft-yoozsoft-ng-date.d.ts +118 -0
  74. package/types/yoozsoft-yoozsoft-ng-datepicker.d.ts +120 -0
  75. package/types/yoozsoft-yoozsoft-ng-dropdown.d.ts +76 -0
  76. package/types/yoozsoft-yoozsoft-ng-file-upload.d.ts +75 -0
  77. package/types/yoozsoft-yoozsoft-ng-footer.d.ts +26 -0
  78. package/types/yoozsoft-yoozsoft-ng-loading.d.ts +14 -0
  79. package/types/yoozsoft-yoozsoft-ng-navbar.d.ts +60 -0
  80. package/types/yoozsoft-yoozsoft-ng-overlay.d.ts +10 -0
  81. package/types/yoozsoft-yoozsoft-ng-pagination.d.ts +31 -0
  82. package/types/yoozsoft-yoozsoft-ng-password-strength.d.ts +73 -0
  83. package/types/yoozsoft-yoozsoft-ng-pipes.d.ts +11 -0
  84. package/types/yoozsoft-yoozsoft-ng-progress.d.ts +31 -0
  85. package/types/yoozsoft-yoozsoft-ng-rating.d.ts +56 -0
  86. package/types/yoozsoft-yoozsoft-ng-select.d.ts +43 -0
  87. package/types/yoozsoft-yoozsoft-ng-sidebar.d.ts +69 -0
  88. package/types/yoozsoft-yoozsoft-ng-table.d.ts +137 -0
  89. package/types/yoozsoft-yoozsoft-ng-tiff-viewer.d.ts +53 -0
  90. package/types/yoozsoft-yoozsoft-ng-toast.d.ts +66 -0
  91. package/types/yoozsoft-yoozsoft-ng-validators.d.ts +5 -0
  92. package/validators/package.json +4 -0
  93. package/autocomplete/index.d.ts +0 -71
  94. package/datepicker/index.d.ts +0 -291
  95. package/directives/index.d.ts +0 -17
  96. package/dropdown/index.d.ts +0 -62
  97. package/fesm2022/yoozsoft-yoozsoft-ng-directives.mjs +0 -57
  98. package/fesm2022/yoozsoft-yoozsoft-ng-directives.mjs.map +0 -1
  99. package/file-upload/index.d.ts +0 -72
  100. package/footer/index.d.ts +0 -25
  101. package/loading/index.d.ts +0 -13
  102. package/navbar/index.d.ts +0 -56
  103. package/overlay/index.d.ts +0 -11
  104. package/pagination/index.d.ts +0 -29
  105. package/password-strength/index.d.ts +0 -84
  106. package/progress/index.d.ts +0 -28
  107. package/select/index.d.ts +0 -39
  108. package/sidebar/index.d.ts +0 -94
  109. package/tiff-viewer/index.d.ts +0 -52
  110. package/toast/index.d.ts +0 -53
  111. /package/assets/styles/{ys-preloader-9.scss → preloaders/ys-preloader-9.scss} +0 -0
  112. /package/assets/styles/{ys-preloader.scss → preloaders/ys-preloader.scss} +0 -0
  113. /package/{index.d.ts → types/yoozsoft-yoozsoft-ng.d.ts} +0 -0
@@ -1,142 +1,156 @@
1
- import { NgClass } from '@angular/common';
1
+ import { isPlatformBrowser, NgClass } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { Input, ViewChild, Component } from '@angular/core';
3
+ import { inject, PLATFORM_ID, input, output, signal, computed, viewChild, effect, ChangeDetectionStrategy, Component } from '@angular/core';
4
4
 
5
- class YsTiffViewerComponent {
6
- canvasRef;
7
- canvas;
8
- context;
9
- /**image file directories */
10
- IFDs = [];
11
- currentIFDIndex = 0;
12
- isDecoding = false;
13
- _buffer;
14
- /**Uint8Array source */
15
- /**ArrayBuffer containing TIFF or EXIF data */
16
- get buffer() { return this._buffer; }
17
- set buffer(value) { this._buffer = value; this.convertSource(this._buffer); }
18
- _currentPageReportTemplate = "Page {current} of {total}";
19
- /**Current page report template */
20
- get currentPageReportTemplate() {
21
- return this._currentPageReportTemplate?.
22
- replace('{current}', `<strong>${this.currentIFDIndex + 1}</strong>`).
23
- replace('{total}', `<strong>${this.IFDs.length}</strong>`);
5
+ const DEFAULT_TIFF_ICONS = {
6
+ first: 'fa fa-fast-backward',
7
+ previous: 'fa fa-step-backward',
8
+ next: 'fa fa-step-forward',
9
+ last: 'fa fa-fast-forward',
10
+ };
11
+ class YsTiffViewer {
12
+ // ---------- injects ----------
13
+ platformId = inject(PLATFORM_ID);
14
+ // ---------- inputs ----------
15
+ buffer = input(/* @ts-ignore */
16
+ ...(ngDevMode ? [undefined, { debugName: "buffer" }] : /* istanbul ignore next */ []));
17
+ styleClass = input(/* @ts-ignore */
18
+ ...(ngDevMode ? [undefined, { debugName: "styleClass" }] : /* istanbul ignore next */ []));
19
+ noFileMessage = input('No image file', /* @ts-ignore */
20
+ ...(ngDevMode ? [{ debugName: "noFileMessage" }] : /* istanbul ignore next */ []));
21
+ noFileStyleClass = input('text-center', /* @ts-ignore */
22
+ ...(ngDevMode ? [{ debugName: "noFileStyleClass" }] : /* istanbul ignore next */ []));
23
+ icons = input({}, /* @ts-ignore */
24
+ ...(ngDevMode ? [{ debugName: "icons" }] : /* istanbul ignore next */ []));
25
+ pageReportTemplate = input('Page {current} of {total}', /* @ts-ignore */
26
+ ...(ngDevMode ? [{ debugName: "pageReportTemplate" }] : /* istanbul ignore next */ []));
27
+ // ---------- outputs ----------
28
+ pageChange = output();
29
+ emitPageChange() {
30
+ this.pageChange.emit({
31
+ index: this.currentIndex(),
32
+ page: this.currentPage(),
33
+ total: this.ifds().length,
34
+ });
24
35
  }
25
- set currentPageReportTemplate(value) { this._currentPageReportTemplate = value; }
26
- /**Canvas container style class */
27
- styleClass;
28
- /**Message displayed before filling the input buffer */
29
- noFileMessage = "No image file";
30
- noFileStyleClass;
31
- /**First button icon class */
32
- firstIconClass = 'fa fa-fast-backward';
33
- /**Previous button icon class */
34
- previousIconClass = 'fa fa-step-backward';
35
- /**Next button icon class */
36
- nextIconClass = 'fa fa-step-forward';
37
- /**Last button icon class */
38
- lastIconClass = 'fa fa-fast-forward';
39
- get isIFDs() { return this.IFDs.length > 0; }
40
- get isFirstImage() { return !this.isIFDs || (this.currentIFDIndex == 0); }
41
- get isLastImage() { return !this.isIFDs || (this.currentIFDIndex == this.IFDs.length - 1); }
42
- /**
43
- * Convert buffer to an array of "IFDs" (image file directories)
44
- * @param buffer ArrayBuffer containing TIFF or EXIF data
45
- * @returns
46
- */
47
- async convertSource(buffer) {
48
- this.canvas = this.canvasRef.nativeElement;
49
- this.context = this.canvas.getContext("2d");
50
- this.IFDs = [];
51
- this.currentIFDIndex = 0;
52
- if (!buffer) {
53
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
36
+ // ---------- state ----------
37
+ ifds = signal([], /* @ts-ignore */
38
+ ...(ngDevMode ? [{ debugName: "ifds" }] : /* istanbul ignore next */ []));
39
+ currentIndex = signal(0, /* @ts-ignore */
40
+ ...(ngDevMode ? [{ debugName: "currentIndex" }] : /* istanbul ignore next */ []));
41
+ isDecoding = signal(false, /* @ts-ignore */
42
+ ...(ngDevMode ? [{ debugName: "isDecoding" }] : /* istanbul ignore next */ []));
43
+ decodeVersion = 0;
44
+ isIFDs = computed(() => this.ifds().length > 0, /* @ts-ignore */
45
+ ...(ngDevMode ? [{ debugName: "isIFDs" }] : /* istanbul ignore next */ []));
46
+ isFirstImage = computed(() => !this.isIFDs() || this.currentIndex() === 0, /* @ts-ignore */
47
+ ...(ngDevMode ? [{ debugName: "isFirstImage" }] : /* istanbul ignore next */ []));
48
+ isLastImage = computed(() => !this.isIFDs() || this.currentIndex() === this.ifds().length - 1, /* @ts-ignore */
49
+ ...(ngDevMode ? [{ debugName: "isLastImage" }] : /* istanbul ignore next */ []));
50
+ currentPage = computed(() => this.currentIndex() + 1, /* @ts-ignore */
51
+ ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
52
+ mergedIcons = computed(() => ({
53
+ ...DEFAULT_TIFF_ICONS,
54
+ ...this.icons(),
55
+ }), /* @ts-ignore */
56
+ ...(ngDevMode ? [{ debugName: "mergedIcons" }] : /* istanbul ignore next */ []));
57
+ pageReport = computed(() => this.pageReportTemplate()
58
+ .replace('{current}', `${this.currentPage()}`)
59
+ .replace('{total}', `${this.ifds().length}`), /* @ts-ignore */
60
+ ...(ngDevMode ? [{ debugName: "pageReport" }] : /* istanbul ignore next */ []));
61
+ // ---------- viewchilds ----------
62
+ canvasRef = viewChild.required('tiffCanvas', /* @ts-ignore */
63
+ ...(ngDevMode ? [{ debugName: "canvasRef" }] : /* istanbul ignore next */ []));
64
+ constructor() {
65
+ effect(() => {
66
+ const buf = this.buffer();
67
+ if (!buf)
68
+ return;
69
+ if (isPlatformBrowser(this.platformId)) {
70
+ this.decode(buf);
71
+ }
72
+ });
73
+ }
74
+ // ---------- logic ----------
75
+ async decode(source) {
76
+ const canvas = this.canvasRef().nativeElement;
77
+ const ctx = canvas.getContext('2d');
78
+ if (!ctx)
54
79
  return;
80
+ try {
81
+ this.isDecoding.set(true);
82
+ const version = ++this.decodeVersion;
83
+ this.ifds.set([]);
84
+ this.currentIndex.set(0);
85
+ let buffer = source instanceof ArrayBuffer ? source : await source.arrayBuffer();
86
+ const decoded = UTIF.decode(buffer);
87
+ if (version !== this.decodeVersion) {
88
+ return;
89
+ }
90
+ decoded.forEach((ifd) => UTIF.decodeImage(buffer, ifd));
91
+ if (version !== this.decodeVersion) {
92
+ return;
93
+ }
94
+ this.ifds.set(decoded);
95
+ this.draw(0);
96
+ this.emitPageChange();
97
+ }
98
+ catch (error) {
99
+ console.error(error);
55
100
  }
56
- if (buffer instanceof File || buffer instanceof Blob) {
57
- // buffer = await this.getAsByteArray(buffer);
58
- buffer = await buffer.arrayBuffer();
101
+ finally {
102
+ this.isDecoding.set(false);
59
103
  }
60
- this.isDecoding = true;
61
- this.IFDs = UTIF.decode(buffer);
62
- this.IFDs.forEach((ifd) => UTIF.decodeImage(buffer, ifd));
63
- this.putImage(this.currentIFDIndex);
64
- this.isDecoding = false;
65
104
  }
66
- putImage(index) {
67
- if (!this.IFDs.length) {
68
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
105
+ draw(index) {
106
+ const ctx = this.canvasRef().nativeElement.getContext('2d');
107
+ if (!ctx)
69
108
  return;
70
- }
71
- const tiffImage = this.IFDs[index];
72
- const rgbaImage = UTIF.toRGBA8(tiffImage); // Uint8Array with RGBA pixels
73
- const data = new Uint8ClampedArray(rgbaImage);
74
- const imageData = new ImageData(data, tiffImage.width, tiffImage.height);
75
- this.context.canvas.width = tiffImage.width;
76
- this.context.canvas.height = tiffImage.height;
77
- // Draw image data to the canvas
78
- this.context.putImageData(imageData, 0, 0);
109
+ const ifd = this.ifds()[index];
110
+ if (!ifd)
111
+ return;
112
+ const rgba = UTIF.toRGBA8(ifd);
113
+ const imageData = new ImageData(new Uint8ClampedArray(rgba), ifd.width, ifd.height);
114
+ ctx.canvas.width = ifd.width;
115
+ ctx.canvas.height = ifd.height;
116
+ ctx.putImageData(imageData, 0, 0);
117
+ }
118
+ // ---------- navigation ----------
119
+ goTo(index) {
120
+ this.currentIndex.set(index);
121
+ this.draw(index);
122
+ this.emitPageChange();
79
123
  }
80
124
  first() {
81
- this.currentIFDIndex = 0;
82
- this.putImage(this.currentIFDIndex);
125
+ this.goTo(0);
83
126
  }
84
127
  previous() {
85
- this.currentIFDIndex -= 1;
86
- if (this.currentIFDIndex < 0) {
87
- this.currentIFDIndex = 0;
88
- return;
89
- }
90
- this.putImage(this.currentIFDIndex);
128
+ const i = Math.max(this.currentIndex() - 1, 0);
129
+ this.goTo(i);
91
130
  }
92
131
  next() {
93
- this.currentIFDIndex += 1;
94
- if (this.currentIFDIndex > (this.IFDs.length - 1)) {
95
- this.currentIFDIndex = this.IFDs.length - 1;
96
- return;
97
- }
98
- this.putImage(this.currentIFDIndex);
132
+ const i = Math.min(this.currentPage(), this.ifds().length - 1);
133
+ this.goTo(i);
99
134
  }
100
135
  last() {
101
- this.currentIFDIndex = this.IFDs.length - 1;
102
- this.putImage(this.currentIFDIndex);
136
+ const i = this.ifds().length - 1;
137
+ this.goTo(i);
103
138
  }
104
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsTiffViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
105
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: YsTiffViewerComponent, isStandalone: true, selector: "ys-tiff-viewer", inputs: { buffer: "buffer", currentPageReportTemplate: "currentPageReportTemplate", styleClass: "styleClass", noFileMessage: "noFileMessage", noFileStyleClass: "noFileStyleClass", firstIconClass: "firstIconClass", previousIconClass: "previousIconClass", nextIconClass: "nextIconClass", lastIconClass: "lastIconClass" }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["tiffCanvas"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"row\">\r\n <div class=\"col d-flex justify-content-between align-items-center\">\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" [ngClass]=\"{'ml-auto': isIFDs}\" type=\"button\" (click)=\"first()\"\r\n [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"firstIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" type=\"button\" (click)=\"previous()\" [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"previousIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n @if (isIFDs) {\r\n <span [innerHtml]=\"currentPageReportTemplate\">\r\n </span>\r\n }\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" type=\"button\" (click)=\"next()\" [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"nextIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" [ngClass]=\"{'mr-auto': isIFDs}\" type=\"button\" (click)=\"last()\"\r\n [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"lastIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n\r\n </div>\r\n</div>\r\n<div class=\"row\">\r\n <div class=\"col\">\r\n <div class=\"canvas-container card d-flex justify-content-center align-items-center mt-1 {{styleClass}}\">\r\n @if (!isIFDs && noFileMessage) {\r\n <span class=\"my-4\" [ngClass]=\"noFileStyleClass\">{{noFileMessage}}</span>\r\n }\r\n <canvas #tiffCanvas class=\"canvas-image img-fluid\" [ngClass]=\"{'d-none': !isIFDs}\"></canvas>\r\n <div class=\"backdrop position-absolute w-100 h-100 d-flex justify-content-center align-items-center\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n\r\n </div>\r\n <div class=\"spinner-border text-info position-absolute\" style=\"width: 3rem; height: 3rem;\" role=\"status\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".backdrop{background-color:rgba(var(--bs-dark-rgb),.3)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
139
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: YsTiffViewer, deps: [], target: i0.ɵɵFactoryTarget.Component });
140
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: YsTiffViewer, isStandalone: true, selector: "ys-tiff-viewer", inputs: { buffer: { classPropertyName: "buffer", publicName: "buffer", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, noFileMessage: { classPropertyName: "noFileMessage", publicName: "noFileMessage", isSignal: true, isRequired: false, transformFunction: null }, noFileStyleClass: { classPropertyName: "noFileStyleClass", publicName: "noFileStyleClass", isSignal: true, isRequired: false, transformFunction: null }, icons: { classPropertyName: "icons", publicName: "icons", isSignal: true, isRequired: false, transformFunction: null }, pageReportTemplate: { classPropertyName: "pageReportTemplate", publicName: "pageReportTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange" }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["tiffCanvas"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"tiff-viewer\">\n <div class=\"row\">\n <div class=\"col d-flex justify-content-between align-items-center\">\n <div>\n <button class=\"btn btn-outline-primary me-2\" (click)=\"first()\" [disabled]=\"isFirstImage()\">\n <i [ngClass]=\"mergedIcons().first\"></i>\n\n </button>\n\n <button class=\"btn btn-outline-primary\" (click)=\"previous()\" [disabled]=\"isFirstImage()\">\n <i [ngClass]=\"mergedIcons().previous\"></i>\n </button>\n </div>\n\n @if (isIFDs()) {\n <span>{{ pageReport() }}</span>\n }\n\n <div>\n <button class=\"btn btn-outline-primary me-2\" (click)=\"next()\" [disabled]=\"isLastImage()\">\n <i [ngClass]=\"mergedIcons().next\"></i>\n </button>\n\n <button class=\"btn btn-outline-primary\" (click)=\"last()\" [disabled]=\"isLastImage()\">\n <i [ngClass]=\"mergedIcons().last\"></i>\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"row\">\n <div class=\"col\">\n <div class=\"canvas-container card mt-1\" [ngClass]=\"styleClass()\">\n @if (!isIFDs() && noFileMessage()) {\n <span [ngClass]=\"noFileStyleClass()\">{{ noFileMessage() }}</span>\n }\n\n <canvas #tiffCanvas class=\"img-fluid\" [class.d-none]=\"!isIFDs()\">\n </canvas>\n\n <div class=\"spinner-border text-info position-absolute\" [class.d-none]=\"!isDecoding()\">\n </div>\n </div>\n </div>\n </div>\n</div>", styles: [".tiff-viewer{direction:ltr!important}.backdrop{background-color:rgba(var(--bs-dark-rgb),.3)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
106
141
  }
107
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsTiffViewerComponent, decorators: [{
142
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: YsTiffViewer, decorators: [{
108
143
  type: Component,
109
- args: [{ selector: 'ys-tiff-viewer', imports: [NgClass], template: "<div class=\"row\">\r\n <div class=\"col d-flex justify-content-between align-items-center\">\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" [ngClass]=\"{'ml-auto': isIFDs}\" type=\"button\" (click)=\"first()\"\r\n [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"firstIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" type=\"button\" (click)=\"previous()\" [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"previousIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n @if (isIFDs) {\r\n <span [innerHtml]=\"currentPageReportTemplate\">\r\n </span>\r\n }\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" type=\"button\" (click)=\"next()\" [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"nextIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" [ngClass]=\"{'mr-auto': isIFDs}\" type=\"button\" (click)=\"last()\"\r\n [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"lastIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n\r\n </div>\r\n</div>\r\n<div class=\"row\">\r\n <div class=\"col\">\r\n <div class=\"canvas-container card d-flex justify-content-center align-items-center mt-1 {{styleClass}}\">\r\n @if (!isIFDs && noFileMessage) {\r\n <span class=\"my-4\" [ngClass]=\"noFileStyleClass\">{{noFileMessage}}</span>\r\n }\r\n <canvas #tiffCanvas class=\"canvas-image img-fluid\" [ngClass]=\"{'d-none': !isIFDs}\"></canvas>\r\n <div class=\"backdrop position-absolute w-100 h-100 d-flex justify-content-center align-items-center\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n\r\n </div>\r\n <div class=\"spinner-border text-info position-absolute\" style=\"width: 3rem; height: 3rem;\" role=\"status\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".backdrop{background-color:rgba(var(--bs-dark-rgb),.3)}\n"] }]
110
- }], propDecorators: { canvasRef: [{
111
- type: ViewChild,
112
- args: ['tiffCanvas', { static: true }]
113
- }], buffer: [{
114
- type: Input
115
- }], currentPageReportTemplate: [{
116
- type: Input
117
- }], styleClass: [{
118
- type: Input
119
- }], noFileMessage: [{
120
- type: Input
121
- }], noFileStyleClass: [{
122
- type: Input
123
- }], firstIconClass: [{
124
- type: Input
125
- }], previousIconClass: [{
126
- type: Input
127
- }], nextIconClass: [{
128
- type: Input
129
- }], lastIconClass: [{
130
- type: Input
131
- }] } });
144
+ args: [{ selector: 'ys-tiff-viewer', imports: [NgClass], changeDetection: ChangeDetectionStrategy.Eager, template: "<div class=\"tiff-viewer\">\n <div class=\"row\">\n <div class=\"col d-flex justify-content-between align-items-center\">\n <div>\n <button class=\"btn btn-outline-primary me-2\" (click)=\"first()\" [disabled]=\"isFirstImage()\">\n <i [ngClass]=\"mergedIcons().first\"></i>\n\n </button>\n\n <button class=\"btn btn-outline-primary\" (click)=\"previous()\" [disabled]=\"isFirstImage()\">\n <i [ngClass]=\"mergedIcons().previous\"></i>\n </button>\n </div>\n\n @if (isIFDs()) {\n <span>{{ pageReport() }}</span>\n }\n\n <div>\n <button class=\"btn btn-outline-primary me-2\" (click)=\"next()\" [disabled]=\"isLastImage()\">\n <i [ngClass]=\"mergedIcons().next\"></i>\n </button>\n\n <button class=\"btn btn-outline-primary\" (click)=\"last()\" [disabled]=\"isLastImage()\">\n <i [ngClass]=\"mergedIcons().last\"></i>\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"row\">\n <div class=\"col\">\n <div class=\"canvas-container card mt-1\" [ngClass]=\"styleClass()\">\n @if (!isIFDs() && noFileMessage()) {\n <span [ngClass]=\"noFileStyleClass()\">{{ noFileMessage() }}</span>\n }\n\n <canvas #tiffCanvas class=\"img-fluid\" [class.d-none]=\"!isIFDs()\">\n </canvas>\n\n <div class=\"spinner-border text-info position-absolute\" [class.d-none]=\"!isDecoding()\">\n </div>\n </div>\n </div>\n </div>\n</div>", styles: [".tiff-viewer{direction:ltr!important}.backdrop{background-color:rgba(var(--bs-dark-rgb),.3)}\n"] }]
145
+ }], ctorParameters: () => [], propDecorators: { buffer: [{ type: i0.Input, args: [{ isSignal: true, alias: "buffer", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], noFileMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noFileMessage", required: false }] }], noFileStyleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "noFileStyleClass", required: false }] }], icons: [{ type: i0.Input, args: [{ isSignal: true, alias: "icons", required: false }] }], pageReportTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageReportTemplate", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], canvasRef: [{ type: i0.ViewChild, args: ['tiffCanvas', { isSignal: true }] }] } });
132
146
 
133
147
  /*
134
- * Public API Surface of ys-sidebar
148
+ * Public API Surface of ys-tiff-viewer
135
149
  */
136
150
 
137
151
  /**
138
152
  * Generated bundle index. Do not edit.
139
153
  */
140
154
 
141
- export { YsTiffViewerComponent };
155
+ export { YsTiffViewer };
142
156
  //# sourceMappingURL=yoozsoft-yoozsoft-ng-tiff-viewer.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"yoozsoft-yoozsoft-ng-tiff-viewer.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/src/ys-tiff-viewer/ys-tiff-viewer.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/src/ys-tiff-viewer/ys-tiff-viewer.component.html","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/yoozsoft-yoozsoft-ng-tiff-viewer.ts"],"sourcesContent":["import { NgClass } from '@angular/common';\r\nimport { Component, ElementRef, Input, ViewChild } from '@angular/core';\r\n\r\ndeclare var UTIF: any;\r\n\r\n@Component({\r\n selector: 'ys-tiff-viewer',\r\n imports: [NgClass],\r\n templateUrl: './ys-tiff-viewer.component.html',\r\n styleUrl: './ys-tiff-viewer.component.scss'\r\n})\r\nexport class YsTiffViewerComponent {\r\n\r\n @ViewChild('tiffCanvas', { static: true }) canvasRef!: ElementRef<HTMLCanvasElement>;\r\n\r\n private canvas: any;\r\n private context: any;\r\n /**image file directories */\r\n private IFDs: any[] = [];\r\n private currentIFDIndex: number = 0;\r\n isDecoding: boolean = false;\r\n\r\n private _buffer: ArrayBuffer | File | Blob | null | undefined;\r\n /**Uint8Array source */\r\n /**ArrayBuffer containing TIFF or EXIF data */\r\n @Input()\r\n get buffer(): ArrayBuffer | File | Blob | null | undefined { return this._buffer; }\r\n set buffer(value: ArrayBuffer | File | Blob | null | undefined) { this._buffer = value; this.convertSource(this._buffer); }\r\n\r\n _currentPageReportTemplate?: string = \"Page {current} of {total}\";\r\n /**Current page report template */\r\n @Input()\r\n get currentPageReportTemplate(): string | undefined {\r\n return this._currentPageReportTemplate?.\r\n replace('{current}', `<strong>${this.currentIFDIndex + 1}</strong>`).\r\n replace('{total}', `<strong>${this.IFDs.length}</strong>`);\r\n }\r\n set currentPageReportTemplate(value: string | undefined) { this._currentPageReportTemplate = value; }\r\n\r\n /**Canvas container style class */\r\n @Input() styleClass?: string;\r\n /**Message displayed before filling the input buffer */\r\n @Input() noFileMessage?: string = \"No image file\";\r\n @Input() noFileStyleClass?: string;\r\n\r\n /**First button icon class */\r\n @Input() firstIconClass: string = 'fa fa-fast-backward';\r\n /**Previous button icon class */\r\n @Input() previousIconClass: string = 'fa fa-step-backward';\r\n /**Next button icon class */\r\n @Input() nextIconClass: string = 'fa fa-step-forward';\r\n /**Last button icon class */\r\n @Input() lastIconClass: string = 'fa fa-fast-forward';\r\n\r\n get isIFDs(): boolean { return this.IFDs.length > 0; }\r\n get isFirstImage(): boolean { return !this.isIFDs || (this.currentIFDIndex == 0); }\r\n get isLastImage(): boolean { return !this.isIFDs || (this.currentIFDIndex == this.IFDs.length - 1); }\r\n\r\n /**\r\n * Convert buffer to an array of \"IFDs\" (image file directories)\r\n * @param buffer ArrayBuffer containing TIFF or EXIF data\r\n * @returns \r\n */\r\n async convertSource(buffer: ArrayBuffer | File | Blob | null | undefined): Promise<void> {\r\n this.canvas = this.canvasRef.nativeElement;\r\n this.context = this.canvas.getContext(\"2d\");\r\n this.IFDs = [];\r\n this.currentIFDIndex = 0;\r\n\r\n if (!buffer) {\r\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\r\n return;\r\n }\r\n\r\n if (buffer instanceof File || buffer instanceof Blob) {\r\n // buffer = await this.getAsByteArray(buffer);\r\n buffer = await buffer.arrayBuffer();\r\n }\r\n\r\n this.isDecoding = true;\r\n\r\n this.IFDs = UTIF.decode(buffer as ArrayBuffer);\r\n this.IFDs.forEach((ifd: any) => UTIF.decodeImage(buffer as ArrayBuffer, ifd));\r\n\r\n this.putImage(this.currentIFDIndex);\r\n this.isDecoding = false;\r\n }\r\n\r\n putImage(index: number): void {\r\n if (!this.IFDs.length) {\r\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\r\n return;\r\n }\r\n\r\n const tiffImage = this.IFDs[index];\r\n const rgbaImage = UTIF.toRGBA8(tiffImage); // Uint8Array with RGBA pixels\r\n\r\n const data = new Uint8ClampedArray(rgbaImage);\r\n const imageData = new ImageData(data, tiffImage.width, tiffImage.height);\r\n\r\n this.context.canvas.width = tiffImage.width;\r\n this.context.canvas.height = tiffImage.height;\r\n // Draw image data to the canvas\r\n this.context.putImageData(imageData, 0, 0);\r\n }\r\n\r\n\r\n first(): void {\r\n this.currentIFDIndex = 0;\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n previous(): void {\r\n this.currentIFDIndex -= 1;\r\n if (this.currentIFDIndex < 0) {\r\n this.currentIFDIndex = 0;\r\n return;\r\n }\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n\r\n next(): void {\r\n this.currentIFDIndex += 1;\r\n if (this.currentIFDIndex > (this.IFDs.length - 1)) {\r\n this.currentIFDIndex = this.IFDs.length - 1;\r\n return;\r\n }\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n last(): void {\r\n this.currentIFDIndex = this.IFDs.length - 1;\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n\r\n // async getAsByteArray(blob: Blob): Promise<ArrayBuffer> {\r\n // return new Promise((resolve, reject) => {\r\n // const reader = new FileReader();\r\n // reader.onload = () => resolve(reader.result as ArrayBuffer);\r\n // reader.onerror = reject;\r\n // reader.readAsArrayBuffer(blob);\r\n // });\r\n // }\r\n\r\n}\r\n","<div class=\"row\">\r\n <div class=\"col d-flex justify-content-between align-items-center\">\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" [ngClass]=\"{'ml-auto': isIFDs}\" type=\"button\" (click)=\"first()\"\r\n [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"firstIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" type=\"button\" (click)=\"previous()\" [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"previousIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n @if (isIFDs) {\r\n <span [innerHtml]=\"currentPageReportTemplate\">\r\n </span>\r\n }\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" type=\"button\" (click)=\"next()\" [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"nextIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" [ngClass]=\"{'mr-auto': isIFDs}\" type=\"button\" (click)=\"last()\"\r\n [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"lastIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n\r\n </div>\r\n</div>\r\n<div class=\"row\">\r\n <div class=\"col\">\r\n <div class=\"canvas-container card d-flex justify-content-center align-items-center mt-1 {{styleClass}}\">\r\n @if (!isIFDs && noFileMessage) {\r\n <span class=\"my-4\" [ngClass]=\"noFileStyleClass\">{{noFileMessage}}</span>\r\n }\r\n <canvas #tiffCanvas class=\"canvas-image img-fluid\" [ngClass]=\"{'d-none': !isIFDs}\"></canvas>\r\n <div class=\"backdrop position-absolute w-100 h-100 d-flex justify-content-center align-items-center\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n\r\n </div>\r\n <div class=\"spinner-border text-info position-absolute\" style=\"width: 3rem; height: 3rem;\" role=\"status\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n</div>","/*\r\n * Public API Surface of ys-sidebar\r\n */\r\n\r\nexport * from './src/ys-tiff-viewer/ys-tiff-viewer.component';\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"yoozsoft-yoozsoft-ng-tiff-viewer.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/src/ys-tiff-viewer/ys-tiff-viewer.ts","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/src/ys-tiff-viewer/ys-tiff-viewer.html","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/yoozsoft-yoozsoft-ng-tiff-viewer.ts"],"sourcesContent":["import { isPlatformBrowser, NgClass } from '@angular/common';\r\nimport {\r\n Component,\r\n computed,\r\n effect,\r\n ElementRef,\r\n inject,\r\n input,\r\n output,\r\n PLATFORM_ID,\r\n signal,\r\n viewChild,\r\n ChangeDetectionStrategy,\r\n} from '@angular/core';\r\nimport { TiffPageChange, TiffViewerIcons } from '../models';\r\n\r\ndeclare var UTIF: any;\r\n\r\nconst DEFAULT_TIFF_ICONS: Record<'first' | 'previous' | 'next' | 'last', string> = {\r\n first: 'fa fa-fast-backward',\r\n previous: 'fa fa-step-backward',\r\n next: 'fa fa-step-forward',\r\n last: 'fa fa-fast-forward',\r\n};\r\n\r\n@Component({\r\n selector: 'ys-tiff-viewer',\r\n imports: [NgClass],\r\n templateUrl: './ys-tiff-viewer.html',\r\n changeDetection: ChangeDetectionStrategy.Eager,\r\n styleUrl: './ys-tiff-viewer.scss',\r\n})\r\nexport class YsTiffViewer {\r\n // ---------- injects ----------\r\n private platformId = inject(PLATFORM_ID);\r\n\r\n // ---------- inputs ----------\r\n buffer = input<ArrayBuffer | Blob | File | null>();\r\n\r\n styleClass = input<string>();\r\n noFileMessage = input('No image file');\r\n noFileStyleClass = input('text-center');\r\n\r\n icons = input<TiffViewerIcons>({});\r\n\r\n pageReportTemplate = input('Page {current} of {total}');\r\n\r\n // ---------- outputs ----------\r\n pageChange = output<TiffPageChange>();\r\n private emitPageChange() {\r\n this.pageChange.emit({\r\n index: this.currentIndex(),\r\n page: this.currentPage(),\r\n total: this.ifds().length,\r\n });\r\n }\r\n\r\n // ---------- state ----------\r\n private ifds = signal<any[]>([]);\r\n private currentIndex = signal(0);\r\n readonly isDecoding = signal(false);\r\n private decodeVersion = 0;\r\n\r\n readonly isIFDs = computed(() => this.ifds().length > 0);\r\n\r\n readonly isFirstImage = computed(() => !this.isIFDs() || this.currentIndex() === 0);\r\n\r\n readonly isLastImage = computed(\r\n () => !this.isIFDs() || this.currentIndex() === this.ifds().length - 1,\r\n );\r\n\r\n readonly currentPage = computed(() => this.currentIndex() + 1);\r\n\r\n readonly mergedIcons = computed(() => ({\r\n ...DEFAULT_TIFF_ICONS,\r\n ...this.icons(),\r\n }));\r\n\r\n readonly pageReport = computed(() =>\r\n this.pageReportTemplate()\r\n .replace('{current}', `${this.currentPage()}`)\r\n .replace('{total}', `${this.ifds().length}`),\r\n );\r\n\r\n // ---------- viewchilds ----------\r\n canvasRef = viewChild.required<ElementRef<HTMLCanvasElement>>('tiffCanvas');\r\n\r\n constructor() {\r\n effect(() => {\r\n const buf = this.buffer();\r\n\r\n if (!buf) return;\r\n\r\n if (isPlatformBrowser(this.platformId)) {\r\n this.decode(buf);\r\n }\r\n });\r\n }\r\n\r\n // ---------- logic ----------\r\n private async decode(source: ArrayBuffer | Blob | File): Promise<void> {\r\n const canvas = this.canvasRef().nativeElement;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n\r\n try {\r\n this.isDecoding.set(true);\r\n\r\n const version = ++this.decodeVersion;\r\n\r\n this.ifds.set([]);\r\n this.currentIndex.set(0);\r\n\r\n let buffer = source instanceof ArrayBuffer ? source : await source.arrayBuffer();\r\n\r\n const decoded = UTIF.decode(buffer);\r\n\r\n if (version !== this.decodeVersion) {\r\n return;\r\n }\r\n\r\n decoded.forEach((ifd: any) => UTIF.decodeImage(buffer, ifd));\r\n\r\n if (version !== this.decodeVersion) {\r\n return;\r\n }\r\n\r\n this.ifds.set(decoded);\r\n this.draw(0);\r\n this.emitPageChange();\r\n } catch (error) {\r\n console.error(error);\r\n } finally {\r\n this.isDecoding.set(false);\r\n }\r\n }\r\n\r\n private draw(index: number): void {\r\n const ctx = this.canvasRef().nativeElement.getContext('2d');\r\n if (!ctx) return;\r\n\r\n const ifd = this.ifds()[index];\r\n if (!ifd) return;\r\n\r\n const rgba = UTIF.toRGBA8(ifd);\r\n const imageData = new ImageData(new Uint8ClampedArray(rgba), ifd.width, ifd.height);\r\n\r\n ctx.canvas.width = ifd.width;\r\n ctx.canvas.height = ifd.height;\r\n ctx.putImageData(imageData, 0, 0);\r\n }\r\n\r\n // ---------- navigation ----------\r\n private goTo(index: number) {\r\n this.currentIndex.set(index);\r\n this.draw(index);\r\n this.emitPageChange();\r\n }\r\n\r\n first() {\r\n this.goTo(0);\r\n }\r\n\r\n previous() {\r\n const i = Math.max(this.currentIndex() - 1, 0);\r\n this.goTo(i);\r\n }\r\n\r\n next() {\r\n const i = Math.min(this.currentPage(), this.ifds().length - 1);\r\n this.goTo(i);\r\n }\r\n\r\n last() {\r\n const i = this.ifds().length - 1;\r\n this.goTo(i);\r\n }\r\n}\r\n","<div class=\"tiff-viewer\">\n <div class=\"row\">\n <div class=\"col d-flex justify-content-between align-items-center\">\n <div>\n <button class=\"btn btn-outline-primary me-2\" (click)=\"first()\" [disabled]=\"isFirstImage()\">\n <i [ngClass]=\"mergedIcons().first\"></i>\n\n </button>\n\n <button class=\"btn btn-outline-primary\" (click)=\"previous()\" [disabled]=\"isFirstImage()\">\n <i [ngClass]=\"mergedIcons().previous\"></i>\n </button>\n </div>\n\n @if (isIFDs()) {\n <span>{{ pageReport() }}</span>\n }\n\n <div>\n <button class=\"btn btn-outline-primary me-2\" (click)=\"next()\" [disabled]=\"isLastImage()\">\n <i [ngClass]=\"mergedIcons().next\"></i>\n </button>\n\n <button class=\"btn btn-outline-primary\" (click)=\"last()\" [disabled]=\"isLastImage()\">\n <i [ngClass]=\"mergedIcons().last\"></i>\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"row\">\n <div class=\"col\">\n <div class=\"canvas-container card mt-1\" [ngClass]=\"styleClass()\">\n @if (!isIFDs() && noFileMessage()) {\n <span [ngClass]=\"noFileStyleClass()\">{{ noFileMessage() }}</span>\n }\n\n <canvas #tiffCanvas class=\"img-fluid\" [class.d-none]=\"!isIFDs()\">\n </canvas>\n\n <div class=\"spinner-border text-info position-absolute\" [class.d-none]=\"!isDecoding()\">\n </div>\n </div>\n </div>\n </div>\n</div>","/*\r\n * Public API Surface of ys-tiff-viewer\r\n */\r\n\r\nexport * from './src/models';\r\nexport * from './src/ys-tiff-viewer/ys-tiff-viewer';\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}