overview-components 1.1.161 → 1.1.165

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 (250) hide show
  1. package/dist/assets/generated/locales/de.js +269 -0
  2. package/dist/assets/generated/locales/de.js.map +1 -0
  3. package/dist/assets/generated/locales/en.js +269 -0
  4. package/dist/assets/generated/locales/en.js.map +1 -0
  5. package/dist/assets/generated/locales/fr.js +269 -0
  6. package/dist/assets/generated/locales/fr.js.map +1 -0
  7. package/dist/assets/generated/locales/hr.js +269 -0
  8. package/dist/assets/generated/locales/hr.js.map +1 -0
  9. package/dist/assets/generated/locales/it.js +269 -0
  10. package/dist/assets/generated/locales/it.js.map +1 -0
  11. package/dist/assets/generated/locales/pl.js +269 -0
  12. package/dist/assets/generated/locales/pl.js.map +1 -0
  13. package/dist/assets/generated/locales/ro.js +269 -0
  14. package/dist/assets/generated/locales/ro.js.map +1 -0
  15. package/dist/assets/generated/locales/sk.js +269 -0
  16. package/dist/assets/generated/locales/sk.js.map +1 -0
  17. package/dist/assets/generated/locales/sr.js +269 -0
  18. package/dist/assets/generated/locales/sr.js.map +1 -0
  19. package/dist/assets/icons/iconGlyphs.js +691 -0
  20. package/dist/assets/icons/iconGlyphs.js.map +1 -0
  21. package/dist/assets/illustration/aichatbot-illustration.js +144 -0
  22. package/dist/assets/illustration/aichatbot-illustration.js.map +1 -0
  23. package/dist/assets/illustration/delete-illustration.js +88 -0
  24. package/dist/assets/illustration/delete-illustration.js.map +1 -0
  25. package/dist/assets/illustration/no-content.js +159 -0
  26. package/dist/assets/illustration/no-content.js.map +1 -0
  27. package/dist/assets/illustration/no-preview.js +125 -0
  28. package/dist/assets/illustration/no-preview.js.map +1 -0
  29. package/dist/assets/illustration/not-found.js +98 -0
  30. package/dist/assets/illustration/not-found.js.map +1 -0
  31. package/dist/assets/illustration/settings-illustration.js +168 -0
  32. package/dist/assets/illustration/settings-illustration.js.map +1 -0
  33. package/dist/components/components-settings/attachments-tab-settings.js +318 -0
  34. package/dist/components/components-settings/attachments-tab-settings.js.map +1 -0
  35. package/dist/components/components-settings/data-grid-settings.js +553 -0
  36. package/dist/components/components-settings/data-grid-settings.js.map +1 -0
  37. package/dist/components/components-settings/section-tab-settings.js +719 -0
  38. package/dist/components/components-settings/section-tab-settings.js.map +1 -0
  39. package/dist/components/components-settings/tabs-overview-settings.js +421 -0
  40. package/dist/components/components-settings/tabs-overview-settings.js.map +1 -0
  41. package/dist/components/index.js +30 -0
  42. package/dist/components/index.js.map +1 -0
  43. package/dist/components/lit-ai-filter-assistant.js +443 -0
  44. package/dist/components/lit-ai-filter-assistant.js.map +1 -0
  45. package/dist/components/lit-attachments-tab.js +2044 -0
  46. package/dist/components/lit-attachments-tab.js.map +1 -0
  47. package/dist/components/lit-badge.js +124 -0
  48. package/dist/components/lit-badge.js.map +1 -0
  49. package/dist/components/lit-case-variables-tab.d.ts +2 -0
  50. package/dist/components/lit-case-variables-tab.d.ts.map +1 -1
  51. package/dist/components/lit-case-variables-tab.js +3763 -0
  52. package/dist/components/lit-case-variables-tab.js.map +1 -0
  53. package/dist/components/lit-chart.js +727 -0
  54. package/dist/components/lit-chart.js.map +1 -0
  55. package/dist/components/lit-data-grid-tanstack.js +2550 -0
  56. package/dist/components/lit-data-grid-tanstack.js.map +1 -0
  57. package/dist/components/lit-filter-builder.js +701 -0
  58. package/dist/components/lit-filter-builder.js.map +1 -0
  59. package/dist/components/lit-filter-modal.js +349 -0
  60. package/dist/components/lit-filter-modal.js.map +1 -0
  61. package/dist/components/lit-multiselect-item.js +707 -0
  62. package/dist/components/lit-multiselect-item.js.map +1 -0
  63. package/dist/components/lit-section-tab.js +268 -0
  64. package/dist/components/lit-section-tab.js.map +1 -0
  65. package/dist/components/lit-tabs-overview.js +356 -0
  66. package/dist/components/lit-tabs-overview.js.map +1 -0
  67. package/dist/components/modals/lit-confirm-modal.js +121 -0
  68. package/dist/components/modals/lit-confirm-modal.js.map +1 -0
  69. package/dist/components/modals/lit-delete-modal.js +131 -0
  70. package/dist/components/modals/lit-delete-modal.js.map +1 -0
  71. package/dist/components/react-wrappers/ai-filter-assistant.js +9 -0
  72. package/dist/components/react-wrappers/ai-filter-assistant.js.map +1 -0
  73. package/dist/components/react-wrappers/attachments-tab.js +9 -0
  74. package/dist/components/react-wrappers/attachments-tab.js.map +1 -0
  75. package/dist/components/react-wrappers/badge.js +9 -0
  76. package/dist/components/react-wrappers/badge.js.map +1 -0
  77. package/dist/components/react-wrappers/button.js +9 -0
  78. package/dist/components/react-wrappers/button.js.map +1 -0
  79. package/dist/components/react-wrappers/calendar.js +9 -0
  80. package/dist/components/react-wrappers/calendar.js.map +1 -0
  81. package/dist/components/react-wrappers/case-variables-tab.js +9 -0
  82. package/dist/components/react-wrappers/case-variables-tab.js.map +1 -0
  83. package/dist/components/react-wrappers/chart.js +9 -0
  84. package/dist/components/react-wrappers/chart.js.map +1 -0
  85. package/dist/components/react-wrappers/data-grid-tanstack.js +9 -0
  86. package/dist/components/react-wrappers/data-grid-tanstack.js.map +1 -0
  87. package/dist/components/react-wrappers/filter-builder.js +12 -0
  88. package/dist/components/react-wrappers/filter-builder.js.map +1 -0
  89. package/dist/components/react-wrappers/filter-modal.js +9 -0
  90. package/dist/components/react-wrappers/filter-modal.js.map +1 -0
  91. package/dist/components/react-wrappers/index.js +27 -0
  92. package/dist/components/react-wrappers/index.js.map +1 -0
  93. package/dist/components/react-wrappers/progress-bar.js +9 -0
  94. package/dist/components/react-wrappers/progress-bar.js.map +1 -0
  95. package/dist/components/react-wrappers/section-tab.js +9 -0
  96. package/dist/components/react-wrappers/section-tab.js.map +1 -0
  97. package/dist/components/react-wrappers/tabs-overview.js +9 -0
  98. package/dist/components/react-wrappers/tabs-overview.js.map +1 -0
  99. package/dist/data/translations.js +2768 -0
  100. package/dist/data/translations.js.map +1 -0
  101. package/dist/index.js +7 -19890
  102. package/dist/index.js.map +1 -0
  103. package/dist/schemas/index.js +18 -0
  104. package/dist/schemas/index.js.map +1 -0
  105. package/dist/schemas/lit-attachments-tab-document.schema.js +39 -0
  106. package/dist/schemas/lit-attachments-tab-document.schema.js.map +1 -0
  107. package/dist/schemas/lit-attachments-tab-settings-value.schema.js +30 -0
  108. package/dist/schemas/lit-attachments-tab-settings-value.schema.js.map +1 -0
  109. package/dist/schemas/lit-attachments-tab.schema.js +68 -0
  110. package/dist/schemas/lit-attachments-tab.schema.js.map +1 -0
  111. package/dist/schemas/lit-case-variables-tab-cell.schema.d.ts +3 -0
  112. package/dist/schemas/lit-case-variables-tab-cell.schema.d.ts.map +1 -1
  113. package/dist/schemas/lit-case-variables-tab-cell.schema.js +226 -0
  114. package/dist/schemas/lit-case-variables-tab-cell.schema.js.map +1 -0
  115. package/dist/schemas/lit-case-variables-tab-rows.schema.d.ts +3 -0
  116. package/dist/schemas/lit-case-variables-tab-rows.schema.d.ts.map +1 -1
  117. package/dist/schemas/lit-case-variables-tab-rows.schema.js +6 -0
  118. package/dist/schemas/lit-case-variables-tab-rows.schema.js.map +1 -0
  119. package/dist/schemas/lit-case-variables-tab.schema.d.ts +6 -0
  120. package/dist/schemas/lit-case-variables-tab.schema.d.ts.map +1 -1
  121. package/dist/schemas/lit-case-variables-tab.schema.js +27 -0
  122. package/dist/schemas/lit-case-variables-tab.schema.js.map +1 -0
  123. package/dist/schemas/lit-data-grid-tanstack-column-array.schema.js +6 -0
  124. package/dist/schemas/lit-data-grid-tanstack-column-array.schema.js.map +1 -0
  125. package/dist/schemas/lit-data-grid-tanstack-column-custom-filter-array.schema.js +6 -0
  126. package/dist/schemas/lit-data-grid-tanstack-column-custom-filter-array.schema.js.map +1 -0
  127. package/dist/schemas/lit-data-grid-tanstack-column-custom-filter.schema.js +11 -0
  128. package/dist/schemas/lit-data-grid-tanstack-column-custom-filter.schema.js.map +1 -0
  129. package/dist/schemas/lit-data-grid-tanstack-column.schema.js +79 -0
  130. package/dist/schemas/lit-data-grid-tanstack-column.schema.js.map +1 -0
  131. package/dist/schemas/lit-data-grid-tanstack.schema.js +108 -0
  132. package/dist/schemas/lit-data-grid-tanstack.schema.js.map +1 -0
  133. package/dist/schemas/lit-filter-builder.schema.js +61 -0
  134. package/dist/schemas/lit-filter-builder.schema.js.map +1 -0
  135. package/dist/schemas/lit-section-tab-schema.js +37 -0
  136. package/dist/schemas/lit-section-tab-schema.js.map +1 -0
  137. package/dist/schemas/lit-tabs-overview-tab-array.schema.js +6 -0
  138. package/dist/schemas/lit-tabs-overview-tab-array.schema.js.map +1 -0
  139. package/dist/schemas/lit-tabs-overview-tab.schema.js +32 -0
  140. package/dist/schemas/lit-tabs-overview-tab.schema.js.map +1 -0
  141. package/dist/schemas/lit-tabs-overview.schema.js +29 -0
  142. package/dist/schemas/lit-tabs-overview.schema.js.map +1 -0
  143. package/dist/scripts/translate-locales.js +241 -0
  144. package/dist/scripts/translate-locales.js.map +1 -0
  145. package/dist/shared/filter-inputs.js +429 -0
  146. package/dist/shared/filter-inputs.js.map +1 -0
  147. package/dist/shared/index.js +40 -0
  148. package/dist/shared/index.js.map +1 -0
  149. package/dist/shared/lit-button.js +159 -0
  150. package/dist/shared/lit-button.js.map +1 -0
  151. package/dist/shared/lit-calendar.js +485 -0
  152. package/dist/shared/lit-calendar.js.map +1 -0
  153. package/dist/shared/lit-case-variables-tab-cell.d.ts +2 -0
  154. package/dist/shared/lit-case-variables-tab-cell.d.ts.map +1 -1
  155. package/dist/shared/lit-case-variables-tab-cell.js +235 -0
  156. package/dist/shared/lit-case-variables-tab-cell.js.map +1 -0
  157. package/dist/shared/lit-checkbox.js +184 -0
  158. package/dist/shared/lit-checkbox.js.map +1 -0
  159. package/dist/shared/lit-custom-popper.js +116 -0
  160. package/dist/shared/lit-custom-popper.js.map +1 -0
  161. package/dist/shared/lit-data-grid-action-buttons-popover.js +295 -0
  162. package/dist/shared/lit-data-grid-action-buttons-popover.js.map +1 -0
  163. package/dist/shared/lit-data-grid-density-popover.js +84 -0
  164. package/dist/shared/lit-data-grid-density-popover.js.map +1 -0
  165. package/dist/shared/lit-data-grid-export-popover.js +68 -0
  166. package/dist/shared/lit-data-grid-export-popover.js.map +1 -0
  167. package/dist/shared/lit-data-grid-operators-popover.js +114 -0
  168. package/dist/shared/lit-data-grid-operators-popover.js.map +1 -0
  169. package/dist/shared/lit-data-grid-row-actions.js +87 -0
  170. package/dist/shared/lit-data-grid-row-actions.js.map +1 -0
  171. package/dist/shared/lit-date-picker.js +608 -0
  172. package/dist/shared/lit-date-picker.js.map +1 -0
  173. package/dist/shared/lit-document-thumbnail.js +383 -0
  174. package/dist/shared/lit-document-thumbnail.js.map +1 -0
  175. package/dist/shared/lit-filter-input.js +115 -0
  176. package/dist/shared/lit-filter-input.js.map +1 -0
  177. package/dist/shared/lit-icon-button.js +165 -0
  178. package/dist/shared/lit-icon-button.js.map +1 -0
  179. package/dist/shared/lit-icon.d.ts.map +1 -1
  180. package/dist/shared/lit-icon.js +337 -0
  181. package/dist/shared/lit-icon.js.map +1 -0
  182. package/dist/shared/lit-input.js +282 -0
  183. package/dist/shared/lit-input.js.map +1 -0
  184. package/dist/shared/lit-label.js +103 -0
  185. package/dist/shared/lit-label.js.map +1 -0
  186. package/dist/shared/lit-loader.js +68 -0
  187. package/dist/shared/lit-loader.js.map +1 -0
  188. package/dist/shared/lit-loading-bar.js +91 -0
  189. package/dist/shared/lit-loading-bar.js.map +1 -0
  190. package/dist/shared/lit-menu-item.js +98 -0
  191. package/dist/shared/lit-menu-item.js.map +1 -0
  192. package/dist/shared/lit-menu.js +29 -0
  193. package/dist/shared/lit-menu.js.map +1 -0
  194. package/dist/shared/lit-modal-body.js +24 -0
  195. package/dist/shared/lit-modal-body.js.map +1 -0
  196. package/dist/shared/lit-modal-footer.js +21 -0
  197. package/dist/shared/lit-modal-footer.js.map +1 -0
  198. package/dist/shared/lit-modal-header.js +34 -0
  199. package/dist/shared/lit-modal-header.js.map +1 -0
  200. package/dist/shared/lit-modal.js +168 -0
  201. package/dist/shared/lit-modal.js.map +1 -0
  202. package/dist/shared/lit-overflow-tooltip.js +114 -0
  203. package/dist/shared/lit-overflow-tooltip.js.map +1 -0
  204. package/dist/shared/lit-pill.js +87 -0
  205. package/dist/shared/lit-pill.js.map +1 -0
  206. package/dist/shared/lit-progress-bar.js +130 -0
  207. package/dist/shared/lit-progress-bar.js.map +1 -0
  208. package/dist/shared/lit-responsive-button.js +106 -0
  209. package/dist/shared/lit-responsive-button.js.map +1 -0
  210. package/dist/shared/lit-select-field.js +457 -0
  211. package/dist/shared/lit-select-field.js.map +1 -0
  212. package/dist/shared/lit-select.js +668 -0
  213. package/dist/shared/lit-select.js.map +1 -0
  214. package/dist/shared/lit-settings.js +76 -0
  215. package/dist/shared/lit-settings.js.map +1 -0
  216. package/dist/shared/lit-text-field.js +252 -0
  217. package/dist/shared/lit-text-field.js.map +1 -0
  218. package/dist/shared/lit-toggle.js +240 -0
  219. package/dist/shared/lit-toggle.js.map +1 -0
  220. package/dist/shared/lit-tooltip.js +165 -0
  221. package/dist/shared/lit-tooltip.js.map +1 -0
  222. package/dist/shared/simple-popper.js +285 -0
  223. package/dist/shared/simple-popper.js.map +1 -0
  224. package/dist/shared/simple-tooltip.js +249 -0
  225. package/dist/shared/simple-tooltip.js.map +1 -0
  226. package/dist/shared/styles/button-shared-styles.js +494 -0
  227. package/dist/shared/styles/button-shared-styles.js.map +1 -0
  228. package/dist/styles.js +169 -0
  229. package/dist/styles.js.map +1 -0
  230. package/dist/utils/custom-filters.js +42 -0
  231. package/dist/utils/custom-filters.js.map +1 -0
  232. package/dist/utils/date.js +21 -0
  233. package/dist/utils/date.js.map +1 -0
  234. package/dist/utils/file-type-utils.js +55 -0
  235. package/dist/utils/file-type-utils.js.map +1 -0
  236. package/dist/utils/formatNumber.js +62 -0
  237. package/dist/utils/formatNumber.js.map +1 -0
  238. package/dist/utils/getOperatorByType.js +70 -0
  239. package/dist/utils/getOperatorByType.js.map +1 -0
  240. package/dist/utils/getOverviewValue.js +175 -0
  241. package/dist/utils/getOverviewValue.js.map +1 -0
  242. package/dist/utils/localization.js +433 -0
  243. package/dist/utils/localization.js.map +1 -0
  244. package/dist/utils/pdf-thumbnail-generator.js +91 -0
  245. package/dist/utils/pdf-thumbnail-generator.js.map +1 -0
  246. package/dist/utils/utils.js +94 -0
  247. package/dist/utils/utils.js.map +1 -0
  248. package/package.json +21 -58
  249. package/README.md +0 -82
  250. package/dist/icons.js +0 -692
@@ -0,0 +1,2044 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { css, html, LitElement } from 'lit';
8
+ import { property, state } from 'lit/decorators.js';
9
+ import { styleMap } from 'lit/directives/style-map.js';
10
+ import { msg } from '@lit/localize';
11
+ import { isEmpty } from 'lodash';
12
+ import { saveAs } from 'file-saver';
13
+ import { formatDate } from '../utils/date.js';
14
+ // components
15
+ import './lit-badge.js';
16
+ import '../shared/lit-icon.js';
17
+ import '../shared/lit-icon-button.js';
18
+ import '../shared/lit-select.js';
19
+ import '../shared/lit-overflow-tooltip.js';
20
+ import '../shared/lit-document-thumbnail.js';
21
+ import '../shared/lit-filter-input.js';
22
+ import '../shared/lit-menu.js';
23
+ import '../shared/lit-menu-item.js';
24
+ import '../shared/lit-checkbox.js';
25
+ import '../shared/lit-toggle.js';
26
+ import '../assets/illustration/no-preview.js';
27
+ import '../assets/illustration/not-found.js';
28
+ import '../shared/lit-loading-bar.js';
29
+ import '../components/lit-section-tab.js';
30
+ import './components-settings/attachments-tab-settings.js';
31
+ // pdf.js
32
+ import * as pdfjsLib from 'pdfjs-dist';
33
+ // Set worker source for PDF.js 5.x - compatible with webpack bundlers
34
+ pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.mjs', import.meta.url).toString();
35
+ export class LitAttachmentsTab extends LitElement {
36
+ constructor() {
37
+ super(...arguments);
38
+ this.hideTabWhen = false;
39
+ this.documents = [];
40
+ this.type = 'compact';
41
+ this.scale = 1;
42
+ this.isDocumentLoading = false;
43
+ this.enableSettings = false;
44
+ this.enableThumbnails = true;
45
+ this.thumbnailSize = 40;
46
+ this.enableAdditionalInformation = true;
47
+ this.enableThumbnailDetail = true;
48
+ this.thumbnailPreviewMaxWidth = 300;
49
+ this.thumbnailPreviewMaxHeight = 300;
50
+ this.enableSearchInDocuments = true;
51
+ this.enableComparison = true;
52
+ this.userLang = 'cs';
53
+ this.dateFormat = null;
54
+ this.onSettingsChanged = () => { };
55
+ this.selectedId = '';
56
+ this.pageNumber = 1;
57
+ this.pageCount = 1;
58
+ this.preview = true;
59
+ this.documentData = null;
60
+ this.isOpenModal = false;
61
+ this.filterText = '';
62
+ this.focusedIndex = 0;
63
+ this.isWideLayout = false;
64
+ // Comparison modal state
65
+ this.comparisonModalOpen = false;
66
+ this.comparisonDocumentLeft = '';
67
+ this.comparisonDocumentRight = '';
68
+ this.pageNumberLeft = 1;
69
+ this.pageNumberRight = 1;
70
+ this.pageCountLeft = 1;
71
+ this.pageCountRight = 1;
72
+ this.isDocumentLoadingLeft = false;
73
+ this.isDocumentLoadingRight = false;
74
+ // Context menu with mobile support
75
+ this.contextMenuOpen = false;
76
+ this.contextMenuPosition = null;
77
+ this.contextMenuDocumentId = null;
78
+ // Comparison settings
79
+ this.syncZoom = true;
80
+ this.handleSyncZoomChange = (e) => {
81
+ this.syncZoom = e.target.checked;
82
+ };
83
+ this.canvas = null;
84
+ this.ctx = null;
85
+ this.outerContainer = null;
86
+ // Track active PDF render tasks to avoid "same canvas during multiple render()" error
87
+ this.activeRenderTask = null;
88
+ this.activeRenderTaskLeft = null;
89
+ this.activeRenderTaskRight = null;
90
+ this.isDragging = false;
91
+ this.clickX = 0;
92
+ this.clickY = 0;
93
+ this.prevScrollLeft = 0;
94
+ this.prevScrollTop = 0;
95
+ this.abortController = new AbortController();
96
+ this.resizeObserver = null;
97
+ this.longPressTimer = null;
98
+ // Track blob URLs for cleanup
99
+ this.blobUrls = new Set();
100
+ // Gesture state for pinch zoom
101
+ this.touchStartDistance = 0;
102
+ this.touchStartScale = 1;
103
+ this.isGesturing = false;
104
+ // Double-tap detection
105
+ this.lastTapTime = 0;
106
+ this.doubleTapThreshold = 300; // ms
107
+ this.handleReadFile = (buffer) => new Promise((resolve, reject) => {
108
+ const reader = new FileReader();
109
+ reader.onload = () => resolve(reader);
110
+ reader.onerror = reject;
111
+ if (buffer !== null)
112
+ reader.readAsArrayBuffer(buffer);
113
+ });
114
+ // Pinch zoom handlers for main viewer
115
+ this.handleTouchStartCanvas = (e) => {
116
+ if (e.touches.length === 2) {
117
+ // Prevent default to stop page zoom
118
+ e.preventDefault();
119
+ this.isGesturing = true;
120
+ this.touchStartScale = this.localScale ?? 1;
121
+ // Calculate initial distance between two touches
122
+ const touch1 = e.touches[0];
123
+ const touch2 = e.touches[1];
124
+ this.touchStartDistance = Math.hypot(touch2.clientX - touch1.clientX, touch2.clientY - touch1.clientY);
125
+ }
126
+ else if (e.touches.length === 1) {
127
+ // Double-tap detection
128
+ const currentTime = Date.now();
129
+ const tapGap = currentTime - this.lastTapTime;
130
+ if (tapGap < this.doubleTapThreshold && tapGap > 0) {
131
+ // Double-tap detected - reset zoom
132
+ e.preventDefault();
133
+ this.localScale = 1;
134
+ this.renderPage();
135
+ }
136
+ this.lastTapTime = currentTime;
137
+ }
138
+ };
139
+ this.handleTouchMoveCanvas = (e) => {
140
+ if (e.touches.length === 2 && this.isGesturing) {
141
+ e.preventDefault();
142
+ // Calculate current distance between touches
143
+ const touch1 = e.touches[0];
144
+ const touch2 = e.touches[1];
145
+ const currentDistance = Math.hypot(touch2.clientX - touch1.clientX, touch2.clientY - touch1.clientY);
146
+ // Calculate scale based on distance change
147
+ const scale = (currentDistance / this.touchStartDistance) * this.touchStartScale;
148
+ // Apply constraints (min 0.5x, max 5x)
149
+ this.localScale = Math.max(0.5, Math.min(5, scale));
150
+ this.renderPage();
151
+ }
152
+ };
153
+ this.handleTouchEndCanvas = (e) => {
154
+ if (e.touches.length < 2) {
155
+ this.isGesturing = false;
156
+ }
157
+ };
158
+ // Pinch zoom handlers for comparison panels
159
+ this.handleTouchStartComparison = (e, side) => {
160
+ if (e.touches.length === 2) {
161
+ e.preventDefault();
162
+ this.isGesturing = true;
163
+ if (this.syncZoom) {
164
+ // When sync is enabled, use left scale as reference for both
165
+ this.touchStartScale = this.localScaleLeft ?? 1;
166
+ }
167
+ else {
168
+ // Independent zoom per side
169
+ this.touchStartScale =
170
+ (side === 'left' ? this.localScaleLeft : this.localScaleRight) ?? 1;
171
+ }
172
+ const touch1 = e.touches[0];
173
+ const touch2 = e.touches[1];
174
+ this.touchStartDistance = Math.hypot(touch2.clientX - touch1.clientX, touch2.clientY - touch1.clientY);
175
+ }
176
+ else if (e.touches.length === 1) {
177
+ // Double-tap to reset
178
+ const currentTime = Date.now();
179
+ const tapGap = currentTime - this.lastTapTime;
180
+ if (tapGap < this.doubleTapThreshold && tapGap > 0) {
181
+ e.preventDefault();
182
+ if (this.syncZoom) {
183
+ // Reset both panels
184
+ this.localScaleLeft = 1;
185
+ this.localScaleRight = 1;
186
+ this.renderComparisonPage('left');
187
+ this.renderComparisonPage('right');
188
+ }
189
+ else {
190
+ // Reset only this side
191
+ if (side === 'left') {
192
+ this.localScaleLeft = 1;
193
+ this.renderComparisonPage('left');
194
+ }
195
+ else {
196
+ this.localScaleRight = 1;
197
+ this.renderComparisonPage('right');
198
+ }
199
+ }
200
+ }
201
+ this.lastTapTime = currentTime;
202
+ }
203
+ };
204
+ this.handleTouchMoveComparison = (e, side) => {
205
+ if (e.touches.length === 2 && this.isGesturing) {
206
+ e.preventDefault();
207
+ const touch1 = e.touches[0];
208
+ const touch2 = e.touches[1];
209
+ const currentDistance = Math.hypot(touch2.clientX - touch1.clientX, touch2.clientY - touch1.clientY);
210
+ const scale = (currentDistance / this.touchStartDistance) * this.touchStartScale;
211
+ const constrainedScale = Math.max(0.5, Math.min(5, scale));
212
+ if (this.syncZoom) {
213
+ // Zoom both panels together
214
+ this.localScaleLeft = constrainedScale;
215
+ this.localScaleRight = constrainedScale;
216
+ this.renderComparisonPage('left');
217
+ this.renderComparisonPage('right');
218
+ }
219
+ else {
220
+ // Zoom only active panel
221
+ if (side === 'left') {
222
+ this.localScaleLeft = constrainedScale;
223
+ this.renderComparisonPage('left');
224
+ }
225
+ else {
226
+ this.localScaleRight = constrainedScale;
227
+ this.renderComparisonPage('right');
228
+ }
229
+ }
230
+ }
231
+ };
232
+ this.handleTouchEndComparison = (e) => {
233
+ if (e.touches.length < 2) {
234
+ this.isGesturing = false;
235
+ }
236
+ };
237
+ // Mouse wheel zoom handlers
238
+ this.handleWheelZoom = (e) => {
239
+ // Only zoom if Ctrl/Cmd key is pressed (standard UX pattern)
240
+ if (e.ctrlKey || e.metaKey) {
241
+ e.preventDefault();
242
+ const delta = e.deltaY > 0 ? 0.9 : 1.1; // Zoom out or in
243
+ const currentScale = this.localScale ?? 1;
244
+ this.localScale = Math.max(0.5, Math.min(5, currentScale * delta));
245
+ this.renderPage();
246
+ }
247
+ };
248
+ this.handleWheelZoomComparison = (e, side) => {
249
+ if (e.ctrlKey || e.metaKey) {
250
+ e.preventDefault();
251
+ const delta = e.deltaY > 0 ? 0.9 : 1.1;
252
+ if (this.syncZoom) {
253
+ const currentScale = this.localScaleLeft ?? 1;
254
+ const newScale = Math.max(0.5, Math.min(5, currentScale * delta));
255
+ this.localScaleLeft = newScale;
256
+ this.localScaleRight = newScale;
257
+ this.renderComparisonPage('left');
258
+ this.renderComparisonPage('right');
259
+ }
260
+ else {
261
+ const currentScale = (side === 'left' ? this.localScaleLeft : this.localScaleRight) ?? 1;
262
+ const newScale = Math.max(0.5, Math.min(5, currentScale * delta));
263
+ if (side === 'left') {
264
+ this.localScaleLeft = newScale;
265
+ this.renderComparisonPage('left');
266
+ }
267
+ else {
268
+ this.localScaleRight = newScale;
269
+ this.renderComparisonPage('right');
270
+ }
271
+ }
272
+ }
273
+ };
274
+ this.handleKeyDown = (e) => {
275
+ // ESC key to close comparison modal
276
+ if (e.key === 'Escape' && this.comparisonModalOpen) {
277
+ e.preventDefault();
278
+ this.closeComparisonModal();
279
+ return;
280
+ }
281
+ // ESC key to close context menu
282
+ if (e.key === 'Escape' && this.contextMenuOpen) {
283
+ e.preventDefault();
284
+ this.closeContextMenu();
285
+ return;
286
+ }
287
+ // Only handle keyboard navigation in compact mode and when modal is not open
288
+ if (this.type !== 'compact' || this.comparisonModalOpen)
289
+ return;
290
+ const filteredDocs = this.getFilteredDocuments();
291
+ if (!filteredDocs.length)
292
+ return;
293
+ switch (e.key) {
294
+ case 'ArrowDown':
295
+ e.preventDefault();
296
+ this.focusedIndex = Math.min(this.focusedIndex + 1, filteredDocs.length - 1);
297
+ this.scrollToFocusedItem();
298
+ break;
299
+ case 'ArrowUp':
300
+ e.preventDefault();
301
+ this.focusedIndex = Math.max(this.focusedIndex - 1, 0);
302
+ this.scrollToFocusedItem();
303
+ break;
304
+ case 'Enter':
305
+ e.preventDefault();
306
+ const focusedDoc = filteredDocs[this.focusedIndex];
307
+ if (focusedDoc?.id) {
308
+ this.handleDocumentClick(focusedDoc.id);
309
+ }
310
+ break;
311
+ }
312
+ };
313
+ // Context menu handlers
314
+ this.handleContextMenu = (e, docId) => {
315
+ e.preventDefault();
316
+ e.stopPropagation();
317
+ // Don't show context menu if comparison is disabled
318
+ if (!this.enableComparison)
319
+ return;
320
+ // Don't show context menu if it would be empty (same document selected)
321
+ // Allow default browser context menu by not preventing default
322
+ if (docId === this.selectedId) {
323
+ return;
324
+ }
325
+ // Only prevent default when we're actually showing our custom menu
326
+ this.contextMenuDocumentId = docId;
327
+ this.contextMenuPosition = { x: e.clientX, y: e.clientY };
328
+ this.contextMenuOpen = true;
329
+ // Add listeners to close context menu on scroll or click outside
330
+ this.addContextMenuListeners();
331
+ };
332
+ this.closeContextMenu = () => {
333
+ this.contextMenuOpen = false;
334
+ this.contextMenuPosition = null;
335
+ this.contextMenuDocumentId = null;
336
+ // Remove listeners
337
+ this.removeContextMenuListeners();
338
+ };
339
+ this.handleContextMenuScroll = () => {
340
+ if (this.contextMenuOpen) {
341
+ this.closeContextMenu();
342
+ }
343
+ };
344
+ this.handleContextMenuClickOutside = (e) => {
345
+ if (this.contextMenuOpen) {
346
+ const contextMenu = this.shadowRoot?.querySelector('.context-menu');
347
+ if (contextMenu && !contextMenu.contains(e.target)) {
348
+ this.closeContextMenu();
349
+ }
350
+ }
351
+ };
352
+ this.addContextMenuListeners = () => {
353
+ // Listen to scroll events on the document list section
354
+ const scrollContainer = this.shadowRoot?.querySelector('.documents-list-section');
355
+ if (scrollContainer) {
356
+ scrollContainer.addEventListener('scroll', this.handleContextMenuScroll);
357
+ }
358
+ // Listen to window scroll
359
+ window.addEventListener('scroll', this.handleContextMenuScroll, true);
360
+ // Listen to clicks outside
361
+ setTimeout(() => {
362
+ document.addEventListener('click', this.handleContextMenuClickOutside);
363
+ }, 0);
364
+ };
365
+ this.removeContextMenuListeners = () => {
366
+ const scrollContainer = this.shadowRoot?.querySelector('.documents-list-section');
367
+ if (scrollContainer) {
368
+ scrollContainer.removeEventListener('scroll', this.handleContextMenuScroll);
369
+ }
370
+ window.removeEventListener('scroll', this.handleContextMenuScroll, true);
371
+ document.removeEventListener('click', this.handleContextMenuClickOutside);
372
+ };
373
+ // Mobile touch handlers for long press
374
+ this.handleTouchStart = (e, docId) => {
375
+ if (!this.enableComparison)
376
+ return;
377
+ // Don't show context menu if it would be empty (same document selected)
378
+ if (docId === this.selectedId) {
379
+ return;
380
+ }
381
+ this.longPressTimer = window.setTimeout(() => {
382
+ const touch = e.touches[0];
383
+ this.handleContextMenu(new MouseEvent('contextmenu', {
384
+ clientX: touch.clientX,
385
+ clientY: touch.clientY,
386
+ }), docId);
387
+ }, 500); // 500ms for long press
388
+ };
389
+ this.handleTouchEnd = () => {
390
+ if (this.longPressTimer) {
391
+ clearTimeout(this.longPressTimer);
392
+ this.longPressTimer = null;
393
+ }
394
+ };
395
+ this.cancelLongPress = () => {
396
+ if (this.longPressTimer) {
397
+ clearTimeout(this.longPressTimer);
398
+ this.longPressTimer = null;
399
+ }
400
+ };
401
+ // Comparison modal methods
402
+ this.openComparisonModal = (leftId, rightId) => {
403
+ // Close context menu first
404
+ this.closeContextMenu();
405
+ this.comparisonDocumentLeft = leftId;
406
+ this.comparisonDocumentRight = rightId;
407
+ this.comparisonModalOpen = true;
408
+ this.isDocumentLoadingLeft = false;
409
+ this.isDocumentLoadingRight = false;
410
+ // Prevent body scroll
411
+ document.body.style.overflow = 'hidden';
412
+ // Load both documents
413
+ this.loadComparisonDocuments();
414
+ };
415
+ this.closeComparisonModal = () => {
416
+ this.comparisonModalOpen = false;
417
+ this.comparisonDocumentLeft = '';
418
+ this.comparisonDocumentRight = '';
419
+ this.selectedDocumentLeftCanvas = null;
420
+ this.selectedDocumentRightCanvas = null;
421
+ this.isDocumentLoadingLeft = false;
422
+ this.isDocumentLoadingRight = false;
423
+ // Restore body scroll
424
+ document.body.style.overflow = '';
425
+ };
426
+ this.handleBackdropClick = (e) => {
427
+ // Only close if clicking the backdrop itself, not its children
428
+ if (e.target === e.currentTarget) {
429
+ this.closeComparisonModal();
430
+ }
431
+ };
432
+ this.swapComparisonSides = () => {
433
+ const temp = this.comparisonDocumentLeft;
434
+ this.comparisonDocumentLeft = this.comparisonDocumentRight;
435
+ this.comparisonDocumentRight = temp;
436
+ const tempDoc = this.selectedDocumentLeftCanvas;
437
+ this.selectedDocumentLeftCanvas = this.selectedDocumentRightCanvas;
438
+ this.selectedDocumentRightCanvas = tempDoc;
439
+ const tempPage = this.pageNumberLeft;
440
+ this.pageNumberLeft = this.pageNumberRight;
441
+ this.pageNumberRight = tempPage;
442
+ const tempCount = this.pageCountLeft;
443
+ this.pageCountLeft = this.pageCountRight;
444
+ this.pageCountRight = tempCount;
445
+ const tempScale = this.localScaleLeft;
446
+ this.localScaleLeft = this.localScaleRight;
447
+ this.localScaleRight = tempScale;
448
+ // Re-render both canvases
449
+ this.renderComparisonPage('left');
450
+ this.renderComparisonPage('right');
451
+ };
452
+ }
453
+ disconnectedCallback() {
454
+ super.disconnectedCallback();
455
+ this.abortController.abort();
456
+ if (this.documentData && this.documentData.cancel) {
457
+ this.documentData.cancel();
458
+ this.documentData = null;
459
+ }
460
+ // Cancel any in-progress PDF render tasks
461
+ if (this.activeRenderTask) {
462
+ this.activeRenderTask.cancel();
463
+ this.activeRenderTask = null;
464
+ }
465
+ if (this.activeRenderTaskLeft) {
466
+ this.activeRenderTaskLeft.cancel();
467
+ this.activeRenderTaskLeft = null;
468
+ }
469
+ if (this.activeRenderTaskRight) {
470
+ this.activeRenderTaskRight.cancel();
471
+ this.activeRenderTaskRight = null;
472
+ }
473
+ this.removeEventListener('keydown', this.handleKeyDown);
474
+ if (this.resizeObserver) {
475
+ this.resizeObserver.disconnect();
476
+ this.resizeObserver = null;
477
+ }
478
+ // Clean up blob URLs
479
+ this.revokeBlobUrls();
480
+ // Remove context menu listeners
481
+ this.removeContextMenuListeners();
482
+ }
483
+ /**
484
+ * Revoke all tracked blob URLs to prevent memory leaks
485
+ */
486
+ revokeBlobUrls() {
487
+ this.blobUrls.forEach((url) => URL.revokeObjectURL(url));
488
+ this.blobUrls.clear();
489
+ }
490
+ /**
491
+ * Create and track a blob URL for cleanup
492
+ */
493
+ createTrackedBlobUrl(blob) {
494
+ const url = URL.createObjectURL(blob);
495
+ this.blobUrls.add(url);
496
+ return url;
497
+ }
498
+ connectedCallback() {
499
+ super.connectedCallback();
500
+ this.localScale = this.scale;
501
+ this.addEventListener('keydown', this.handleKeyDown);
502
+ }
503
+ async firstUpdated() {
504
+ this.canvas = this.shadowRoot?.querySelector('canvas') ?? null;
505
+ this.ctx = this.canvas?.getContext('2d');
506
+ this.outerContainer = this.shadowRoot?.querySelector('.document-container') || null;
507
+ // Setup ResizeObserver for container width tracking
508
+ const container = this.shadowRoot?.querySelector('.attachments-container');
509
+ if (container) {
510
+ this.resizeObserver = new ResizeObserver((entries) => {
511
+ for (const entry of entries) {
512
+ this.isWideLayout = entry.contentRect.width >= 1000;
513
+ }
514
+ });
515
+ this.resizeObserver.observe(container);
516
+ }
517
+ await this.renderPage();
518
+ }
519
+ updated(_changedProperties) {
520
+ super.updated(_changedProperties);
521
+ if (_changedProperties.has('documents')) {
522
+ // Clean up blob URLs when documents change
523
+ this.revokeBlobUrls();
524
+ const newSelectedId = this.initialSelection || (this.documents?.[0]?.id ?? '');
525
+ if (isEmpty(this.documents)) {
526
+ // Reset state when no documents
527
+ this.selectedDocument = null;
528
+ this.preview = true;
529
+ this.pageNumber = 1;
530
+ this.pageCount = 1;
531
+ this.selectedId = '';
532
+ if (this.documentData && this.documentData.cancel) {
533
+ this.documentData.cancel();
534
+ this.documentData = null;
535
+ }
536
+ }
537
+ else if (!this.hideTabWhen) {
538
+ // Force reset and reload when documents change
539
+ this.selectedDocument = null;
540
+ this.preview = true;
541
+ if (this.documentData && this.documentData.cancel) {
542
+ this.documentData.cancel();
543
+ this.documentData = null;
544
+ }
545
+ this.selectedId = newSelectedId;
546
+ this.focusedIndex = 0;
547
+ this.handleDocumentClick(this.selectedId);
548
+ }
549
+ }
550
+ if (_changedProperties.has('filterText')) {
551
+ // Reset focused index when filter changes
552
+ this.focusedIndex = 0;
553
+ }
554
+ if (_changedProperties.has('selectedId')) {
555
+ if (this.documentData && this.documentData.cancel) {
556
+ this.documentData.cancel();
557
+ this.documentData = null;
558
+ }
559
+ }
560
+ }
561
+ /**
562
+ * Shared method to fetch document data from either onClick handler or URL
563
+ */
564
+ async fetchDocumentData(docId) {
565
+ if (this.onClick) {
566
+ const documentData = await this.onClick(docId);
567
+ const reader = await this.handleReadFile(documentData);
568
+ return reader.result;
569
+ }
570
+ else {
571
+ const document = this.documents?.find((doc) => doc.id === docId);
572
+ if (!document?.dmsf_src) {
573
+ throw new Error('Document not found or missing source URL');
574
+ }
575
+ return await fetch(document.dmsf_src).then((res) => res.arrayBuffer());
576
+ }
577
+ }
578
+ async loadDocumentData(documentData) {
579
+ try {
580
+ const selectedDoc = this.documents?.find((doc) => doc.id === this.selectedId);
581
+ if (!selectedDoc) {
582
+ console.error('Selected document not found in documents array.');
583
+ return;
584
+ }
585
+ if (selectedDoc.file_type === 'application/pdf') {
586
+ // PDF.js 3.x - simpler API that works with webpack bundlers
587
+ const loadingTask = pdfjsLib.getDocument(documentData);
588
+ this.selectedDocument = await loadingTask.promise;
589
+ if (this.selectedDocument) {
590
+ this.pageCount = this.selectedDocument.numPages;
591
+ }
592
+ this.preview = true;
593
+ }
594
+ else if (selectedDoc.file_type?.startsWith('image/')) {
595
+ const img = new Image();
596
+ img.onload = () => {
597
+ this.selectedDocument = img;
598
+ this.pageCount = 1;
599
+ this.preview = true;
600
+ this.renderPage();
601
+ };
602
+ const blob = new Blob([documentData], { type: selectedDoc.file_type });
603
+ img.src = this.createTrackedBlobUrl(blob);
604
+ return;
605
+ }
606
+ else {
607
+ this.selectedDocument = documentData;
608
+ this.preview = false;
609
+ }
610
+ this.pageNumber = 1;
611
+ await this.renderPage();
612
+ }
613
+ catch (error) {
614
+ console.error('Error loading document data:', error);
615
+ }
616
+ }
617
+ async handleDocumentClick(id) {
618
+ this.selectedId = id;
619
+ this.localScale = this.scale;
620
+ // Update focused index to match the clicked document
621
+ const filteredDocs = this.getFilteredDocuments();
622
+ const clickedIndex = filteredDocs.findIndex((doc) => doc.id === id);
623
+ if (clickedIndex !== -1) {
624
+ this.focusedIndex = clickedIndex;
625
+ }
626
+ try {
627
+ this.isDocumentLoading = true;
628
+ const documentData = await this.fetchDocumentData(id);
629
+ this.isDocumentLoading = false;
630
+ this.loadDocumentData(documentData);
631
+ }
632
+ catch (error) {
633
+ console.error('Error fetching document:', error);
634
+ this.isDocumentLoading = false;
635
+ }
636
+ }
637
+ /**
638
+ * Shared rendering method for both main viewer and comparison panels
639
+ */
640
+ async renderDocumentToCanvas(canvas, ctx, container, document, pageNumber, userScale, abortSignal, onRenderTask) {
641
+ const containerWidth = container.offsetWidth;
642
+ const dpr = window.devicePixelRatio || 1;
643
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
644
+ try {
645
+ if ('getPage' in document) {
646
+ // PDF rendering
647
+ const page = await document.getPage(pageNumber);
648
+ const viewportBase = page.getViewport({ scale: 1 });
649
+ const fitScale = containerWidth / viewportBase.width;
650
+ const logicalScale = fitScale * userScale;
651
+ const renderScale = fitScale * Math.max(userScale, 1);
652
+ const renderViewport = page.getViewport({ scale: renderScale * dpr });
653
+ canvas.width = renderViewport.width;
654
+ canvas.height = renderViewport.height;
655
+ canvas.style.width = `${viewportBase.width * logicalScale}px`;
656
+ canvas.style.height = 'auto';
657
+ const renderOptions = {
658
+ canvasContext: ctx,
659
+ viewport: renderViewport,
660
+ };
661
+ if (abortSignal) {
662
+ renderOptions.signal = abortSignal;
663
+ }
664
+ const renderTask = page.render(renderOptions);
665
+ onRenderTask?.(renderTask);
666
+ await renderTask.promise;
667
+ onRenderTask?.(null);
668
+ }
669
+ else if (document instanceof HTMLImageElement) {
670
+ // Image rendering
671
+ const img = document;
672
+ const fitScale = containerWidth / img.naturalWidth;
673
+ const logicalScale = fitScale * userScale;
674
+ const renderScale = fitScale * Math.max(userScale, 1);
675
+ const renderWidth = img.naturalWidth * renderScale * dpr;
676
+ const renderHeight = img.naturalHeight * renderScale * dpr;
677
+ canvas.width = renderWidth;
678
+ canvas.height = renderHeight;
679
+ canvas.style.width = `${img.naturalWidth * logicalScale}px`;
680
+ canvas.style.height = 'auto';
681
+ ctx.drawImage(img, 0, 0, renderWidth, renderHeight);
682
+ }
683
+ }
684
+ catch (error) {
685
+ onRenderTask?.(null);
686
+ // Ignore cancellation – it's expected when a new render supersedes this one
687
+ if (error instanceof Error &&
688
+ error.name !== 'AbortError' &&
689
+ error.name !== 'RenderingCancelledException') {
690
+ console.error('Error rendering document:', error);
691
+ }
692
+ throw error;
693
+ }
694
+ }
695
+ async renderPage() {
696
+ if (!this.selectedDocument)
697
+ return;
698
+ // Cancel any in-progress render on this canvas before starting a new one
699
+ if (this.activeRenderTask) {
700
+ this.activeRenderTask.cancel();
701
+ this.activeRenderTask = null;
702
+ }
703
+ // Ensure canvas elements are initialized
704
+ if (!this.canvas || !this.ctx || !this.outerContainer) {
705
+ this.canvas = this.shadowRoot?.querySelector('canvas') ?? null;
706
+ this.ctx = this.canvas?.getContext('2d');
707
+ this.outerContainer = this.shadowRoot?.querySelector('.document-container') || null;
708
+ }
709
+ if (!this.canvas || !this.ctx || !this.outerContainer)
710
+ return;
711
+ this.canvas.style.display = this.preview ? 'block' : 'none';
712
+ if (!this.preview)
713
+ return;
714
+ try {
715
+ await this.renderDocumentToCanvas(this.canvas, this.ctx, this.outerContainer, this.selectedDocument, this.pageNumber ?? 1, this.localScale ?? 1, this.abortController.signal, (task) => {
716
+ this.activeRenderTask = task;
717
+ });
718
+ }
719
+ catch (error) {
720
+ // Error already logged in renderDocumentToCanvas (cancellations are silently ignored)
721
+ }
722
+ }
723
+ getSelectedDocumentName() {
724
+ if (isEmpty(this.documents))
725
+ return '';
726
+ const selectedDoc = this.documents?.find((doc) => doc.id === this.selectedId);
727
+ return selectedDoc?.name || msg('Neznámý dokument');
728
+ }
729
+ handlePageChange(next) {
730
+ const newPage = next ? (this.pageNumber ?? 1) + 1 : (this.pageNumber ?? 1) - 1;
731
+ if (newPage >= 1 && newPage <= (this.pageCount ?? 1)) {
732
+ this.pageNumber = newPage;
733
+ this.renderPage();
734
+ }
735
+ }
736
+ async handleDownload() {
737
+ if (!this.selectedDocument) {
738
+ console.error('No document selected for download.');
739
+ return;
740
+ }
741
+ const selectedDoc = this.documents?.find((doc) => doc.id === this.selectedId);
742
+ if (!selectedDoc) {
743
+ console.error('Selected document not found.');
744
+ return;
745
+ }
746
+ try {
747
+ let blob;
748
+ const filename = selectedDoc.name || 'document';
749
+ if (this.onClick) {
750
+ // Fetch document via onClick handler
751
+ const documentData = await this.onClick(this.selectedId);
752
+ blob = new Blob([documentData.data || documentData], {
753
+ type: selectedDoc.file_type || 'application/octet-stream',
754
+ });
755
+ }
756
+ else if (selectedDoc.dmsf_src) {
757
+ // Fetch document from URL
758
+ const response = await fetch(selectedDoc.dmsf_src);
759
+ if (!response.ok) {
760
+ throw new Error(`Failed to fetch document: ${response.statusText}`);
761
+ }
762
+ blob = await response.blob();
763
+ }
764
+ else {
765
+ console.error('No download method available for document.');
766
+ return;
767
+ }
768
+ // Use FileSaver to download
769
+ saveAs(blob, filename);
770
+ }
771
+ catch (error) {
772
+ console.error('Error downloading document:', error);
773
+ }
774
+ }
775
+ handleZoom(increase) {
776
+ const currentScale = this.localScale ?? 1;
777
+ this.localScale = increase ? currentScale * 1.1 : currentScale / 1.1;
778
+ this.renderPage();
779
+ }
780
+ handleMouseDown(e) {
781
+ if ((this.localScale ?? 1) <= 1)
782
+ return;
783
+ this.isDragging = true;
784
+ this.clickX = e.clientX;
785
+ this.clickY = e.clientY;
786
+ if (this.outerContainer) {
787
+ this.prevScrollLeft = this.outerContainer.scrollLeft;
788
+ this.prevScrollTop = this.outerContainer.scrollTop;
789
+ }
790
+ }
791
+ handleMouseMove(e) {
792
+ if (!this.isDragging)
793
+ return;
794
+ const deltaX = e.clientX - this.clickX;
795
+ const deltaY = e.clientY - this.clickY;
796
+ if (this.outerContainer) {
797
+ this.outerContainer.scrollLeft = this.prevScrollLeft - deltaX;
798
+ this.outerContainer.scrollTop = this.prevScrollTop - deltaY;
799
+ }
800
+ }
801
+ handleMouseUp() {
802
+ this.isDragging = false;
803
+ }
804
+ toggleModal() {
805
+ this.isOpenModal = !this.isOpenModal;
806
+ }
807
+ async onSettingsChangedCallback(value) {
808
+ if (value?.scale !== undefined) {
809
+ this.scale = value.scale;
810
+ this.localScale = value.scale;
811
+ }
812
+ if (value?.type !== undefined) {
813
+ this.type = value.type;
814
+ }
815
+ if (value?.enableThumbnails !== undefined) {
816
+ this.enableThumbnails = value.enableThumbnails;
817
+ }
818
+ if (value?.thumbnailSize !== undefined) {
819
+ this.thumbnailSize = value.thumbnailSize;
820
+ }
821
+ if (value?.enableAdditionalInformation !== undefined) {
822
+ this.enableAdditionalInformation = value.enableAdditionalInformation;
823
+ }
824
+ if (value?.enableThumbnailDetail !== undefined) {
825
+ this.enableThumbnailDetail = value.enableThumbnailDetail;
826
+ }
827
+ if (value?.enableSearchInDocuments !== undefined) {
828
+ this.enableSearchInDocuments = value.enableSearchInDocuments;
829
+ }
830
+ // Force re-render after property changes
831
+ this.requestUpdate();
832
+ await this.renderPage();
833
+ this.dispatchEvent(new CustomEvent('onSettingsChanged', {
834
+ bubbles: true,
835
+ composed: true,
836
+ detail: value,
837
+ }));
838
+ this.onSettingsChanged?.(value);
839
+ }
840
+ getThumbnailUrl(doc) {
841
+ return doc.thumbnail;
842
+ }
843
+ getFilteredDocuments() {
844
+ if (!this.documents)
845
+ return [];
846
+ if (!this.filterText.trim())
847
+ return this.documents;
848
+ const searchTerm = this.filterText.toLowerCase().trim();
849
+ return this.documents.filter((doc) => {
850
+ const nameMatch = doc.name?.toLowerCase().includes(searchTerm);
851
+ const metaMatch = Array.isArray(doc.meta) && doc.meta.some((meta) => meta.toLowerCase().includes(searchTerm));
852
+ const userMatch = doc.userName?.toLowerCase().includes(searchTerm);
853
+ return nameMatch || metaMatch || userMatch;
854
+ });
855
+ }
856
+ scrollToFocusedItem() {
857
+ requestAnimationFrame(() => {
858
+ const focusedElement = this.shadowRoot?.querySelector(`.document-label[data-index="${this.focusedIndex}"]`);
859
+ if (focusedElement) {
860
+ focusedElement.scrollIntoView({ block: 'center', behavior: 'smooth' });
861
+ }
862
+ });
863
+ }
864
+ async loadComparisonDocuments() {
865
+ // Load both documents in parallel
866
+ const promises = [];
867
+ if (this.comparisonDocumentLeft) {
868
+ promises.push(this.loadComparisonDocument(this.comparisonDocumentLeft, 'left'));
869
+ }
870
+ if (this.comparisonDocumentRight) {
871
+ promises.push(this.loadComparisonDocument(this.comparisonDocumentRight, 'right'));
872
+ }
873
+ // Wait for both documents to load
874
+ await Promise.all(promises);
875
+ }
876
+ async loadComparisonDocument(docId, side) {
877
+ try {
878
+ // Set loading state
879
+ if (side === 'left') {
880
+ this.isDocumentLoadingLeft = true;
881
+ }
882
+ else {
883
+ this.isDocumentLoadingRight = true;
884
+ }
885
+ const documentData = await this.fetchDocumentData(docId);
886
+ await this.loadComparisonDocumentData(documentData, docId, side);
887
+ }
888
+ catch (error) {
889
+ console.error(`Error loading comparison document ${docId}:`, error);
890
+ }
891
+ finally {
892
+ // Clear loading state
893
+ if (side === 'left') {
894
+ this.isDocumentLoadingLeft = false;
895
+ }
896
+ else {
897
+ this.isDocumentLoadingRight = false;
898
+ }
899
+ }
900
+ }
901
+ async loadComparisonDocumentData(documentData, docId, side) {
902
+ const doc = this.documents?.find((d) => d.id === docId);
903
+ if (!doc)
904
+ return;
905
+ try {
906
+ if (doc.file_type === 'application/pdf') {
907
+ const loadingTask = pdfjsLib.getDocument({ data: documentData });
908
+ const pdfDoc = await loadingTask.promise;
909
+ if (side === 'left') {
910
+ this.selectedDocumentLeftCanvas = pdfDoc;
911
+ this.pageCountLeft = pdfDoc.numPages;
912
+ this.pageNumberLeft = 1;
913
+ this.localScaleLeft = this.scale;
914
+ }
915
+ else {
916
+ this.selectedDocumentRightCanvas = pdfDoc;
917
+ this.pageCountRight = pdfDoc.numPages;
918
+ this.pageNumberRight = 1;
919
+ this.localScaleRight = this.scale;
920
+ }
921
+ }
922
+ else if (doc.file_type?.startsWith('image/')) {
923
+ const img = new Image();
924
+ const blob = new Blob([documentData], { type: doc.file_type });
925
+ img.src = this.createTrackedBlobUrl(blob);
926
+ await new Promise((resolve) => {
927
+ img.onload = () => {
928
+ if (side === 'left') {
929
+ this.selectedDocumentLeftCanvas = img;
930
+ this.pageCountLeft = 1;
931
+ this.pageNumberLeft = 1;
932
+ this.localScaleLeft = this.scale;
933
+ }
934
+ else {
935
+ this.selectedDocumentRightCanvas = img;
936
+ this.pageCountRight = 1;
937
+ this.pageNumberRight = 1;
938
+ this.localScaleRight = this.scale;
939
+ }
940
+ resolve(true);
941
+ };
942
+ });
943
+ }
944
+ // Render the canvas after loading
945
+ await this.renderComparisonPage(side);
946
+ }
947
+ catch (error) {
948
+ console.error(`Error loading document data for ${side}:`, error);
949
+ }
950
+ }
951
+ async renderComparisonPage(side) {
952
+ // Cancel any in-progress render on this side's canvas before starting a new one
953
+ if (side === 'left') {
954
+ if (this.activeRenderTaskLeft) {
955
+ this.activeRenderTaskLeft.cancel();
956
+ this.activeRenderTaskLeft = null;
957
+ }
958
+ }
959
+ else {
960
+ if (this.activeRenderTaskRight) {
961
+ this.activeRenderTaskRight.cancel();
962
+ this.activeRenderTaskRight = null;
963
+ }
964
+ }
965
+ const canvas = this.shadowRoot?.querySelector(`#comparison-canvas-${side}`);
966
+ if (!canvas)
967
+ return;
968
+ const ctx = canvas.getContext('2d');
969
+ if (!ctx)
970
+ return;
971
+ const document = side === 'left' ? this.selectedDocumentLeftCanvas : this.selectedDocumentRightCanvas;
972
+ if (!document)
973
+ return;
974
+ const pageNumber = side === 'left' ? this.pageNumberLeft : this.pageNumberRight;
975
+ const userScale = (side === 'left' ? this.localScaleLeft : this.localScaleRight) ?? 1;
976
+ const container = this.shadowRoot?.querySelector(`#comparison-${side}-container`);
977
+ if (!container)
978
+ return;
979
+ try {
980
+ await this.renderDocumentToCanvas(canvas, ctx, container, document, pageNumber, userScale, undefined, (task) => {
981
+ if (side === 'left') {
982
+ this.activeRenderTaskLeft = task;
983
+ }
984
+ else {
985
+ this.activeRenderTaskRight = task;
986
+ }
987
+ });
988
+ }
989
+ catch (error) {
990
+ // Cancellations are silently ignored inside renderDocumentToCanvas
991
+ if (error instanceof Error &&
992
+ error.name !== 'AbortError' &&
993
+ error.name !== 'RenderingCancelledException') {
994
+ console.error(`Error rendering comparison page for ${side}:`, error);
995
+ }
996
+ }
997
+ }
998
+ handleComparisonPageChange(side, next) {
999
+ const pageNumber = side === 'left' ? this.pageNumberLeft : this.pageNumberRight;
1000
+ const pageCount = side === 'left' ? this.pageCountLeft : this.pageCountRight;
1001
+ const newPage = next ? pageNumber + 1 : pageNumber - 1;
1002
+ if (newPage >= 1 && newPage <= pageCount) {
1003
+ if (side === 'left') {
1004
+ this.pageNumberLeft = newPage;
1005
+ }
1006
+ else {
1007
+ this.pageNumberRight = newPage;
1008
+ }
1009
+ this.renderComparisonPage(side);
1010
+ }
1011
+ }
1012
+ handleComparisonZoom(side, increase) {
1013
+ const delta = increase ? 1.1 : 1 / 1.1;
1014
+ if (this.syncZoom) {
1015
+ // Apply to both sides
1016
+ this.localScaleLeft = (this.localScaleLeft ?? 1) * delta;
1017
+ this.localScaleRight = (this.localScaleRight ?? 1) * delta;
1018
+ this.renderComparisonPage('left');
1019
+ this.renderComparisonPage('right');
1020
+ }
1021
+ else {
1022
+ // Apply only to active side
1023
+ if (side === 'left') {
1024
+ this.localScaleLeft = (this.localScaleLeft ?? 1) * delta;
1025
+ this.renderComparisonPage('left');
1026
+ }
1027
+ else {
1028
+ this.localScaleRight = (this.localScaleRight ?? 1) * delta;
1029
+ this.renderComparisonPage('right');
1030
+ }
1031
+ }
1032
+ }
1033
+ render() {
1034
+ if (this.hideTabWhen)
1035
+ return null;
1036
+ return html `
1037
+ <div
1038
+ class="attachments-container ${this.type === 'compact' && this.isWideLayout
1039
+ ? 'compact-layout'
1040
+ : ''}"
1041
+ tabindex="0"
1042
+ >
1043
+ <div class="documents-list-section">
1044
+ ${this.type === 'compact'
1045
+ ? html ` ${this.enableSearchInDocuments
1046
+ ? html `
1047
+ <lit-filter-input
1048
+ .value="${this.filterText}"
1049
+ .placeholder="${msg('Hledat dokumenty...')}"
1050
+ .onChange="${(value) => {
1051
+ this.filterText = value;
1052
+ }}"
1053
+ ></lit-filter-input>
1054
+ `
1055
+ : null}
1056
+ ${this.getFilteredDocuments().length === 0 &&
1057
+ this.filterText &&
1058
+ this.enableSearchInDocuments
1059
+ ? html `
1060
+ <div class="no-results-message">
1061
+ <lit-icon icon="search" size="1.5rem"></lit-icon>
1062
+ <span>${msg('Žádné dokumenty nenalezeny')}</span>
1063
+ </div>
1064
+ `
1065
+ : this.getFilteredDocuments().map((doc, index) => html `
1066
+ <div
1067
+ class="document-label ${this.selectedId == doc.id
1068
+ ? 'selected'
1069
+ : ''} ${this.focusedIndex === index
1070
+ ? 'focused'
1071
+ : ''}"
1072
+ data-index="${index}"
1073
+ @click=${() => doc.id && this.handleDocumentClick(doc.id)}
1074
+ @contextmenu="${(e) => this.handleContextMenu(e, doc.id)}"
1075
+ @touchstart="${(e) => this.handleTouchStart(e, doc.id)}"
1076
+ @touchend="${this.handleTouchEnd}"
1077
+ @touchmove="${this.cancelLongPress}"
1078
+ >
1079
+ <div class="document-item" id="${doc.id}">
1080
+ ${this.enableThumbnails
1081
+ ? html `
1082
+ <lit-document-thumbnail
1083
+ .thumbnail="${this.getThumbnailUrl(doc)}"
1084
+ .fileType="${doc.file_type}"
1085
+ .size="${this.thumbnailSize}"
1086
+ .enableThumbnailDetail="${this
1087
+ .enableThumbnailDetail}"
1088
+ .previewMaxWidth="${this
1089
+ .thumbnailPreviewMaxWidth}"
1090
+ .previewMaxHeight="${this
1091
+ .thumbnailPreviewMaxHeight}"
1092
+ ></lit-document-thumbnail>
1093
+ `
1094
+ : null}
1095
+ <div class="document-item-content">
1096
+ <div class="document-name">
1097
+ <span class="document-name-text">
1098
+ <lit-overflow-tooltip
1099
+ label="${doc.name ||
1100
+ `${msg('Dokument')} ${index + 1}`}"
1101
+ >
1102
+ ${doc.name ||
1103
+ `${msg('Dokument')} ${index + 1}`}
1104
+ </lit-overflow-tooltip>
1105
+ </span>
1106
+ ${doc.meta && doc.meta.length > 0
1107
+ ? doc.meta.map((metaItem) => html `<lit-badge
1108
+ content="neutral"
1109
+ .text=${metaItem}
1110
+ ></lit-badge>`)
1111
+ : null}
1112
+ </div>
1113
+ ${this.enableAdditionalInformation &&
1114
+ (doc.dateOfUpload || doc.userName)
1115
+ ? html `
1116
+ <div class="document-info">
1117
+ ${doc.dateOfUpload
1118
+ ? html `${formatDate(doc.dateOfUpload, this.userLang || 'cs', true, this.dateFormat)}`
1119
+ : null}
1120
+ ${doc.dateOfUpload && doc.userName
1121
+ ? html ` • `
1122
+ : null}
1123
+ ${doc.userName
1124
+ ? html `${doc.userName}`
1125
+ : null}
1126
+ </div>
1127
+ `
1128
+ : null}
1129
+ </div>
1130
+ </div>
1131
+
1132
+ <!-- ${this.selectedId == doc.id
1133
+ ? html `
1134
+ <div class="document-checked">
1135
+ <span>${msg('Zobrazen náhled')}</span>
1136
+ </div>
1137
+ `
1138
+ : html `
1139
+ <div class="document-unchecked">
1140
+ <lit-icon
1141
+ icon="reading"
1142
+ size="1rem"
1143
+ ></lit-icon>
1144
+ <span>${msg('Zobrazit náhled')}</span>
1145
+ </div>
1146
+ `} -->
1147
+ </div>
1148
+ `)}`
1149
+ : html `
1150
+ <lit-select
1151
+ id="document-select"
1152
+ .value="${this.selectedId}"
1153
+ .options="${this.documents?.map((doc) => ({
1154
+ value: doc.id,
1155
+ label: doc.name,
1156
+ meta: doc.meta,
1157
+ fileType: doc.file_type,
1158
+ thumbnail: this.getThumbnailUrl(doc),
1159
+ dateOfUpload: doc.dateOfUpload,
1160
+ userName: doc.userName,
1161
+ }))}"
1162
+ .renderOption="${(option, _isActive, _isSelected) => html `
1163
+ <span
1164
+ style="display: flex; align-items: center; gap: 0.5rem; width: 100%;"
1165
+ @contextmenu="${(e) => this.handleContextMenu(e, option.value)}"
1166
+ @touchstart="${(e) => this.handleTouchStart(e, option.value)}"
1167
+ @touchend="${this.handleTouchEnd}"
1168
+ @touchmove="${this.cancelLongPress}"
1169
+ >
1170
+ ${this.enableThumbnails
1171
+ ? html `
1172
+ <lit-document-thumbnail
1173
+ .thumbnail="${option.thumbnail}"
1174
+ .fileType="${option.fileType}"
1175
+ .size="${this.thumbnailSize || 40}"
1176
+ .enableHoverPreview="${true}"
1177
+ .enableThumbnailDetail="${this
1178
+ .enableThumbnailDetail}"
1179
+ .previewMaxWidth="${this
1180
+ .thumbnailPreviewMaxWidth}"
1181
+ .previewMaxHeight="${this
1182
+ .thumbnailPreviewMaxHeight}"
1183
+ ></lit-document-thumbnail>
1184
+ `
1185
+ : null}
1186
+ <span
1187
+ style="flex: 1; overflow: hidden; display: flex; flex-direction: column; gap: 0.125rem; min-width: 0;"
1188
+ >
1189
+ <span
1190
+ style="display: flex; align-items: center; gap: 0.5rem; overflow: hidden;"
1191
+ >
1192
+ <span
1193
+ style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"
1194
+ >
1195
+ ${option.label}
1196
+ </span>
1197
+ ${option.meta?.map((metaItem) => html `
1198
+ <lit-badge
1199
+ content="neutral"
1200
+ .text=${metaItem}
1201
+ ></lit-badge>
1202
+ `) ?? ''}
1203
+ </span>
1204
+ ${this.enableAdditionalInformation &&
1205
+ (option.dateOfUpload || option.userName)
1206
+ ? html `
1207
+ <span
1208
+ style="font-size: 0.6875rem; font-weight: 400; color: var(--text-secondary, #6b7280); overflow: hidden; white-space: nowrap; text-overflow: ellipsis;"
1209
+ >
1210
+ ${option.dateOfUpload
1211
+ ? formatDate(option.dateOfUpload, this.userLang || 'cs', true, this.dateFormat)
1212
+ : ''}
1213
+ ${option.dateOfUpload && option.userName
1214
+ ? ' • '
1215
+ : ''}
1216
+ ${option.userName || ''}
1217
+ </span>
1218
+ `
1219
+ : null}
1220
+ </span>
1221
+ </span>
1222
+ `}"
1223
+ .onChange="${(selectedValue) => {
1224
+ this.handleDocumentClick(selectedValue);
1225
+ }}"
1226
+ .disableClearButton="${true}"
1227
+ ></lit-select>
1228
+ `}
1229
+ </div>
1230
+
1231
+ <div class="document">
1232
+ <span style="height: 0.1875rem; top: -12px; position: relative;">
1233
+ ${this.isDocumentLoading
1234
+ ? html ` <lit-loading-bar></lit-loading-bar> `
1235
+ : null}
1236
+ </span>
1237
+ <div class="document-box">
1238
+ <div
1239
+ class="document-selected"
1240
+ @contextmenu="${(e) => this.selectedId && this.handleContextMenu(e, this.selectedId)}"
1241
+ @touchstart="${(e) => this.selectedId && this.handleTouchStart(e, this.selectedId)}"
1242
+ @touchend="${this.handleTouchEnd}"
1243
+ @touchmove="${this.cancelLongPress}"
1244
+ >
1245
+ <lit-overflow-tooltip label="${this.getSelectedDocumentName()}">
1246
+ ${this.getSelectedDocumentName()}
1247
+ </lit-overflow-tooltip>
1248
+ </div>
1249
+ ${!isEmpty(this.documents)
1250
+ ? html `
1251
+ <div class="action-buttons">
1252
+ ${this.preview
1253
+ ? html `
1254
+ <lit-icon
1255
+ style="cursor: pointer"
1256
+ icon="chevronLeftFilled"
1257
+ size="1rem"
1258
+ @click=${() => this.handlePageChange(false)}
1259
+ ></lit-icon>
1260
+ <span
1261
+ >${msg('stránka')} ${this.pageNumber} /
1262
+ ${this.pageCount}</span
1263
+ >
1264
+ <lit-icon
1265
+ style="cursor: pointer"
1266
+ icon="chevronRightFilled"
1267
+ size="1rem"
1268
+ @click=${() => this.handlePageChange(true)}
1269
+ ></lit-icon>
1270
+ <lit-icon-button
1271
+ color="secondary"
1272
+ icon="zoomout"
1273
+ variant="text"
1274
+ size="small"
1275
+ @click=${() => this.handleZoom(false)}
1276
+ ></lit-icon-button>
1277
+ <lit-icon-button
1278
+ color="secondary"
1279
+ icon="zoomIn"
1280
+ variant="text"
1281
+ size="small"
1282
+ @click=${() => this.handleZoom(true)}
1283
+ ></lit-icon-button>
1284
+ `
1285
+ : null}
1286
+
1287
+ <lit-icon-button
1288
+ color="secondary"
1289
+ icon="download"
1290
+ variant="text"
1291
+ size="small"
1292
+ @click=${this.handleDownload}
1293
+ ></lit-icon-button>
1294
+ </div>
1295
+ `
1296
+ : null}
1297
+ </div>
1298
+ <div
1299
+ class="document-container"
1300
+ @mousemove=${this.handleMouseMove}
1301
+ @mouseup=${this.handleMouseUp}
1302
+ @mouseleave=${this.handleMouseUp}
1303
+ @wheel=${this.handleWheelZoom}
1304
+ >
1305
+ ${!isEmpty(this.documents)
1306
+ ? html `
1307
+ <canvas
1308
+ style=${styleMap({
1309
+ cursor: (this.localScale ?? 1) > 1 ? 'grab' : 'default',
1310
+ })}
1311
+ @mousedown=${this.handleMouseDown}
1312
+ @touchstart=${this.handleTouchStartCanvas}
1313
+ @touchmove=${this.handleTouchMoveCanvas}
1314
+ @touchend=${this.handleTouchEndCanvas}
1315
+ >
1316
+ </canvas>
1317
+ `
1318
+ : null}
1319
+ ${!this.preview && (this.documents || !isEmpty(this.documents))
1320
+ ? html `
1321
+ <div class="not-supported__format">
1322
+ <div style="max-height: 7.125rem; max-width: 7.125rem">
1323
+ <no-preview></no-preview>
1324
+ </div>
1325
+ ${msg('Náhled dokumentu není možný vzhledem k typu dokumentu.')}
1326
+ </div>
1327
+ `
1328
+ : null}
1329
+ ${!this.documents || isEmpty(this.documents)
1330
+ ? html `
1331
+ <div class="not-supported__format">
1332
+ <div style="max-height: 7.125rem; max-width: 7.125rem">
1333
+ <not-found></not-found>
1334
+ </div>
1335
+ ${msg('Nic dalšího tu není')}
1336
+ </div>
1337
+ `
1338
+ : null}
1339
+ </div>
1340
+ </div>
1341
+
1342
+ ${this.enableSettings
1343
+ ? html `<div class="footer">
1344
+ <lit-icon-button
1345
+ color="secondary"
1346
+ icon="administration"
1347
+ @click="${this.toggleModal}"
1348
+ variant="dashed"
1349
+ style="display: inline-block"
1350
+ ></lit-icon-button>
1351
+ <attachments-tab-settings
1352
+ .onClose="${() => {
1353
+ this.isOpenModal = false;
1354
+ }}"
1355
+ .isOpenModal="${this.isOpenModal}"
1356
+ .onSettingsChangedModal="${this.onSettingsChangedCallback.bind(this)}"
1357
+ .type="${this.type}"
1358
+ .scale="${this.scale}"
1359
+ .enableThumbnails="${this.enableThumbnails}"
1360
+ .thumbnailSize="${this.thumbnailSize}"
1361
+ .enableAdditionalInformation="${this.enableAdditionalInformation}"
1362
+ .enableThumbnailDetail="${this.enableThumbnailDetail}"
1363
+ .enableSearchInDocuments="${this.enableSearchInDocuments}"
1364
+ .userLang="${this.userLang}"
1365
+ ></attachments-tab-settings>
1366
+ </div>`
1367
+ : null}
1368
+ </div>
1369
+
1370
+ <!-- Context Menu -->
1371
+ ${this.contextMenuOpen && this.contextMenuPosition && this.enableComparison
1372
+ ? html `
1373
+ <div
1374
+ class="context-menu"
1375
+ style="left: ${this.contextMenuPosition.x}px; top: ${this
1376
+ .contextMenuPosition.y}px;"
1377
+ @click="${(e) => e.stopPropagation()}"
1378
+ >
1379
+ <lit-menu>
1380
+ ${this.contextMenuDocumentId !== this.selectedId
1381
+ ? html `
1382
+ <lit-menu-item
1383
+ icon="duplicate"
1384
+ .onClick="${() => this.openComparisonModal(this.selectedId, this.contextMenuDocumentId || '')}"
1385
+ >
1386
+ ${msg('Porovnat s tímto')}
1387
+ </lit-menu-item>
1388
+ `
1389
+ : null}
1390
+ </lit-menu>
1391
+ </div>
1392
+ `
1393
+ : null}
1394
+
1395
+ <!-- Comparison Modal -->
1396
+ ${this.comparisonModalOpen
1397
+ ? html `
1398
+ <div class="comparison-modal" @click="${this.handleBackdropClick}">
1399
+ <div
1400
+ class="comparison-modal-content"
1401
+ @click="${(e) => e.stopPropagation()}"
1402
+ >
1403
+ <!-- Modal Header -->
1404
+ <div class="comparison-modal-header">
1405
+ <div class="header-title">
1406
+ <lit-icon
1407
+ icon="duplicate"
1408
+ size="1.25rem"
1409
+ .isActive=${true}
1410
+ ></lit-icon>
1411
+ <span>${msg('Porovnání dokumentů')}</span>
1412
+ </div>
1413
+
1414
+ <div class="header-controls">
1415
+ <lit-toggle
1416
+ .checked="${this.syncZoom}"
1417
+ .onChange="${this.handleSyncZoomChange}"
1418
+ .label="${msg('Synchronizovat přiblížení')}"
1419
+ size="small"
1420
+ .inline="${true}"
1421
+ ></lit-toggle>
1422
+
1423
+ <lit-icon-button
1424
+ icon="totakedelegate"
1425
+ color="secondary"
1426
+ variant="text"
1427
+ size="small"
1428
+ @click="${this.swapComparisonSides}"
1429
+ title="${msg('Prohodit strany')}"
1430
+ ></lit-icon-button>
1431
+
1432
+ <lit-icon-button
1433
+ icon="close"
1434
+ color="secondary"
1435
+ variant="text"
1436
+ size="small"
1437
+ @click="${this.closeComparisonModal}"
1438
+ ></lit-icon-button>
1439
+ </div>
1440
+ </div>
1441
+
1442
+ <!-- Comparison Grid -->
1443
+ <div class="comparison-grid">
1444
+ ${this.renderComparisonPanel('left')}
1445
+ ${this.renderComparisonPanel('right')}
1446
+ </div>
1447
+ </div>
1448
+ </div>
1449
+ `
1450
+ : null}
1451
+ `;
1452
+ }
1453
+ renderComparisonPanel(side) {
1454
+ const docId = side === 'left' ? this.comparisonDocumentLeft : this.comparisonDocumentRight;
1455
+ const doc = this.documents?.find((d) => d.id === docId);
1456
+ const pageNumber = side === 'left' ? this.pageNumberLeft : this.pageNumberRight;
1457
+ const pageCount = side === 'left' ? this.pageCountLeft : this.pageCountRight;
1458
+ const hasPages = pageCount > 1;
1459
+ const isLoading = side === 'left' ? this.isDocumentLoadingLeft : this.isDocumentLoadingRight;
1460
+ return html `
1461
+ <div class="comparison-panel">
1462
+ <!-- Loading Bar -->
1463
+ ${isLoading
1464
+ ? html `
1465
+ <span style="height: 0.1875rem; position: relative; display: block;">
1466
+ <lit-loading-bar></lit-loading-bar>
1467
+ </span>
1468
+ `
1469
+ : ''}
1470
+
1471
+ <!-- Panel Header -->
1472
+ <div class="comparison-panel-header">
1473
+ <span class="comparison-panel-title"> ${doc?.name || msg('Dokument')} </span>
1474
+ </div>
1475
+
1476
+ <!-- Panel Controls -->
1477
+ <div class="comparison-panel-controls">
1478
+ ${hasPages
1479
+ ? html `
1480
+ <lit-icon-button
1481
+ icon="chevronLeftFilled"
1482
+ color="secondary"
1483
+ variant="text"
1484
+ size="small"
1485
+ @click="${() => this.handleComparisonPageChange(side, false)}"
1486
+ ></lit-icon-button>
1487
+ <span style="font-size: 0.875rem;">
1488
+ ${msg('stránka')} ${pageNumber} / ${pageCount}
1489
+ </span>
1490
+ <lit-icon-button
1491
+ icon="chevronRightFilled"
1492
+ color="secondary"
1493
+ variant="text"
1494
+ size="small"
1495
+ @click="${() => this.handleComparisonPageChange(side, true)}"
1496
+ ></lit-icon-button>
1497
+ `
1498
+ : null}
1499
+
1500
+ <lit-icon-button
1501
+ icon="zoomout"
1502
+ color="secondary"
1503
+ variant="text"
1504
+ size="small"
1505
+ @click="${() => this.handleComparisonZoom(side, false)}"
1506
+ ></lit-icon-button>
1507
+
1508
+ <lit-icon-button
1509
+ icon="zoomIn"
1510
+ color="secondary"
1511
+ variant="text"
1512
+ size="small"
1513
+ @click="${() => this.handleComparisonZoom(side, true)}"
1514
+ ></lit-icon-button>
1515
+
1516
+ <lit-icon-button
1517
+ icon="download"
1518
+ color="secondary"
1519
+ variant="text"
1520
+ size="small"
1521
+ @click="${() => this.handleDownloadComparison(side)}"
1522
+ ></lit-icon-button>
1523
+ </div>
1524
+
1525
+ <!-- Document Container -->
1526
+ <div
1527
+ class="comparison-document-container"
1528
+ id="comparison-${side}-container"
1529
+ @wheel="${(e) => this.handleWheelZoomComparison(e, side)}"
1530
+ >
1531
+ <canvas
1532
+ id="comparison-canvas-${side}"
1533
+ @touchstart="${(e) => this.handleTouchStartComparison(e, side)}"
1534
+ @touchmove="${(e) => this.handleTouchMoveComparison(e, side)}"
1535
+ @touchend="${this.handleTouchEndComparison}"
1536
+ ></canvas>
1537
+ </div>
1538
+ </div>
1539
+ `;
1540
+ }
1541
+ handleDownloadComparison(side) {
1542
+ const docId = side === 'left' ? this.comparisonDocumentLeft : this.comparisonDocumentRight;
1543
+ if (docId) {
1544
+ // Temporarily set selectedId to trigger download for this document
1545
+ const originalSelectedId = this.selectedId;
1546
+ this.selectedId = docId;
1547
+ this.handleDownload();
1548
+ this.selectedId = originalSelectedId;
1549
+ }
1550
+ }
1551
+ }
1552
+ LitAttachmentsTab.styles = [
1553
+ css `
1554
+ .no-results-message {
1555
+ display: flex;
1556
+ flex-direction: column;
1557
+ align-items: center;
1558
+ justify-content: center;
1559
+ gap: 0.5rem;
1560
+ padding: 2rem 1rem;
1561
+ color: var(--text-secondary, #6b7280);
1562
+ font-size: 0.875rem;
1563
+ text-align: center;
1564
+ }
1565
+
1566
+ .document-label {
1567
+ min-height: 2.125rem;
1568
+ gap: 0.25rem;
1569
+ display: flex;
1570
+ justify-content: space-between;
1571
+ flex-direction: row;
1572
+ align-items: center;
1573
+ position: relative;
1574
+ font-weight: 500;
1575
+ font-size: 0.8125rem;
1576
+ padding: 0.375rem 0.5rem;
1577
+ background: var(--background-paper, #ffffff);
1578
+ color: var(--color-secondary-main, #111827);
1579
+ border-radius: 0.5rem;
1580
+ cursor: pointer;
1581
+ }
1582
+
1583
+ .document-item {
1584
+ font-weight: 500;
1585
+ font-size: 0.8125rem;
1586
+ color: var(--color-secondary-main, #111827);
1587
+ display: flex;
1588
+ align-items: center;
1589
+ gap: 0.75rem;
1590
+ overflow: hidden;
1591
+ flex: 1;
1592
+ }
1593
+
1594
+ .document-item-content {
1595
+ display: flex;
1596
+ flex-direction: column;
1597
+ overflow: hidden;
1598
+ flex: 1;
1599
+ }
1600
+
1601
+ .document-name {
1602
+ display: flex;
1603
+ align-items: center;
1604
+ gap: 0.5rem;
1605
+ min-width: 0;
1606
+ }
1607
+
1608
+ .document-name-text {
1609
+ overflow: hidden;
1610
+ white-space: nowrap;
1611
+ text-overflow: ellipsis;
1612
+ flex-shrink: 1;
1613
+ min-width: 0;
1614
+ height: 20px;
1615
+ }
1616
+
1617
+ .document-info {
1618
+ font-size: 0.6875rem;
1619
+ font-weight: 400;
1620
+ color: var(--text-secondary, #6b7280);
1621
+ overflow: hidden;
1622
+ white-space: nowrap;
1623
+ text-overflow: ellipsis;
1624
+ }
1625
+
1626
+ .document-label:hover {
1627
+ background: var(--color-primary-light, #f0fadf);
1628
+ }
1629
+
1630
+ .selected {
1631
+ background: var(--color-primary-light, #f0fadf);
1632
+ }
1633
+
1634
+ .focused {
1635
+ outline: 1px solid var(--color-primary-main, #7ab800);
1636
+ outline-offset: -1px;
1637
+ }
1638
+
1639
+ .document-checked {
1640
+ padding: 0 1rem 0 1rem;
1641
+ font-size: 0.75rem;
1642
+ color: var(--color-primary-dark, #5f9402);
1643
+ white-space: nowrap;
1644
+ }
1645
+ .document-unchecked {
1646
+ display: none;
1647
+ padding: 0 1rem 0 1rem;
1648
+ font-size: 0.75rem;
1649
+ align-items: center;
1650
+ gap: 0.5rem;
1651
+ white-space: nowrap;
1652
+ }
1653
+
1654
+ .document-label:hover .document-unchecked {
1655
+ display: flex;
1656
+ }
1657
+
1658
+ .document {
1659
+ background: var(--background-default, #eff3f4);
1660
+ border-radius: 0.5rem;
1661
+ padding: 0.75rem 0.5rem 0.5rem 0.5rem;
1662
+
1663
+ flex: 1;
1664
+ min-height: 0;
1665
+ min-width: 0;
1666
+ display: flex;
1667
+ flex-direction: column;
1668
+ overflow: hidden;
1669
+ }
1670
+
1671
+ .document-box {
1672
+ display: flex;
1673
+ align-items: center;
1674
+ justify-content: space-between;
1675
+ padding: 0 0.75rem 0.75rem 0.75rem;
1676
+ flex-shrink: 0;
1677
+ }
1678
+
1679
+ .action-buttons {
1680
+ display: flex;
1681
+ align-items: center;
1682
+ font-size: 0.8125rem;
1683
+ gap: 0.75rem;
1684
+ white-space: nowrap;
1685
+ }
1686
+
1687
+ .document-selected {
1688
+ color: var(--color-secondary-main, #111827);
1689
+ font-size: 0.8125rem;
1690
+ font-weight: 500;
1691
+ max-width: 100%;
1692
+ overflow: hidden;
1693
+ white-space: nowrap;
1694
+ text-overflow: ellipsis;
1695
+ display: flex;
1696
+ }
1697
+
1698
+ .document-container {
1699
+ position: relative;
1700
+ width: 100%;
1701
+ flex: 1;
1702
+ min-height: 0;
1703
+ overflow: auto;
1704
+ }
1705
+
1706
+ canvas {
1707
+ display: block;
1708
+ margin: 0 auto;
1709
+ transform-origin: 0 0;
1710
+ touch-action: none; /* Prevent default touch behaviors */
1711
+ }
1712
+
1713
+ .not-supported__format {
1714
+ min-height: 40vh;
1715
+ font-size: 0.875rem;
1716
+ text-align: center;
1717
+ display: flex;
1718
+ align-items: center;
1719
+ justify-content: center;
1720
+ flex-direction: column;
1721
+ margin: 1rem 0 1rem 0;
1722
+ }
1723
+ .attachments-container {
1724
+ height: 100%;
1725
+ overflow: hidden;
1726
+ display: flex;
1727
+ flex-direction: column;
1728
+ outline: none;
1729
+ container-type: inline-size;
1730
+ container-name: attachments;
1731
+ }
1732
+
1733
+ .compact-layout {
1734
+ flex-direction: row;
1735
+ gap: 0.5rem;
1736
+ }
1737
+
1738
+ .compact-layout .documents-list-section {
1739
+ flex-shrink: 0;
1740
+ width: 25rem;
1741
+ position: sticky;
1742
+ top: 0;
1743
+ max-height: 70vh;
1744
+ overflow: auto;
1745
+ }
1746
+
1747
+ .compact-layout .document {
1748
+ flex: 1;
1749
+ }
1750
+
1751
+ .documents-list-section {
1752
+ max-height: 15.625rem;
1753
+ overflow: auto;
1754
+ flex-shrink: 0;
1755
+ }
1756
+
1757
+ .footer {
1758
+ flex-shrink: 0;
1759
+ justify-content: end;
1760
+ display: flex;
1761
+ margin-top: 0.5rem;
1762
+ }
1763
+
1764
+ /* Comparison Modal Styles */
1765
+ .comparison-modal {
1766
+ position: fixed;
1767
+ top: 0;
1768
+ left: 0;
1769
+ right: 0;
1770
+ bottom: 0;
1771
+ z-index: 99999;
1772
+ display: flex;
1773
+ align-items: center;
1774
+ justify-content: center;
1775
+ background: rgba(0, 0, 0, 0.75);
1776
+ }
1777
+
1778
+ .comparison-modal-content {
1779
+ background: var(--background-paper, #ffffff);
1780
+ border-radius: 0.5rem;
1781
+ width: 95vw;
1782
+ height: 95vh;
1783
+ max-width: 1400px;
1784
+ display: flex;
1785
+ flex-direction: column;
1786
+ overflow: hidden;
1787
+ box-shadow:
1788
+ 0 20px 25px -5px rgba(0, 0, 0, 0.1),
1789
+ 0 10px 10px -5px rgba(0, 0, 0, 0.04);
1790
+ }
1791
+
1792
+ .comparison-modal-header {
1793
+ display: flex;
1794
+ justify-content: space-between;
1795
+ align-items: center;
1796
+ padding: 0.5rem 0.75rem;
1797
+ border-bottom: 1px solid var(--color-divider, #e5e7eb);
1798
+ background: var(--background-paper, #ffffff);
1799
+ }
1800
+
1801
+ .comparison-modal-header .header-title {
1802
+ display: flex;
1803
+ align-items: center;
1804
+ gap: 0.5rem;
1805
+ font-size: 0.875rem;
1806
+ font-weight: 400;
1807
+ color: var(--color-secondary-main, #111827);
1808
+ }
1809
+
1810
+ .comparison-modal-header .header-controls {
1811
+ display: flex;
1812
+ align-items: center;
1813
+ gap: 1rem;
1814
+ }
1815
+
1816
+ .comparison-grid {
1817
+ display: grid;
1818
+ grid-template-columns: 1fr 1fr;
1819
+ gap: 0.5rem;
1820
+ flex: 1;
1821
+ overflow: hidden;
1822
+ padding: 0rem 0.5rem 0.5rem 0.5rem;
1823
+ }
1824
+
1825
+ .comparison-panel {
1826
+ display: flex;
1827
+ flex-direction: column;
1828
+ background: var(--background-default, #eff3f4);
1829
+ border-radius: 0.5rem;
1830
+ overflow: hidden;
1831
+ }
1832
+
1833
+ .comparison-panel-header {
1834
+ display: flex;
1835
+ justify-content: space-between;
1836
+ align-items: center;
1837
+ padding: 0.5rem 0.75rem;
1838
+ background: var(--background-paper, #ffffff);
1839
+ border-bottom: 1px solid var(--color-divider, #e5e7eb);
1840
+ }
1841
+
1842
+ .comparison-panel-title {
1843
+ font-size: 0.875rem;
1844
+ font-weight: 500;
1845
+ color: var(--color-secondary-main, #111827);
1846
+ overflow: hidden;
1847
+ white-space: nowrap;
1848
+ text-overflow: ellipsis;
1849
+ }
1850
+
1851
+ .comparison-panel-controls {
1852
+ display: flex;
1853
+ align-items: center;
1854
+ gap: 0.5rem;
1855
+ padding: 0.5rem 0.75rem;
1856
+ background: var(--background-paper, #ffffff);
1857
+ border-bottom: 1px solid var(--color-divider, #e5e7eb);
1858
+ }
1859
+
1860
+ .comparison-document-container {
1861
+ flex: 1;
1862
+ overflow: auto;
1863
+ display: flex;
1864
+ }
1865
+
1866
+ .comparison-document-container canvas {
1867
+ display: block;
1868
+ margin: auto;
1869
+ max-width: max-content;
1870
+ max-height: max-content;
1871
+ touch-action: none; /* Prevent default touch behaviors */
1872
+ }
1873
+
1874
+ /* Context Menu Styles */
1875
+ .context-menu {
1876
+ position: fixed;
1877
+ z-index: 100000;
1878
+ background: var(--background-paper, #ffffff);
1879
+ border-radius: 0.5rem;
1880
+ padding: 0.375rem;
1881
+ box-shadow:
1882
+ 0 10px 15px -3px rgba(0, 0, 0, 0.1),
1883
+ 0 4px 6px -2px rgba(0, 0, 0, 0.05);
1884
+ min-width: 200px;
1885
+ }
1886
+
1887
+ @media (max-width: 800px) {
1888
+ .comparison-grid {
1889
+ grid-template-columns: 1fr;
1890
+ grid-template-rows: 1fr 1fr;
1891
+ }
1892
+
1893
+ .comparison-modal-content {
1894
+ width: 95vw;
1895
+ height: 95vh;
1896
+ }
1897
+ }
1898
+ `,
1899
+ ];
1900
+ __decorate([
1901
+ property({ type: Boolean })
1902
+ ], LitAttachmentsTab.prototype, "hideTabWhen", void 0);
1903
+ __decorate([
1904
+ property({ type: String })
1905
+ ], LitAttachmentsTab.prototype, "initialSelection", void 0);
1906
+ __decorate([
1907
+ property({ type: Array })
1908
+ ], LitAttachmentsTab.prototype, "documents", void 0);
1909
+ __decorate([
1910
+ property({ type: String })
1911
+ ], LitAttachmentsTab.prototype, "type", void 0);
1912
+ __decorate([
1913
+ property({ type: Number })
1914
+ ], LitAttachmentsTab.prototype, "scale", void 0);
1915
+ __decorate([
1916
+ property({ type: Function })
1917
+ ], LitAttachmentsTab.prototype, "onClick", void 0);
1918
+ __decorate([
1919
+ property({ type: Boolean })
1920
+ ], LitAttachmentsTab.prototype, "isDocumentLoading", void 0);
1921
+ __decorate([
1922
+ property({ type: Boolean })
1923
+ ], LitAttachmentsTab.prototype, "enableSettings", void 0);
1924
+ __decorate([
1925
+ property({ type: Boolean })
1926
+ ], LitAttachmentsTab.prototype, "enableThumbnails", void 0);
1927
+ __decorate([
1928
+ property({ type: Number })
1929
+ ], LitAttachmentsTab.prototype, "thumbnailSize", void 0);
1930
+ __decorate([
1931
+ property({ type: Boolean })
1932
+ ], LitAttachmentsTab.prototype, "enableAdditionalInformation", void 0);
1933
+ __decorate([
1934
+ property({ type: Boolean })
1935
+ ], LitAttachmentsTab.prototype, "enableThumbnailDetail", void 0);
1936
+ __decorate([
1937
+ property({ type: Number })
1938
+ ], LitAttachmentsTab.prototype, "thumbnailPreviewMaxWidth", void 0);
1939
+ __decorate([
1940
+ property({ type: Number })
1941
+ ], LitAttachmentsTab.prototype, "thumbnailPreviewMaxHeight", void 0);
1942
+ __decorate([
1943
+ property({ type: Boolean })
1944
+ ], LitAttachmentsTab.prototype, "enableSearchInDocuments", void 0);
1945
+ __decorate([
1946
+ property({ type: Boolean })
1947
+ ], LitAttachmentsTab.prototype, "enableComparison", void 0);
1948
+ __decorate([
1949
+ property({ type: String })
1950
+ ], LitAttachmentsTab.prototype, "userLang", void 0);
1951
+ __decorate([
1952
+ property({ type: String })
1953
+ ], LitAttachmentsTab.prototype, "dateFormat", void 0);
1954
+ __decorate([
1955
+ property({ attribute: false })
1956
+ ], LitAttachmentsTab.prototype, "onSettingsChanged", void 0);
1957
+ __decorate([
1958
+ state()
1959
+ ], LitAttachmentsTab.prototype, "selectedDocument", void 0);
1960
+ __decorate([
1961
+ state()
1962
+ ], LitAttachmentsTab.prototype, "selectedId", void 0);
1963
+ __decorate([
1964
+ state()
1965
+ ], LitAttachmentsTab.prototype, "pageNumber", void 0);
1966
+ __decorate([
1967
+ state()
1968
+ ], LitAttachmentsTab.prototype, "pageCount", void 0);
1969
+ __decorate([
1970
+ state()
1971
+ ], LitAttachmentsTab.prototype, "preview", void 0);
1972
+ __decorate([
1973
+ state()
1974
+ ], LitAttachmentsTab.prototype, "documentData", void 0);
1975
+ __decorate([
1976
+ state()
1977
+ ], LitAttachmentsTab.prototype, "isOpenModal", void 0);
1978
+ __decorate([
1979
+ state()
1980
+ ], LitAttachmentsTab.prototype, "localScale", void 0);
1981
+ __decorate([
1982
+ state()
1983
+ ], LitAttachmentsTab.prototype, "filterText", void 0);
1984
+ __decorate([
1985
+ state()
1986
+ ], LitAttachmentsTab.prototype, "focusedIndex", void 0);
1987
+ __decorate([
1988
+ state()
1989
+ ], LitAttachmentsTab.prototype, "isWideLayout", void 0);
1990
+ __decorate([
1991
+ state()
1992
+ ], LitAttachmentsTab.prototype, "comparisonModalOpen", void 0);
1993
+ __decorate([
1994
+ state()
1995
+ ], LitAttachmentsTab.prototype, "comparisonDocumentLeft", void 0);
1996
+ __decorate([
1997
+ state()
1998
+ ], LitAttachmentsTab.prototype, "comparisonDocumentRight", void 0);
1999
+ __decorate([
2000
+ state()
2001
+ ], LitAttachmentsTab.prototype, "selectedDocumentLeftCanvas", void 0);
2002
+ __decorate([
2003
+ state()
2004
+ ], LitAttachmentsTab.prototype, "selectedDocumentRightCanvas", void 0);
2005
+ __decorate([
2006
+ state()
2007
+ ], LitAttachmentsTab.prototype, "pageNumberLeft", void 0);
2008
+ __decorate([
2009
+ state()
2010
+ ], LitAttachmentsTab.prototype, "pageNumberRight", void 0);
2011
+ __decorate([
2012
+ state()
2013
+ ], LitAttachmentsTab.prototype, "pageCountLeft", void 0);
2014
+ __decorate([
2015
+ state()
2016
+ ], LitAttachmentsTab.prototype, "pageCountRight", void 0);
2017
+ __decorate([
2018
+ state()
2019
+ ], LitAttachmentsTab.prototype, "localScaleLeft", void 0);
2020
+ __decorate([
2021
+ state()
2022
+ ], LitAttachmentsTab.prototype, "localScaleRight", void 0);
2023
+ __decorate([
2024
+ state()
2025
+ ], LitAttachmentsTab.prototype, "isDocumentLoadingLeft", void 0);
2026
+ __decorate([
2027
+ state()
2028
+ ], LitAttachmentsTab.prototype, "isDocumentLoadingRight", void 0);
2029
+ __decorate([
2030
+ state()
2031
+ ], LitAttachmentsTab.prototype, "contextMenuOpen", void 0);
2032
+ __decorate([
2033
+ state()
2034
+ ], LitAttachmentsTab.prototype, "contextMenuPosition", void 0);
2035
+ __decorate([
2036
+ state()
2037
+ ], LitAttachmentsTab.prototype, "contextMenuDocumentId", void 0);
2038
+ __decorate([
2039
+ state()
2040
+ ], LitAttachmentsTab.prototype, "syncZoom", void 0);
2041
+ if (!window.customElements.get('lit-attachments-tab')) {
2042
+ window.customElements.define('lit-attachments-tab', LitAttachmentsTab);
2043
+ }
2044
+ //# sourceMappingURL=lit-attachments-tab.js.map