@shival99/z-ui 2.1.29 → 2.1.30
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/fesm2022/shival99-z-ui-components-z-autocomplete.mjs +1079 -0
- package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-drawer.mjs +742 -0
- package/fesm2022/shival99-z-ui-components-z-drawer.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs +58 -0
- package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-editor.mjs +1750 -0
- package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-gallery.mjs +2419 -0
- package/fesm2022/shival99-z-ui-components-z-gallery.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-kanban.mjs +981 -0
- package/fesm2022/shival99-z-ui-components-z-kanban.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-marquee.mjs +70 -0
- package/fesm2022/shival99-z-ui-components-z-marquee.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-media-player.mjs +668 -0
- package/fesm2022/shival99-z-ui-components-z-media-player.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-menu.mjs +843 -0
- package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-metric-card.mjs +128 -0
- package/fesm2022/shival99-z-ui-components-z-metric-card.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-pagination.mjs +158 -0
- package/fesm2022/shival99-z-ui-components-z-pagination.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-qrcode.mjs +383 -0
- package/fesm2022/shival99-z-ui-components-z-qrcode.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-radio.mjs +167 -0
- package/fesm2022/shival99-z-ui-components-z-radio.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-scrollarea.mjs +131 -0
- package/fesm2022/shival99-z-ui-components-z-scrollarea.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-show-more.mjs +121 -0
- package/fesm2022/shival99-z-ui-components-z-show-more.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-skeleton-auto.mjs +61 -0
- package/fesm2022/shival99-z-ui-components-z-skeleton-auto.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-steps.mjs +396 -0
- package/fesm2022/shival99-z-ui-components-z-steps.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-table.mjs +10510 -0
- package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-tabs.mjs +507 -0
- package/fesm2022/shival99-z-ui-components-z-tabs.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-tags.mjs +349 -0
- package/fesm2022/shival99-z-ui-components-z-tags.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-timeline.mjs +237 -0
- package/fesm2022/shival99-z-ui-components-z-timeline.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-upload.mjs +523 -0
- package/fesm2022/shival99-z-ui-components-z-upload.mjs.map +1 -0
- package/package.json +1 -1
- package/types/shival99-z-ui-components-z-autocomplete.d.ts +290 -0
- package/types/shival99-z-ui-components-z-calendar.d.ts +4 -4
- package/types/shival99-z-ui-components-z-drawer.d.ts +266 -0
- package/types/shival99-z-ui-components-z-dropdown-menu.d.ts +54 -0
- package/types/shival99-z-ui-components-z-editor.d.ts +337 -0
- package/types/shival99-z-ui-components-z-gallery.d.ts +402 -0
- package/types/shival99-z-ui-components-z-kanban.d.ts +237 -0
- package/types/shival99-z-ui-components-z-marquee.d.ts +35 -0
- package/types/shival99-z-ui-components-z-media-player.d.ts +124 -0
- package/types/shival99-z-ui-components-z-menu.d.ts +222 -0
- package/types/shival99-z-ui-components-z-metric-card.d.ts +67 -0
- package/types/shival99-z-ui-components-z-pagination.d.ts +55 -0
- package/types/shival99-z-ui-components-z-qrcode.d.ts +76 -0
- package/types/shival99-z-ui-components-z-radio.d.ts +69 -0
- package/types/shival99-z-ui-components-z-scrollarea.d.ts +46 -0
- package/types/shival99-z-ui-components-z-show-more.d.ts +36 -0
- package/types/shival99-z-ui-components-z-skeleton-auto.d.ts +35 -0
- package/types/shival99-z-ui-components-z-steps.d.ts +106 -0
- package/types/shival99-z-ui-components-z-table.d.ts +1924 -0
- package/types/shival99-z-ui-components-z-tabs.d.ts +92 -0
- package/types/shival99-z-ui-components-z-tags.d.ts +128 -0
- package/types/shival99-z-ui-components-z-timeline.d.ts +71 -0
- package/types/shival99-z-ui-components-z-upload.d.ts +153 -0
|
@@ -0,0 +1,2419 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, output, signal, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, inject, viewChild, effect, EventEmitter, Injector, PLATFORM_ID, Injectable, DestroyRef, model, ElementRef, Directive } from '@angular/core';
|
|
3
|
+
import * as i1$1 from '@angular/forms';
|
|
4
|
+
import { FormsModule } from '@angular/forms';
|
|
5
|
+
import { TranslatePipe } from '@ngx-translate/core';
|
|
6
|
+
import { ZButtonComponent } from '@shival99/z-ui/components/z-button';
|
|
7
|
+
import { ZButtonGroupComponent, ZButtonGroupItemDirective } from '@shival99/z-ui/components/z-button-group';
|
|
8
|
+
import { ZCheckboxComponent } from '@shival99/z-ui/components/z-checkbox';
|
|
9
|
+
import { ZEmptyComponent } from '@shival99/z-ui/components/z-empty';
|
|
10
|
+
import { ZIconComponent } from '@shival99/z-ui/components/z-icon';
|
|
11
|
+
import { ZInputComponent } from '@shival99/z-ui/components/z-input';
|
|
12
|
+
import { ZSkeletonComponent } from '@shival99/z-ui/components/z-skeleton';
|
|
13
|
+
import { zMergeClasses, zTransform } from '@shival99/z-ui/utils';
|
|
14
|
+
import { ZTooltipDirective } from '@shival99/z-ui/components/z-tooltip';
|
|
15
|
+
import { Overlay, OverlayConfig } from '@angular/cdk/overlay';
|
|
16
|
+
import { ComponentPortal } from '@angular/cdk/portal';
|
|
17
|
+
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
18
|
+
import { ZOverlayZIndexService } from '@shival99/z-ui/services';
|
|
19
|
+
import { DomSanitizer } from '@angular/platform-browser';
|
|
20
|
+
import * as i1 from 'ng2-pdfjs-viewer';
|
|
21
|
+
import { PdfJsViewerModule } from 'ng2-pdfjs-viewer';
|
|
22
|
+
import { cva } from 'class-variance-authority';
|
|
23
|
+
|
|
24
|
+
const FILE_CATEGORY_STYLES = {
|
|
25
|
+
image: {
|
|
26
|
+
bg: 'bg-purple-100 dark:bg-purple-900/30',
|
|
27
|
+
text: 'text-purple-600 dark:text-purple-400',
|
|
28
|
+
label: 'IMG',
|
|
29
|
+
icon: 'lucideImage',
|
|
30
|
+
},
|
|
31
|
+
pdf: {
|
|
32
|
+
bg: 'bg-red-100 dark:bg-red-900/30',
|
|
33
|
+
text: 'text-red-600 dark:text-red-400',
|
|
34
|
+
label: 'PDF',
|
|
35
|
+
icon: 'lucideFileText',
|
|
36
|
+
},
|
|
37
|
+
word: {
|
|
38
|
+
bg: 'bg-blue-100 dark:bg-blue-900/30',
|
|
39
|
+
text: 'text-blue-600 dark:text-blue-400',
|
|
40
|
+
label: 'DOC',
|
|
41
|
+
icon: 'lucideFileText',
|
|
42
|
+
},
|
|
43
|
+
excel: {
|
|
44
|
+
bg: 'bg-green-100 dark:bg-green-900/30',
|
|
45
|
+
text: 'text-green-600 dark:text-green-400',
|
|
46
|
+
label: 'XLS',
|
|
47
|
+
icon: 'lucideFileSpreadsheet',
|
|
48
|
+
},
|
|
49
|
+
powerpoint: {
|
|
50
|
+
bg: 'bg-orange-100 dark:bg-orange-900/30',
|
|
51
|
+
text: 'text-orange-600 dark:text-orange-400',
|
|
52
|
+
label: 'PPT',
|
|
53
|
+
icon: 'lucideFileText',
|
|
54
|
+
},
|
|
55
|
+
video: {
|
|
56
|
+
bg: 'bg-pink-100 dark:bg-pink-900/30',
|
|
57
|
+
text: 'text-pink-600 dark:text-pink-400',
|
|
58
|
+
label: 'VID',
|
|
59
|
+
icon: 'lucideVideo',
|
|
60
|
+
},
|
|
61
|
+
audio: {
|
|
62
|
+
bg: 'bg-yellow-100 dark:bg-yellow-900/30',
|
|
63
|
+
text: 'text-yellow-700 dark:text-yellow-400',
|
|
64
|
+
label: 'AUD',
|
|
65
|
+
icon: 'lucideMusic',
|
|
66
|
+
},
|
|
67
|
+
archive: {
|
|
68
|
+
bg: 'bg-amber-100 dark:bg-amber-900/30',
|
|
69
|
+
text: 'text-amber-600 dark:text-amber-400',
|
|
70
|
+
label: 'ZIP',
|
|
71
|
+
icon: 'lucideFileArchive',
|
|
72
|
+
},
|
|
73
|
+
code: {
|
|
74
|
+
bg: 'bg-slate-100 dark:bg-slate-800',
|
|
75
|
+
text: 'text-slate-600 dark:text-slate-400',
|
|
76
|
+
label: 'CODE',
|
|
77
|
+
icon: 'lucideCode',
|
|
78
|
+
},
|
|
79
|
+
text: {
|
|
80
|
+
bg: 'bg-gray-100 dark:bg-gray-800',
|
|
81
|
+
text: 'text-gray-600 dark:text-gray-400',
|
|
82
|
+
label: 'TXT',
|
|
83
|
+
icon: 'lucideFileText',
|
|
84
|
+
},
|
|
85
|
+
unknown: {
|
|
86
|
+
bg: 'bg-gray-100 dark:bg-gray-800',
|
|
87
|
+
text: 'text-gray-500 dark:text-gray-400',
|
|
88
|
+
label: 'FILE',
|
|
89
|
+
icon: 'lucideFile',
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico'];
|
|
94
|
+
const VIDEO_EXTENSIONS = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv'];
|
|
95
|
+
const AUDIO_EXTENSIONS = ['mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a'];
|
|
96
|
+
const ARCHIVE_EXTENSIONS = ['zip', 'rar', 'tar', 'gz', '7z', 'bz2'];
|
|
97
|
+
const CODE_EXTENSIONS = [
|
|
98
|
+
'js',
|
|
99
|
+
'ts',
|
|
100
|
+
'jsx',
|
|
101
|
+
'tsx',
|
|
102
|
+
'html',
|
|
103
|
+
'css',
|
|
104
|
+
'scss',
|
|
105
|
+
'json',
|
|
106
|
+
'xml',
|
|
107
|
+
'py',
|
|
108
|
+
'java',
|
|
109
|
+
'c',
|
|
110
|
+
'cpp',
|
|
111
|
+
'go',
|
|
112
|
+
'rs',
|
|
113
|
+
'php',
|
|
114
|
+
'rb',
|
|
115
|
+
'swift',
|
|
116
|
+
'kt',
|
|
117
|
+
];
|
|
118
|
+
const TEXT_EXTENSIONS = ['txt', 'md', 'log'];
|
|
119
|
+
const WORD_EXTENSIONS = ['doc', 'docx', 'odt', 'rtf'];
|
|
120
|
+
const EXCEL_EXTENSIONS = ['xls', 'xlsx', 'csv', 'ods'];
|
|
121
|
+
const POWERPOINT_EXTENSIONS = ['ppt', 'pptx', 'odp'];
|
|
122
|
+
const FILE_SIZE_UNITS = ['B', 'KB', 'MB', 'GB'];
|
|
123
|
+
const FILE_SIZE_BASE = 1024;
|
|
124
|
+
const getFileCategory = (file) => {
|
|
125
|
+
const type = file.type?.toLowerCase() || '';
|
|
126
|
+
const name = file.name?.toLowerCase() || '';
|
|
127
|
+
const ext = name.split('.').pop() || '';
|
|
128
|
+
if (type.startsWith('image/') || IMAGE_EXTENSIONS.includes(ext)) {
|
|
129
|
+
return 'image';
|
|
130
|
+
}
|
|
131
|
+
if (type === 'application/pdf' || ext === 'pdf') {
|
|
132
|
+
return 'pdf';
|
|
133
|
+
}
|
|
134
|
+
if (type.includes('excel') || type.includes('spreadsheet') || EXCEL_EXTENSIONS.includes(ext)) {
|
|
135
|
+
return 'excel';
|
|
136
|
+
}
|
|
137
|
+
if (type.includes('powerpoint') || type.includes('presentation') || POWERPOINT_EXTENSIONS.includes(ext)) {
|
|
138
|
+
return 'powerpoint';
|
|
139
|
+
}
|
|
140
|
+
if (type.includes('word') || type.includes('wordprocessingml') || WORD_EXTENSIONS.includes(ext)) {
|
|
141
|
+
return 'word';
|
|
142
|
+
}
|
|
143
|
+
if (type.startsWith('video/') || VIDEO_EXTENSIONS.includes(ext)) {
|
|
144
|
+
return 'video';
|
|
145
|
+
}
|
|
146
|
+
if (type.startsWith('audio/') || AUDIO_EXTENSIONS.includes(ext)) {
|
|
147
|
+
return 'audio';
|
|
148
|
+
}
|
|
149
|
+
if (type.includes('zip') ||
|
|
150
|
+
type.includes('rar') ||
|
|
151
|
+
type.includes('tar') ||
|
|
152
|
+
type.includes('compressed') ||
|
|
153
|
+
ARCHIVE_EXTENSIONS.includes(ext)) {
|
|
154
|
+
return 'archive';
|
|
155
|
+
}
|
|
156
|
+
if (CODE_EXTENSIONS.includes(ext)) {
|
|
157
|
+
return 'code';
|
|
158
|
+
}
|
|
159
|
+
if (type.startsWith('text/') || TEXT_EXTENSIONS.includes(ext)) {
|
|
160
|
+
return 'text';
|
|
161
|
+
}
|
|
162
|
+
return 'unknown';
|
|
163
|
+
};
|
|
164
|
+
const formatFileSize = (bytes) => {
|
|
165
|
+
if (bytes === 0) {
|
|
166
|
+
return '0 B';
|
|
167
|
+
}
|
|
168
|
+
const i = Math.floor(Math.log(bytes) / Math.log(FILE_SIZE_BASE));
|
|
169
|
+
const size = bytes / Math.pow(FILE_SIZE_BASE, i);
|
|
170
|
+
return `${size.toFixed(i > 0 ? 1 : 0)} ${FILE_SIZE_UNITS[i]}`;
|
|
171
|
+
};
|
|
172
|
+
const isPreviewable = (file) => {
|
|
173
|
+
const category = getFileCategory(file);
|
|
174
|
+
return (category === 'image' ||
|
|
175
|
+
category === 'pdf' ||
|
|
176
|
+
category === 'video' ||
|
|
177
|
+
category === 'word' ||
|
|
178
|
+
category === 'excel' ||
|
|
179
|
+
category === 'text' ||
|
|
180
|
+
category === 'code');
|
|
181
|
+
};
|
|
182
|
+
const isImage = (file) => getFileCategory(file) === 'image';
|
|
183
|
+
|
|
184
|
+
class ZGalleryItemComponent {
|
|
185
|
+
file = input.required(...(ngDevMode ? [{ debugName: "file" }] : []));
|
|
186
|
+
zMode = input('grid', ...(ngDevMode ? [{ debugName: "zMode" }] : []));
|
|
187
|
+
zSize = input('default', ...(ngDevMode ? [{ debugName: "zSize" }] : []));
|
|
188
|
+
zShowDownload = input(true, ...(ngDevMode ? [{ debugName: "zShowDownload" }] : []));
|
|
189
|
+
zShowPreview = input(true, ...(ngDevMode ? [{ debugName: "zShowPreview" }] : []));
|
|
190
|
+
zShowRemove = input(false, ...(ngDevMode ? [{ debugName: "zShowRemove" }] : []));
|
|
191
|
+
zSelectable = input(false, ...(ngDevMode ? [{ debugName: "zSelectable" }] : []));
|
|
192
|
+
zSelected = input(false, ...(ngDevMode ? [{ debugName: "zSelected" }] : []));
|
|
193
|
+
zOnDownload = output();
|
|
194
|
+
zOnPreview = output();
|
|
195
|
+
zOnRemove = output();
|
|
196
|
+
zOnSelect = output();
|
|
197
|
+
isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
198
|
+
formattedSize = computed(() => formatFileSize(this.file().size), ...(ngDevMode ? [{ debugName: "formattedSize" }] : []));
|
|
199
|
+
category = computed(() => getFileCategory(this.file()), ...(ngDevMode ? [{ debugName: "category" }] : []));
|
|
200
|
+
isImage = computed(() => this.category() === 'image', ...(ngDevMode ? [{ debugName: "isImage" }] : []));
|
|
201
|
+
isVideo = computed(() => this.category() === 'video', ...(ngDevMode ? [{ debugName: "isVideo" }] : []));
|
|
202
|
+
hasVideoPreview = computed(() => this.isVideo() && !!this.file().url, ...(ngDevMode ? [{ debugName: "hasVideoPreview" }] : []));
|
|
203
|
+
fileExtension = computed(() => {
|
|
204
|
+
const fileName = this.file().name;
|
|
205
|
+
const parts = fileName.split('.');
|
|
206
|
+
if (parts.length < 2) {
|
|
207
|
+
return 'FILE';
|
|
208
|
+
}
|
|
209
|
+
return parts[parts.length - 1].toUpperCase();
|
|
210
|
+
}, ...(ngDevMode ? [{ debugName: "fileExtension" }] : []));
|
|
211
|
+
mediaHeightClass = computed(() => {
|
|
212
|
+
const size = this.zSize();
|
|
213
|
+
switch (size) {
|
|
214
|
+
case 'sm':
|
|
215
|
+
return 'h-36';
|
|
216
|
+
case 'lg':
|
|
217
|
+
return 'h-56';
|
|
218
|
+
default:
|
|
219
|
+
return 'h-44';
|
|
220
|
+
}
|
|
221
|
+
}, ...(ngDevMode ? [{ debugName: "mediaHeightClass" }] : []));
|
|
222
|
+
formattedDate = computed(() => {
|
|
223
|
+
const file = this.file();
|
|
224
|
+
const date = file.updatedAt || file.createdAt;
|
|
225
|
+
if (!date) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
return new Intl.DateTimeFormat(undefined, {
|
|
229
|
+
month: 'short',
|
|
230
|
+
day: '2-digit',
|
|
231
|
+
year: 'numeric',
|
|
232
|
+
}).format(date);
|
|
233
|
+
}, ...(ngDevMode ? [{ debugName: "formattedDate" }] : []));
|
|
234
|
+
categoryStyle = computed(() => {
|
|
235
|
+
const style = FILE_CATEGORY_STYLES[this.category()];
|
|
236
|
+
return {
|
|
237
|
+
...style,
|
|
238
|
+
icon: style.icon,
|
|
239
|
+
};
|
|
240
|
+
}, ...(ngDevMode ? [{ debugName: "categoryStyle" }] : []));
|
|
241
|
+
fileTypeClasses = computed(() => zMergeClasses('inline-flex min-w-14 items-center justify-center rounded-sm border border-black/5 px-2.5 py-1 text-[0.6875rem] font-semibold tracking-wide dark:border-white/10', this.categoryStyle().bg, this.categoryStyle().text), ...(ngDevMode ? [{ debugName: "fileTypeClasses" }] : []));
|
|
242
|
+
canPreview = computed(() => isPreviewable(this.file()), ...(ngDevMode ? [{ debugName: "canPreview" }] : []));
|
|
243
|
+
onImageLoad() {
|
|
244
|
+
this.isLoading.set(false);
|
|
245
|
+
}
|
|
246
|
+
onImageError() {
|
|
247
|
+
this.isLoading.set(false);
|
|
248
|
+
}
|
|
249
|
+
onDownload(event) {
|
|
250
|
+
event.stopPropagation();
|
|
251
|
+
this.zOnDownload.emit(this.file());
|
|
252
|
+
}
|
|
253
|
+
onPreviewClick(event) {
|
|
254
|
+
event.stopPropagation();
|
|
255
|
+
this.zOnPreview.emit(this.file());
|
|
256
|
+
}
|
|
257
|
+
onPreview() {
|
|
258
|
+
if (this.canPreview()) {
|
|
259
|
+
this.zOnPreview.emit(this.file());
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
onItemClick() {
|
|
263
|
+
if (this.zSelectable()) {
|
|
264
|
+
this.zOnSelect.emit(this.file());
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
this.onPreview();
|
|
268
|
+
}
|
|
269
|
+
onRemove(event) {
|
|
270
|
+
event.stopPropagation();
|
|
271
|
+
this.zOnRemove.emit(this.file());
|
|
272
|
+
}
|
|
273
|
+
onSelectClick(event) {
|
|
274
|
+
event.stopPropagation();
|
|
275
|
+
this.zOnSelect.emit(this.file());
|
|
276
|
+
}
|
|
277
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
278
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: ZGalleryItemComponent, isStandalone: true, selector: "z-gallery-item", inputs: { file: { classPropertyName: "file", publicName: "file", isSignal: true, isRequired: true, transformFunction: null }, zMode: { classPropertyName: "zMode", publicName: "zMode", isSignal: true, isRequired: false, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zShowDownload: { classPropertyName: "zShowDownload", publicName: "zShowDownload", isSignal: true, isRequired: false, transformFunction: null }, zShowPreview: { classPropertyName: "zShowPreview", publicName: "zShowPreview", isSignal: true, isRequired: false, transformFunction: null }, zShowRemove: { classPropertyName: "zShowRemove", publicName: "zShowRemove", isSignal: true, isRequired: false, transformFunction: null }, zSelectable: { classPropertyName: "zSelectable", publicName: "zSelectable", isSignal: true, isRequired: false, transformFunction: null }, zSelected: { classPropertyName: "zSelected", publicName: "zSelected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOnDownload: "zOnDownload", zOnPreview: "zOnPreview", zOnRemove: "zOnRemove", zOnSelect: "zOnSelect" }, host: { classAttribute: "z-gallery-item block" }, ngImport: i0, template: `
|
|
279
|
+
@if (zMode() === 'grid') {
|
|
280
|
+
<div
|
|
281
|
+
class="group border-border bg-card hover:border-primary/30 relative cursor-pointer overflow-hidden rounded-md border shadow-sm transition-all duration-300 hover:shadow-lg"
|
|
282
|
+
[class.border-primary]="zSelected()"
|
|
283
|
+
[class.ring-1]="zSelected()"
|
|
284
|
+
[class.ring-primary/35]="zSelected()"
|
|
285
|
+
(click)="onItemClick()"
|
|
286
|
+
>
|
|
287
|
+
@if (zSelectable()) {
|
|
288
|
+
<div
|
|
289
|
+
class="bg-primary shadow-card absolute top-3 right-3 z-20 flex size-6 items-center justify-center rounded-full transition-all duration-200"
|
|
290
|
+
[class.scale-100]="zSelected()"
|
|
291
|
+
[class.opacity-100]="zSelected()"
|
|
292
|
+
[class.scale-90]="!zSelected()"
|
|
293
|
+
[class.opacity-0]="!zSelected()"
|
|
294
|
+
>
|
|
295
|
+
<i z-icon zType="lucideCheck" zSize="14" class="text-primary-foreground"></i>
|
|
296
|
+
</div>
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
<div class="relative overflow-hidden" [class]="mediaHeightClass()">
|
|
300
|
+
@if (isImage()) {
|
|
301
|
+
@if (isLoading()) {
|
|
302
|
+
<div class="absolute inset-0">
|
|
303
|
+
<z-skeleton class="size-full" />
|
|
304
|
+
</div>
|
|
305
|
+
}
|
|
306
|
+
<img
|
|
307
|
+
[src]="file().thumbnailUrl || file().url"
|
|
308
|
+
[alt]="file().name"
|
|
309
|
+
class="size-full object-cover transition-all duration-500"
|
|
310
|
+
[class.opacity-0]="isLoading()"
|
|
311
|
+
[class.scale-100]="!isLoading()"
|
|
312
|
+
[class.group-hover:scale-110]="!isLoading()"
|
|
313
|
+
loading="lazy"
|
|
314
|
+
(load)="onImageLoad()"
|
|
315
|
+
(error)="onImageError()"
|
|
316
|
+
/>
|
|
317
|
+
} @else if (hasVideoPreview()) {
|
|
318
|
+
<video
|
|
319
|
+
[src]="file().url"
|
|
320
|
+
[poster]="file().thumbnailUrl ?? ''"
|
|
321
|
+
class="size-full object-cover transition-all duration-500 group-hover:scale-110"
|
|
322
|
+
muted
|
|
323
|
+
playsinline
|
|
324
|
+
preload="metadata"
|
|
325
|
+
></video>
|
|
326
|
+
<div
|
|
327
|
+
class="absolute inset-0 flex items-center justify-center bg-black/10 transition-colors duration-300 group-hover:bg-black/25"
|
|
328
|
+
>
|
|
329
|
+
<div
|
|
330
|
+
class="flex size-12 items-center justify-center rounded-full bg-black/50 shadow-lg backdrop-blur-sm transition-transform duration-300 group-hover:scale-110"
|
|
331
|
+
>
|
|
332
|
+
<i z-icon zType="lucidePlay" zSize="20" class="fill-white text-white"></i>
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
} @else {
|
|
336
|
+
<div
|
|
337
|
+
class="flex size-full flex-col items-center justify-center gap-2 bg-gradient-to-br"
|
|
338
|
+
[class]="categoryStyle().bg"
|
|
339
|
+
>
|
|
340
|
+
<i z-icon [zType]="categoryStyle().icon" zSize="34" [class]="categoryStyle().text"></i>
|
|
341
|
+
<span class="text-xs font-semibold tracking-wide" [class]="categoryStyle().text">
|
|
342
|
+
{{ categoryStyle().label }}
|
|
343
|
+
</span>
|
|
344
|
+
</div>
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
<div class="absolute inset-x-0 top-0 z-10 flex items-start justify-between p-3">
|
|
348
|
+
<span
|
|
349
|
+
class="rounded-full border border-white/35 bg-black/45 px-2.5 py-1 text-[0.6875rem] font-semibold tracking-wide text-white backdrop-blur-md"
|
|
350
|
+
>
|
|
351
|
+
{{ fileExtension() }}
|
|
352
|
+
</span>
|
|
353
|
+
<span
|
|
354
|
+
class="rounded-full border border-white/25 bg-black/35 px-2 py-1 text-[0.625rem] font-medium text-white/95 backdrop-blur-md"
|
|
355
|
+
>
|
|
356
|
+
{{ formattedSize() }}
|
|
357
|
+
</span>
|
|
358
|
+
</div>
|
|
359
|
+
|
|
360
|
+
<div
|
|
361
|
+
class="absolute inset-x-0 bottom-0 h-24 bg-gradient-to-t from-black/70 via-black/30 to-transparent opacity-85 transition-opacity duration-300 group-hover:opacity-100"
|
|
362
|
+
></div>
|
|
363
|
+
|
|
364
|
+
<div
|
|
365
|
+
class="absolute right-3 bottom-3 z-20 flex items-center gap-1.5 rounded-full border border-white/20 bg-black/40 p-1 opacity-0 backdrop-blur-md transition-all duration-200 group-hover:opacity-100"
|
|
366
|
+
>
|
|
367
|
+
@if (zShowPreview() && canPreview()) {
|
|
368
|
+
<button
|
|
369
|
+
z-button
|
|
370
|
+
zType="secondary"
|
|
371
|
+
zSize="xs"
|
|
372
|
+
zShape="circle"
|
|
373
|
+
class="shadow-lg"
|
|
374
|
+
(click)="onPreviewClick($event)"
|
|
375
|
+
z-tooltip
|
|
376
|
+
[zContent]="'i18n_z_ui_gallery_preview' | translate"
|
|
377
|
+
>
|
|
378
|
+
<i z-icon zType="lucideEye" zSize="14"></i>
|
|
379
|
+
</button>
|
|
380
|
+
}
|
|
381
|
+
@if (zShowDownload() && (file().downloadUrl || file().url)) {
|
|
382
|
+
<button
|
|
383
|
+
z-button
|
|
384
|
+
zType="secondary"
|
|
385
|
+
zSize="xs"
|
|
386
|
+
zShape="circle"
|
|
387
|
+
class="shadow-lg"
|
|
388
|
+
(click)="onDownload($event)"
|
|
389
|
+
z-tooltip
|
|
390
|
+
[zContent]="'i18n_z_ui_gallery_download' | translate"
|
|
391
|
+
>
|
|
392
|
+
<i z-icon zType="lucideDownload" zSize="14"></i>
|
|
393
|
+
</button>
|
|
394
|
+
}
|
|
395
|
+
@if (zShowRemove()) {
|
|
396
|
+
<button
|
|
397
|
+
z-button
|
|
398
|
+
zType="secondary"
|
|
399
|
+
zSize="xs"
|
|
400
|
+
zShape="circle"
|
|
401
|
+
class="shadow-lg"
|
|
402
|
+
(click)="onRemove($event)"
|
|
403
|
+
z-tooltip
|
|
404
|
+
[zContent]="'i18n_z_ui_gallery_remove' | translate"
|
|
405
|
+
>
|
|
406
|
+
<i z-icon zType="lucideTrash2" zSize="14"></i>
|
|
407
|
+
</button>
|
|
408
|
+
}
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
|
|
412
|
+
<div class="p-3">
|
|
413
|
+
<p class="text-foreground truncate text-sm leading-normal font-semibold" z-tooltip [zContent]="file().name">
|
|
414
|
+
{{ file().name }}
|
|
415
|
+
</p>
|
|
416
|
+
@if (formattedDate()) {
|
|
417
|
+
<p class="text-muted-foreground mt-1 text-xs">{{ formattedDate() }}</p>
|
|
418
|
+
}
|
|
419
|
+
</div>
|
|
420
|
+
</div>
|
|
421
|
+
} @else {
|
|
422
|
+
<div
|
|
423
|
+
class="group border-border bg-card hover:border-primary/35 flex cursor-pointer items-center gap-3 rounded-sm border px-3 py-2.5 shadow-sm transition-all duration-200 hover:shadow-md"
|
|
424
|
+
[class.border-primary]="zSelected()"
|
|
425
|
+
[class.ring-1]="zSelected()"
|
|
426
|
+
[class.ring-primary/30]="zSelected()"
|
|
427
|
+
(click)="onItemClick()"
|
|
428
|
+
>
|
|
429
|
+
@if (zSelectable()) {
|
|
430
|
+
<div
|
|
431
|
+
class="bg-primary -ml-1 flex size-5 shrink-0 items-center justify-center rounded-full transition-all duration-200"
|
|
432
|
+
[class.scale-100]="zSelected()"
|
|
433
|
+
[class.opacity-100]="zSelected()"
|
|
434
|
+
[class.scale-90]="!zSelected()"
|
|
435
|
+
[class.opacity-0]="!zSelected()"
|
|
436
|
+
>
|
|
437
|
+
<i z-icon zType="lucideCheck" zSize="12" class="text-primary-foreground"></i>
|
|
438
|
+
</div>
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
<div
|
|
442
|
+
class="relative flex size-11 shrink-0 items-center justify-center overflow-hidden rounded-sm border border-black/5 bg-white/40 shadow-sm backdrop-blur-sm dark:border-white/10 dark:bg-white/5"
|
|
443
|
+
>
|
|
444
|
+
@if (isImage() && (file().thumbnailUrl || file().url)) {
|
|
445
|
+
<img
|
|
446
|
+
[src]="file().thumbnailUrl || file().url"
|
|
447
|
+
[alt]="file().name"
|
|
448
|
+
class="size-full rounded-sm object-cover"
|
|
449
|
+
loading="lazy"
|
|
450
|
+
/>
|
|
451
|
+
} @else if (hasVideoPreview()) {
|
|
452
|
+
<video
|
|
453
|
+
[src]="file().url"
|
|
454
|
+
[poster]="file().thumbnailUrl ?? ''"
|
|
455
|
+
class="size-full rounded-sm object-cover"
|
|
456
|
+
muted
|
|
457
|
+
playsinline
|
|
458
|
+
preload="metadata"
|
|
459
|
+
></video>
|
|
460
|
+
<div class="absolute inset-0 flex items-center justify-center rounded-sm bg-black/25">
|
|
461
|
+
<i z-icon zType="lucidePlay" zSize="12" class="fill-white text-white"></i>
|
|
462
|
+
</div>
|
|
463
|
+
} @else {
|
|
464
|
+
<span class="absolute inset-0 opacity-30 dark:opacity-20" [class]="categoryStyle().bg"></span>
|
|
465
|
+
<i
|
|
466
|
+
z-icon
|
|
467
|
+
[zType]="categoryStyle().icon"
|
|
468
|
+
zSize="18"
|
|
469
|
+
class="relative z-10"
|
|
470
|
+
[class]="categoryStyle().text"
|
|
471
|
+
></i>
|
|
472
|
+
}
|
|
473
|
+
</div>
|
|
474
|
+
|
|
475
|
+
<div class="min-w-0 flex-1">
|
|
476
|
+
<p class="text-foreground truncate text-sm font-medium" z-tooltip [zContent]="file().name">
|
|
477
|
+
{{ file().name }}
|
|
478
|
+
</p>
|
|
479
|
+
<p class="text-muted-foreground truncate text-xs">{{ formattedSize() }} · {{ categoryStyle().label }}</p>
|
|
480
|
+
</div>
|
|
481
|
+
|
|
482
|
+
<div class="ml-auto flex shrink-0 items-center gap-1.5">
|
|
483
|
+
<span [class]="fileTypeClasses()">
|
|
484
|
+
{{ fileExtension() }}
|
|
485
|
+
</span>
|
|
486
|
+
@if (zShowPreview() && canPreview()) {
|
|
487
|
+
<button
|
|
488
|
+
z-button
|
|
489
|
+
zType="ghost"
|
|
490
|
+
zSize="xs"
|
|
491
|
+
zShape="circle"
|
|
492
|
+
class="text-muted-foreground hover:text-foreground"
|
|
493
|
+
(click)="onPreviewClick($event)"
|
|
494
|
+
z-tooltip
|
|
495
|
+
[zContent]="'i18n_z_ui_gallery_preview' | translate"
|
|
496
|
+
>
|
|
497
|
+
<i z-icon zType="lucideEye" zSize="16"></i>
|
|
498
|
+
</button>
|
|
499
|
+
}
|
|
500
|
+
@if (zShowDownload() && (file().downloadUrl || file().url)) {
|
|
501
|
+
<button
|
|
502
|
+
z-button
|
|
503
|
+
zType="ghost"
|
|
504
|
+
zSize="xs"
|
|
505
|
+
zShape="circle"
|
|
506
|
+
class="text-muted-foreground hover:text-foreground"
|
|
507
|
+
(click)="onDownload($event)"
|
|
508
|
+
z-tooltip
|
|
509
|
+
[zContent]="'i18n_z_ui_gallery_download' | translate"
|
|
510
|
+
>
|
|
511
|
+
<i z-icon zType="lucideDownload" zSize="16"></i>
|
|
512
|
+
</button>
|
|
513
|
+
}
|
|
514
|
+
@if (zShowRemove()) {
|
|
515
|
+
<button
|
|
516
|
+
z-button
|
|
517
|
+
zType="ghost"
|
|
518
|
+
zSize="xs"
|
|
519
|
+
zShape="circle"
|
|
520
|
+
class="text-muted-foreground hover:text-destructive"
|
|
521
|
+
(click)="onRemove($event)"
|
|
522
|
+
z-tooltip
|
|
523
|
+
[zContent]="'i18n_z_ui_gallery_remove' | translate"
|
|
524
|
+
>
|
|
525
|
+
<i z-icon zType="lucideTrash2" zSize="16"></i>
|
|
526
|
+
</button>
|
|
527
|
+
}
|
|
528
|
+
</div>
|
|
529
|
+
</div>
|
|
530
|
+
}
|
|
531
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTooltipPosition", "zTrigger", "zTooltipTrigger", "zTooltipType", "zTooltipSize", "zClass", "zTooltipClass", "zShowDelay", "zTooltipShowDelay", "zHideDelay", "zTooltipHideDelay", "zArrow", "zTooltipArrow", "zDisabled", "zTooltipDisabled", "zOffset", "zTooltipOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "component", type: ZSkeletonComponent, selector: "z-skeleton", inputs: ["class", "zType", "zSize", "zWidth", "zHeight", "zRows", "zGap", "zAnimated", "zRadius"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
532
|
+
}
|
|
533
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryItemComponent, decorators: [{
|
|
534
|
+
type: Component,
|
|
535
|
+
args: [{
|
|
536
|
+
selector: 'z-gallery-item',
|
|
537
|
+
imports: [ZButtonComponent, ZIconComponent, ZTooltipDirective, ZSkeletonComponent, TranslatePipe],
|
|
538
|
+
standalone: true,
|
|
539
|
+
template: `
|
|
540
|
+
@if (zMode() === 'grid') {
|
|
541
|
+
<div
|
|
542
|
+
class="group border-border bg-card hover:border-primary/30 relative cursor-pointer overflow-hidden rounded-md border shadow-sm transition-all duration-300 hover:shadow-lg"
|
|
543
|
+
[class.border-primary]="zSelected()"
|
|
544
|
+
[class.ring-1]="zSelected()"
|
|
545
|
+
[class.ring-primary/35]="zSelected()"
|
|
546
|
+
(click)="onItemClick()"
|
|
547
|
+
>
|
|
548
|
+
@if (zSelectable()) {
|
|
549
|
+
<div
|
|
550
|
+
class="bg-primary shadow-card absolute top-3 right-3 z-20 flex size-6 items-center justify-center rounded-full transition-all duration-200"
|
|
551
|
+
[class.scale-100]="zSelected()"
|
|
552
|
+
[class.opacity-100]="zSelected()"
|
|
553
|
+
[class.scale-90]="!zSelected()"
|
|
554
|
+
[class.opacity-0]="!zSelected()"
|
|
555
|
+
>
|
|
556
|
+
<i z-icon zType="lucideCheck" zSize="14" class="text-primary-foreground"></i>
|
|
557
|
+
</div>
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
<div class="relative overflow-hidden" [class]="mediaHeightClass()">
|
|
561
|
+
@if (isImage()) {
|
|
562
|
+
@if (isLoading()) {
|
|
563
|
+
<div class="absolute inset-0">
|
|
564
|
+
<z-skeleton class="size-full" />
|
|
565
|
+
</div>
|
|
566
|
+
}
|
|
567
|
+
<img
|
|
568
|
+
[src]="file().thumbnailUrl || file().url"
|
|
569
|
+
[alt]="file().name"
|
|
570
|
+
class="size-full object-cover transition-all duration-500"
|
|
571
|
+
[class.opacity-0]="isLoading()"
|
|
572
|
+
[class.scale-100]="!isLoading()"
|
|
573
|
+
[class.group-hover:scale-110]="!isLoading()"
|
|
574
|
+
loading="lazy"
|
|
575
|
+
(load)="onImageLoad()"
|
|
576
|
+
(error)="onImageError()"
|
|
577
|
+
/>
|
|
578
|
+
} @else if (hasVideoPreview()) {
|
|
579
|
+
<video
|
|
580
|
+
[src]="file().url"
|
|
581
|
+
[poster]="file().thumbnailUrl ?? ''"
|
|
582
|
+
class="size-full object-cover transition-all duration-500 group-hover:scale-110"
|
|
583
|
+
muted
|
|
584
|
+
playsinline
|
|
585
|
+
preload="metadata"
|
|
586
|
+
></video>
|
|
587
|
+
<div
|
|
588
|
+
class="absolute inset-0 flex items-center justify-center bg-black/10 transition-colors duration-300 group-hover:bg-black/25"
|
|
589
|
+
>
|
|
590
|
+
<div
|
|
591
|
+
class="flex size-12 items-center justify-center rounded-full bg-black/50 shadow-lg backdrop-blur-sm transition-transform duration-300 group-hover:scale-110"
|
|
592
|
+
>
|
|
593
|
+
<i z-icon zType="lucidePlay" zSize="20" class="fill-white text-white"></i>
|
|
594
|
+
</div>
|
|
595
|
+
</div>
|
|
596
|
+
} @else {
|
|
597
|
+
<div
|
|
598
|
+
class="flex size-full flex-col items-center justify-center gap-2 bg-gradient-to-br"
|
|
599
|
+
[class]="categoryStyle().bg"
|
|
600
|
+
>
|
|
601
|
+
<i z-icon [zType]="categoryStyle().icon" zSize="34" [class]="categoryStyle().text"></i>
|
|
602
|
+
<span class="text-xs font-semibold tracking-wide" [class]="categoryStyle().text">
|
|
603
|
+
{{ categoryStyle().label }}
|
|
604
|
+
</span>
|
|
605
|
+
</div>
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
<div class="absolute inset-x-0 top-0 z-10 flex items-start justify-between p-3">
|
|
609
|
+
<span
|
|
610
|
+
class="rounded-full border border-white/35 bg-black/45 px-2.5 py-1 text-[0.6875rem] font-semibold tracking-wide text-white backdrop-blur-md"
|
|
611
|
+
>
|
|
612
|
+
{{ fileExtension() }}
|
|
613
|
+
</span>
|
|
614
|
+
<span
|
|
615
|
+
class="rounded-full border border-white/25 bg-black/35 px-2 py-1 text-[0.625rem] font-medium text-white/95 backdrop-blur-md"
|
|
616
|
+
>
|
|
617
|
+
{{ formattedSize() }}
|
|
618
|
+
</span>
|
|
619
|
+
</div>
|
|
620
|
+
|
|
621
|
+
<div
|
|
622
|
+
class="absolute inset-x-0 bottom-0 h-24 bg-gradient-to-t from-black/70 via-black/30 to-transparent opacity-85 transition-opacity duration-300 group-hover:opacity-100"
|
|
623
|
+
></div>
|
|
624
|
+
|
|
625
|
+
<div
|
|
626
|
+
class="absolute right-3 bottom-3 z-20 flex items-center gap-1.5 rounded-full border border-white/20 bg-black/40 p-1 opacity-0 backdrop-blur-md transition-all duration-200 group-hover:opacity-100"
|
|
627
|
+
>
|
|
628
|
+
@if (zShowPreview() && canPreview()) {
|
|
629
|
+
<button
|
|
630
|
+
z-button
|
|
631
|
+
zType="secondary"
|
|
632
|
+
zSize="xs"
|
|
633
|
+
zShape="circle"
|
|
634
|
+
class="shadow-lg"
|
|
635
|
+
(click)="onPreviewClick($event)"
|
|
636
|
+
z-tooltip
|
|
637
|
+
[zContent]="'i18n_z_ui_gallery_preview' | translate"
|
|
638
|
+
>
|
|
639
|
+
<i z-icon zType="lucideEye" zSize="14"></i>
|
|
640
|
+
</button>
|
|
641
|
+
}
|
|
642
|
+
@if (zShowDownload() && (file().downloadUrl || file().url)) {
|
|
643
|
+
<button
|
|
644
|
+
z-button
|
|
645
|
+
zType="secondary"
|
|
646
|
+
zSize="xs"
|
|
647
|
+
zShape="circle"
|
|
648
|
+
class="shadow-lg"
|
|
649
|
+
(click)="onDownload($event)"
|
|
650
|
+
z-tooltip
|
|
651
|
+
[zContent]="'i18n_z_ui_gallery_download' | translate"
|
|
652
|
+
>
|
|
653
|
+
<i z-icon zType="lucideDownload" zSize="14"></i>
|
|
654
|
+
</button>
|
|
655
|
+
}
|
|
656
|
+
@if (zShowRemove()) {
|
|
657
|
+
<button
|
|
658
|
+
z-button
|
|
659
|
+
zType="secondary"
|
|
660
|
+
zSize="xs"
|
|
661
|
+
zShape="circle"
|
|
662
|
+
class="shadow-lg"
|
|
663
|
+
(click)="onRemove($event)"
|
|
664
|
+
z-tooltip
|
|
665
|
+
[zContent]="'i18n_z_ui_gallery_remove' | translate"
|
|
666
|
+
>
|
|
667
|
+
<i z-icon zType="lucideTrash2" zSize="14"></i>
|
|
668
|
+
</button>
|
|
669
|
+
}
|
|
670
|
+
</div>
|
|
671
|
+
</div>
|
|
672
|
+
|
|
673
|
+
<div class="p-3">
|
|
674
|
+
<p class="text-foreground truncate text-sm leading-normal font-semibold" z-tooltip [zContent]="file().name">
|
|
675
|
+
{{ file().name }}
|
|
676
|
+
</p>
|
|
677
|
+
@if (formattedDate()) {
|
|
678
|
+
<p class="text-muted-foreground mt-1 text-xs">{{ formattedDate() }}</p>
|
|
679
|
+
}
|
|
680
|
+
</div>
|
|
681
|
+
</div>
|
|
682
|
+
} @else {
|
|
683
|
+
<div
|
|
684
|
+
class="group border-border bg-card hover:border-primary/35 flex cursor-pointer items-center gap-3 rounded-sm border px-3 py-2.5 shadow-sm transition-all duration-200 hover:shadow-md"
|
|
685
|
+
[class.border-primary]="zSelected()"
|
|
686
|
+
[class.ring-1]="zSelected()"
|
|
687
|
+
[class.ring-primary/30]="zSelected()"
|
|
688
|
+
(click)="onItemClick()"
|
|
689
|
+
>
|
|
690
|
+
@if (zSelectable()) {
|
|
691
|
+
<div
|
|
692
|
+
class="bg-primary -ml-1 flex size-5 shrink-0 items-center justify-center rounded-full transition-all duration-200"
|
|
693
|
+
[class.scale-100]="zSelected()"
|
|
694
|
+
[class.opacity-100]="zSelected()"
|
|
695
|
+
[class.scale-90]="!zSelected()"
|
|
696
|
+
[class.opacity-0]="!zSelected()"
|
|
697
|
+
>
|
|
698
|
+
<i z-icon zType="lucideCheck" zSize="12" class="text-primary-foreground"></i>
|
|
699
|
+
</div>
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
<div
|
|
703
|
+
class="relative flex size-11 shrink-0 items-center justify-center overflow-hidden rounded-sm border border-black/5 bg-white/40 shadow-sm backdrop-blur-sm dark:border-white/10 dark:bg-white/5"
|
|
704
|
+
>
|
|
705
|
+
@if (isImage() && (file().thumbnailUrl || file().url)) {
|
|
706
|
+
<img
|
|
707
|
+
[src]="file().thumbnailUrl || file().url"
|
|
708
|
+
[alt]="file().name"
|
|
709
|
+
class="size-full rounded-sm object-cover"
|
|
710
|
+
loading="lazy"
|
|
711
|
+
/>
|
|
712
|
+
} @else if (hasVideoPreview()) {
|
|
713
|
+
<video
|
|
714
|
+
[src]="file().url"
|
|
715
|
+
[poster]="file().thumbnailUrl ?? ''"
|
|
716
|
+
class="size-full rounded-sm object-cover"
|
|
717
|
+
muted
|
|
718
|
+
playsinline
|
|
719
|
+
preload="metadata"
|
|
720
|
+
></video>
|
|
721
|
+
<div class="absolute inset-0 flex items-center justify-center rounded-sm bg-black/25">
|
|
722
|
+
<i z-icon zType="lucidePlay" zSize="12" class="fill-white text-white"></i>
|
|
723
|
+
</div>
|
|
724
|
+
} @else {
|
|
725
|
+
<span class="absolute inset-0 opacity-30 dark:opacity-20" [class]="categoryStyle().bg"></span>
|
|
726
|
+
<i
|
|
727
|
+
z-icon
|
|
728
|
+
[zType]="categoryStyle().icon"
|
|
729
|
+
zSize="18"
|
|
730
|
+
class="relative z-10"
|
|
731
|
+
[class]="categoryStyle().text"
|
|
732
|
+
></i>
|
|
733
|
+
}
|
|
734
|
+
</div>
|
|
735
|
+
|
|
736
|
+
<div class="min-w-0 flex-1">
|
|
737
|
+
<p class="text-foreground truncate text-sm font-medium" z-tooltip [zContent]="file().name">
|
|
738
|
+
{{ file().name }}
|
|
739
|
+
</p>
|
|
740
|
+
<p class="text-muted-foreground truncate text-xs">{{ formattedSize() }} · {{ categoryStyle().label }}</p>
|
|
741
|
+
</div>
|
|
742
|
+
|
|
743
|
+
<div class="ml-auto flex shrink-0 items-center gap-1.5">
|
|
744
|
+
<span [class]="fileTypeClasses()">
|
|
745
|
+
{{ fileExtension() }}
|
|
746
|
+
</span>
|
|
747
|
+
@if (zShowPreview() && canPreview()) {
|
|
748
|
+
<button
|
|
749
|
+
z-button
|
|
750
|
+
zType="ghost"
|
|
751
|
+
zSize="xs"
|
|
752
|
+
zShape="circle"
|
|
753
|
+
class="text-muted-foreground hover:text-foreground"
|
|
754
|
+
(click)="onPreviewClick($event)"
|
|
755
|
+
z-tooltip
|
|
756
|
+
[zContent]="'i18n_z_ui_gallery_preview' | translate"
|
|
757
|
+
>
|
|
758
|
+
<i z-icon zType="lucideEye" zSize="16"></i>
|
|
759
|
+
</button>
|
|
760
|
+
}
|
|
761
|
+
@if (zShowDownload() && (file().downloadUrl || file().url)) {
|
|
762
|
+
<button
|
|
763
|
+
z-button
|
|
764
|
+
zType="ghost"
|
|
765
|
+
zSize="xs"
|
|
766
|
+
zShape="circle"
|
|
767
|
+
class="text-muted-foreground hover:text-foreground"
|
|
768
|
+
(click)="onDownload($event)"
|
|
769
|
+
z-tooltip
|
|
770
|
+
[zContent]="'i18n_z_ui_gallery_download' | translate"
|
|
771
|
+
>
|
|
772
|
+
<i z-icon zType="lucideDownload" zSize="16"></i>
|
|
773
|
+
</button>
|
|
774
|
+
}
|
|
775
|
+
@if (zShowRemove()) {
|
|
776
|
+
<button
|
|
777
|
+
z-button
|
|
778
|
+
zType="ghost"
|
|
779
|
+
zSize="xs"
|
|
780
|
+
zShape="circle"
|
|
781
|
+
class="text-muted-foreground hover:text-destructive"
|
|
782
|
+
(click)="onRemove($event)"
|
|
783
|
+
z-tooltip
|
|
784
|
+
[zContent]="'i18n_z_ui_gallery_remove' | translate"
|
|
785
|
+
>
|
|
786
|
+
<i z-icon zType="lucideTrash2" zSize="16"></i>
|
|
787
|
+
</button>
|
|
788
|
+
}
|
|
789
|
+
</div>
|
|
790
|
+
</div>
|
|
791
|
+
}
|
|
792
|
+
`,
|
|
793
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
794
|
+
encapsulation: ViewEncapsulation.None,
|
|
795
|
+
host: {
|
|
796
|
+
class: 'z-gallery-item block',
|
|
797
|
+
},
|
|
798
|
+
}]
|
|
799
|
+
}], propDecorators: { file: [{ type: i0.Input, args: [{ isSignal: true, alias: "file", required: true }] }], zMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMode", required: false }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zShowDownload: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowDownload", required: false }] }], zShowPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowPreview", required: false }] }], zShowRemove: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowRemove", required: false }] }], zSelectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSelectable", required: false }] }], zSelected: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSelected", required: false }] }], zOnDownload: [{ type: i0.Output, args: ["zOnDownload"] }], zOnPreview: [{ type: i0.Output, args: ["zOnPreview"] }], zOnRemove: [{ type: i0.Output, args: ["zOnRemove"] }], zOnSelect: [{ type: i0.Output, args: ["zOnSelect"] }] } });
|
|
800
|
+
|
|
801
|
+
const Z_GALLERY_PDF_VIEWER_CHROME_CSS = `
|
|
802
|
+
#toolbarContainer,
|
|
803
|
+
#toolbarContainer * {
|
|
804
|
+
box-sizing: border-box;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
#toolbarContainer,
|
|
808
|
+
.findbar,
|
|
809
|
+
.secondaryToolbar {
|
|
810
|
+
--toolbar-bg-color: #050505;
|
|
811
|
+
--toolbar-box-shadow: none;
|
|
812
|
+
--toolbar-border-bottom: 1px solid #222222;
|
|
813
|
+
--main-color: #f5f5f5;
|
|
814
|
+
--toolbar-icon-bg-color: #e7e7e7;
|
|
815
|
+
--toolbar-icon-hover-bg-color: #ffffff;
|
|
816
|
+
--toolbar-icon-opacity: 0.92;
|
|
817
|
+
--button-hover-color: #1f1f1f;
|
|
818
|
+
--toggled-btn-bg-color: #2a2a2a;
|
|
819
|
+
--toggled-btn-color: #ffffff;
|
|
820
|
+
--separator-color: #303030;
|
|
821
|
+
--field-bg-color: #111111;
|
|
822
|
+
--field-color: #f5f5f5;
|
|
823
|
+
--field-border-color: #3a3a3a;
|
|
824
|
+
--dropdown-btn-bg-color: #111111;
|
|
825
|
+
--dropdown-btn-border: 1px solid #3a3a3a;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
#toolbarContainer {
|
|
829
|
+
height: var(--toolbar-height) !important;
|
|
830
|
+
padding: var(--toolbar-vertical-padding) var(--toolbar-horizontal-padding) !important;
|
|
831
|
+
background-color: var(--toolbar-bg-color) !important;
|
|
832
|
+
box-shadow: var(--toolbar-box-shadow) !important;
|
|
833
|
+
border-bottom: var(--toolbar-border-bottom) !important;
|
|
834
|
+
font: message-box !important;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
#toolbarContainer #toolbarViewer,
|
|
838
|
+
#toolbarViewerLeft,
|
|
839
|
+
#toolbarViewerMiddle,
|
|
840
|
+
#toolbarViewerRight {
|
|
841
|
+
height: 100%;
|
|
842
|
+
align-items: center;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
#toolbarContainer #toolbarViewer {
|
|
846
|
+
justify-content: space-between;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
#toolbarViewerLeft,
|
|
850
|
+
#toolbarViewerMiddle,
|
|
851
|
+
#toolbarViewerRight,
|
|
852
|
+
.toolbarHorizontalGroup {
|
|
853
|
+
gap: 1px;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
#toolbarViewerLeft .loadingInput {
|
|
857
|
+
position: relative;
|
|
858
|
+
display: inline-flex;
|
|
859
|
+
align-items: center;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
.toolbarButton,
|
|
863
|
+
.toolbarButtonWithContainer {
|
|
864
|
+
height: 100% !important;
|
|
865
|
+
aspect-ratio: 1 !important;
|
|
866
|
+
flex: none !important;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
.toolbarButton {
|
|
870
|
+
display: flex !important;
|
|
871
|
+
align-items: center !important;
|
|
872
|
+
justify-content: center !important;
|
|
873
|
+
padding: 0 !important;
|
|
874
|
+
border: none !important;
|
|
875
|
+
border-radius: 2px !important;
|
|
876
|
+
background: none !important;
|
|
877
|
+
color: var(--main-color) !important;
|
|
878
|
+
font: message-box !important;
|
|
879
|
+
outline: none !important;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
.toolbarButton:is(:hover, :focus-visible) {
|
|
883
|
+
background-color: var(--button-hover-color) !important;
|
|
884
|
+
color: var(--main-color) !important;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
.toolbarButton::before {
|
|
888
|
+
width: var(--icon-size) !important;
|
|
889
|
+
height: var(--icon-size) !important;
|
|
890
|
+
background-color: var(--toolbar-icon-bg-color) !important;
|
|
891
|
+
opacity: var(--toolbar-icon-opacity) !important;
|
|
892
|
+
-webkit-mask-size: cover !important;
|
|
893
|
+
mask-size: cover !important;
|
|
894
|
+
-webkit-mask-position: center !important;
|
|
895
|
+
mask-position: center !important;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
.toolbarButton:is(:hover, :focus-visible)::before {
|
|
899
|
+
background-color: var(--toolbar-icon-hover-bg-color) !important;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
.toolbarButton.toggled {
|
|
903
|
+
background-color: var(--toggled-btn-bg-color) !important;
|
|
904
|
+
color: var(--toggled-btn-color) !important;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
.toolbarButton.toggled::before {
|
|
908
|
+
background-color: var(--toggled-btn-color) !important;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
.splitToolbarButtonSeparator {
|
|
912
|
+
width: 0 !important;
|
|
913
|
+
height: 62% !important;
|
|
914
|
+
border-left: 1px solid var(--separator-color) !important;
|
|
915
|
+
border-right: none !important;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
.toolbarField {
|
|
919
|
+
padding: 4px 7px !important;
|
|
920
|
+
margin: 3px 0 !important;
|
|
921
|
+
border-radius: 2px !important;
|
|
922
|
+
background-color: var(--field-bg-color) !important;
|
|
923
|
+
background-clip: padding-box !important;
|
|
924
|
+
border: 1px solid var(--field-border-color) !important;
|
|
925
|
+
box-shadow: none !important;
|
|
926
|
+
color: var(--field-color) !important;
|
|
927
|
+
font: message-box !important;
|
|
928
|
+
font-size: 12px !important;
|
|
929
|
+
line-height: 16px !important;
|
|
930
|
+
outline: none !important;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
.toolbarField:focus {
|
|
934
|
+
border-color: #0a84ff !important;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
#toolbarViewerLeft #pageNumber.toolbarField {
|
|
938
|
+
appearance: textfield !important;
|
|
939
|
+
width: 48px !important;
|
|
940
|
+
min-width: 48px !important;
|
|
941
|
+
max-width: 48px !important;
|
|
942
|
+
height: auto !important;
|
|
943
|
+
min-height: 0 !important;
|
|
944
|
+
margin: 3px 0 !important;
|
|
945
|
+
padding: 4px 7px !important;
|
|
946
|
+
border-radius: 2px !important;
|
|
947
|
+
font-size: 12px !important;
|
|
948
|
+
line-height: 16px !important;
|
|
949
|
+
text-align: end !important;
|
|
950
|
+
background-size: 0 0 !important;
|
|
951
|
+
transition-property: none !important;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
#pageNumber::-webkit-inner-spin-button {
|
|
955
|
+
-webkit-appearance: none !important;
|
|
956
|
+
appearance: none !important;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
#toolbarViewerLeft #numPages.toolbarLabel {
|
|
960
|
+
white-space: nowrap;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
.toolbarLabel {
|
|
964
|
+
width: max-content !important;
|
|
965
|
+
min-width: 16px !important;
|
|
966
|
+
height: 100% !important;
|
|
967
|
+
padding-inline: 4px !important;
|
|
968
|
+
margin: 2px !important;
|
|
969
|
+
border-radius: 2px !important;
|
|
970
|
+
color: var(--main-color) !important;
|
|
971
|
+
font-size: 12px !important;
|
|
972
|
+
line-height: 14px !important;
|
|
973
|
+
text-align: left !important;
|
|
974
|
+
user-select: none !important;
|
|
975
|
+
cursor: default !important;
|
|
976
|
+
display: inline flex !important;
|
|
977
|
+
flex-direction: column !important;
|
|
978
|
+
align-items: center !important;
|
|
979
|
+
justify-content: center !important;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.dropdownToolbarButton {
|
|
983
|
+
width: fit-content !important;
|
|
984
|
+
min-width: 140px !important;
|
|
985
|
+
padding: 0 !important;
|
|
986
|
+
border: var(--dropdown-btn-border) !important;
|
|
987
|
+
border-radius: 2px !important;
|
|
988
|
+
background-color: var(--dropdown-btn-bg-color) !important;
|
|
989
|
+
color: var(--main-color) !important;
|
|
990
|
+
font-size: 12px !important;
|
|
991
|
+
line-height: 14px !important;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
.dropdownToolbarButton:hover {
|
|
995
|
+
background-color: var(--button-hover-color) !important;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
.dropdownToolbarButton > select {
|
|
999
|
+
height: 28px !important;
|
|
1000
|
+
margin: 0 !important;
|
|
1001
|
+
padding-block: 1px 2px !important;
|
|
1002
|
+
padding-inline: 6px 38px !important;
|
|
1003
|
+
border: none !important;
|
|
1004
|
+
background-color: var(--dropdown-btn-bg-color) !important;
|
|
1005
|
+
color: var(--main-color) !important;
|
|
1006
|
+
font: message-box !important;
|
|
1007
|
+
font-size: 12px !important;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
.dropdownToolbarButton > select > option {
|
|
1011
|
+
background-color: #111111 !important;
|
|
1012
|
+
color: #f5f5f5 !important;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
#viewerContainer,
|
|
1016
|
+
#viewer,
|
|
1017
|
+
.pdfViewer,
|
|
1018
|
+
.pdfViewer .page,
|
|
1019
|
+
.pdfViewer .page canvas {
|
|
1020
|
+
border-color: oklch(0.49 0 0) !important;
|
|
1021
|
+
outline-color: oklch(0.49 0 0) !important;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
.pdfViewer .page {
|
|
1025
|
+
background-color: oklch(0.49 0 0) !important;
|
|
1026
|
+
border: 0 !important;
|
|
1027
|
+
box-shadow: none !important;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
@media (max-width: 768px) {
|
|
1031
|
+
#toolbarContainer {
|
|
1032
|
+
--toolbar-horizontal-padding: 4px;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
#editorModeButtons,
|
|
1036
|
+
#editorSignatureButton,
|
|
1037
|
+
#editorHighlightButton,
|
|
1038
|
+
#editorFreeTextButton,
|
|
1039
|
+
#editorInkButton,
|
|
1040
|
+
#editorStampButton {
|
|
1041
|
+
display: none !important;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
#toolbarViewerRight {
|
|
1045
|
+
gap: 0;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
.dropdownToolbarButton {
|
|
1049
|
+
min-width: 112px !important;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
#toolbarViewerLeft #pageNumber.toolbarField {
|
|
1053
|
+
width: 40px !important;
|
|
1054
|
+
min-width: 40px !important;
|
|
1055
|
+
max-width: 40px !important;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
@media (max-width: 480px) {
|
|
1060
|
+
#printButton,
|
|
1061
|
+
#secondaryToolbarToggleButton {
|
|
1062
|
+
display: none !important;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
.dropdownToolbarButton {
|
|
1066
|
+
min-width: 96px !important;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
`;
|
|
1070
|
+
|
|
1071
|
+
class ZGalleryPreviewComponent {
|
|
1072
|
+
_document = inject(DOCUMENT);
|
|
1073
|
+
_sanitizer = inject(DomSanitizer);
|
|
1074
|
+
file = input.required(...(ngDevMode ? [{ debugName: "file" }] : []));
|
|
1075
|
+
files = input([], ...(ngDevMode ? [{ debugName: "files" }] : []));
|
|
1076
|
+
zShowRemove = input(false, ...(ngDevMode ? [{ debugName: "zShowRemove" }] : []));
|
|
1077
|
+
zPdfViewerConfig = input({}, ...(ngDevMode ? [{ debugName: "zPdfViewerConfig" }] : []));
|
|
1078
|
+
zTrustedResourceOrigins = input([], ...(ngDevMode ? [{ debugName: "zTrustedResourceOrigins" }] : []));
|
|
1079
|
+
zOnClose = output();
|
|
1080
|
+
zOnDownload = output();
|
|
1081
|
+
zOnNavigate = output();
|
|
1082
|
+
zOnRemove = output();
|
|
1083
|
+
zoomed = signal(false, ...(ngDevMode ? [{ debugName: "zoomed" }] : []));
|
|
1084
|
+
isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1085
|
+
rotation = signal(0, ...(ngDevMode ? [{ debugName: "rotation" }] : []));
|
|
1086
|
+
isConverting = signal(false, ...(ngDevMode ? [{ debugName: "isConverting" }] : []));
|
|
1087
|
+
conversionError = signal(null, ...(ngDevMode ? [{ debugName: "conversionError" }] : []));
|
|
1088
|
+
previewError = signal(false, ...(ngDevMode ? [{ debugName: "previewError" }] : []));
|
|
1089
|
+
docHtmlContent = signal(null, ...(ngDevMode ? [{ debugName: "docHtmlContent" }] : []));
|
|
1090
|
+
textContent = signal('', ...(ngDevMode ? [{ debugName: "textContent" }] : []));
|
|
1091
|
+
pdfViewer = viewChild('pdfViewer', ...(ngDevMode ? [{ debugName: "pdfViewer" }] : []));
|
|
1092
|
+
_mediaLoaded = signal(false, ...(ngDevMode ? [{ debugName: "_mediaLoaded" }] : []));
|
|
1093
|
+
_loadingStartTime = 0;
|
|
1094
|
+
_minLoadingTime = 300;
|
|
1095
|
+
constructor() {
|
|
1096
|
+
effect(() => {
|
|
1097
|
+
const currentFile = this.file();
|
|
1098
|
+
if (!currentFile) {
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
this.isLoading.set(true);
|
|
1102
|
+
this._mediaLoaded.set(false);
|
|
1103
|
+
this._loadingStartTime = Date.now();
|
|
1104
|
+
this.zoomed.set(false);
|
|
1105
|
+
this.rotation.set(0);
|
|
1106
|
+
this.isConverting.set(false);
|
|
1107
|
+
this.conversionError.set(null);
|
|
1108
|
+
this.previewError.set(false);
|
|
1109
|
+
this.docHtmlContent.set(null);
|
|
1110
|
+
this.textContent.set('');
|
|
1111
|
+
const category = getFileCategory(currentFile);
|
|
1112
|
+
if (category === 'word' || category === 'excel' || category === 'text' || category === 'code') {
|
|
1113
|
+
void this._loadFileContent(currentFile, category);
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
async _loadFileContent(file, category) {
|
|
1118
|
+
const url = file.url || file.downloadUrl;
|
|
1119
|
+
if (!url) {
|
|
1120
|
+
this.conversionError.set('No URL available for preview');
|
|
1121
|
+
this._completeLoading();
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
this.isConverting.set(true);
|
|
1125
|
+
try {
|
|
1126
|
+
if (category === 'word') {
|
|
1127
|
+
await this._loadDocx(url);
|
|
1128
|
+
}
|
|
1129
|
+
else if (category === 'excel') {
|
|
1130
|
+
await this._loadExcel(url);
|
|
1131
|
+
}
|
|
1132
|
+
else {
|
|
1133
|
+
await this._loadText(url);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
catch (error) {
|
|
1137
|
+
const message = error instanceof Error ? error.message : 'Failed to load file content';
|
|
1138
|
+
this.conversionError.set(message);
|
|
1139
|
+
}
|
|
1140
|
+
finally {
|
|
1141
|
+
this.isConverting.set(false);
|
|
1142
|
+
this._completeLoading();
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
async _loadDocx(url) {
|
|
1146
|
+
const response = await fetch(url);
|
|
1147
|
+
this._assertSuccessfulResponse(response);
|
|
1148
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
1149
|
+
const mammothModule = await import('mammoth');
|
|
1150
|
+
const mammoth = mammothModule.default ?? mammothModule;
|
|
1151
|
+
const result = await mammoth.convertToHtml({ arrayBuffer });
|
|
1152
|
+
this.docHtmlContent.set(this._sanitizer.bypassSecurityTrustHtml(result.value));
|
|
1153
|
+
}
|
|
1154
|
+
async _loadExcel(url) {
|
|
1155
|
+
const response = await fetch(url);
|
|
1156
|
+
this._assertSuccessfulResponse(response);
|
|
1157
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
1158
|
+
const xlsxModule = await import('xlsx');
|
|
1159
|
+
const XLSX = xlsxModule.default ?? xlsxModule;
|
|
1160
|
+
const workbook = XLSX.read(arrayBuffer);
|
|
1161
|
+
const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
|
|
1162
|
+
const html = XLSX.utils.sheet_to_html(firstSheet);
|
|
1163
|
+
this.docHtmlContent.set(this._sanitizer.bypassSecurityTrustHtml(html));
|
|
1164
|
+
}
|
|
1165
|
+
async _loadText(url) {
|
|
1166
|
+
const response = await fetch(url);
|
|
1167
|
+
this._assertSuccessfulResponse(response);
|
|
1168
|
+
const text = await response.text();
|
|
1169
|
+
this.textContent.set(text);
|
|
1170
|
+
}
|
|
1171
|
+
_assertSuccessfulResponse(response) {
|
|
1172
|
+
if (!response.ok) {
|
|
1173
|
+
throw new Error(`Failed to fetch file: ${response.status}`);
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
_completeLoading() {
|
|
1177
|
+
const elapsed = Date.now() - this._loadingStartTime;
|
|
1178
|
+
const remaining = this._minLoadingTime - elapsed;
|
|
1179
|
+
if (remaining > 0) {
|
|
1180
|
+
setTimeout(() => this.isLoading.set(false), remaining);
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
this.isLoading.set(false);
|
|
1184
|
+
}
|
|
1185
|
+
currentIndex = computed(() => {
|
|
1186
|
+
const allFiles = this.files();
|
|
1187
|
+
const current = this.file();
|
|
1188
|
+
return allFiles.findIndex(f => f.id === current.id);
|
|
1189
|
+
}, ...(ngDevMode ? [{ debugName: "currentIndex" }] : []));
|
|
1190
|
+
hasPrev = computed(() => this.currentIndex() > 0, ...(ngDevMode ? [{ debugName: "hasPrev" }] : []));
|
|
1191
|
+
hasNext = computed(() => this.currentIndex() < this.files().length - 1, ...(ngDevMode ? [{ debugName: "hasNext" }] : []));
|
|
1192
|
+
isImageFile = computed(() => isImage(this.file()), ...(ngDevMode ? [{ debugName: "isImageFile" }] : []));
|
|
1193
|
+
isPdf = computed(() => getFileCategory(this.file()) === 'pdf', ...(ngDevMode ? [{ debugName: "isPdf" }] : []));
|
|
1194
|
+
pdfUrl = computed(() => {
|
|
1195
|
+
const url = this.file().url || this.file().downloadUrl;
|
|
1196
|
+
if (!url) {
|
|
1197
|
+
return null;
|
|
1198
|
+
}
|
|
1199
|
+
if (!this._isAllowedResourceUrl(url)) {
|
|
1200
|
+
return null;
|
|
1201
|
+
}
|
|
1202
|
+
return url;
|
|
1203
|
+
}, ...(ngDevMode ? [{ debugName: "pdfUrl" }] : []));
|
|
1204
|
+
pdfViewerId = computed(() => {
|
|
1205
|
+
const normalizedId = this.file().id.replace(/[^a-zA-Z0-9_-]/g, '-');
|
|
1206
|
+
return `z-gallery-preview-${normalizedId}`;
|
|
1207
|
+
}, ...(ngDevMode ? [{ debugName: "pdfViewerId" }] : []));
|
|
1208
|
+
pdfViewerConfig = computed(() => {
|
|
1209
|
+
const config = this.zPdfViewerConfig();
|
|
1210
|
+
const { controlVisibility } = config;
|
|
1211
|
+
const { groupVisibility } = config;
|
|
1212
|
+
const { autoActions } = config;
|
|
1213
|
+
const { viewerConfig } = config;
|
|
1214
|
+
const { themeConfig } = config;
|
|
1215
|
+
const { layoutConfig } = config;
|
|
1216
|
+
return {
|
|
1217
|
+
...config,
|
|
1218
|
+
viewerFolder: config.viewerFolder ?? '/assets/pdfjs',
|
|
1219
|
+
locale: viewerConfig?.locale ?? config.locale ?? '',
|
|
1220
|
+
showSpinner: viewerConfig?.showSpinner ?? config.showSpinner ?? false,
|
|
1221
|
+
useOnlyCssZoom: viewerConfig?.useOnlyCssZoom ?? config.useOnlyCssZoom ?? false,
|
|
1222
|
+
diagnosticLogs: viewerConfig?.diagnosticLogs ?? config.diagnosticLogs ?? false,
|
|
1223
|
+
showOpenFile: controlVisibility?.openFile ?? config.showOpenFile ?? false,
|
|
1224
|
+
showAnnotations: controlVisibility?.annotations ?? config.showAnnotations ?? true,
|
|
1225
|
+
showDownload: controlVisibility?.download ?? config.showDownload ?? true,
|
|
1226
|
+
showViewBookmark: controlVisibility?.viewBookmark ?? config.showViewBookmark ?? true,
|
|
1227
|
+
showPrint: controlVisibility?.print ?? config.showPrint ?? true,
|
|
1228
|
+
showFullScreen: controlVisibility?.fullScreen ?? config.showFullScreen ?? true,
|
|
1229
|
+
showFind: controlVisibility?.find ?? config.showFind ?? true,
|
|
1230
|
+
downloadOnLoad: autoActions?.downloadOnLoad ?? config.downloadOnLoad ?? false,
|
|
1231
|
+
printOnLoad: autoActions?.printOnLoad ?? config.printOnLoad ?? false,
|
|
1232
|
+
rotateCW: autoActions?.rotateCW ?? config.rotateCW ?? false,
|
|
1233
|
+
rotateCCW: autoActions?.rotateCCW ?? config.rotateCCW ?? false,
|
|
1234
|
+
showLastPageOnLoad: autoActions?.showLastPageOnLoad ?? config.showLastPageOnLoad ?? false,
|
|
1235
|
+
showToolbarLeft: groupVisibility?.toolbarLeft ?? config.showToolbarLeft ?? true,
|
|
1236
|
+
showToolbarMiddle: groupVisibility?.toolbarMiddle ?? config.showToolbarMiddle ?? true,
|
|
1237
|
+
showToolbarRight: groupVisibility?.toolbarRight ?? config.showToolbarRight ?? true,
|
|
1238
|
+
showSecondaryToolbarToggle: groupVisibility?.secondaryToolbarToggle ?? config.showSecondaryToolbarToggle ?? true,
|
|
1239
|
+
showSidebar: groupVisibility?.sidebar ?? config.showSidebar ?? true,
|
|
1240
|
+
showSidebarLeft: groupVisibility?.sidebarLeft ?? config.showSidebarLeft ?? true,
|
|
1241
|
+
showSidebarRight: groupVisibility?.sidebarRight ?? config.showSidebarRight ?? true,
|
|
1242
|
+
toolbarDensity: layoutConfig?.toolbarDensity ?? config.toolbarDensity ?? 'default',
|
|
1243
|
+
sidebarWidth: layoutConfig?.sidebarWidth ?? config.sidebarWidth,
|
|
1244
|
+
toolbarPosition: layoutConfig?.toolbarPosition ?? config.toolbarPosition ?? 'top',
|
|
1245
|
+
sidebarPosition: layoutConfig?.sidebarPosition ?? config.sidebarPosition ?? 'left',
|
|
1246
|
+
responsiveBreakpoint: layoutConfig?.responsiveBreakpoint ?? config.responsiveBreakpoint,
|
|
1247
|
+
zoom: config.zoom ?? 'page-fit',
|
|
1248
|
+
rotation: config.rotation ?? 0,
|
|
1249
|
+
cursor: config.cursor ?? 'select',
|
|
1250
|
+
scroll: config.scroll ?? 'vertical',
|
|
1251
|
+
spread: config.spread ?? 'none',
|
|
1252
|
+
pageMode: config.pageMode ?? 'none',
|
|
1253
|
+
page: config.page ?? 1,
|
|
1254
|
+
iframeBorder: config.iframeBorder ?? 0,
|
|
1255
|
+
theme: themeConfig?.theme ?? config.theme ?? 'auto',
|
|
1256
|
+
primaryColor: themeConfig?.primaryColor ?? config.primaryColor,
|
|
1257
|
+
backgroundColor: themeConfig?.backgroundColor ?? config.backgroundColor,
|
|
1258
|
+
pageBorderColor: themeConfig?.pageBorderColor ?? config.pageBorderColor,
|
|
1259
|
+
pageSpacing: themeConfig?.pageSpacing ?? config.pageSpacing,
|
|
1260
|
+
toolbarColor: themeConfig?.toolbarColor ?? config.toolbarColor,
|
|
1261
|
+
textColor: themeConfig?.textColor ?? config.textColor,
|
|
1262
|
+
borderRadius: themeConfig?.borderRadius ?? config.borderRadius,
|
|
1263
|
+
customCSS: this._mergePdfViewerCss(themeConfig?.customCSS ?? config.customCSS),
|
|
1264
|
+
cspNonce: themeConfig?.cspNonce ?? config.cspNonce,
|
|
1265
|
+
iframeTitle: themeConfig?.iframeTitle ?? config.iframeTitle,
|
|
1266
|
+
urlValidation: config.urlValidation ?? true,
|
|
1267
|
+
controlVisibility: controlVisibility ?? {},
|
|
1268
|
+
groupVisibility: groupVisibility ?? {},
|
|
1269
|
+
autoActions: autoActions ?? {},
|
|
1270
|
+
viewerConfig: viewerConfig ?? {},
|
|
1271
|
+
themeConfig: themeConfig ?? {},
|
|
1272
|
+
layoutConfig: layoutConfig ?? {},
|
|
1273
|
+
};
|
|
1274
|
+
}, ...(ngDevMode ? [{ debugName: "pdfViewerConfig" }] : []));
|
|
1275
|
+
_mergePdfViewerCss(customCSS) {
|
|
1276
|
+
if (!customCSS) {
|
|
1277
|
+
return Z_GALLERY_PDF_VIEWER_CHROME_CSS;
|
|
1278
|
+
}
|
|
1279
|
+
return `${Z_GALLERY_PDF_VIEWER_CHROME_CSS}\n${customCSS}`;
|
|
1280
|
+
}
|
|
1281
|
+
isVideo = computed(() => getFileCategory(this.file()) === 'video', ...(ngDevMode ? [{ debugName: "isVideo" }] : []));
|
|
1282
|
+
isWordFile = computed(() => getFileCategory(this.file()) === 'word', ...(ngDevMode ? [{ debugName: "isWordFile" }] : []));
|
|
1283
|
+
isExcelFile = computed(() => getFileCategory(this.file()) === 'excel', ...(ngDevMode ? [{ debugName: "isExcelFile" }] : []));
|
|
1284
|
+
isTextFile = computed(() => {
|
|
1285
|
+
const category = getFileCategory(this.file());
|
|
1286
|
+
return category === 'text' || category === 'code';
|
|
1287
|
+
}, ...(ngDevMode ? [{ debugName: "isTextFile" }] : []));
|
|
1288
|
+
canPreview = computed(() => isPreviewable(this.file()), ...(ngDevMode ? [{ debugName: "canPreview" }] : []));
|
|
1289
|
+
formattedSize = computed(() => formatFileSize(this.file().size), ...(ngDevMode ? [{ debugName: "formattedSize" }] : []));
|
|
1290
|
+
imageTransform = computed(() => {
|
|
1291
|
+
const rot = this.rotation();
|
|
1292
|
+
const zoom = this.zoomed() ? 'scale(1.5)' : 'scale(1)';
|
|
1293
|
+
return `rotate(${rot}deg) ${zoom}`;
|
|
1294
|
+
}, ...(ngDevMode ? [{ debugName: "imageTransform" }] : []));
|
|
1295
|
+
_isAllowedResourceUrl(url) {
|
|
1296
|
+
const currentOrigin = globalThis.location?.origin;
|
|
1297
|
+
const baseUrl = currentOrigin ?? 'http://localhost';
|
|
1298
|
+
try {
|
|
1299
|
+
const parsedUrl = new URL(url, baseUrl);
|
|
1300
|
+
if (parsedUrl.protocol === 'blob:') {
|
|
1301
|
+
return parsedUrl.origin === baseUrl;
|
|
1302
|
+
}
|
|
1303
|
+
return parsedUrl.origin === baseUrl || this._trustedOrigins().has(parsedUrl.origin);
|
|
1304
|
+
}
|
|
1305
|
+
catch {
|
|
1306
|
+
return false;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
_trustedOrigins = computed(() => new Set(this.zTrustedResourceOrigins()
|
|
1310
|
+
.map(origin => this._normalizeOrigin(origin))
|
|
1311
|
+
.filter((origin) => Boolean(origin))), ...(ngDevMode ? [{ debugName: "_trustedOrigins" }] : []));
|
|
1312
|
+
_normalizeOrigin(origin) {
|
|
1313
|
+
try {
|
|
1314
|
+
return new URL(origin).origin;
|
|
1315
|
+
}
|
|
1316
|
+
catch {
|
|
1317
|
+
return null;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
fileIcon = computed(() => {
|
|
1321
|
+
const category = getFileCategory(this.file());
|
|
1322
|
+
const iconMap = {
|
|
1323
|
+
pdf: 'lucideFileText',
|
|
1324
|
+
word: 'lucideFileText',
|
|
1325
|
+
excel: 'lucideFileSpreadsheet',
|
|
1326
|
+
video: 'lucideVideo',
|
|
1327
|
+
audio: 'lucideMusic',
|
|
1328
|
+
archive: 'lucideFileArchive',
|
|
1329
|
+
code: 'lucideCode',
|
|
1330
|
+
text: 'lucideFileText',
|
|
1331
|
+
unknown: 'lucideFile',
|
|
1332
|
+
};
|
|
1333
|
+
return iconMap[category] || 'lucideFile';
|
|
1334
|
+
}, ...(ngDevMode ? [{ debugName: "fileIcon" }] : []));
|
|
1335
|
+
onKeyDown(event) {
|
|
1336
|
+
switch (event.key) {
|
|
1337
|
+
case 'Escape':
|
|
1338
|
+
this.close();
|
|
1339
|
+
break;
|
|
1340
|
+
case 'ArrowLeft':
|
|
1341
|
+
if (this.hasPrev()) {
|
|
1342
|
+
this.navigate(-1);
|
|
1343
|
+
}
|
|
1344
|
+
break;
|
|
1345
|
+
case 'ArrowRight':
|
|
1346
|
+
if (this.hasNext()) {
|
|
1347
|
+
this.navigate(1);
|
|
1348
|
+
}
|
|
1349
|
+
break;
|
|
1350
|
+
case 'r':
|
|
1351
|
+
case 'R':
|
|
1352
|
+
if (this.isImageFile()) {
|
|
1353
|
+
this.rotateRight();
|
|
1354
|
+
}
|
|
1355
|
+
break;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
close() {
|
|
1359
|
+
this.zOnClose.emit();
|
|
1360
|
+
}
|
|
1361
|
+
navigate(direction) {
|
|
1362
|
+
const allFiles = this.files();
|
|
1363
|
+
const newIndex = this.currentIndex() + direction;
|
|
1364
|
+
if (newIndex >= 0 && newIndex < allFiles.length) {
|
|
1365
|
+
this.zoomed.set(false);
|
|
1366
|
+
this.rotation.set(0);
|
|
1367
|
+
this.isLoading.set(true);
|
|
1368
|
+
this._mediaLoaded.set(false);
|
|
1369
|
+
this._loadingStartTime = Date.now();
|
|
1370
|
+
this.previewError.set(false);
|
|
1371
|
+
this.zOnNavigate.emit(allFiles[newIndex]);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
toggleZoom() {
|
|
1375
|
+
if (this.isImageFile()) {
|
|
1376
|
+
this.zoomed.update(z => !z);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
rotateLeft() {
|
|
1380
|
+
this.rotation.update(r => (r - 90 + 360) % 360);
|
|
1381
|
+
}
|
|
1382
|
+
rotateRight() {
|
|
1383
|
+
this.rotation.update(r => (r + 90) % 360);
|
|
1384
|
+
}
|
|
1385
|
+
onImageLoad() {
|
|
1386
|
+
this._completeLoading();
|
|
1387
|
+
}
|
|
1388
|
+
onVideoLoad() {
|
|
1389
|
+
this._completeLoading();
|
|
1390
|
+
}
|
|
1391
|
+
onPdfLoad() {
|
|
1392
|
+
this._queueMobilePdfFit();
|
|
1393
|
+
this._completeLoading();
|
|
1394
|
+
}
|
|
1395
|
+
onMediaError() {
|
|
1396
|
+
this.previewError.set(true);
|
|
1397
|
+
this._completeLoading();
|
|
1398
|
+
}
|
|
1399
|
+
download() {
|
|
1400
|
+
this.zOnDownload.emit(this.file());
|
|
1401
|
+
}
|
|
1402
|
+
remove() {
|
|
1403
|
+
this.zOnRemove.emit(this.file());
|
|
1404
|
+
}
|
|
1405
|
+
onBackdropClick(event) {
|
|
1406
|
+
if (event.target.classList.contains('fixed')) {
|
|
1407
|
+
this.close();
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
_queueMobilePdfFit() {
|
|
1411
|
+
if (this.zPdfViewerConfig().zoom) {
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1414
|
+
const { defaultView } = this._document;
|
|
1415
|
+
if (!defaultView?.matchMedia('(max-width: 768px)').matches) {
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
const syncZoom = () => {
|
|
1419
|
+
void this.pdfViewer()?.setZoom('page-fit');
|
|
1420
|
+
};
|
|
1421
|
+
defaultView.requestAnimationFrame(() => {
|
|
1422
|
+
syncZoom();
|
|
1423
|
+
defaultView.setTimeout(syncZoom, 120);
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1427
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: ZGalleryPreviewComponent, isStandalone: true, selector: "z-gallery-preview", inputs: { file: { classPropertyName: "file", publicName: "file", isSignal: true, isRequired: true, transformFunction: null }, files: { classPropertyName: "files", publicName: "files", isSignal: true, isRequired: false, transformFunction: null }, zShowRemove: { classPropertyName: "zShowRemove", publicName: "zShowRemove", isSignal: true, isRequired: false, transformFunction: null }, zPdfViewerConfig: { classPropertyName: "zPdfViewerConfig", publicName: "zPdfViewerConfig", isSignal: true, isRequired: false, transformFunction: null }, zTrustedResourceOrigins: { classPropertyName: "zTrustedResourceOrigins", publicName: "zTrustedResourceOrigins", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOnClose: "zOnClose", zOnDownload: "zOnDownload", zOnNavigate: "zOnNavigate", zOnRemove: "zOnRemove" }, host: { listeners: { "document:keydown": "onKeyDown($event)" }, classAttribute: "z-gallery-preview z-[9999]" }, viewQueries: [{ propertyName: "pdfViewer", first: true, predicate: ["pdfViewer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"animate-in fade-in fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm duration-200\"\n (click)=\"onBackdropClick($event)\">\n <button\n z-button\n zType=\"ghost\"\n zShape=\"circle\"\n class=\"absolute top-3 right-3 z-20 text-white hover:bg-white/20 lg:top-4 lg:right-4\"\n (click)=\"close()\">\n <i z-icon zType=\"lucideX\" zSize=\"24\"></i>\n </button>\n\n @if (hasPrev()) {\n <button\n z-button\n zType=\"ghost\"\n zShape=\"circle\"\n class=\"absolute left-4 z-10 text-white hover:bg-white/20\"\n (click)=\"navigate(-1)\">\n <i z-icon zType=\"lucideChevronLeft\" zSize=\"32\"></i>\n </button>\n }\n\n @if (hasNext()) {\n <button\n z-button\n zType=\"ghost\"\n zShape=\"circle\"\n class=\"absolute right-4 z-10 text-white hover:bg-white/20\"\n (click)=\"navigate(1)\">\n <i z-icon zType=\"lucideChevronRight\" zSize=\"32\"></i>\n </button>\n }\n\n <div class=\"flex h-full w-full flex-col items-center\" (click)=\"$event.stopPropagation()\">\n <div\n class=\"dark:!border-border absolute top-3 right-14 left-3 z-10 flex min-w-0 items-center justify-between gap-2 rounded-[0.375rem] border !border-transparent bg-black/70 px-2.5 py-1.5 text-xs text-white shadow-lg backdrop-blur-sm lg:top-4 lg:right-auto lg:left-1/2 lg:max-w-[calc(100vw-10rem)] lg:-translate-x-1/2 lg:justify-start lg:bg-black/60 lg:px-4 lg:py-2 lg:text-sm dark:border\">\n <div class=\"flex min-w-0 items-baseline gap-1.5\">\n <span class=\"min-w-0 truncate font-medium lg:max-w-[12.5rem]\">{{ file().name }}</span>\n <span class=\"hidden shrink-0 text-white/70 lg:inline\">({{ formattedSize() }})</span>\n </div>\n\n @if (files().length > 1) {\n <span class=\"hidden shrink-0 text-white/70 md:inline\">{{ currentIndex() + 1 }} / {{ files().length }}</span>\n }\n\n <div class=\"ml-1 flex shrink-0 items-center gap-0.5\">\n @if (isImageFile()) {\n <button\n z-button\n zType=\"ghost\"\n zSize=\"xs\"\n zShape=\"circle\"\n class=\"text-white hover:bg-white/20\"\n z-tooltip\n [zContent]=\"'i18n_z_ui_gallery_rotate_left' | translate\"\n (click)=\"rotateLeft()\">\n <i z-icon zType=\"lucideUndo\" zSize=\"14\"></i>\n </button>\n <button\n z-button\n zType=\"ghost\"\n zSize=\"xs\"\n zShape=\"circle\"\n class=\"text-white hover:bg-white/20\"\n z-tooltip\n [zContent]=\"'i18n_z_ui_gallery_rotate_right' | translate\"\n (click)=\"rotateRight()\">\n <i z-icon zType=\"lucideRedo\" zSize=\"14\"></i>\n </button>\n }\n\n <button\n z-button\n zType=\"ghost\"\n zSize=\"xs\"\n zShape=\"circle\"\n class=\"text-white hover:bg-white/20\"\n z-tooltip\n [zContent]=\"'i18n_z_ui_gallery_download' | translate\"\n (click)=\"download()\">\n <i z-icon zType=\"lucideDownload\" zSize=\"14\"></i>\n </button>\n\n @if (zShowRemove()) {\n <button\n z-button\n zType=\"ghost\"\n zSize=\"xs\"\n zShape=\"circle\"\n class=\"text-white hover:bg-white/20\"\n z-tooltip\n [zContent]=\"'i18n_z_ui_gallery_delete' | translate\"\n (click)=\"remove()\">\n <i z-icon zType=\"lucideTrash2\" zSize=\"14\"></i>\n </button>\n }\n </div>\n </div>\n\n <div class=\"relative flex flex-1 items-center justify-center pt-16\">\n @if (isImageFile()) {\n <div class=\"relative flex h-[60vh] w-[70vw] items-center justify-center\">\n @if (isLoading()) {\n <z-skeleton class=\"absolute inset-0 rounded-lg\" />\n <div class=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (previewError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center rounded-lg p-8 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-16 items-center justify-center rounded-xl\">\n <i z-icon zType=\"lucideTriangleAlert\" zSize=\"28\" class=\"text-destructive\"></i>\n </div>\n <span class=\"text-foreground text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_preview_load_error' | translate }}\n </span>\n </div>\n } @else {\n <img\n [src]=\"file().url || file().thumbnailUrl\"\n [alt]=\"file().name\"\n class=\"max-h-full max-w-full rounded-lg object-contain shadow-2xl transition-opacity duration-300\"\n [class.opacity-0]=\"isLoading()\"\n [class.opacity-100]=\"!isLoading()\"\n [class.cursor-zoom-in]=\"!zoomed()\"\n [class.cursor-zoom-out]=\"zoomed()\"\n [style.transform]=\"imageTransform()\"\n (load)=\"onImageLoad()\"\n (error)=\"onMediaError()\"\n (click)=\"toggleZoom()\" />\n }\n </div>\n } @else if (isPdf() && pdfUrl()) {\n <div\n class=\"z-gallery-pdf-frame relative h-[75vh] w-[85vw] max-w-[96vw] overflow-hidden rounded-sm border shadow-xs\">\n @if (isLoading()) {\n <z-skeleton class=\"absolute inset-0 rounded-sm\" />\n <div\n class=\"text-muted-foreground absolute inset-0 z-10 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (previewError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center p-8\">\n <div class=\"bg-muted mb-4 flex size-16 items-center justify-center rounded-xl\">\n <i z-icon zType=\"lucideTriangleAlert\" zSize=\"28\" class=\"text-destructive\"></i>\n </div>\n <span class=\"text-foreground text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_preview_load_error' | translate }}\n </span>\n </div>\n } @else {\n <div\n class=\"relative size-full bg-white transition-opacity duration-300\"\n [class.opacity-0]=\"isLoading()\"\n [class.opacity-100]=\"!isLoading()\">\n @let pdfConfig = pdfViewerConfig();\n <ng2-pdfjs-viewer\n #pdfViewer\n class=\"block size-full\"\n [viewerFolder]=\"pdfConfig.viewerFolder!\"\n [viewerId]=\"pdfViewerId()\"\n [pdfSrc]=\"pdfUrl()!\"\n [downloadFileName]=\"file().name\"\n [locale]=\"pdfConfig.locale!\"\n [showSpinner]=\"pdfConfig.showSpinner!\"\n [useOnlyCssZoom]=\"pdfConfig.useOnlyCssZoom!\"\n [diagnosticLogs]=\"pdfConfig.diagnosticLogs!\"\n [showOpenFile]=\"pdfConfig.showOpenFile!\"\n [showAnnotations]=\"pdfConfig.showAnnotations!\"\n [showDownload]=\"pdfConfig.showDownload!\"\n [showViewBookmark]=\"pdfConfig.showViewBookmark!\"\n [showPrint]=\"pdfConfig.showPrint!\"\n [showFullScreen]=\"pdfConfig.showFullScreen!\"\n [showFind]=\"pdfConfig.showFind!\"\n [downloadOnLoad]=\"pdfConfig.downloadOnLoad!\"\n [printOnLoad]=\"pdfConfig.printOnLoad!\"\n [rotateCW]=\"pdfConfig.rotateCW!\"\n [rotateCCW]=\"pdfConfig.rotateCCW!\"\n [showLastPageOnLoad]=\"pdfConfig.showLastPageOnLoad!\"\n [showToolbarLeft]=\"pdfConfig.showToolbarLeft!\"\n [showToolbarMiddle]=\"pdfConfig.showToolbarMiddle!\"\n [showToolbarRight]=\"pdfConfig.showToolbarRight!\"\n [showSecondaryToolbarToggle]=\"pdfConfig.showSecondaryToolbarToggle!\"\n [showSidebar]=\"pdfConfig.showSidebar!\"\n [showSidebarLeft]=\"pdfConfig.showSidebarLeft!\"\n [showSidebarRight]=\"pdfConfig.showSidebarRight!\"\n [toolbarDensity]=\"pdfConfig.toolbarDensity!\"\n [sidebarWidth]=\"pdfConfig.sidebarWidth\"\n [toolbarPosition]=\"pdfConfig.toolbarPosition!\"\n [sidebarPosition]=\"pdfConfig.sidebarPosition!\"\n [responsiveBreakpoint]=\"pdfConfig.responsiveBreakpoint\"\n [zoom]=\"pdfConfig.zoom!\"\n [rotation]=\"pdfConfig.rotation!\"\n [cursor]=\"pdfConfig.cursor!\"\n [scroll]=\"pdfConfig.scroll!\"\n [spread]=\"pdfConfig.spread!\"\n [pageMode]=\"pdfConfig.pageMode!\"\n [page]=\"pdfConfig.page!\"\n [iframeBorder]=\"pdfConfig.iframeBorder!\"\n [theme]=\"pdfConfig.theme!\"\n [primaryColor]=\"pdfConfig.primaryColor\"\n [backgroundColor]=\"pdfConfig.backgroundColor\"\n [pageBorderColor]=\"pdfConfig.pageBorderColor\"\n [pageSpacing]=\"pdfConfig.pageSpacing\"\n [toolbarColor]=\"pdfConfig.toolbarColor\"\n [textColor]=\"pdfConfig.textColor\"\n [borderRadius]=\"pdfConfig.borderRadius\"\n [customCSS]=\"pdfConfig.customCSS\"\n [cspNonce]=\"pdfConfig.cspNonce\"\n [iframeTitle]=\"pdfConfig.iframeTitle || ('i18n_z_ui_gallery_pdf_preview' | translate)\"\n [urlValidation]=\"pdfConfig.urlValidation!\"\n [controlVisibility]=\"pdfConfig.controlVisibility!\"\n [groupVisibility]=\"pdfConfig.groupVisibility!\"\n [autoActions]=\"pdfConfig.autoActions!\"\n [viewerConfig]=\"pdfConfig.viewerConfig!\"\n [themeConfig]=\"pdfConfig.themeConfig!\"\n [layoutConfig]=\"pdfConfig.layoutConfig!\"\n (onDocumentLoad)=\"onPdfLoad()\"\n (onDocumentError)=\"onMediaError()\" />\n </div>\n }\n </div>\n } @else if (isVideo()) {\n <div class=\"relative flex h-[60vh] w-[70vw] items-center justify-center\">\n @if (isLoading()) {\n <z-skeleton class=\"absolute inset-0 rounded-lg\" />\n <div class=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (previewError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center rounded-lg p-8 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-16 items-center justify-center rounded-xl\">\n <i z-icon zType=\"lucideTriangleAlert\" zSize=\"28\" class=\"text-destructive\"></i>\n </div>\n <span class=\"text-foreground text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_preview_load_error' | translate }}\n </span>\n </div>\n } @else {\n <video\n [src]=\"file().url\"\n controls\n autoplay\n class=\"max-h-full max-w-full rounded-lg shadow-2xl transition-opacity duration-300\"\n [class.opacity-0]=\"isLoading()\"\n [class.opacity-100]=\"!isLoading()\"\n (loadeddata)=\"onVideoLoad()\"\n (error)=\"onMediaError()\">\n {{ 'i18n_z_ui_gallery_video_not_supported' | translate }}\n </video>\n }\n </div>\n } @else if (isWordFile()) {\n <div class=\"relative h-[75vh] w-[85vw]\">\n @if (isLoading() || isConverting()) {\n <z-skeleton class=\"absolute inset-0 rounded-lg\" />\n <div class=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (conversionError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center rounded-lg p-12 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-24 items-center justify-center rounded-xl\">\n <i z-icon [zType]=\"fileIcon()\" zSize=\"40\" class=\"text-muted-foreground\"></i>\n </div>\n <span class=\"text-foreground mb-2 text-lg font-medium\">{{ file().name }}</span>\n <span class=\"text-muted-foreground rounded-md bg-red-100 px-3 py-1.5 text-xs dark:bg-red-900/30\">\n <span class=\"text-red-700 dark:text-red-300\">{{ conversionError() }}</span>\n </span>\n </div>\n } @else if (docHtmlContent()) {\n <div\n class=\"absolute inset-0 overflow-auto rounded-lg bg-white p-8 text-gray-950 shadow-2xl\"\n [innerHTML]=\"docHtmlContent()\"></div>\n }\n </div>\n } @else if (isExcelFile()) {\n <div class=\"relative h-[75vh] w-[85vw]\">\n @if (isLoading() || isConverting()) {\n <z-skeleton class=\"absolute inset-0 rounded-lg\" />\n <div class=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (conversionError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center rounded-lg p-12 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-24 items-center justify-center rounded-xl\">\n <i z-icon [zType]=\"fileIcon()\" zSize=\"40\" class=\"text-muted-foreground\"></i>\n </div>\n <span class=\"text-foreground mb-2 text-lg font-medium\">{{ file().name }}</span>\n <span class=\"text-muted-foreground rounded-md bg-red-100 px-3 py-1.5 text-xs dark:bg-red-900/30\">\n <span class=\"text-red-700 dark:text-red-300\">{{ conversionError() }}</span>\n </span>\n </div>\n } @else if (docHtmlContent()) {\n <div\n class=\"absolute inset-0 overflow-auto rounded-lg bg-white p-4 text-gray-950 shadow-2xl\"\n [innerHTML]=\"docHtmlContent()\"></div>\n }\n </div>\n } @else if (isTextFile()) {\n <div class=\"relative h-[75vh] w-[85vw]\">\n @if (isLoading() || isConverting()) {\n <z-skeleton class=\"absolute inset-0 rounded-lg\" />\n <div class=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (conversionError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center rounded-lg p-12 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-24 items-center justify-center rounded-xl\">\n <i z-icon [zType]=\"fileIcon()\" zSize=\"40\" class=\"text-muted-foreground\"></i>\n </div>\n <span class=\"text-foreground mb-2 text-lg font-medium\">{{ file().name }}</span>\n <span class=\"text-muted-foreground rounded-md bg-red-100 px-3 py-1.5 text-xs dark:bg-red-900/30\">\n <span class=\"text-red-700 dark:text-red-300\">{{ conversionError() }}</span>\n </span>\n </div>\n } @else if (textContent()) {\n <div class=\"absolute inset-0 overflow-auto rounded-lg bg-gray-950 p-6 shadow-2xl\">\n <pre class=\"font-mono text-sm leading-relaxed whitespace-pre-wrap text-gray-100\">{{ textContent() }}</pre>\n </div>\n }\n </div>\n } @else {\n <div class=\"bg-card flex flex-col items-center justify-center rounded-lg p-12 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-24 items-center justify-center rounded-xl\">\n <i z-icon [zType]=\"fileIcon()\" zSize=\"40\" class=\"text-muted-foreground\"></i>\n </div>\n <span class=\"text-foreground mb-2 text-lg font-medium\">{{ file().name }}</span>\n <span class=\"text-muted-foreground mb-4 text-sm\">{{ formattedSize() }}</span>\n <span class=\"text-muted-foreground rounded-md bg-amber-100 px-3 py-1.5 text-xs dark:bg-amber-900/30\">\n <i\n z-icon\n zType=\"lucideInfo\"\n zSize=\"14\"\n class=\"mr-1 inline-block align-middle text-amber-600 dark:text-amber-400\"></i>\n <span class=\"align-middle text-amber-700 dark:text-amber-300\">\n {{ 'i18n_z_ui_gallery_preview_not_supported' | translate }}\n </span>\n </span>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".z-gallery-pdf-frame,.z-gallery-pdf-frame *{border-color:#606060!important;outline-color:#606060!important}.z-gallery-pdf-frame{border-width:1px!important;border-style:solid!important;background:#606060}.z-gallery-pdf-frame ng2-pdfjs-viewer,.z-gallery-pdf-frame ng2-pdfjs-viewer iframe{display:block;width:100%;height:100%;border:0!important;outline:0!important;box-shadow:none!important;background:#606060}\n"], dependencies: [{ kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "component", type: ZSkeletonComponent, selector: "z-skeleton", inputs: ["class", "zType", "zSize", "zWidth", "zHeight", "zRows", "zGap", "zAnimated", "zRadius"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTooltipPosition", "zTrigger", "zTooltipTrigger", "zTooltipType", "zTooltipSize", "zClass", "zTooltipClass", "zShowDelay", "zTooltipShowDelay", "zHideDelay", "zTooltipHideDelay", "zArrow", "zTooltipArrow", "zDisabled", "zTooltipDisabled", "zOffset", "zTooltipOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "ngmodule", type: PdfJsViewerModule }, { kind: "component", type: i1.PdfJsViewerComponent, selector: "ng2-pdfjs-viewer", inputs: ["viewerId", "viewerFolder", "externalWindow", "target", "showSpinner", "downloadFileName", "locale", "useOnlyCssZoom", "externalLinkTarget", "rememberLastView", "annotationEditor", "highlightEditorColors", "enableSignatureEditor", "signatureStorage", "pageColors", "pdfJsOptions", "enableCommentEditor", "enablePageEditing", "showToolbar", "chromeless", "customToolbarTpl", "customSidebarTpl", "aiAssistantConfig", "pageOverlayTpl", "httpHeaders", "withCredentials", "formData", "contentProtection", "iframeSandbox", "diagnosticLogs", "showOpenFile", "showAnnotations", "showDownload", "showViewBookmark", "showPrint", "showFullScreen", "showFind", "downloadOnLoad", "printOnLoad", "rotateCW", "rotateCCW", "showLastPageOnLoad", "namedDest", "errorOverride", "errorAppend", "errorMessage", "urlValidation", "customSecurityTpl", "theme", "primaryColor", "backgroundColor", "pageBorderColor", "pageSpacing", "toolbarColor", "textColor", "borderRadius", "customCSS", "cspNonce", "iframeTitle", "customSpinnerTpl", "spinnerClass", "customErrorTpl", "errorClass", "showToolbarLeft", "showToolbarMiddle", "showToolbarRight", "showSecondaryToolbarToggle", "showSidebar", "showSidebarLeft", "showSidebarRight", "toolbarDensity", "sidebarWidth", "toolbarPosition", "sidebarPosition", "responsiveBreakpoint", "controlVisibility", "autoActions", "errorHandling", "viewerConfig", "themeConfig", "groupVisibility", "layoutConfig", "startDownload", "startPrint", "openFile", "download", "print", "fullScreen", "find", "viewBookmark", "lastPage", "externalWindowOptions", "iframeBorder", "zoom", "rotation", "cursor", "scroll", "spread", "pageMode", "page", "pdfSrc"], outputs: ["onBeforePrint", "onAfterPrint", "onDocumentLoad", "onPageChange", "onScaleChange", "onRotationChange", "onDocumentError", "onDocumentInit", "onPagesInit", "onPresentationModeChanged", "onOpenFile", "onFind", "onUpdateFindMatchesCount", "onMetadataLoaded", "onOutlineLoaded", "onPageRendered", "onAnnotationLayerRendered", "onBookmarkClick", "onIdle", "onPasswordPrompt", "onAnnotationEditorStateChange", "onPagesEdited", "onReadAloudStateChange", "onSidebarViewChanged", "onLayersChanged", "onNamedAction", "onDocumentProperties", "annotationEditorChange", "onProgress", "formDataChange", "zoomChange", "cursorChange", "scrollChange", "spreadChange", "pageModeChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1428
|
+
}
|
|
1429
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryPreviewComponent, decorators: [{
|
|
1430
|
+
type: Component,
|
|
1431
|
+
args: [{ selector: 'z-gallery-preview', imports: [ZButtonComponent, ZIconComponent, ZSkeletonComponent, ZTooltipDirective, TranslatePipe, PdfJsViewerModule], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
1432
|
+
class: 'z-gallery-preview z-[9999]',
|
|
1433
|
+
'(document:keydown)': 'onKeyDown($event)',
|
|
1434
|
+
}, template: "<div\n class=\"animate-in fade-in fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm duration-200\"\n (click)=\"onBackdropClick($event)\">\n <button\n z-button\n zType=\"ghost\"\n zShape=\"circle\"\n class=\"absolute top-3 right-3 z-20 text-white hover:bg-white/20 lg:top-4 lg:right-4\"\n (click)=\"close()\">\n <i z-icon zType=\"lucideX\" zSize=\"24\"></i>\n </button>\n\n @if (hasPrev()) {\n <button\n z-button\n zType=\"ghost\"\n zShape=\"circle\"\n class=\"absolute left-4 z-10 text-white hover:bg-white/20\"\n (click)=\"navigate(-1)\">\n <i z-icon zType=\"lucideChevronLeft\" zSize=\"32\"></i>\n </button>\n }\n\n @if (hasNext()) {\n <button\n z-button\n zType=\"ghost\"\n zShape=\"circle\"\n class=\"absolute right-4 z-10 text-white hover:bg-white/20\"\n (click)=\"navigate(1)\">\n <i z-icon zType=\"lucideChevronRight\" zSize=\"32\"></i>\n </button>\n }\n\n <div class=\"flex h-full w-full flex-col items-center\" (click)=\"$event.stopPropagation()\">\n <div\n class=\"dark:!border-border absolute top-3 right-14 left-3 z-10 flex min-w-0 items-center justify-between gap-2 rounded-[0.375rem] border !border-transparent bg-black/70 px-2.5 py-1.5 text-xs text-white shadow-lg backdrop-blur-sm lg:top-4 lg:right-auto lg:left-1/2 lg:max-w-[calc(100vw-10rem)] lg:-translate-x-1/2 lg:justify-start lg:bg-black/60 lg:px-4 lg:py-2 lg:text-sm dark:border\">\n <div class=\"flex min-w-0 items-baseline gap-1.5\">\n <span class=\"min-w-0 truncate font-medium lg:max-w-[12.5rem]\">{{ file().name }}</span>\n <span class=\"hidden shrink-0 text-white/70 lg:inline\">({{ formattedSize() }})</span>\n </div>\n\n @if (files().length > 1) {\n <span class=\"hidden shrink-0 text-white/70 md:inline\">{{ currentIndex() + 1 }} / {{ files().length }}</span>\n }\n\n <div class=\"ml-1 flex shrink-0 items-center gap-0.5\">\n @if (isImageFile()) {\n <button\n z-button\n zType=\"ghost\"\n zSize=\"xs\"\n zShape=\"circle\"\n class=\"text-white hover:bg-white/20\"\n z-tooltip\n [zContent]=\"'i18n_z_ui_gallery_rotate_left' | translate\"\n (click)=\"rotateLeft()\">\n <i z-icon zType=\"lucideUndo\" zSize=\"14\"></i>\n </button>\n <button\n z-button\n zType=\"ghost\"\n zSize=\"xs\"\n zShape=\"circle\"\n class=\"text-white hover:bg-white/20\"\n z-tooltip\n [zContent]=\"'i18n_z_ui_gallery_rotate_right' | translate\"\n (click)=\"rotateRight()\">\n <i z-icon zType=\"lucideRedo\" zSize=\"14\"></i>\n </button>\n }\n\n <button\n z-button\n zType=\"ghost\"\n zSize=\"xs\"\n zShape=\"circle\"\n class=\"text-white hover:bg-white/20\"\n z-tooltip\n [zContent]=\"'i18n_z_ui_gallery_download' | translate\"\n (click)=\"download()\">\n <i z-icon zType=\"lucideDownload\" zSize=\"14\"></i>\n </button>\n\n @if (zShowRemove()) {\n <button\n z-button\n zType=\"ghost\"\n zSize=\"xs\"\n zShape=\"circle\"\n class=\"text-white hover:bg-white/20\"\n z-tooltip\n [zContent]=\"'i18n_z_ui_gallery_delete' | translate\"\n (click)=\"remove()\">\n <i z-icon zType=\"lucideTrash2\" zSize=\"14\"></i>\n </button>\n }\n </div>\n </div>\n\n <div class=\"relative flex flex-1 items-center justify-center pt-16\">\n @if (isImageFile()) {\n <div class=\"relative flex h-[60vh] w-[70vw] items-center justify-center\">\n @if (isLoading()) {\n <z-skeleton class=\"absolute inset-0 rounded-lg\" />\n <div class=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (previewError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center rounded-lg p-8 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-16 items-center justify-center rounded-xl\">\n <i z-icon zType=\"lucideTriangleAlert\" zSize=\"28\" class=\"text-destructive\"></i>\n </div>\n <span class=\"text-foreground text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_preview_load_error' | translate }}\n </span>\n </div>\n } @else {\n <img\n [src]=\"file().url || file().thumbnailUrl\"\n [alt]=\"file().name\"\n class=\"max-h-full max-w-full rounded-lg object-contain shadow-2xl transition-opacity duration-300\"\n [class.opacity-0]=\"isLoading()\"\n [class.opacity-100]=\"!isLoading()\"\n [class.cursor-zoom-in]=\"!zoomed()\"\n [class.cursor-zoom-out]=\"zoomed()\"\n [style.transform]=\"imageTransform()\"\n (load)=\"onImageLoad()\"\n (error)=\"onMediaError()\"\n (click)=\"toggleZoom()\" />\n }\n </div>\n } @else if (isPdf() && pdfUrl()) {\n <div\n class=\"z-gallery-pdf-frame relative h-[75vh] w-[85vw] max-w-[96vw] overflow-hidden rounded-sm border shadow-xs\">\n @if (isLoading()) {\n <z-skeleton class=\"absolute inset-0 rounded-sm\" />\n <div\n class=\"text-muted-foreground absolute inset-0 z-10 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (previewError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center p-8\">\n <div class=\"bg-muted mb-4 flex size-16 items-center justify-center rounded-xl\">\n <i z-icon zType=\"lucideTriangleAlert\" zSize=\"28\" class=\"text-destructive\"></i>\n </div>\n <span class=\"text-foreground text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_preview_load_error' | translate }}\n </span>\n </div>\n } @else {\n <div\n class=\"relative size-full bg-white transition-opacity duration-300\"\n [class.opacity-0]=\"isLoading()\"\n [class.opacity-100]=\"!isLoading()\">\n @let pdfConfig = pdfViewerConfig();\n <ng2-pdfjs-viewer\n #pdfViewer\n class=\"block size-full\"\n [viewerFolder]=\"pdfConfig.viewerFolder!\"\n [viewerId]=\"pdfViewerId()\"\n [pdfSrc]=\"pdfUrl()!\"\n [downloadFileName]=\"file().name\"\n [locale]=\"pdfConfig.locale!\"\n [showSpinner]=\"pdfConfig.showSpinner!\"\n [useOnlyCssZoom]=\"pdfConfig.useOnlyCssZoom!\"\n [diagnosticLogs]=\"pdfConfig.diagnosticLogs!\"\n [showOpenFile]=\"pdfConfig.showOpenFile!\"\n [showAnnotations]=\"pdfConfig.showAnnotations!\"\n [showDownload]=\"pdfConfig.showDownload!\"\n [showViewBookmark]=\"pdfConfig.showViewBookmark!\"\n [showPrint]=\"pdfConfig.showPrint!\"\n [showFullScreen]=\"pdfConfig.showFullScreen!\"\n [showFind]=\"pdfConfig.showFind!\"\n [downloadOnLoad]=\"pdfConfig.downloadOnLoad!\"\n [printOnLoad]=\"pdfConfig.printOnLoad!\"\n [rotateCW]=\"pdfConfig.rotateCW!\"\n [rotateCCW]=\"pdfConfig.rotateCCW!\"\n [showLastPageOnLoad]=\"pdfConfig.showLastPageOnLoad!\"\n [showToolbarLeft]=\"pdfConfig.showToolbarLeft!\"\n [showToolbarMiddle]=\"pdfConfig.showToolbarMiddle!\"\n [showToolbarRight]=\"pdfConfig.showToolbarRight!\"\n [showSecondaryToolbarToggle]=\"pdfConfig.showSecondaryToolbarToggle!\"\n [showSidebar]=\"pdfConfig.showSidebar!\"\n [showSidebarLeft]=\"pdfConfig.showSidebarLeft!\"\n [showSidebarRight]=\"pdfConfig.showSidebarRight!\"\n [toolbarDensity]=\"pdfConfig.toolbarDensity!\"\n [sidebarWidth]=\"pdfConfig.sidebarWidth\"\n [toolbarPosition]=\"pdfConfig.toolbarPosition!\"\n [sidebarPosition]=\"pdfConfig.sidebarPosition!\"\n [responsiveBreakpoint]=\"pdfConfig.responsiveBreakpoint\"\n [zoom]=\"pdfConfig.zoom!\"\n [rotation]=\"pdfConfig.rotation!\"\n [cursor]=\"pdfConfig.cursor!\"\n [scroll]=\"pdfConfig.scroll!\"\n [spread]=\"pdfConfig.spread!\"\n [pageMode]=\"pdfConfig.pageMode!\"\n [page]=\"pdfConfig.page!\"\n [iframeBorder]=\"pdfConfig.iframeBorder!\"\n [theme]=\"pdfConfig.theme!\"\n [primaryColor]=\"pdfConfig.primaryColor\"\n [backgroundColor]=\"pdfConfig.backgroundColor\"\n [pageBorderColor]=\"pdfConfig.pageBorderColor\"\n [pageSpacing]=\"pdfConfig.pageSpacing\"\n [toolbarColor]=\"pdfConfig.toolbarColor\"\n [textColor]=\"pdfConfig.textColor\"\n [borderRadius]=\"pdfConfig.borderRadius\"\n [customCSS]=\"pdfConfig.customCSS\"\n [cspNonce]=\"pdfConfig.cspNonce\"\n [iframeTitle]=\"pdfConfig.iframeTitle || ('i18n_z_ui_gallery_pdf_preview' | translate)\"\n [urlValidation]=\"pdfConfig.urlValidation!\"\n [controlVisibility]=\"pdfConfig.controlVisibility!\"\n [groupVisibility]=\"pdfConfig.groupVisibility!\"\n [autoActions]=\"pdfConfig.autoActions!\"\n [viewerConfig]=\"pdfConfig.viewerConfig!\"\n [themeConfig]=\"pdfConfig.themeConfig!\"\n [layoutConfig]=\"pdfConfig.layoutConfig!\"\n (onDocumentLoad)=\"onPdfLoad()\"\n (onDocumentError)=\"onMediaError()\" />\n </div>\n }\n </div>\n } @else if (isVideo()) {\n <div class=\"relative flex h-[60vh] w-[70vw] items-center justify-center\">\n @if (isLoading()) {\n <z-skeleton class=\"absolute inset-0 rounded-lg\" />\n <div class=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (previewError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center rounded-lg p-8 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-16 items-center justify-center rounded-xl\">\n <i z-icon zType=\"lucideTriangleAlert\" zSize=\"28\" class=\"text-destructive\"></i>\n </div>\n <span class=\"text-foreground text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_preview_load_error' | translate }}\n </span>\n </div>\n } @else {\n <video\n [src]=\"file().url\"\n controls\n autoplay\n class=\"max-h-full max-w-full rounded-lg shadow-2xl transition-opacity duration-300\"\n [class.opacity-0]=\"isLoading()\"\n [class.opacity-100]=\"!isLoading()\"\n (loadeddata)=\"onVideoLoad()\"\n (error)=\"onMediaError()\">\n {{ 'i18n_z_ui_gallery_video_not_supported' | translate }}\n </video>\n }\n </div>\n } @else if (isWordFile()) {\n <div class=\"relative h-[75vh] w-[85vw]\">\n @if (isLoading() || isConverting()) {\n <z-skeleton class=\"absolute inset-0 rounded-lg\" />\n <div class=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (conversionError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center rounded-lg p-12 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-24 items-center justify-center rounded-xl\">\n <i z-icon [zType]=\"fileIcon()\" zSize=\"40\" class=\"text-muted-foreground\"></i>\n </div>\n <span class=\"text-foreground mb-2 text-lg font-medium\">{{ file().name }}</span>\n <span class=\"text-muted-foreground rounded-md bg-red-100 px-3 py-1.5 text-xs dark:bg-red-900/30\">\n <span class=\"text-red-700 dark:text-red-300\">{{ conversionError() }}</span>\n </span>\n </div>\n } @else if (docHtmlContent()) {\n <div\n class=\"absolute inset-0 overflow-auto rounded-lg bg-white p-8 text-gray-950 shadow-2xl\"\n [innerHTML]=\"docHtmlContent()\"></div>\n }\n </div>\n } @else if (isExcelFile()) {\n <div class=\"relative h-[75vh] w-[85vw]\">\n @if (isLoading() || isConverting()) {\n <z-skeleton class=\"absolute inset-0 rounded-lg\" />\n <div class=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (conversionError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center rounded-lg p-12 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-24 items-center justify-center rounded-xl\">\n <i z-icon [zType]=\"fileIcon()\" zSize=\"40\" class=\"text-muted-foreground\"></i>\n </div>\n <span class=\"text-foreground mb-2 text-lg font-medium\">{{ file().name }}</span>\n <span class=\"text-muted-foreground rounded-md bg-red-100 px-3 py-1.5 text-xs dark:bg-red-900/30\">\n <span class=\"text-red-700 dark:text-red-300\">{{ conversionError() }}</span>\n </span>\n </div>\n } @else if (docHtmlContent()) {\n <div\n class=\"absolute inset-0 overflow-auto rounded-lg bg-white p-4 text-gray-950 shadow-2xl\"\n [innerHTML]=\"docHtmlContent()\"></div>\n }\n </div>\n } @else if (isTextFile()) {\n <div class=\"relative h-[75vh] w-[85vw]\">\n @if (isLoading() || isConverting()) {\n <z-skeleton class=\"absolute inset-0 rounded-lg\" />\n <div class=\"text-muted-foreground absolute inset-0 flex items-center justify-center text-sm font-medium\">\n {{ 'i18n_z_ui_gallery_loading_preview' | translate }}\n </div>\n }\n @if (conversionError()) {\n <div class=\"bg-card flex size-full flex-col items-center justify-center rounded-lg p-12 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-24 items-center justify-center rounded-xl\">\n <i z-icon [zType]=\"fileIcon()\" zSize=\"40\" class=\"text-muted-foreground\"></i>\n </div>\n <span class=\"text-foreground mb-2 text-lg font-medium\">{{ file().name }}</span>\n <span class=\"text-muted-foreground rounded-md bg-red-100 px-3 py-1.5 text-xs dark:bg-red-900/30\">\n <span class=\"text-red-700 dark:text-red-300\">{{ conversionError() }}</span>\n </span>\n </div>\n } @else if (textContent()) {\n <div class=\"absolute inset-0 overflow-auto rounded-lg bg-gray-950 p-6 shadow-2xl\">\n <pre class=\"font-mono text-sm leading-relaxed whitespace-pre-wrap text-gray-100\">{{ textContent() }}</pre>\n </div>\n }\n </div>\n } @else {\n <div class=\"bg-card flex flex-col items-center justify-center rounded-lg p-12 shadow-2xl\">\n <div class=\"bg-muted mb-4 flex size-24 items-center justify-center rounded-xl\">\n <i z-icon [zType]=\"fileIcon()\" zSize=\"40\" class=\"text-muted-foreground\"></i>\n </div>\n <span class=\"text-foreground mb-2 text-lg font-medium\">{{ file().name }}</span>\n <span class=\"text-muted-foreground mb-4 text-sm\">{{ formattedSize() }}</span>\n <span class=\"text-muted-foreground rounded-md bg-amber-100 px-3 py-1.5 text-xs dark:bg-amber-900/30\">\n <i\n z-icon\n zType=\"lucideInfo\"\n zSize=\"14\"\n class=\"mr-1 inline-block align-middle text-amber-600 dark:text-amber-400\"></i>\n <span class=\"align-middle text-amber-700 dark:text-amber-300\">\n {{ 'i18n_z_ui_gallery_preview_not_supported' | translate }}\n </span>\n </span>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".z-gallery-pdf-frame,.z-gallery-pdf-frame *{border-color:#606060!important;outline-color:#606060!important}.z-gallery-pdf-frame{border-width:1px!important;border-style:solid!important;background:#606060}.z-gallery-pdf-frame ng2-pdfjs-viewer,.z-gallery-pdf-frame ng2-pdfjs-viewer iframe{display:block;width:100%;height:100%;border:0!important;outline:0!important;box-shadow:none!important;background:#606060}\n"] }]
|
|
1435
|
+
}], ctorParameters: () => [], propDecorators: { file: [{ type: i0.Input, args: [{ isSignal: true, alias: "file", required: true }] }], files: [{ type: i0.Input, args: [{ isSignal: true, alias: "files", required: false }] }], zShowRemove: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowRemove", required: false }] }], zPdfViewerConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPdfViewerConfig", required: false }] }], zTrustedResourceOrigins: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTrustedResourceOrigins", required: false }] }], zOnClose: [{ type: i0.Output, args: ["zOnClose"] }], zOnDownload: [{ type: i0.Output, args: ["zOnDownload"] }], zOnNavigate: [{ type: i0.Output, args: ["zOnNavigate"] }], zOnRemove: [{ type: i0.Output, args: ["zOnRemove"] }], pdfViewer: [{ type: i0.ViewChild, args: ['pdfViewer', { isSignal: true }] }] } });
|
|
1436
|
+
|
|
1437
|
+
class ZGalleryPreviewRef {
|
|
1438
|
+
_overlayRef;
|
|
1439
|
+
_closed = false;
|
|
1440
|
+
componentInstance = null;
|
|
1441
|
+
zAfterClose = new EventEmitter();
|
|
1442
|
+
constructor(_overlayRef) {
|
|
1443
|
+
this._overlayRef = _overlayRef;
|
|
1444
|
+
}
|
|
1445
|
+
close() {
|
|
1446
|
+
if (this._closed) {
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
this._closed = true;
|
|
1450
|
+
this.zAfterClose.emit();
|
|
1451
|
+
this.zAfterClose.complete();
|
|
1452
|
+
this._overlayRef?.dispose();
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
class ZGalleryPreviewService {
|
|
1457
|
+
_document = inject(DOCUMENT);
|
|
1458
|
+
_injector = inject(Injector);
|
|
1459
|
+
_overlay = inject(Overlay);
|
|
1460
|
+
_platformId = inject(PLATFORM_ID);
|
|
1461
|
+
_zIndexService = inject(ZOverlayZIndexService);
|
|
1462
|
+
open(fileOrOptions, options = {}) {
|
|
1463
|
+
const previewOptions = this._normalizeOptions(fileOrOptions, options);
|
|
1464
|
+
const overlayRef = this._createOverlay();
|
|
1465
|
+
const previewRef = new ZGalleryPreviewRef(overlayRef ?? null);
|
|
1466
|
+
if (!overlayRef) {
|
|
1467
|
+
return previewRef;
|
|
1468
|
+
}
|
|
1469
|
+
const componentRef = overlayRef.attach(new ComponentPortal(ZGalleryPreviewComponent, null, this._injector));
|
|
1470
|
+
previewRef.componentInstance = componentRef.instance;
|
|
1471
|
+
componentRef.setInput('file', previewOptions.file);
|
|
1472
|
+
componentRef.setInput('files', previewOptions.files);
|
|
1473
|
+
componentRef.setInput('zShowRemove', previewOptions.zShowRemove ?? false);
|
|
1474
|
+
componentRef.setInput('zPdfViewerConfig', previewOptions.zPdfViewerConfig ?? {});
|
|
1475
|
+
componentRef.setInput('zTrustedResourceOrigins', previewOptions.zTrustedResourceOrigins ?? []);
|
|
1476
|
+
componentRef.instance.zOnClose.subscribe(() => {
|
|
1477
|
+
previewOptions.zOnClose?.();
|
|
1478
|
+
previewRef.close();
|
|
1479
|
+
});
|
|
1480
|
+
componentRef.instance.zOnDownload.subscribe(file => this._handleDownload(file, previewOptions));
|
|
1481
|
+
componentRef.instance.zOnNavigate.subscribe(file => {
|
|
1482
|
+
componentRef.setInput('file', file);
|
|
1483
|
+
previewOptions.zOnNavigate?.(file);
|
|
1484
|
+
});
|
|
1485
|
+
componentRef.instance.zOnRemove.subscribe(file => previewOptions.zOnRemove?.(file));
|
|
1486
|
+
return previewRef;
|
|
1487
|
+
}
|
|
1488
|
+
_createOverlay() {
|
|
1489
|
+
if (!isPlatformBrowser(this._platformId)) {
|
|
1490
|
+
return undefined;
|
|
1491
|
+
}
|
|
1492
|
+
const overlayRef = this._overlay.create(new OverlayConfig({
|
|
1493
|
+
hasBackdrop: false,
|
|
1494
|
+
panelClass: 'z-gallery-preview-overlay-pane',
|
|
1495
|
+
positionStrategy: this._overlay.position().global(),
|
|
1496
|
+
scrollStrategy: this._overlay.scrollStrategies.block(),
|
|
1497
|
+
}));
|
|
1498
|
+
this._zIndexService.applyToOverlay(overlayRef);
|
|
1499
|
+
this._zIndexService.deferMoveToTop(overlayRef);
|
|
1500
|
+
return overlayRef;
|
|
1501
|
+
}
|
|
1502
|
+
_normalizeOptions(fileOrOptions, options) {
|
|
1503
|
+
const previewOptions = 'file' in fileOrOptions ? fileOrOptions : { ...options, file: fileOrOptions };
|
|
1504
|
+
const files = previewOptions.files?.length ? previewOptions.files : [previewOptions.file];
|
|
1505
|
+
const hasCurrentFile = files.some(file => file.id === previewOptions.file.id);
|
|
1506
|
+
return {
|
|
1507
|
+
...previewOptions,
|
|
1508
|
+
files: hasCurrentFile ? files : [previewOptions.file, ...files],
|
|
1509
|
+
};
|
|
1510
|
+
}
|
|
1511
|
+
_handleDownload(file, options) {
|
|
1512
|
+
options.zOnDownload?.(file);
|
|
1513
|
+
if (options.zDownload === false) {
|
|
1514
|
+
return;
|
|
1515
|
+
}
|
|
1516
|
+
const downloadLink = file.downloadUrl || file.url;
|
|
1517
|
+
if (!downloadLink || !isPlatformBrowser(this._platformId)) {
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
const link = this._document.createElement('a');
|
|
1521
|
+
link.href = downloadLink;
|
|
1522
|
+
link.download = file.name;
|
|
1523
|
+
link.target = '_blank';
|
|
1524
|
+
this._document.body.appendChild(link);
|
|
1525
|
+
link.click();
|
|
1526
|
+
this._document.body.removeChild(link);
|
|
1527
|
+
}
|
|
1528
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryPreviewService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1529
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryPreviewService, providedIn: 'root' });
|
|
1530
|
+
}
|
|
1531
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryPreviewService, decorators: [{
|
|
1532
|
+
type: Injectable,
|
|
1533
|
+
args: [{
|
|
1534
|
+
providedIn: 'root',
|
|
1535
|
+
}]
|
|
1536
|
+
}] });
|
|
1537
|
+
|
|
1538
|
+
const zGalleryVariants = cva('z-gallery', {
|
|
1539
|
+
variants: {
|
|
1540
|
+
zSize: {
|
|
1541
|
+
sm: 'z-gallery--sm',
|
|
1542
|
+
default: 'z-gallery--default',
|
|
1543
|
+
lg: 'z-gallery--lg',
|
|
1544
|
+
},
|
|
1545
|
+
},
|
|
1546
|
+
defaultVariants: {
|
|
1547
|
+
zSize: 'default',
|
|
1548
|
+
},
|
|
1549
|
+
});
|
|
1550
|
+
// Grid item variants
|
|
1551
|
+
const zGalleryItemVariants = cva('group relative overflow-hidden rounded-lg border border-border bg-card transition-all duration-200 cursor-pointer', {
|
|
1552
|
+
variants: {
|
|
1553
|
+
zMode: {
|
|
1554
|
+
grid: 'flex flex-col hover:scale-[1.02] hover:shadow-md hover:border-primary/50',
|
|
1555
|
+
list: 'flex flex-row items-center gap-3 p-3 hover:bg-accent hover:border-primary/50',
|
|
1556
|
+
},
|
|
1557
|
+
zSize: {
|
|
1558
|
+
sm: '',
|
|
1559
|
+
default: '',
|
|
1560
|
+
lg: '',
|
|
1561
|
+
},
|
|
1562
|
+
},
|
|
1563
|
+
compoundVariants: [
|
|
1564
|
+
// Grid sizes
|
|
1565
|
+
{ zMode: 'grid', zSize: 'sm', class: '' },
|
|
1566
|
+
{ zMode: 'grid', zSize: 'default', class: '' },
|
|
1567
|
+
{ zMode: 'grid', zSize: 'lg', class: '' },
|
|
1568
|
+
// List sizes
|
|
1569
|
+
{ zMode: 'list', zSize: 'sm', class: 'p-2' },
|
|
1570
|
+
{ zMode: 'list', zSize: 'default', class: 'p-3' },
|
|
1571
|
+
{ zMode: 'list', zSize: 'lg', class: 'p-4' },
|
|
1572
|
+
],
|
|
1573
|
+
defaultVariants: {
|
|
1574
|
+
zMode: 'grid',
|
|
1575
|
+
zSize: 'default',
|
|
1576
|
+
},
|
|
1577
|
+
});
|
|
1578
|
+
// File icon badge variants
|
|
1579
|
+
const zGalleryFileIconVariants = cva('flex items-center justify-center rounded-md font-bold uppercase select-none', {
|
|
1580
|
+
variants: {
|
|
1581
|
+
zSize: {
|
|
1582
|
+
sm: 'w-full h-16 text-xs',
|
|
1583
|
+
default: 'w-full h-24 text-sm',
|
|
1584
|
+
lg: 'w-full h-32 text-base',
|
|
1585
|
+
},
|
|
1586
|
+
zMode: {
|
|
1587
|
+
grid: '',
|
|
1588
|
+
list: '',
|
|
1589
|
+
},
|
|
1590
|
+
},
|
|
1591
|
+
compoundVariants: [
|
|
1592
|
+
{ zMode: 'list', zSize: 'sm', class: 'size-8 text-[0.625rem]' },
|
|
1593
|
+
{ zMode: 'list', zSize: 'default', class: 'size-10 text-xs' },
|
|
1594
|
+
{ zMode: 'list', zSize: 'lg', class: 'size-12 text-sm' },
|
|
1595
|
+
],
|
|
1596
|
+
defaultVariants: {
|
|
1597
|
+
zSize: 'default',
|
|
1598
|
+
zMode: 'grid',
|
|
1599
|
+
},
|
|
1600
|
+
});
|
|
1601
|
+
|
|
1602
|
+
class ZGalleryComponent {
|
|
1603
|
+
_destroyRef = inject(DestroyRef);
|
|
1604
|
+
_previewService = inject(ZGalleryPreviewService);
|
|
1605
|
+
_previewRef = null;
|
|
1606
|
+
zFiles = input([], ...(ngDevMode ? [{ debugName: "zFiles" }] : []));
|
|
1607
|
+
zMode = model('grid', ...(ngDevMode ? [{ debugName: "zMode" }] : []));
|
|
1608
|
+
zSize = input('default', ...(ngDevMode ? [{ debugName: "zSize" }] : []));
|
|
1609
|
+
zColumns = input(4, ...(ngDevMode ? [{ debugName: "zColumns" }] : []));
|
|
1610
|
+
zItemWidth = input(null, ...(ngDevMode ? [{ debugName: "zItemWidth" }] : []));
|
|
1611
|
+
zLoading = input(false, ...(ngDevMode ? [{ debugName: "zLoading" }] : []));
|
|
1612
|
+
zSkeletonRows = input(2, ...(ngDevMode ? [{ debugName: "zSkeletonRows" }] : []));
|
|
1613
|
+
zSkeletonItems = input(null, ...(ngDevMode ? [{ debugName: "zSkeletonItems" }] : []));
|
|
1614
|
+
zShowDownload = input(true, ...(ngDevMode ? [{ debugName: "zShowDownload" }] : []));
|
|
1615
|
+
zShowPreview = input(true, ...(ngDevMode ? [{ debugName: "zShowPreview" }] : []));
|
|
1616
|
+
zShowRemove = input(false, ...(ngDevMode ? [{ debugName: "zShowRemove" }] : []));
|
|
1617
|
+
zPdfViewerConfig = input({}, ...(ngDevMode ? [{ debugName: "zPdfViewerConfig" }] : []));
|
|
1618
|
+
zTrustedResourceOrigins = input([], ...(ngDevMode ? [{ debugName: "zTrustedResourceOrigins" }] : []));
|
|
1619
|
+
zShowModeToggle = input(true, ...(ngDevMode ? [{ debugName: "zShowModeToggle" }] : []));
|
|
1620
|
+
zShowSearch = input(false, ...(ngDevMode ? [{ debugName: "zShowSearch" }] : []));
|
|
1621
|
+
zServerSearch = input(false, ...(ngDevMode ? [{ debugName: "zServerSearch" }] : []));
|
|
1622
|
+
zSearchDebounce = input(300, ...(ngDevMode ? [{ debugName: "zSearchDebounce" }] : []));
|
|
1623
|
+
zSearchPlaceholder = input('Search files...', ...(ngDevMode ? [{ debugName: "zSearchPlaceholder" }] : []));
|
|
1624
|
+
zToggleSize = input('default', ...(ngDevMode ? [{ debugName: "zToggleSize" }] : []));
|
|
1625
|
+
zTitle = input('', ...(ngDevMode ? [{ debugName: "zTitle" }] : []));
|
|
1626
|
+
zEmptyText = input('No files', ...(ngDevMode ? [{ debugName: "zEmptyText" }] : []));
|
|
1627
|
+
zEmptyIcon = input('lucideImage', ...(ngDevMode ? [{ debugName: "zEmptyIcon" }] : []));
|
|
1628
|
+
zClass = input('', ...(ngDevMode ? [{ debugName: "zClass" }] : []));
|
|
1629
|
+
zSelectable = input(false, ...(ngDevMode ? [{ debugName: "zSelectable" }] : []));
|
|
1630
|
+
zSelectedFiles = model([], ...(ngDevMode ? [{ debugName: "zSelectedFiles" }] : []));
|
|
1631
|
+
zOnDownload = output();
|
|
1632
|
+
zOnPreview = output();
|
|
1633
|
+
zOnRemove = output();
|
|
1634
|
+
zModeChange = output();
|
|
1635
|
+
zSearchChange = output();
|
|
1636
|
+
zControl = output();
|
|
1637
|
+
zSelectionChange = output();
|
|
1638
|
+
zOnAction = output();
|
|
1639
|
+
modeIndex = signal(0, ...(ngDevMode ? [{ debugName: "modeIndex" }] : []));
|
|
1640
|
+
searchInputQuery = signal('', ...(ngDevMode ? [{ debugName: "searchInputQuery" }] : []));
|
|
1641
|
+
searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
|
|
1642
|
+
skeletonItems = computed(() => {
|
|
1643
|
+
const itemCount = this.zSkeletonItems();
|
|
1644
|
+
if (itemCount !== null) {
|
|
1645
|
+
return Array.from({ length: Math.max(1, itemCount) }, (_, index) => index);
|
|
1646
|
+
}
|
|
1647
|
+
const columns = this.currentMode() === 'list' ? 1 : Math.max(1, this.zColumns());
|
|
1648
|
+
const rows = Math.max(1, this.zSkeletonRows());
|
|
1649
|
+
return Array.from({ length: columns * rows }, (_, index) => index);
|
|
1650
|
+
}, ...(ngDevMode ? [{ debugName: "skeletonItems" }] : []));
|
|
1651
|
+
currentMode = computed(() => {
|
|
1652
|
+
const index = this.modeIndex();
|
|
1653
|
+
return index === 1 ? 'list' : 'grid';
|
|
1654
|
+
}, ...(ngDevMode ? [{ debugName: "currentMode" }] : []));
|
|
1655
|
+
gridColumnsClass = computed(() => {
|
|
1656
|
+
if (this.zItemWidth()) {
|
|
1657
|
+
return 'justify-start';
|
|
1658
|
+
}
|
|
1659
|
+
const cols = this.zColumns();
|
|
1660
|
+
switch (cols) {
|
|
1661
|
+
case 1:
|
|
1662
|
+
return 'grid-cols-1';
|
|
1663
|
+
case 2:
|
|
1664
|
+
return 'grid-cols-1 sm:grid-cols-2';
|
|
1665
|
+
case 3:
|
|
1666
|
+
return 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3';
|
|
1667
|
+
case 4:
|
|
1668
|
+
return 'grid-cols-2 sm:grid-cols-3 lg:grid-cols-4';
|
|
1669
|
+
case 5:
|
|
1670
|
+
return 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5';
|
|
1671
|
+
case 6:
|
|
1672
|
+
return 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6';
|
|
1673
|
+
default:
|
|
1674
|
+
return `grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-${cols}`;
|
|
1675
|
+
}
|
|
1676
|
+
}, ...(ngDevMode ? [{ debugName: "gridColumnsClass" }] : []));
|
|
1677
|
+
gridTemplateColumns = computed(() => {
|
|
1678
|
+
const itemWidth = this.zItemWidth();
|
|
1679
|
+
return itemWidth ? `repeat(auto-fill, minmax(${itemWidth}, ${itemWidth}))` : null;
|
|
1680
|
+
}, ...(ngDevMode ? [{ debugName: "gridTemplateColumns" }] : []));
|
|
1681
|
+
containerClasses = computed(() => zMergeClasses(zGalleryVariants({ zSize: this.zSize() }), this.zClass()), ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
1682
|
+
showHeader = computed(() => this.zTitle() || this.zShowSearch() || (this.zShowModeToggle() && (this.zFiles().length > 0 || this.zLoading())), ...(ngDevMode ? [{ debugName: "showHeader" }] : []));
|
|
1683
|
+
headerControlHeight = computed(() => {
|
|
1684
|
+
switch (this.zToggleSize()) {
|
|
1685
|
+
case 'xs':
|
|
1686
|
+
return '1.75rem';
|
|
1687
|
+
case 'sm':
|
|
1688
|
+
return '2rem';
|
|
1689
|
+
case 'lg':
|
|
1690
|
+
return '2.5rem';
|
|
1691
|
+
default:
|
|
1692
|
+
return '2.25rem';
|
|
1693
|
+
}
|
|
1694
|
+
}, ...(ngDevMode ? [{ debugName: "headerControlHeight" }] : []));
|
|
1695
|
+
skeletonMediaHeight = computed(() => {
|
|
1696
|
+
switch (this.zSize()) {
|
|
1697
|
+
case 'sm':
|
|
1698
|
+
return '9rem';
|
|
1699
|
+
case 'lg':
|
|
1700
|
+
return '14rem';
|
|
1701
|
+
default:
|
|
1702
|
+
return '11rem';
|
|
1703
|
+
}
|
|
1704
|
+
}, ...(ngDevMode ? [{ debugName: "skeletonMediaHeight" }] : []));
|
|
1705
|
+
toggleIconSize = computed(() => {
|
|
1706
|
+
const size = this.zToggleSize();
|
|
1707
|
+
switch (size) {
|
|
1708
|
+
case 'xs':
|
|
1709
|
+
return '14';
|
|
1710
|
+
case 'sm':
|
|
1711
|
+
return '16';
|
|
1712
|
+
case 'lg':
|
|
1713
|
+
return '20';
|
|
1714
|
+
default:
|
|
1715
|
+
return '18';
|
|
1716
|
+
}
|
|
1717
|
+
}, ...(ngDevMode ? [{ debugName: "toggleIconSize" }] : []));
|
|
1718
|
+
searchInputSize = computed(() => {
|
|
1719
|
+
const size = this.zToggleSize();
|
|
1720
|
+
if (size === 'xs') {
|
|
1721
|
+
return 'sm';
|
|
1722
|
+
}
|
|
1723
|
+
return size;
|
|
1724
|
+
}, ...(ngDevMode ? [{ debugName: "searchInputSize" }] : []));
|
|
1725
|
+
filteredFiles = computed(() => {
|
|
1726
|
+
const files = this.zFiles();
|
|
1727
|
+
const query = this.searchQuery().toLowerCase().trim();
|
|
1728
|
+
if (!query || this.zServerSearch()) {
|
|
1729
|
+
return files;
|
|
1730
|
+
}
|
|
1731
|
+
return files.filter(file => file.name.toLowerCase().includes(query));
|
|
1732
|
+
}, ...(ngDevMode ? [{ debugName: "filteredFiles" }] : []));
|
|
1733
|
+
selectedIds = computed(() => new Set(this.zSelectedFiles().map(f => f.id)), ...(ngDevMode ? [{ debugName: "selectedIds" }] : []));
|
|
1734
|
+
isAllSelected = computed(() => {
|
|
1735
|
+
const files = this.filteredFiles();
|
|
1736
|
+
const selectedIds = this.selectedIds();
|
|
1737
|
+
return files.length > 0 && files.every(f => selectedIds.has(f.id));
|
|
1738
|
+
}, ...(ngDevMode ? [{ debugName: "isAllSelected" }] : []));
|
|
1739
|
+
isIndeterminate = computed(() => {
|
|
1740
|
+
const files = this.filteredFiles();
|
|
1741
|
+
const selectedIds = this.selectedIds();
|
|
1742
|
+
const selectedCount = files.filter(f => selectedIds.has(f.id)).length;
|
|
1743
|
+
return selectedCount > 0 && selectedCount < files.length;
|
|
1744
|
+
}, ...(ngDevMode ? [{ debugName: "isIndeterminate" }] : []));
|
|
1745
|
+
selectedCount = computed(() => this.zSelectedFiles().length, ...(ngDevMode ? [{ debugName: "selectedCount" }] : []));
|
|
1746
|
+
ngAfterViewInit() {
|
|
1747
|
+
this._destroyRef.onDestroy(() => this.closePreview());
|
|
1748
|
+
this.zControl.emit({
|
|
1749
|
+
setMode: mode => {
|
|
1750
|
+
this.modeIndex.set(mode === 'list' ? 1 : 0);
|
|
1751
|
+
this.zMode.set(mode);
|
|
1752
|
+
this.zModeChange.emit(mode);
|
|
1753
|
+
},
|
|
1754
|
+
getMode: () => this.currentMode(),
|
|
1755
|
+
getFiles: () => this.zFiles(),
|
|
1756
|
+
openPreview: file => this._openPreview(file),
|
|
1757
|
+
closePreview: () => this.closePreview(),
|
|
1758
|
+
selectAll: () => this.selectAll(),
|
|
1759
|
+
deselectAll: () => this.deselectAll(),
|
|
1760
|
+
toggleSelection: file => this.toggleSelection(file),
|
|
1761
|
+
getSelectedFiles: () => this.zSelectedFiles(),
|
|
1762
|
+
isSelected: file => this.isFileSelected(file),
|
|
1763
|
+
});
|
|
1764
|
+
}
|
|
1765
|
+
onSearchChange(query) {
|
|
1766
|
+
const normalizedQuery = String(query ?? '');
|
|
1767
|
+
this.searchQuery.set(normalizedQuery);
|
|
1768
|
+
this.zSearchChange.emit(normalizedQuery);
|
|
1769
|
+
}
|
|
1770
|
+
onDownload(file) {
|
|
1771
|
+
this.zOnDownload.emit(file);
|
|
1772
|
+
const downloadLink = file.downloadUrl || file.url;
|
|
1773
|
+
if (downloadLink) {
|
|
1774
|
+
const link = document.createElement('a');
|
|
1775
|
+
link.href = downloadLink;
|
|
1776
|
+
link.download = file.name;
|
|
1777
|
+
link.target = '_blank';
|
|
1778
|
+
document.body.appendChild(link);
|
|
1779
|
+
link.click();
|
|
1780
|
+
document.body.removeChild(link);
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
onPreview(file) {
|
|
1784
|
+
this._openPreview(file, true);
|
|
1785
|
+
}
|
|
1786
|
+
onRemove(file) {
|
|
1787
|
+
this.zOnRemove.emit(file);
|
|
1788
|
+
}
|
|
1789
|
+
closePreview() {
|
|
1790
|
+
this._previewRef?.close();
|
|
1791
|
+
this._previewRef = null;
|
|
1792
|
+
}
|
|
1793
|
+
onRemoveFromPreview(file) {
|
|
1794
|
+
this.zOnRemove.emit(file);
|
|
1795
|
+
const allFiles = this.filteredFiles();
|
|
1796
|
+
const currentIndex = allFiles.findIndex(f => f.id === file.id);
|
|
1797
|
+
if (allFiles.length <= 1) {
|
|
1798
|
+
this.closePreview();
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1801
|
+
const nextFile = currentIndex < allFiles.length - 1 ? allFiles[currentIndex + 1] : allFiles[currentIndex - 1];
|
|
1802
|
+
this._openPreview(nextFile);
|
|
1803
|
+
}
|
|
1804
|
+
_openPreview(file, emitPreview = false) {
|
|
1805
|
+
this.closePreview();
|
|
1806
|
+
if (emitPreview) {
|
|
1807
|
+
this.zOnPreview.emit(file);
|
|
1808
|
+
}
|
|
1809
|
+
const previewRef = this._previewService.open({
|
|
1810
|
+
file,
|
|
1811
|
+
files: this.filteredFiles(),
|
|
1812
|
+
zShowRemove: this.zShowRemove(),
|
|
1813
|
+
zPdfViewerConfig: this.zPdfViewerConfig(),
|
|
1814
|
+
zTrustedResourceOrigins: this.zTrustedResourceOrigins(),
|
|
1815
|
+
zDownload: false,
|
|
1816
|
+
zOnClose: () => {
|
|
1817
|
+
this._previewRef = null;
|
|
1818
|
+
},
|
|
1819
|
+
zOnDownload: previewFile => this.onDownload(previewFile),
|
|
1820
|
+
zOnRemove: previewFile => this.onRemoveFromPreview(previewFile),
|
|
1821
|
+
});
|
|
1822
|
+
this._previewRef = previewRef;
|
|
1823
|
+
}
|
|
1824
|
+
isFileSelected(file) {
|
|
1825
|
+
return this.selectedIds().has(file.id);
|
|
1826
|
+
}
|
|
1827
|
+
toggleSelection(file) {
|
|
1828
|
+
const currentSelected = this.zSelectedFiles();
|
|
1829
|
+
const isSelected = this.isFileSelected(file);
|
|
1830
|
+
const newSelected = isSelected ? currentSelected.filter(f => f.id !== file.id) : [...currentSelected, file];
|
|
1831
|
+
this.zOnAction.emit({ type: isSelected ? 'deselect' : 'select', file });
|
|
1832
|
+
this.zSelectedFiles.set(newSelected);
|
|
1833
|
+
this.zSelectionChange.emit({
|
|
1834
|
+
selectedFiles: newSelected,
|
|
1835
|
+
addedFiles: isSelected ? undefined : [file],
|
|
1836
|
+
removedFiles: isSelected ? [file] : undefined,
|
|
1837
|
+
});
|
|
1838
|
+
}
|
|
1839
|
+
selectAll() {
|
|
1840
|
+
const files = this.filteredFiles();
|
|
1841
|
+
this.zSelectedFiles.set([...files]);
|
|
1842
|
+
this.zOnAction.emit({ type: 'select-all', files });
|
|
1843
|
+
this.zSelectionChange.emit({
|
|
1844
|
+
selectedFiles: files,
|
|
1845
|
+
addedFiles: files,
|
|
1846
|
+
});
|
|
1847
|
+
}
|
|
1848
|
+
deselectAll() {
|
|
1849
|
+
const previousSelected = this.zSelectedFiles();
|
|
1850
|
+
this.zSelectedFiles.set([]);
|
|
1851
|
+
this.zOnAction.emit({ type: 'deselect-all', files: previousSelected });
|
|
1852
|
+
this.zSelectionChange.emit({
|
|
1853
|
+
selectedFiles: [],
|
|
1854
|
+
removedFiles: previousSelected,
|
|
1855
|
+
});
|
|
1856
|
+
}
|
|
1857
|
+
toggleSelectAll() {
|
|
1858
|
+
if (this.isAllSelected()) {
|
|
1859
|
+
this.deselectAll();
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1862
|
+
this.selectAll();
|
|
1863
|
+
}
|
|
1864
|
+
onBulkDelete() {
|
|
1865
|
+
const selectedFiles = this.zSelectedFiles();
|
|
1866
|
+
this.zOnAction.emit({ type: 'delete', files: selectedFiles });
|
|
1867
|
+
}
|
|
1868
|
+
onBulkDownload() {
|
|
1869
|
+
const selectedFiles = this.zSelectedFiles();
|
|
1870
|
+
this.zOnAction.emit({ type: 'download', files: selectedFiles });
|
|
1871
|
+
selectedFiles.forEach(file => this.onDownload(file));
|
|
1872
|
+
}
|
|
1873
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1874
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: ZGalleryComponent, isStandalone: true, selector: "z-gallery", inputs: { zFiles: { classPropertyName: "zFiles", publicName: "zFiles", isSignal: true, isRequired: false, transformFunction: null }, zMode: { classPropertyName: "zMode", publicName: "zMode", isSignal: true, isRequired: false, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zColumns: { classPropertyName: "zColumns", publicName: "zColumns", isSignal: true, isRequired: false, transformFunction: null }, zItemWidth: { classPropertyName: "zItemWidth", publicName: "zItemWidth", isSignal: true, isRequired: false, transformFunction: null }, zLoading: { classPropertyName: "zLoading", publicName: "zLoading", isSignal: true, isRequired: false, transformFunction: null }, zSkeletonRows: { classPropertyName: "zSkeletonRows", publicName: "zSkeletonRows", isSignal: true, isRequired: false, transformFunction: null }, zSkeletonItems: { classPropertyName: "zSkeletonItems", publicName: "zSkeletonItems", isSignal: true, isRequired: false, transformFunction: null }, zShowDownload: { classPropertyName: "zShowDownload", publicName: "zShowDownload", isSignal: true, isRequired: false, transformFunction: null }, zShowPreview: { classPropertyName: "zShowPreview", publicName: "zShowPreview", isSignal: true, isRequired: false, transformFunction: null }, zShowRemove: { classPropertyName: "zShowRemove", publicName: "zShowRemove", isSignal: true, isRequired: false, transformFunction: null }, zPdfViewerConfig: { classPropertyName: "zPdfViewerConfig", publicName: "zPdfViewerConfig", isSignal: true, isRequired: false, transformFunction: null }, zTrustedResourceOrigins: { classPropertyName: "zTrustedResourceOrigins", publicName: "zTrustedResourceOrigins", isSignal: true, isRequired: false, transformFunction: null }, zShowModeToggle: { classPropertyName: "zShowModeToggle", publicName: "zShowModeToggle", isSignal: true, isRequired: false, transformFunction: null }, zShowSearch: { classPropertyName: "zShowSearch", publicName: "zShowSearch", isSignal: true, isRequired: false, transformFunction: null }, zServerSearch: { classPropertyName: "zServerSearch", publicName: "zServerSearch", isSignal: true, isRequired: false, transformFunction: null }, zSearchDebounce: { classPropertyName: "zSearchDebounce", publicName: "zSearchDebounce", isSignal: true, isRequired: false, transformFunction: null }, zSearchPlaceholder: { classPropertyName: "zSearchPlaceholder", publicName: "zSearchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, zToggleSize: { classPropertyName: "zToggleSize", publicName: "zToggleSize", isSignal: true, isRequired: false, transformFunction: null }, zTitle: { classPropertyName: "zTitle", publicName: "zTitle", isSignal: true, isRequired: false, transformFunction: null }, zEmptyText: { classPropertyName: "zEmptyText", publicName: "zEmptyText", isSignal: true, isRequired: false, transformFunction: null }, zEmptyIcon: { classPropertyName: "zEmptyIcon", publicName: "zEmptyIcon", isSignal: true, isRequired: false, transformFunction: null }, zClass: { classPropertyName: "zClass", publicName: "zClass", isSignal: true, isRequired: false, transformFunction: null }, zSelectable: { classPropertyName: "zSelectable", publicName: "zSelectable", isSignal: true, isRequired: false, transformFunction: null }, zSelectedFiles: { classPropertyName: "zSelectedFiles", publicName: "zSelectedFiles", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zMode: "zModeChange", zSelectedFiles: "zSelectedFilesChange", zOnDownload: "zOnDownload", zOnPreview: "zOnPreview", zOnRemove: "zOnRemove", zModeChange: "zModeChange", zSearchChange: "zSearchChange", zControl: "zControl", zSelectionChange: "zSelectionChange", zOnAction: "zOnAction" }, host: { classAttribute: "z-gallery block" }, exportAs: ["zGallery"], ngImport: i0, template: `
|
|
1875
|
+
<div [class]="containerClasses()">
|
|
1876
|
+
@if (showHeader()) {
|
|
1877
|
+
<div class="mb-4 flex flex-wrap items-center justify-between gap-3">
|
|
1878
|
+
<div class="flex items-center gap-3">
|
|
1879
|
+
@if (zTitle()) {
|
|
1880
|
+
@if (zLoading()) {
|
|
1881
|
+
<z-skeleton zWidth="7rem" zHeight="1.25rem" />
|
|
1882
|
+
} @else {
|
|
1883
|
+
<h3 class="text-sm font-medium">{{ zTitle() }}</h3>
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
@if (zShowSearch()) {
|
|
1888
|
+
@if (zLoading()) {
|
|
1889
|
+
<z-skeleton zWidth="16rem" [zHeight]="headerControlHeight()" zRadius="0.375rem" />
|
|
1890
|
+
} @else {
|
|
1891
|
+
<z-input
|
|
1892
|
+
zSearch
|
|
1893
|
+
[zSize]="searchInputSize()"
|
|
1894
|
+
[zPlaceholder]="zSearchPlaceholder() || ('i18n_z_ui_gallery_search_placeholder' | translate)"
|
|
1895
|
+
[zDebounce]="zSearchDebounce()"
|
|
1896
|
+
[ngModel]="searchInputQuery()"
|
|
1897
|
+
(ngModelChange)="searchInputQuery.set($event)"
|
|
1898
|
+
(zOnSearch)="onSearchChange($event)"
|
|
1899
|
+
class="w-64"
|
|
1900
|
+
/>
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
</div>
|
|
1904
|
+
|
|
1905
|
+
@if (zShowModeToggle() && (zFiles().length > 0 || zLoading())) {
|
|
1906
|
+
@if (zLoading()) {
|
|
1907
|
+
<z-skeleton zWidth="5rem" [zHeight]="headerControlHeight()" zRadius="0.375rem" />
|
|
1908
|
+
} @else {
|
|
1909
|
+
<z-button-group [(zActive)]="modeIndex">
|
|
1910
|
+
<button z-button zType="outline" [zSize]="zToggleSize()" z-button-group-item>
|
|
1911
|
+
<i z-icon zType="lucideLayoutGrid" [zSize]="toggleIconSize()"></i>
|
|
1912
|
+
</button>
|
|
1913
|
+
<button z-button zType="outline" [zSize]="zToggleSize()" z-button-group-item>
|
|
1914
|
+
<i z-icon zType="lucideList" [zSize]="toggleIconSize()"></i>
|
|
1915
|
+
</button>
|
|
1916
|
+
</z-button-group>
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
</div>
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
@if (zLoading()) {
|
|
1923
|
+
@if (currentMode() === 'grid') {
|
|
1924
|
+
<div class="grid gap-4" [class]="gridColumnsClass()" [style.gridTemplateColumns]="gridTemplateColumns()">
|
|
1925
|
+
@for (item of skeletonItems(); track item) {
|
|
1926
|
+
<div class="border-border bg-card overflow-hidden rounded-md border shadow-sm">
|
|
1927
|
+
<z-skeleton [zHeight]="skeletonMediaHeight()" zRadius="0" />
|
|
1928
|
+
<div class="p-3">
|
|
1929
|
+
<z-skeleton zWidth="75%" zHeight="1.25rem" />
|
|
1930
|
+
</div>
|
|
1931
|
+
</div>
|
|
1932
|
+
}
|
|
1933
|
+
</div>
|
|
1934
|
+
} @else {
|
|
1935
|
+
<div class="flex flex-col gap-2">
|
|
1936
|
+
@for (item of skeletonItems(); track item) {
|
|
1937
|
+
<div class="border-border bg-card flex items-center gap-3 rounded-sm border px-3 py-2.5 shadow-sm">
|
|
1938
|
+
<z-skeleton class="shrink-0" zWidth="2.75rem" zHeight="2.75rem" zRadius="0.125rem" />
|
|
1939
|
+
<div class="min-w-0 flex-1 space-y-2">
|
|
1940
|
+
<z-skeleton zWidth="40%" zHeight="0.875rem" />
|
|
1941
|
+
<z-skeleton zWidth="25%" zHeight="0.75rem" />
|
|
1942
|
+
</div>
|
|
1943
|
+
<z-skeleton class="shrink-0" zWidth="3.5rem" zHeight="1.5rem" zRadius="0.125rem" />
|
|
1944
|
+
</div>
|
|
1945
|
+
}
|
|
1946
|
+
</div>
|
|
1947
|
+
}
|
|
1948
|
+
} @else if (zSelectable() && filteredFiles().length > 0) {
|
|
1949
|
+
<div
|
|
1950
|
+
class="bg-muted/30 shadow-card dark:!border-border mb-4 flex h-11 items-center justify-between gap-3 rounded-[0.375rem] border border-transparent px-3"
|
|
1951
|
+
>
|
|
1952
|
+
<div class="flex items-center gap-3">
|
|
1953
|
+
<z-checkbox
|
|
1954
|
+
[zChecked]="isAllSelected()"
|
|
1955
|
+
[zIndeterminate]="isIndeterminate()"
|
|
1956
|
+
(zChange)="toggleSelectAll()"
|
|
1957
|
+
zSize="sm"
|
|
1958
|
+
/>
|
|
1959
|
+
<span class="text-muted-foreground text-sm">
|
|
1960
|
+
@if (selectedCount() > 0) {
|
|
1961
|
+
{{ selectedCount() }} {{ 'i18n_z_ui_gallery_selected' | translate }}
|
|
1962
|
+
} @else {
|
|
1963
|
+
{{ 'i18n_z_ui_gallery_select_all' | translate }}
|
|
1964
|
+
}
|
|
1965
|
+
</span>
|
|
1966
|
+
</div>
|
|
1967
|
+
|
|
1968
|
+
@if (selectedCount() > 0) {
|
|
1969
|
+
<div class="flex items-center gap-1">
|
|
1970
|
+
@if (zShowDownload()) {
|
|
1971
|
+
<button
|
|
1972
|
+
z-button
|
|
1973
|
+
zType="ghost"
|
|
1974
|
+
zSize="xs"
|
|
1975
|
+
(click)="onBulkDownload()"
|
|
1976
|
+
class="text-muted-foreground hover:text-foreground"
|
|
1977
|
+
>
|
|
1978
|
+
<i z-icon zType="lucideDownload" zSize="14"></i>
|
|
1979
|
+
<span class="ml-1">{{ 'i18n_z_ui_gallery_download' | translate }}</span>
|
|
1980
|
+
</button>
|
|
1981
|
+
}
|
|
1982
|
+
@if (zShowRemove()) {
|
|
1983
|
+
<button
|
|
1984
|
+
z-button
|
|
1985
|
+
zType="ghost"
|
|
1986
|
+
zSize="xs"
|
|
1987
|
+
(click)="onBulkDelete()"
|
|
1988
|
+
class="text-destructive hover:text-destructive"
|
|
1989
|
+
>
|
|
1990
|
+
<i z-icon zType="lucideTrash2" zSize="14"></i>
|
|
1991
|
+
<span class="ml-1">{{ 'i18n_z_ui_gallery_delete' | translate }}</span>
|
|
1992
|
+
</button>
|
|
1993
|
+
}
|
|
1994
|
+
<button z-button zType="ghost" zSize="xs" (click)="deselectAll()">
|
|
1995
|
+
<i z-icon zType="lucideX" zSize="14"></i>
|
|
1996
|
+
</button>
|
|
1997
|
+
</div>
|
|
1998
|
+
}
|
|
1999
|
+
</div>
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
@if (!zLoading() && filteredFiles().length > 0) {
|
|
2003
|
+
@if (currentMode() === 'grid') {
|
|
2004
|
+
<div class="grid gap-4" [class]="gridColumnsClass()" [style.gridTemplateColumns]="gridTemplateColumns()">
|
|
2005
|
+
@for (file of filteredFiles(); track file.id) {
|
|
2006
|
+
<z-gallery-item
|
|
2007
|
+
[file]="file"
|
|
2008
|
+
zMode="grid"
|
|
2009
|
+
[zSize]="zSize()"
|
|
2010
|
+
[zShowDownload]="zShowDownload()"
|
|
2011
|
+
[zShowPreview]="zShowPreview()"
|
|
2012
|
+
[zShowRemove]="zShowRemove()"
|
|
2013
|
+
[zSelectable]="zSelectable()"
|
|
2014
|
+
[zSelected]="isFileSelected(file)"
|
|
2015
|
+
(zOnDownload)="onDownload($event)"
|
|
2016
|
+
(zOnPreview)="onPreview($event)"
|
|
2017
|
+
(zOnRemove)="onRemove($event)"
|
|
2018
|
+
(zOnSelect)="toggleSelection($event)"
|
|
2019
|
+
/>
|
|
2020
|
+
}
|
|
2021
|
+
</div>
|
|
2022
|
+
} @else {
|
|
2023
|
+
<div class="flex flex-col gap-2">
|
|
2024
|
+
@for (file of filteredFiles(); track file.id) {
|
|
2025
|
+
<z-gallery-item
|
|
2026
|
+
[file]="file"
|
|
2027
|
+
zMode="list"
|
|
2028
|
+
[zSize]="zSize()"
|
|
2029
|
+
[zShowDownload]="zShowDownload()"
|
|
2030
|
+
[zShowPreview]="zShowPreview()"
|
|
2031
|
+
[zShowRemove]="zShowRemove()"
|
|
2032
|
+
[zSelectable]="zSelectable()"
|
|
2033
|
+
[zSelected]="isFileSelected(file)"
|
|
2034
|
+
(zOnDownload)="onDownload($event)"
|
|
2035
|
+
(zOnPreview)="onPreview($event)"
|
|
2036
|
+
(zOnRemove)="onRemove($event)"
|
|
2037
|
+
(zOnSelect)="toggleSelection($event)"
|
|
2038
|
+
/>
|
|
2039
|
+
}
|
|
2040
|
+
</div>
|
|
2041
|
+
}
|
|
2042
|
+
} @else if (!zLoading() && zFiles().length > 0 && searchQuery()) {
|
|
2043
|
+
<z-empty zIcon="lucideSearchX" [zMessage]="'i18n_z_ui_gallery_no_search_results' | translate" zSize="sm" />
|
|
2044
|
+
} @else if (!zLoading()) {
|
|
2045
|
+
<z-empty
|
|
2046
|
+
[zIcon]="zEmptyIcon()"
|
|
2047
|
+
[zMessage]="zEmptyText() || ('i18n_z_ui_gallery_no_files' | translate)"
|
|
2048
|
+
zSize="sm"
|
|
2049
|
+
/>
|
|
2050
|
+
}
|
|
2051
|
+
</div>
|
|
2052
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ZGalleryItemComponent, selector: "z-gallery-item", inputs: ["file", "zMode", "zSize", "zShowDownload", "zShowPreview", "zShowRemove", "zSelectable", "zSelected"], outputs: ["zOnDownload", "zOnPreview", "zOnRemove", "zOnSelect"] }, { kind: "component", type: ZButtonGroupComponent, selector: "z-button-group", inputs: ["zClass", "zOrientation", "zActive"], outputs: ["zActiveChange", "zActiveIndexChange", "zActiveValueChange"], exportAs: ["zButtonGroup"] }, { kind: "directive", type: ZButtonGroupItemDirective, selector: "[z-button-group-item]", inputs: ["zValue"], exportAs: ["zButtonGroupItem"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZCheckboxComponent, selector: "z-checkbox", inputs: ["class", "zType", "zSize", "zLabel", "zText", "zDisabled", "zIndeterminate", "zValue", "zOptions", "zOrientation", "zCheckAll", "zCheckAllText", "zChecked", "zGroupValue"], outputs: ["zChange", "zGroupChange", "zOnBlur", "zOnFocus", "zControl", "zEvent", "zCheckedChange", "zGroupValueChange"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "component", type: ZEmptyComponent, selector: "z-empty", inputs: ["class", "zType", "zIcon", "zIconSize", "zSize", "zMessage", "zDescription"] }, { kind: "component", type: ZInputComponent, selector: "z-input", inputs: ["class", "zType", "zSize", "zAlign", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zLoadingOutline", "zPrefix", "zSuffix", "zMin", "zMax", "zStep", "zShowArrows", "zMask", "zDecimalPlaces", "zAllowNegative", "zThousandSeparator", "zDecimalMarker", "zValidators", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zShowPasswordToggle", "zSearch", "zDebounce", "zAutofocus", "zAutoComplete", "zAllowClear", "zAutoSizeContent", "zRows", "zResize", "zMaxLength", "zAutoSuggest", "zColorConfig"], outputs: ["zOnSearch", "zOnChange", "zOnBlur", "zOnFocus", "zOnKeydown", "zOnEnter", "zOnColorCollapse", "zControl", "zEvent"], exportAs: ["zInput"] }, { kind: "component", type: ZSkeletonComponent, selector: "z-skeleton", inputs: ["class", "zType", "zSize", "zWidth", "zHeight", "zRows", "zGap", "zAnimated", "zRadius"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2053
|
+
}
|
|
2054
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryComponent, decorators: [{
|
|
2055
|
+
type: Component,
|
|
2056
|
+
args: [{
|
|
2057
|
+
selector: 'z-gallery',
|
|
2058
|
+
imports: [
|
|
2059
|
+
FormsModule,
|
|
2060
|
+
TranslatePipe,
|
|
2061
|
+
ZGalleryItemComponent,
|
|
2062
|
+
ZButtonGroupComponent,
|
|
2063
|
+
ZButtonGroupItemDirective,
|
|
2064
|
+
ZButtonComponent,
|
|
2065
|
+
ZCheckboxComponent,
|
|
2066
|
+
ZIconComponent,
|
|
2067
|
+
ZEmptyComponent,
|
|
2068
|
+
ZInputComponent,
|
|
2069
|
+
ZSkeletonComponent,
|
|
2070
|
+
],
|
|
2071
|
+
standalone: true,
|
|
2072
|
+
template: `
|
|
2073
|
+
<div [class]="containerClasses()">
|
|
2074
|
+
@if (showHeader()) {
|
|
2075
|
+
<div class="mb-4 flex flex-wrap items-center justify-between gap-3">
|
|
2076
|
+
<div class="flex items-center gap-3">
|
|
2077
|
+
@if (zTitle()) {
|
|
2078
|
+
@if (zLoading()) {
|
|
2079
|
+
<z-skeleton zWidth="7rem" zHeight="1.25rem" />
|
|
2080
|
+
} @else {
|
|
2081
|
+
<h3 class="text-sm font-medium">{{ zTitle() }}</h3>
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
@if (zShowSearch()) {
|
|
2086
|
+
@if (zLoading()) {
|
|
2087
|
+
<z-skeleton zWidth="16rem" [zHeight]="headerControlHeight()" zRadius="0.375rem" />
|
|
2088
|
+
} @else {
|
|
2089
|
+
<z-input
|
|
2090
|
+
zSearch
|
|
2091
|
+
[zSize]="searchInputSize()"
|
|
2092
|
+
[zPlaceholder]="zSearchPlaceholder() || ('i18n_z_ui_gallery_search_placeholder' | translate)"
|
|
2093
|
+
[zDebounce]="zSearchDebounce()"
|
|
2094
|
+
[ngModel]="searchInputQuery()"
|
|
2095
|
+
(ngModelChange)="searchInputQuery.set($event)"
|
|
2096
|
+
(zOnSearch)="onSearchChange($event)"
|
|
2097
|
+
class="w-64"
|
|
2098
|
+
/>
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
</div>
|
|
2102
|
+
|
|
2103
|
+
@if (zShowModeToggle() && (zFiles().length > 0 || zLoading())) {
|
|
2104
|
+
@if (zLoading()) {
|
|
2105
|
+
<z-skeleton zWidth="5rem" [zHeight]="headerControlHeight()" zRadius="0.375rem" />
|
|
2106
|
+
} @else {
|
|
2107
|
+
<z-button-group [(zActive)]="modeIndex">
|
|
2108
|
+
<button z-button zType="outline" [zSize]="zToggleSize()" z-button-group-item>
|
|
2109
|
+
<i z-icon zType="lucideLayoutGrid" [zSize]="toggleIconSize()"></i>
|
|
2110
|
+
</button>
|
|
2111
|
+
<button z-button zType="outline" [zSize]="zToggleSize()" z-button-group-item>
|
|
2112
|
+
<i z-icon zType="lucideList" [zSize]="toggleIconSize()"></i>
|
|
2113
|
+
</button>
|
|
2114
|
+
</z-button-group>
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
</div>
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
@if (zLoading()) {
|
|
2121
|
+
@if (currentMode() === 'grid') {
|
|
2122
|
+
<div class="grid gap-4" [class]="gridColumnsClass()" [style.gridTemplateColumns]="gridTemplateColumns()">
|
|
2123
|
+
@for (item of skeletonItems(); track item) {
|
|
2124
|
+
<div class="border-border bg-card overflow-hidden rounded-md border shadow-sm">
|
|
2125
|
+
<z-skeleton [zHeight]="skeletonMediaHeight()" zRadius="0" />
|
|
2126
|
+
<div class="p-3">
|
|
2127
|
+
<z-skeleton zWidth="75%" zHeight="1.25rem" />
|
|
2128
|
+
</div>
|
|
2129
|
+
</div>
|
|
2130
|
+
}
|
|
2131
|
+
</div>
|
|
2132
|
+
} @else {
|
|
2133
|
+
<div class="flex flex-col gap-2">
|
|
2134
|
+
@for (item of skeletonItems(); track item) {
|
|
2135
|
+
<div class="border-border bg-card flex items-center gap-3 rounded-sm border px-3 py-2.5 shadow-sm">
|
|
2136
|
+
<z-skeleton class="shrink-0" zWidth="2.75rem" zHeight="2.75rem" zRadius="0.125rem" />
|
|
2137
|
+
<div class="min-w-0 flex-1 space-y-2">
|
|
2138
|
+
<z-skeleton zWidth="40%" zHeight="0.875rem" />
|
|
2139
|
+
<z-skeleton zWidth="25%" zHeight="0.75rem" />
|
|
2140
|
+
</div>
|
|
2141
|
+
<z-skeleton class="shrink-0" zWidth="3.5rem" zHeight="1.5rem" zRadius="0.125rem" />
|
|
2142
|
+
</div>
|
|
2143
|
+
}
|
|
2144
|
+
</div>
|
|
2145
|
+
}
|
|
2146
|
+
} @else if (zSelectable() && filteredFiles().length > 0) {
|
|
2147
|
+
<div
|
|
2148
|
+
class="bg-muted/30 shadow-card dark:!border-border mb-4 flex h-11 items-center justify-between gap-3 rounded-[0.375rem] border border-transparent px-3"
|
|
2149
|
+
>
|
|
2150
|
+
<div class="flex items-center gap-3">
|
|
2151
|
+
<z-checkbox
|
|
2152
|
+
[zChecked]="isAllSelected()"
|
|
2153
|
+
[zIndeterminate]="isIndeterminate()"
|
|
2154
|
+
(zChange)="toggleSelectAll()"
|
|
2155
|
+
zSize="sm"
|
|
2156
|
+
/>
|
|
2157
|
+
<span class="text-muted-foreground text-sm">
|
|
2158
|
+
@if (selectedCount() > 0) {
|
|
2159
|
+
{{ selectedCount() }} {{ 'i18n_z_ui_gallery_selected' | translate }}
|
|
2160
|
+
} @else {
|
|
2161
|
+
{{ 'i18n_z_ui_gallery_select_all' | translate }}
|
|
2162
|
+
}
|
|
2163
|
+
</span>
|
|
2164
|
+
</div>
|
|
2165
|
+
|
|
2166
|
+
@if (selectedCount() > 0) {
|
|
2167
|
+
<div class="flex items-center gap-1">
|
|
2168
|
+
@if (zShowDownload()) {
|
|
2169
|
+
<button
|
|
2170
|
+
z-button
|
|
2171
|
+
zType="ghost"
|
|
2172
|
+
zSize="xs"
|
|
2173
|
+
(click)="onBulkDownload()"
|
|
2174
|
+
class="text-muted-foreground hover:text-foreground"
|
|
2175
|
+
>
|
|
2176
|
+
<i z-icon zType="lucideDownload" zSize="14"></i>
|
|
2177
|
+
<span class="ml-1">{{ 'i18n_z_ui_gallery_download' | translate }}</span>
|
|
2178
|
+
</button>
|
|
2179
|
+
}
|
|
2180
|
+
@if (zShowRemove()) {
|
|
2181
|
+
<button
|
|
2182
|
+
z-button
|
|
2183
|
+
zType="ghost"
|
|
2184
|
+
zSize="xs"
|
|
2185
|
+
(click)="onBulkDelete()"
|
|
2186
|
+
class="text-destructive hover:text-destructive"
|
|
2187
|
+
>
|
|
2188
|
+
<i z-icon zType="lucideTrash2" zSize="14"></i>
|
|
2189
|
+
<span class="ml-1">{{ 'i18n_z_ui_gallery_delete' | translate }}</span>
|
|
2190
|
+
</button>
|
|
2191
|
+
}
|
|
2192
|
+
<button z-button zType="ghost" zSize="xs" (click)="deselectAll()">
|
|
2193
|
+
<i z-icon zType="lucideX" zSize="14"></i>
|
|
2194
|
+
</button>
|
|
2195
|
+
</div>
|
|
2196
|
+
}
|
|
2197
|
+
</div>
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
@if (!zLoading() && filteredFiles().length > 0) {
|
|
2201
|
+
@if (currentMode() === 'grid') {
|
|
2202
|
+
<div class="grid gap-4" [class]="gridColumnsClass()" [style.gridTemplateColumns]="gridTemplateColumns()">
|
|
2203
|
+
@for (file of filteredFiles(); track file.id) {
|
|
2204
|
+
<z-gallery-item
|
|
2205
|
+
[file]="file"
|
|
2206
|
+
zMode="grid"
|
|
2207
|
+
[zSize]="zSize()"
|
|
2208
|
+
[zShowDownload]="zShowDownload()"
|
|
2209
|
+
[zShowPreview]="zShowPreview()"
|
|
2210
|
+
[zShowRemove]="zShowRemove()"
|
|
2211
|
+
[zSelectable]="zSelectable()"
|
|
2212
|
+
[zSelected]="isFileSelected(file)"
|
|
2213
|
+
(zOnDownload)="onDownload($event)"
|
|
2214
|
+
(zOnPreview)="onPreview($event)"
|
|
2215
|
+
(zOnRemove)="onRemove($event)"
|
|
2216
|
+
(zOnSelect)="toggleSelection($event)"
|
|
2217
|
+
/>
|
|
2218
|
+
}
|
|
2219
|
+
</div>
|
|
2220
|
+
} @else {
|
|
2221
|
+
<div class="flex flex-col gap-2">
|
|
2222
|
+
@for (file of filteredFiles(); track file.id) {
|
|
2223
|
+
<z-gallery-item
|
|
2224
|
+
[file]="file"
|
|
2225
|
+
zMode="list"
|
|
2226
|
+
[zSize]="zSize()"
|
|
2227
|
+
[zShowDownload]="zShowDownload()"
|
|
2228
|
+
[zShowPreview]="zShowPreview()"
|
|
2229
|
+
[zShowRemove]="zShowRemove()"
|
|
2230
|
+
[zSelectable]="zSelectable()"
|
|
2231
|
+
[zSelected]="isFileSelected(file)"
|
|
2232
|
+
(zOnDownload)="onDownload($event)"
|
|
2233
|
+
(zOnPreview)="onPreview($event)"
|
|
2234
|
+
(zOnRemove)="onRemove($event)"
|
|
2235
|
+
(zOnSelect)="toggleSelection($event)"
|
|
2236
|
+
/>
|
|
2237
|
+
}
|
|
2238
|
+
</div>
|
|
2239
|
+
}
|
|
2240
|
+
} @else if (!zLoading() && zFiles().length > 0 && searchQuery()) {
|
|
2241
|
+
<z-empty zIcon="lucideSearchX" [zMessage]="'i18n_z_ui_gallery_no_search_results' | translate" zSize="sm" />
|
|
2242
|
+
} @else if (!zLoading()) {
|
|
2243
|
+
<z-empty
|
|
2244
|
+
[zIcon]="zEmptyIcon()"
|
|
2245
|
+
[zMessage]="zEmptyText() || ('i18n_z_ui_gallery_no_files' | translate)"
|
|
2246
|
+
zSize="sm"
|
|
2247
|
+
/>
|
|
2248
|
+
}
|
|
2249
|
+
</div>
|
|
2250
|
+
`,
|
|
2251
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2252
|
+
encapsulation: ViewEncapsulation.None,
|
|
2253
|
+
host: {
|
|
2254
|
+
class: 'z-gallery block',
|
|
2255
|
+
},
|
|
2256
|
+
exportAs: 'zGallery',
|
|
2257
|
+
}]
|
|
2258
|
+
}], propDecorators: { zFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "zFiles", required: false }] }], zMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMode", required: false }] }, { type: i0.Output, args: ["zModeChange"] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "zColumns", required: false }] }], zItemWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "zItemWidth", required: false }] }], zLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLoading", required: false }] }], zSkeletonRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSkeletonRows", required: false }] }], zSkeletonItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSkeletonItems", required: false }] }], zShowDownload: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowDownload", required: false }] }], zShowPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowPreview", required: false }] }], zShowRemove: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowRemove", required: false }] }], zPdfViewerConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPdfViewerConfig", required: false }] }], zTrustedResourceOrigins: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTrustedResourceOrigins", required: false }] }], zShowModeToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowModeToggle", required: false }] }], zShowSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowSearch", required: false }] }], zServerSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "zServerSearch", required: false }] }], zSearchDebounce: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSearchDebounce", required: false }] }], zSearchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSearchPlaceholder", required: false }] }], zToggleSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zToggleSize", required: false }] }], zTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTitle", required: false }] }], zEmptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "zEmptyText", required: false }] }], zEmptyIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "zEmptyIcon", required: false }] }], zClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zClass", required: false }] }], zSelectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSelectable", required: false }] }], zSelectedFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSelectedFiles", required: false }] }, { type: i0.Output, args: ["zSelectedFilesChange"] }], zOnDownload: [{ type: i0.Output, args: ["zOnDownload"] }], zOnPreview: [{ type: i0.Output, args: ["zOnPreview"] }], zOnRemove: [{ type: i0.Output, args: ["zOnRemove"] }], zModeChange: [{ type: i0.Output, args: ["zModeChange"] }], zSearchChange: [{ type: i0.Output, args: ["zSearchChange"] }], zControl: [{ type: i0.Output, args: ["zControl"] }], zSelectionChange: [{ type: i0.Output, args: ["zSelectionChange"] }], zOnAction: [{ type: i0.Output, args: ["zOnAction"] }] } });
|
|
2259
|
+
|
|
2260
|
+
class ZGalleryFileIconComponent {
|
|
2261
|
+
file = input.required(...(ngDevMode ? [{ debugName: "file" }] : []));
|
|
2262
|
+
zSize = input('default', ...(ngDevMode ? [{ debugName: "zSize" }] : []));
|
|
2263
|
+
zMode = input('grid', ...(ngDevMode ? [{ debugName: "zMode" }] : []));
|
|
2264
|
+
imageError = signal(false, ...(ngDevMode ? [{ debugName: "imageError" }] : []));
|
|
2265
|
+
isLoading = signal(true, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
2266
|
+
category = computed(() => getFileCategory(this.file()), ...(ngDevMode ? [{ debugName: "category" }] : []));
|
|
2267
|
+
style = computed(() => FILE_CATEGORY_STYLES[this.category()], ...(ngDevMode ? [{ debugName: "style" }] : []));
|
|
2268
|
+
showThumbnail = computed(() => {
|
|
2269
|
+
const file = this.file();
|
|
2270
|
+
const cat = this.category();
|
|
2271
|
+
return cat === 'image' && (file.thumbnailUrl || file.url) && !this.imageError();
|
|
2272
|
+
}, ...(ngDevMode ? [{ debugName: "showThumbnail" }] : []));
|
|
2273
|
+
containerClasses = computed(() => {
|
|
2274
|
+
const style = this.style();
|
|
2275
|
+
const showThumb = this.showThumbnail();
|
|
2276
|
+
return zMergeClasses(zGalleryFileIconVariants({
|
|
2277
|
+
zSize: this.zSize(),
|
|
2278
|
+
zMode: this.zMode(),
|
|
2279
|
+
}), showThumb ? 'bg-muted relative' : [style.bg, style.text]);
|
|
2280
|
+
}, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
2281
|
+
onImageLoad() {
|
|
2282
|
+
this.isLoading.set(false);
|
|
2283
|
+
}
|
|
2284
|
+
onImageError(event) {
|
|
2285
|
+
this.imageError.set(true);
|
|
2286
|
+
this.isLoading.set(false);
|
|
2287
|
+
const img = event.target;
|
|
2288
|
+
img.style.display = 'none';
|
|
2289
|
+
}
|
|
2290
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryFileIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2291
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: ZGalleryFileIconComponent, isStandalone: true, selector: "z-gallery-file-icon", inputs: { file: { classPropertyName: "file", publicName: "file", isSignal: true, isRequired: true, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zMode: { classPropertyName: "zMode", publicName: "zMode", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "z-gallery-file-icon block" }, ngImport: i0, template: `
|
|
2292
|
+
<div [class]="containerClasses()" class="group/icon overflow-hidden">
|
|
2293
|
+
@if (showThumbnail()) {
|
|
2294
|
+
@if (isLoading()) {
|
|
2295
|
+
<z-skeleton class="absolute inset-0 size-full" />
|
|
2296
|
+
}
|
|
2297
|
+
<img
|
|
2298
|
+
[src]="file().thumbnailUrl || file().url"
|
|
2299
|
+
[alt]="file().name"
|
|
2300
|
+
class="size-full object-cover transition-transform duration-300 group-hover/icon:scale-105"
|
|
2301
|
+
loading="lazy"
|
|
2302
|
+
[class.opacity-0]="isLoading()"
|
|
2303
|
+
[class.opacity-100]="!isLoading()"
|
|
2304
|
+
(load)="onImageLoad()"
|
|
2305
|
+
(error)="onImageError($event)"
|
|
2306
|
+
/>
|
|
2307
|
+
} @else {
|
|
2308
|
+
<div class="flex flex-col items-center justify-center gap-1">
|
|
2309
|
+
<span class="font-bold tracking-wide">{{ style().label }}</span>
|
|
2310
|
+
</div>
|
|
2311
|
+
}
|
|
2312
|
+
</div>
|
|
2313
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ZSkeletonComponent, selector: "z-skeleton", inputs: ["class", "zType", "zSize", "zWidth", "zHeight", "zRows", "zGap", "zAnimated", "zRadius"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2314
|
+
}
|
|
2315
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryFileIconComponent, decorators: [{
|
|
2316
|
+
type: Component,
|
|
2317
|
+
args: [{
|
|
2318
|
+
selector: 'z-gallery-file-icon',
|
|
2319
|
+
imports: [ZSkeletonComponent],
|
|
2320
|
+
standalone: true,
|
|
2321
|
+
template: `
|
|
2322
|
+
<div [class]="containerClasses()" class="group/icon overflow-hidden">
|
|
2323
|
+
@if (showThumbnail()) {
|
|
2324
|
+
@if (isLoading()) {
|
|
2325
|
+
<z-skeleton class="absolute inset-0 size-full" />
|
|
2326
|
+
}
|
|
2327
|
+
<img
|
|
2328
|
+
[src]="file().thumbnailUrl || file().url"
|
|
2329
|
+
[alt]="file().name"
|
|
2330
|
+
class="size-full object-cover transition-transform duration-300 group-hover/icon:scale-105"
|
|
2331
|
+
loading="lazy"
|
|
2332
|
+
[class.opacity-0]="isLoading()"
|
|
2333
|
+
[class.opacity-100]="!isLoading()"
|
|
2334
|
+
(load)="onImageLoad()"
|
|
2335
|
+
(error)="onImageError($event)"
|
|
2336
|
+
/>
|
|
2337
|
+
} @else {
|
|
2338
|
+
<div class="flex flex-col items-center justify-center gap-1">
|
|
2339
|
+
<span class="font-bold tracking-wide">{{ style().label }}</span>
|
|
2340
|
+
</div>
|
|
2341
|
+
}
|
|
2342
|
+
</div>
|
|
2343
|
+
`,
|
|
2344
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2345
|
+
encapsulation: ViewEncapsulation.None,
|
|
2346
|
+
host: {
|
|
2347
|
+
class: 'z-gallery-file-icon block',
|
|
2348
|
+
},
|
|
2349
|
+
}]
|
|
2350
|
+
}], propDecorators: { file: [{ type: i0.Input, args: [{ isSignal: true, alias: "file", required: true }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMode", required: false }] }] } });
|
|
2351
|
+
|
|
2352
|
+
class ZGalleryPreviewItemDirective {
|
|
2353
|
+
zGalleryPreviewItem = input.required(...(ngDevMode ? [{ debugName: "zGalleryPreviewItem" }] : []));
|
|
2354
|
+
zGalleryPreviewFiles = input(null, ...(ngDevMode ? [{ debugName: "zGalleryPreviewFiles" }] : []));
|
|
2355
|
+
zGalleryPreviewOptions = input({}, ...(ngDevMode ? [{ debugName: "zGalleryPreviewOptions" }] : []));
|
|
2356
|
+
zDisabled = input(false, { ...(ngDevMode ? { debugName: "zDisabled" } : {}), transform: zTransform });
|
|
2357
|
+
zOnPreview = output();
|
|
2358
|
+
_elementRef = inject((ElementRef));
|
|
2359
|
+
_previewService = inject(ZGalleryPreviewService);
|
|
2360
|
+
hostRole = computed(() => (this._isNativeInteractive() ? null : 'button'), ...(ngDevMode ? [{ debugName: "hostRole" }] : []));
|
|
2361
|
+
hostTabIndex = computed(() => {
|
|
2362
|
+
if (this._isNativeInteractive()) {
|
|
2363
|
+
return null;
|
|
2364
|
+
}
|
|
2365
|
+
return this.zDisabled() ? -1 : 0;
|
|
2366
|
+
}, ...(ngDevMode ? [{ debugName: "hostTabIndex" }] : []));
|
|
2367
|
+
hostAriaDisabled = computed(() => (this.zDisabled() ? true : null), ...(ngDevMode ? [{ debugName: "hostAriaDisabled" }] : []));
|
|
2368
|
+
openPreview(event) {
|
|
2369
|
+
if (this.zDisabled()) {
|
|
2370
|
+
return;
|
|
2371
|
+
}
|
|
2372
|
+
if (event instanceof KeyboardEvent && this._isNativeInteractive()) {
|
|
2373
|
+
return;
|
|
2374
|
+
}
|
|
2375
|
+
const file = this.zGalleryPreviewItem();
|
|
2376
|
+
if (!isPreviewable(file)) {
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
if (event instanceof KeyboardEvent) {
|
|
2380
|
+
event.preventDefault();
|
|
2381
|
+
}
|
|
2382
|
+
this.zOnPreview.emit(file);
|
|
2383
|
+
this._previewService.open({
|
|
2384
|
+
...this.zGalleryPreviewOptions(),
|
|
2385
|
+
file,
|
|
2386
|
+
files: this.zGalleryPreviewFiles() ?? undefined,
|
|
2387
|
+
});
|
|
2388
|
+
}
|
|
2389
|
+
_isNativeInteractive() {
|
|
2390
|
+
const tagName = this._elementRef.nativeElement.tagName.toLowerCase();
|
|
2391
|
+
return tagName === 'button' || tagName === 'a';
|
|
2392
|
+
}
|
|
2393
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryPreviewItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2394
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.9", type: ZGalleryPreviewItemDirective, isStandalone: true, selector: "[zGalleryPreviewItem], [z-gallery-preview-item]", inputs: { zGalleryPreviewItem: { classPropertyName: "zGalleryPreviewItem", publicName: "zGalleryPreviewItem", isSignal: true, isRequired: true, transformFunction: null }, zGalleryPreviewFiles: { classPropertyName: "zGalleryPreviewFiles", publicName: "zGalleryPreviewFiles", isSignal: true, isRequired: false, transformFunction: null }, zGalleryPreviewOptions: { classPropertyName: "zGalleryPreviewOptions", publicName: "zGalleryPreviewOptions", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOnPreview: "zOnPreview" }, host: { listeners: { "click": "openPreview()", "keydown.enter": "openPreview($event)", "keydown.space": "openPreview($event)" }, properties: { "attr.role": "hostRole()", "attr.tabindex": "hostTabIndex()", "attr.aria-disabled": "hostAriaDisabled()" }, classAttribute: "z-gallery-preview-item" }, exportAs: ["zGalleryPreviewItem"], ngImport: i0 });
|
|
2395
|
+
}
|
|
2396
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZGalleryPreviewItemDirective, decorators: [{
|
|
2397
|
+
type: Directive,
|
|
2398
|
+
args: [{
|
|
2399
|
+
selector: '[zGalleryPreviewItem], [z-gallery-preview-item]',
|
|
2400
|
+
standalone: true,
|
|
2401
|
+
host: {
|
|
2402
|
+
class: 'z-gallery-preview-item',
|
|
2403
|
+
'[attr.role]': 'hostRole()',
|
|
2404
|
+
'[attr.tabindex]': 'hostTabIndex()',
|
|
2405
|
+
'[attr.aria-disabled]': 'hostAriaDisabled()',
|
|
2406
|
+
'(click)': 'openPreview()',
|
|
2407
|
+
'(keydown.enter)': 'openPreview($event)',
|
|
2408
|
+
'(keydown.space)': 'openPreview($event)',
|
|
2409
|
+
},
|
|
2410
|
+
exportAs: 'zGalleryPreviewItem',
|
|
2411
|
+
}]
|
|
2412
|
+
}], propDecorators: { zGalleryPreviewItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "zGalleryPreviewItem", required: true }] }], zGalleryPreviewFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "zGalleryPreviewFiles", required: false }] }], zGalleryPreviewOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "zGalleryPreviewOptions", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zOnPreview: [{ type: i0.Output, args: ["zOnPreview"] }] } });
|
|
2413
|
+
|
|
2414
|
+
/**
|
|
2415
|
+
* Generated bundle index. Do not edit.
|
|
2416
|
+
*/
|
|
2417
|
+
|
|
2418
|
+
export { FILE_CATEGORY_STYLES, ZGalleryComponent, ZGalleryFileIconComponent, ZGalleryItemComponent, ZGalleryPreviewComponent, ZGalleryPreviewItemDirective, ZGalleryPreviewRef, ZGalleryPreviewService, formatFileSize, getFileCategory, isImage, isPreviewable, zGalleryFileIconVariants, zGalleryItemVariants, zGalleryVariants };
|
|
2419
|
+
//# sourceMappingURL=shival99-z-ui-components-z-gallery.mjs.map
|