@amirjalili1374/ui-kit 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/README.md +11 -11
  2. package/package.json +3 -3
  3. package/src/assets/fonts/A Massir Spray.ttf +0 -0
  4. package/src/assets/fonts/BYekan.ttf +0 -0
  5. package/src/assets/fonts/BYekan.woff +0 -0
  6. package/src/assets/fonts/BYekan.woff2 +0 -0
  7. package/src/assets/fonts/Dima Shekasteh 2 Free.ttf +0 -0
  8. package/src/assets/fonts/Dima Shekasteh Free Regular.ttf +0 -0
  9. package/src/assets/fonts/IRANSansWeb.ts +0 -1
  10. package/src/assets/fonts/IRANSansWeb.ttf +0 -0
  11. package/src/assets/fonts/IRANSansXBlack.ttf +0 -0
  12. package/src/assets/fonts/IRANSansXBold.ttf +0 -0
  13. package/src/assets/fonts/IRANSansXDemiBold.ttf +0 -0
  14. package/src/assets/fonts/IRANSansXExtraBold.ttf +0 -0
  15. package/src/assets/fonts/IRANSansXLight.ttf +0 -0
  16. package/src/assets/fonts/IRANSansXMedium.ttf +0 -0
  17. package/src/assets/fonts/IRANSansXRegular.ttf +0 -0
  18. package/src/assets/fonts/IRANSansXThin.ttf +0 -0
  19. package/src/assets/fonts/IRANSansXUltraLight.ttf +0 -0
  20. package/src/assets/fonts/IranNastaliq.ttf +0 -0
  21. package/src/assets/fonts/Vazir-Medium-FD.ttf +0 -0
  22. package/src/assets/fonts/Vazir-Medium-FD.woff +0 -0
  23. package/src/assets/fonts/Vazir-Medium-FD.woff2 +0 -0
  24. package/src/assets/fonts/Vazir-Regular-FD.eot +0 -0
  25. package/src/assets/fonts/kalamehBold.woff +0 -0
  26. package/src/assets/fonts/kalamehBold.woff2 +0 -0
  27. package/src/assets/fonts/kalamehHeavy.woff +0 -0
  28. package/src/assets/fonts/kalamehHeavy.woff2 +0 -0
  29. package/src/assets/fonts/kalamehLight.woff +0 -0
  30. package/src/assets/fonts/kalamehLight.woff2 +0 -0
  31. package/src/assets/fonts/kalamehRegular.woff +0 -0
  32. package/src/assets/fonts/kalamehRegular.woff2 +0 -0
  33. package/src/assets/images/auth/social-google.svg +0 -6
  34. package/src/assets/images/favicon.svg +0 -18
  35. package/src/assets/images/icons/icon-card.svg +0 -5
  36. package/src/assets/images/logos/logo.svg +0 -12
  37. package/src/assets/images/logos/logolight.svg +0 -12
  38. package/src/assets/images/maintenance/img-error-bg.svg +0 -34
  39. package/src/assets/images/maintenance/img-error-blue.svg +0 -43
  40. package/src/assets/images/maintenance/img-error-purple.svg +0 -42
  41. package/src/assets/images/maintenance/img-error-text.svg +0 -27
  42. package/src/assets/images/profile/profile-user-account-svgrepo-com.svg +0 -12
  43. package/src/assets/images/profile/user-round.svg +0 -15
  44. package/src/assets/images/template/template-01.ts +0 -1
  45. package/src/assets/images/vectors/colorized-bg.svg +0 -40
  46. package/src/assets/images/vectors/logo_stroke_1px.svg +0 -26
  47. package/src/assets/images/vectors/logo_stroke_2px.svg +0 -26
  48. package/src/assets/scss/components/_approval-sections.scss +0 -75
  49. package/src/assets/styles/fonts.scss +0 -77
  50. package/src/components/Loading.vue +0 -88
  51. package/src/components/common/AppStepper.vue +0 -139
  52. package/src/components/shared/BaseBreadcrumb.vue +0 -55
  53. package/src/components/shared/BaseIcon.vue +0 -27
  54. package/src/components/shared/ConfirmDialog.vue +0 -72
  55. package/src/components/shared/CustomAutocomplete.vue +0 -306
  56. package/src/components/shared/CustomDataTable.vue +0 -1859
  57. package/src/components/shared/DescriptionInput.vue +0 -204
  58. package/src/components/shared/DownloadButton.vue +0 -169
  59. package/src/components/shared/MoneyInput.vue +0 -105
  60. package/src/components/shared/PdfViewer.vue +0 -645
  61. package/src/components/shared/ShamsiDatePicker.vue +0 -444
  62. package/src/components/shared/UiChildCard.vue +0 -17
  63. package/src/components/shared/UiParentCard.vue +0 -21
  64. package/src/components/shared/VPriceTextField.vue +0 -136
  65. package/src/composables/useDataTable.ts +0 -152
  66. package/src/composables/usePermissions.ts +0 -90
  67. package/src/composables/useRouteGuard.ts +0 -36
  68. package/src/composables/useTableActions.ts +0 -207
  69. package/src/composables/useTableHeaders.ts +0 -172
  70. package/src/composables/useTableSelection.ts +0 -201
  71. package/src/constants/enums/approval.ts +0 -13
  72. package/src/constants/enums/booleanEnum.ts +0 -11
  73. package/src/constants/enums/contractType.ts +0 -11
  74. package/src/constants/enums/lcProductType.ts +0 -21
  75. package/src/constants/enums/repaymentType.ts +0 -11
  76. package/src/directives/v-digit-limit.ts +0 -15
  77. package/src/directives/v-permission.ts +0 -31
  78. package/src/features/index.ts +0 -48
  79. package/src/index.ts +0 -119
  80. package/src/plugins/key-clock.ts +0 -39
  81. package/src/plugins/mdi-icon.ts +0 -31
  82. package/src/plugins/vuetify.ts +0 -74
  83. package/src/scss/_override.scss +0 -72
  84. package/src/scss/_variables.scss +0 -124
  85. package/src/scss/components/_VButtons.scss +0 -23
  86. package/src/scss/components/_VCard.scss +0 -20
  87. package/src/scss/components/_VCustomDataTable.scss +0 -282
  88. package/src/scss/components/_VField.scss +0 -9
  89. package/src/scss/components/_VInput.scss +0 -17
  90. package/src/scss/components/_VNavigationDrawer.scss +0 -3
  91. package/src/scss/components/_VShadow.scss +0 -3
  92. package/src/scss/components/_VStepper.scss +0 -235
  93. package/src/scss/components/_VTabs.scss +0 -11
  94. package/src/scss/components/_VTextField.scss +0 -40
  95. package/src/scss/components/_approval.scss +0 -128
  96. package/src/scss/layout/_container.scss +0 -147
  97. package/src/scss/layout/_sidebar.scss +0 -138
  98. package/src/scss/layout/_topbar.scss +0 -39
  99. package/src/scss/pages/_dashboards.scss +0 -97
  100. package/src/scss/style.scss +0 -21
  101. package/src/services/apiService.ts +0 -59
  102. package/src/services/axiosInstance.ts +0 -14
  103. package/src/stores/customizer.ts +0 -55
  104. package/src/stores/permissions.ts +0 -237
  105. package/src/theme/darkThemes/DarkModernTheme.ts +0 -54
  106. package/src/theme/darkThemes/DarkOrangeTheme.ts +0 -53
  107. package/src/theme/darkThemes/DarkPurpleTheme.ts +0 -54
  108. package/src/theme/darkThemes/DarkRedTheme.ts +0 -54
  109. package/src/theme/darkThemes/DarkSilverTheme.ts +0 -53
  110. package/src/theme/darkThemes/DarkSteelTealGreen.ts +0 -53
  111. package/src/theme/darkThemes/DarkTealTheme.ts +0 -52
  112. package/src/theme/lightThemes/ModernTheme.ts +0 -55
  113. package/src/theme/lightThemes/OrangeTheme.ts +0 -54
  114. package/src/theme/lightThemes/PurpleTheme.ts +0 -54
  115. package/src/theme/lightThemes/RedTheme.ts +0 -55
  116. package/src/theme/lightThemes/SilverTheme.ts +0 -55
  117. package/src/theme/lightThemes/SteelTealGreen.ts +0 -54
  118. package/src/theme/lightThemes/TealTheme.ts +0 -54
  119. package/src/types/approval/approvalType.ts +0 -473
  120. package/src/types/cartable/cartableTypes.ts +0 -169
  121. package/src/types/componentTypes/DataTableType.ts +0 -14
  122. package/src/types/componentTypes/DataTableTypes.ts +0 -130
  123. package/src/types/enums/global.ts +0 -267
  124. package/src/types/jalaali-js.d.ts +0 -6
  125. package/src/types/models/Base.ts +0 -4
  126. package/src/types/models/env.d.ts +0 -10
  127. package/src/types/models/person.ts +0 -13
  128. package/src/types/models/userInfo.ts +0 -29
  129. package/src/types/preApproval/preApprovalTypes.ts +0 -67
  130. package/src/types/shims-tabler-icons.d.ts +0 -58
  131. package/src/types/themeTypes/ThemeType.ts +0 -47
  132. package/src/types/vue-apexcharts.d.ts +0 -1
  133. package/src/types/vue3-print-nb.d.ts +0 -1
  134. package/src/types/vue_tabler_icon.d.ts +0 -10
  135. package/src/utils/NationalCodeValidator.ts +0 -33
  136. package/src/utils/date-convertor.ts +0 -40
  137. package/src/utils/greetingUtils.ts +0 -97
  138. package/src/utils/helpers/fake-backend.ts +0 -68
  139. package/src/utils/helpers/fetch-wrapper.ts +0 -86
  140. package/src/utils/number-formatter.ts +0 -33
  141. package/src/validators/nationalCodeRule.ts +0 -6
@@ -1,645 +0,0 @@
1
- <template>
2
- <div class="pdf-viewer-container" :class="{ 'fullscreen': isFullscreen }">
3
- <!-- Header with controls -->
4
- <div class="pdf-viewer-header" v-if="showHeader">
5
- <div class="pdf-viewer-title">
6
- <h3>{{ title || 'PDF Viewer' }}</h3>
7
- </div>
8
-
9
- <div class="pdf-viewer-controls">
10
- <!-- Zoom Controls -->
11
- <div class="zoom-controls" v-if="showZoomControls">
12
- <v-btn
13
- size="small"
14
- variant="text"
15
- @click="zoomOut"
16
- :disabled="zoom <= minZoom"
17
- title="Zoom Out"
18
- >
19
- <IconMinus size="16" color="white" />
20
- </v-btn>
21
- <span class="zoom-level">{{ Math.round(zoom * 100) }}%</span>
22
- <v-btn
23
- size="small"
24
- variant="text"
25
- @click="zoomIn"
26
- :disabled="zoom >= maxZoom"
27
- title="Zoom In"
28
- >
29
- <IconPlus size="16" color="white" />
30
- </v-btn>
31
- <v-btn
32
- size="small"
33
- variant="text"
34
- @click="resetZoom"
35
- title="Reset Zoom"
36
- >
37
- <IconRefresh size="16" color="white" />
38
- </v-btn>
39
- </div>
40
-
41
- <!-- Navigation Controls -->
42
- <div class="navigation-controls" v-if="showNavigationControls">
43
- <v-btn
44
- size="small"
45
- variant="text"
46
- @click="previousPage"
47
- :disabled="currentPage <= 1"
48
- title="Previous Page"
49
- >
50
- <IconChevronLeft size="16" color="white" />
51
- </v-btn>
52
- <span class="page-info">
53
- {{ currentPage }} / {{ totalPages }}
54
- </span>
55
- <v-btn
56
- size="small"
57
- variant="text"
58
- @click="nextPage"
59
- :disabled="currentPage >= totalPages"
60
- title="Next Page"
61
- >
62
- <IconChevronRight size="16" color="white" />
63
- </v-btn>
64
- </div>
65
-
66
- <!-- Action Controls -->
67
- <div class="action-controls">
68
- <v-btn
69
- v-if="showDownload"
70
- size="small"
71
- variant="text"
72
- @click="downloadPdf"
73
- :loading="downloading"
74
- title="Download PDF"
75
- >
76
- <IconDownload size="16" color="white" />
77
- </v-btn>
78
- <v-btn
79
- v-if="showPrint"
80
- size="small"
81
- variant="text"
82
- @click="printPdf"
83
- title="Print PDF"
84
- >
85
- <IconPrinter size="16" color="white" />
86
- </v-btn>
87
- <v-btn
88
- v-if="showFullscreen"
89
- size="small"
90
- variant="text"
91
- @click="toggleFullscreen"
92
- :title="isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'"
93
- >
94
- <IconMaximize v-if="!isFullscreen" size="16" color="white" />
95
- <IconMinimize v-else size="16" color="white" />
96
- </v-btn>
97
- <v-btn
98
- v-if="showClose"
99
- size="small"
100
- variant="text"
101
- @click="$emit('close')"
102
- title="Close"
103
- >
104
- <IconX size="16" color="white" />
105
- </v-btn>
106
- </div>
107
- </div>
108
- </div>
109
-
110
- <!-- PDF Content -->
111
- <div class="pdf-viewer-content" :style="contentStyle">
112
- <!-- Loading State -->
113
- <div v-if="loading" class="pdf-loading">
114
- <v-progress-circular
115
- indeterminate
116
- color="primary"
117
- size="64"
118
- />
119
- <p>{{ loadingText || 'Loading PDF...' }}</p>
120
- </div>
121
-
122
- <!-- Error State -->
123
- <div v-else-if="error" class="pdf-error">
124
- <IconFileText size="64" color="error" />
125
- <h3>{{ errorTitle || 'Error Loading PDF' }}</h3>
126
- <p>{{ error }}</p>
127
- <v-btn
128
- color="primary"
129
- @click="loadPdf"
130
- :loading="loading"
131
- >
132
- Retry
133
- </v-btn>
134
- </div>
135
-
136
- <!-- PDF Display -->
137
- <div v-else class="pdf-display">
138
- <iframe
139
- v-if="pdfUrl"
140
- :src="pdfUrl"
141
- :style="iframeStyle"
142
- @load="onPdfLoad"
143
- @error="onPdfError"
144
- :title="title || 'PDF Document'"
145
- />
146
-
147
- <!-- Fallback for browsers that don't support PDF -->
148
- <div v-else class="pdf-fallback">
149
- <IconFileText size="64" color="grey" />
150
- <h3>PDF Preview Not Available</h3>
151
- <p>Your browser does not support PDF preview.</p>
152
- <v-btn
153
- color="primary"
154
- @click="downloadPdf"
155
- :loading="downloading"
156
- >
157
- Download PDF
158
- </v-btn>
159
- </div>
160
- </div>
161
- </div>
162
-
163
- <!-- Footer with page info -->
164
- <div class="pdf-viewer-footer" v-if="showFooter">
165
- <div class="page-info">
166
- Page {{ currentPage }} of {{ totalPages }}
167
- </div>
168
- <div class="file-info" v-if="fileSize">
169
- {{ formatFileSize(fileSize) }}
170
- </div>
171
- </div>
172
- </div>
173
- </template>
174
-
175
- <script lang="ts" setup>
176
- import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
177
- import {
178
- IconMinus,
179
- IconPlus,
180
- IconRefresh,
181
- IconChevronLeft,
182
- IconChevronRight,
183
- IconDownload,
184
- IconPrinter,
185
- IconMaximize,
186
- IconMinimize,
187
- IconX,
188
- IconFileText
189
- } from '@tabler/icons-vue';
190
-
191
- // Props
192
- interface Props {
193
- src?: string;
194
- title?: string;
195
- width?: string | number;
196
- height?: string | number;
197
- showHeader?: boolean;
198
- showFooter?: boolean;
199
- showZoomControls?: boolean;
200
- showNavigationControls?: boolean;
201
- showDownload?: boolean;
202
- showPrint?: boolean;
203
- showFullscreen?: boolean;
204
- showClose?: boolean;
205
- loadingText?: string;
206
- errorTitle?: string;
207
- fileSize?: number;
208
- initialZoom?: number;
209
- minZoom?: number;
210
- maxZoom?: number;
211
- autoLoad?: boolean;
212
- downloadFileName?: string;
213
- }
214
-
215
- const props = withDefaults(defineProps<Props>(), {
216
- showHeader: true,
217
- showFooter: true,
218
- showZoomControls: true,
219
- showNavigationControls: true,
220
- showDownload: true,
221
- showPrint: true,
222
- showFullscreen: true,
223
- showClose: false,
224
- loadingText: 'Loading PDF...',
225
- errorTitle: 'Error Loading PDF',
226
- initialZoom: 1,
227
- minZoom: 0.25,
228
- maxZoom: 3,
229
- autoLoad: true,
230
- downloadFileName: 'document.pdf'
231
- });
232
-
233
- // Emits
234
- const emit = defineEmits<{
235
- load: [pdf: any];
236
- error: [error: string];
237
- pageChange: [page: number];
238
- zoomChange: [zoom: number];
239
- download: [url: string];
240
- print: [url: string];
241
- close: [];
242
- }>();
243
-
244
- // Reactive state
245
- const loading = ref(false);
246
- const error = ref<string | null>(null);
247
- const downloading = ref(false);
248
- const isFullscreen = ref(false);
249
- const currentPage = ref(1);
250
- const totalPages = ref(1);
251
- const zoom = ref(props.initialZoom);
252
-
253
- // Computed properties
254
- const pdfUrl = computed(() => {
255
- if (!props.src) return null;
256
-
257
- // If it's already a blob URL or data URL, return as is
258
- if (props.src.startsWith('blob:') || props.src.startsWith('data:')) {
259
- return props.src;
260
- }
261
-
262
- // For regular URLs, add zoom parameter if supported
263
- const url = new URL(props.src, window.location.origin);
264
- url.searchParams.set('zoom', zoom.value.toString());
265
- return url.toString();
266
- });
267
-
268
- const contentStyle = computed(() => ({
269
- width: typeof props.width === 'number' ? `${props.width}px` : props.width || '100%',
270
- height: typeof props.height === 'number' ? `${props.height}px` : props.height || '500px',
271
- transform: `scale(${zoom.value})`,
272
- transformOrigin: 'top left'
273
- }));
274
-
275
- const iframeStyle = computed(() => ({
276
- width: '100%',
277
- height: '100%',
278
- border: 'none'
279
- }));
280
-
281
- // Methods
282
- const loadPdf = async () => {
283
- if (!props.src) return;
284
-
285
- loading.value = true;
286
- error.value = null;
287
-
288
- try {
289
- // For now, we'll just set the URL and let the iframe handle loading
290
- // In a real implementation, you might want to fetch and validate the PDF
291
- loading.value = false;
292
- } catch (err) {
293
- error.value = err instanceof Error ? err.message : 'Failed to load PDF';
294
- loading.value = false;
295
- emit('error', error.value);
296
- }
297
- };
298
-
299
- const onPdfLoad = () => {
300
- loading.value = false;
301
- // Note: Getting actual page count from iframe is complex due to CORS
302
- // This is a simplified implementation
303
- totalPages.value = 1; // You might want to implement actual page counting
304
- emit('load', { currentPage: currentPage.value, totalPages: totalPages.value });
305
- };
306
-
307
- const onPdfError = () => {
308
- error.value = 'Failed to load PDF document';
309
- loading.value = false;
310
- emit('error', error.value);
311
- };
312
-
313
- const zoomIn = () => {
314
- if (zoom.value < props.maxZoom) {
315
- zoom.value = Math.min(zoom.value + 0.25, props.maxZoom);
316
- emit('zoomChange', zoom.value);
317
- }
318
- };
319
-
320
- const zoomOut = () => {
321
- if (zoom.value > props.minZoom) {
322
- zoom.value = Math.max(zoom.value - 0.25, props.minZoom);
323
- emit('zoomChange', zoom.value);
324
- }
325
- };
326
-
327
- const resetZoom = () => {
328
- zoom.value = props.initialZoom;
329
- emit('zoomChange', zoom.value);
330
- };
331
-
332
- const previousPage = () => {
333
- if (currentPage.value > 1) {
334
- currentPage.value--;
335
- emit('pageChange', currentPage.value);
336
- }
337
- };
338
-
339
- const nextPage = () => {
340
- if (currentPage.value < totalPages.value) {
341
- currentPage.value++;
342
- emit('pageChange', currentPage.value);
343
- }
344
- };
345
-
346
- const downloadPdf = async () => {
347
- if (!props.src) return;
348
-
349
- downloading.value = true;
350
-
351
- try {
352
- const response = await fetch(props.src);
353
- const blob = await response.blob();
354
- const url = window.URL.createObjectURL(blob);
355
-
356
- const link = document.createElement('a');
357
- link.href = url;
358
- link.download = props.downloadFileName;
359
- document.body.appendChild(link);
360
- link.click();
361
- document.body.removeChild(link);
362
-
363
- window.URL.revokeObjectURL(url);
364
- emit('download', props.src);
365
- } catch (err) {
366
- console.error('Download failed:', err);
367
- // Fallback: open in new tab
368
- window.open(props.src, '_blank');
369
- } finally {
370
- downloading.value = false;
371
- }
372
- };
373
-
374
- const printPdf = () => {
375
- if (!props.src) return;
376
-
377
- const printWindow = window.open(props.src, '_blank');
378
- if (printWindow) {
379
- printWindow.onload = () => {
380
- printWindow.print();
381
- };
382
- }
383
- emit('print', props.src);
384
- };
385
-
386
- const toggleFullscreen = () => {
387
- isFullscreen.value = !isFullscreen.value;
388
-
389
- if (isFullscreen.value) {
390
- document.body.style.overflow = 'hidden';
391
- } else {
392
- document.body.style.overflow = '';
393
- }
394
- };
395
-
396
- const formatFileSize = (bytes: number): string => {
397
- if (bytes === 0) return '0 Bytes';
398
-
399
- const k = 1024;
400
- const sizes = ['Bytes', 'KB', 'MB', 'GB'];
401
- const i = Math.floor(Math.log(bytes) / Math.log(k));
402
-
403
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
404
- };
405
-
406
- // Keyboard shortcuts
407
- const handleKeydown = (event: KeyboardEvent) => {
408
- if (!isFullscreen.value) return;
409
-
410
- switch (event.key) {
411
- case 'Escape':
412
- if (isFullscreen.value) {
413
- toggleFullscreen();
414
- }
415
- break;
416
- case 'ArrowLeft':
417
- previousPage();
418
- break;
419
- case 'ArrowRight':
420
- nextPage();
421
- break;
422
- case '+':
423
- case '=':
424
- zoomIn();
425
- break;
426
- case '-':
427
- zoomOut();
428
- break;
429
- case '0':
430
- resetZoom();
431
- break;
432
- }
433
- };
434
-
435
- // Lifecycle
436
- onMounted(() => {
437
- if (props.autoLoad) {
438
- loadPdf();
439
- }
440
-
441
- document.addEventListener('keydown', handleKeydown);
442
- });
443
-
444
- onUnmounted(() => {
445
- document.removeEventListener('keydown', handleKeydown);
446
- document.body.style.overflow = '';
447
- });
448
-
449
- // Watch for src changes
450
- watch(() => props.src, () => {
451
- if (props.autoLoad) {
452
- loadPdf();
453
- }
454
- });
455
-
456
- // Expose methods
457
- defineExpose({
458
- loadPdf,
459
- zoomIn,
460
- zoomOut,
461
- resetZoom,
462
- previousPage,
463
- nextPage,
464
- downloadPdf,
465
- printPdf,
466
- toggleFullscreen
467
- });
468
- </script>
469
-
470
- <style lang="scss" scoped>
471
- .pdf-viewer-container {
472
- display: flex;
473
- flex-direction: column;
474
- border: 1px solid #e0e0e0;
475
- border-radius: 8px;
476
- background: white;
477
- overflow: hidden;
478
- height: 456px;
479
-
480
- &.fullscreen {
481
- position: fixed;
482
- top: 0;
483
- left: 0;
484
- width: 100vw;
485
- height: 100vh;
486
- z-index: 9999;
487
- border: none;
488
- border-radius: 0;
489
- }
490
- }
491
-
492
- .pdf-viewer-header {
493
- display: flex;
494
- justify-content: space-between;
495
- align-items: center;
496
- padding: 12px 16px;
497
- background: #fff9f9;
498
- border-bottom: 1px solid #e0e0e0;
499
-
500
- .pdf-viewer-title {
501
- h3 {
502
- margin: 0;
503
- font-size: 16px;
504
- font-weight: 600;
505
- color: #333;
506
- }
507
- }
508
-
509
- .pdf-viewer-controls {
510
- display: flex;
511
- align-items: center;
512
- gap: 8px;
513
-
514
- .zoom-controls,
515
- .navigation-controls,
516
- .action-controls {
517
- display: flex;
518
- align-items: center;
519
- gap: 4px;
520
-
521
- .zoom-level,
522
- .page-info {
523
- font-size: 14px;
524
- color: #666;
525
- min-width: 60px;
526
- text-align: center;
527
- }
528
- }
529
- }
530
- }
531
-
532
- .pdf-viewer-content {
533
- flex: 1;
534
- position: relative;
535
- overflow: auto;
536
- background: #f9f9f9;
537
-
538
- .pdf-loading,
539
- .pdf-error,
540
- .pdf-fallback {
541
- display: flex;
542
- flex-direction: column;
543
- align-items: center;
544
- justify-content: center;
545
- height: 100%;
546
- padding: 40px;
547
- text-align: center;
548
-
549
- p {
550
- margin: 16px 0 0 0;
551
- color: #666;
552
- }
553
-
554
- h3 {
555
- margin: 16px 0 8px 0;
556
- color: #333;
557
- }
558
- }
559
-
560
- .pdf-display {
561
- width: 100%;
562
- height: 100%;
563
-
564
- iframe {
565
- width: 100%;
566
- height: 100%;
567
- border: none;
568
- }
569
- }
570
- }
571
-
572
- .pdf-viewer-footer {
573
- display: flex;
574
- justify-content: space-between;
575
- align-items: center;
576
- padding: 8px 16px;
577
- background: #f5f5f5;
578
- border-top: 1px solid #e0e0e0;
579
- font-size: 12px;
580
- color: #666;
581
-
582
- .page-info,
583
- .file-info {
584
- font-weight: 500;
585
- }
586
- }
587
-
588
- // Responsive design
589
- @media (max-width: 768px) {
590
- .pdf-viewer-header {
591
- flex-direction: column;
592
- gap: 12px;
593
-
594
- .pdf-viewer-controls {
595
- flex-wrap: wrap;
596
- justify-content: center;
597
- }
598
- }
599
-
600
- .pdf-viewer-footer {
601
- flex-direction: column;
602
- gap: 4px;
603
- text-align: center;
604
- }
605
- }
606
-
607
- // Dark theme support
608
- @media (prefers-color-scheme: dark) {
609
- .pdf-viewer-container {
610
- background: #1e1e1e;
611
- border-color: #333;
612
- }
613
-
614
- .pdf-viewer-header,
615
- .pdf-viewer-footer {
616
- background: #2d2d2d;
617
- border-color: #333;
618
-
619
- .pdf-viewer-title h3 {
620
- color: #fff;
621
- }
622
-
623
- .zoom-level,
624
- .page-info {
625
- color: #ccc;
626
- }
627
- }
628
-
629
- .pdf-viewer-content {
630
- background: #1e1e1e;
631
-
632
- .pdf-loading,
633
- .pdf-error,
634
- .pdf-fallback {
635
- p {
636
- color: #ccc;
637
- }
638
-
639
- h3 {
640
- color: #fff;
641
- }
642
- }
643
- }
644
- }
645
- </style>