@file-viewer/core 2.0.0

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 (166) hide show
  1. package/LICENSE +160 -0
  2. package/README.en.md +78 -0
  3. package/README.md +83 -0
  4. package/dist/assets.d.ts +62 -0
  5. package/dist/assets.js +260 -0
  6. package/dist/browser.d.ts +1 -0
  7. package/dist/browser.js +1 -0
  8. package/dist/capabilities.d.ts +24 -0
  9. package/dist/capabilities.js +95 -0
  10. package/dist/document.d.ts +9 -0
  11. package/dist/document.js +86 -0
  12. package/dist/documentDom/anchors.d.ts +7 -0
  13. package/dist/documentDom/anchors.js +196 -0
  14. package/dist/documentDom/index.d.ts +5 -0
  15. package/dist/documentDom/index.js +3 -0
  16. package/dist/documentDom/providers.d.ts +13 -0
  17. package/dist/documentDom/providers.js +52 -0
  18. package/dist/documentDom/scroll.d.ts +12 -0
  19. package/dist/documentDom/scroll.js +42 -0
  20. package/dist/documentDom.d.ts +5 -0
  21. package/dist/documentDom.js +3 -0
  22. package/dist/documentEvents.d.ts +73 -0
  23. package/dist/documentEvents.js +150 -0
  24. package/dist/documentSearch.d.ts +50 -0
  25. package/dist/documentSearch.js +459 -0
  26. package/dist/documentZoom.d.ts +47 -0
  27. package/dist/documentZoom.js +184 -0
  28. package/dist/export.d.ts +26 -0
  29. package/dist/export.js +466 -0
  30. package/dist/formats.d.ts +305 -0
  31. package/dist/formats.js +207 -0
  32. package/dist/headless.d.ts +25 -0
  33. package/dist/headless.js +14 -0
  34. package/dist/index.d.ts +78 -0
  35. package/dist/index.js +118 -0
  36. package/dist/lifecycleFacade.d.ts +46 -0
  37. package/dist/lifecycleFacade.js +68 -0
  38. package/dist/loading.d.ts +59 -0
  39. package/dist/loading.js +489 -0
  40. package/dist/operations.d.ts +287 -0
  41. package/dist/operations.js +485 -0
  42. package/dist/options.d.ts +16 -0
  43. package/dist/options.js +92 -0
  44. package/dist/presentation.d.ts +14 -0
  45. package/dist/presentation.js +16 -0
  46. package/dist/printLayout.d.ts +19 -0
  47. package/dist/printLayout.js +83 -0
  48. package/dist/registry.d.ts +2 -0
  49. package/dist/registry.js +63 -0
  50. package/dist/rendererDispatcher.d.ts +21 -0
  51. package/dist/rendererDispatcher.js +42 -0
  52. package/dist/rendererHandler.d.ts +165 -0
  53. package/dist/rendererHandler.js +354 -0
  54. package/dist/renderers/archive.d.ts +2 -0
  55. package/dist/renderers/archive.js +547 -0
  56. package/dist/renderers/archiveCache.d.ts +10 -0
  57. package/dist/renderers/archiveCache.js +96 -0
  58. package/dist/renderers/archiveFallback.d.ts +7 -0
  59. package/dist/renderers/archiveFallback.js +166 -0
  60. package/dist/renderers/archiveShared.d.ts +23 -0
  61. package/dist/renderers/archiveShared.js +71 -0
  62. package/dist/renderers/audio.d.ts +8 -0
  63. package/dist/renderers/audio.js +219 -0
  64. package/dist/renderers/cad.d.ts +2 -0
  65. package/dist/renderers/cad.js +445 -0
  66. package/dist/renderers/code.d.ts +11 -0
  67. package/dist/renderers/code.js +233 -0
  68. package/dist/renderers/data.d.ts +7 -0
  69. package/dist/renderers/data.js +370 -0
  70. package/dist/renderers/drawing.d.ts +10 -0
  71. package/dist/renderers/drawing.js +537 -0
  72. package/dist/renderers/eda.d.ts +2 -0
  73. package/dist/renderers/eda.js +434 -0
  74. package/dist/renderers/edaParser.d.ts +77 -0
  75. package/dist/renderers/edaParser.js +569 -0
  76. package/dist/renderers/email.d.ts +2 -0
  77. package/dist/renderers/email.js +463 -0
  78. package/dist/renderers/epub.d.ts +2 -0
  79. package/dist/renderers/epub.js +330 -0
  80. package/dist/renderers/geo.d.ts +2 -0
  81. package/dist/renderers/geo.js +284 -0
  82. package/dist/renderers/image.d.ts +2 -0
  83. package/dist/renderers/image.js +179 -0
  84. package/dist/renderers/index.d.ts +21 -0
  85. package/dist/renderers/index.js +207 -0
  86. package/dist/renderers/markdown.d.ts +2 -0
  87. package/dist/renderers/markdown.js +83 -0
  88. package/dist/renderers/model.d.ts +2 -0
  89. package/dist/renderers/model.js +566 -0
  90. package/dist/renderers/ofd.d.ts +2 -0
  91. package/dist/renderers/ofd.js +255 -0
  92. package/dist/renderers/openDocument.d.ts +2 -0
  93. package/dist/renderers/openDocument.js +122 -0
  94. package/dist/renderers/pdf.d.ts +3 -0
  95. package/dist/renderers/pdf.js +846 -0
  96. package/dist/renderers/pdfStyles.d.ts +1 -0
  97. package/dist/renderers/pdfStyles.js +1 -0
  98. package/dist/renderers/pptx.d.ts +2 -0
  99. package/dist/renderers/pptx.js +202 -0
  100. package/dist/renderers/spreadsheet/state.d.ts +80 -0
  101. package/dist/renderers/spreadsheet/state.js +96 -0
  102. package/dist/renderers/spreadsheet/view.d.ts +25 -0
  103. package/dist/renderers/spreadsheet/view.js +833 -0
  104. package/dist/renderers/spreadsheet/worker/index.d.ts +2 -0
  105. package/dist/renderers/spreadsheet/worker/index.js +1 -0
  106. package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.d.ts +73 -0
  107. package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.js +623 -0
  108. package/dist/renderers/spreadsheet/worker/sheetjs/color.d.ts +2 -0
  109. package/dist/renderers/spreadsheet/worker/sheetjs/color.js +73 -0
  110. package/dist/renderers/spreadsheet/worker/sheetjs/index.d.ts +1 -0
  111. package/dist/renderers/spreadsheet/worker/sheetjs/index.js +1 -0
  112. package/dist/renderers/spreadsheet/worker/sheetjs/parser.d.ts +18 -0
  113. package/dist/renderers/spreadsheet/worker/sheetjs/parser.js +106 -0
  114. package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.d.ts +1 -0
  115. package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.js +11 -0
  116. package/dist/renderers/spreadsheet/worker/type.d.ts +57 -0
  117. package/dist/renderers/spreadsheet/worker/type.js +1 -0
  118. package/dist/renderers/spreadsheet.d.ts +3 -0
  119. package/dist/renderers/spreadsheet.js +929 -0
  120. package/dist/renderers/typst.d.ts +8 -0
  121. package/dist/renderers/typst.js +415 -0
  122. package/dist/renderers/umd/parser.d.ts +30 -0
  123. package/dist/renderers/umd/parser.js +408 -0
  124. package/dist/renderers/umd.d.ts +2 -0
  125. package/dist/renderers/umd.js +297 -0
  126. package/dist/renderers/video.d.ts +8 -0
  127. package/dist/renderers/video.js +108 -0
  128. package/dist/renderers/wordDoc.d.ts +5 -0
  129. package/dist/renderers/wordDoc.js +284 -0
  130. package/dist/renderers/wordDocx.d.ts +5 -0
  131. package/dist/renderers/wordDocx.js +501 -0
  132. package/dist/renderers/wordDocx.worker.d.ts +1 -0
  133. package/dist/renderers/wordDocx.worker.js +96 -0
  134. package/dist/source.d.ts +18 -0
  135. package/dist/source.js +152 -0
  136. package/dist/sourceLoading.d.ts +566 -0
  137. package/dist/sourceLoading.js +918 -0
  138. package/dist/state.d.ts +16 -0
  139. package/dist/state.js +81 -0
  140. package/dist/types.d.ts +446 -0
  141. package/dist/types.js +1 -0
  142. package/dist/viewer.d.ts +8 -0
  143. package/dist/viewer.js +285 -0
  144. package/dist/viewerOperations.d.ts +88 -0
  145. package/dist/viewerOperations.js +242 -0
  146. package/dist/watermark.d.ts +15 -0
  147. package/dist/watermark.js +81 -0
  148. package/dist/worker.d.ts +34 -0
  149. package/dist/worker.js +101 -0
  150. package/package.json +109 -0
  151. package/vendor/ofd/dltech/jbig2/arithmetic_decoder.js +183 -0
  152. package/vendor/ofd/dltech/jbig2/ccitt.js +1070 -0
  153. package/vendor/ofd/dltech/jbig2/compatibility.js +12 -0
  154. package/vendor/ofd/dltech/jbig2/core_utils.js +180 -0
  155. package/vendor/ofd/dltech/jbig2/is_node.js +27 -0
  156. package/vendor/ofd/dltech/jbig2/jbig2.js +2589 -0
  157. package/vendor/ofd/dltech/jbig2/jbig2_stream.js +81 -0
  158. package/vendor/ofd/dltech/jbig2/primitives.js +387 -0
  159. package/vendor/ofd/dltech/jbig2/stream.js +1348 -0
  160. package/vendor/ofd/dltech/jbig2/util.js +972 -0
  161. package/vendor/ofd/dltech/ofd/ofd.d.ts +11 -0
  162. package/vendor/ofd/dltech/ofd/ofd.js +100 -0
  163. package/vendor/ofd/dltech/ofd/ofd_parser.js +395 -0
  164. package/vendor/ofd/dltech/ofd/ofd_render.js +473 -0
  165. package/vendor/ofd/dltech/ofd/ofd_util.js +350 -0
  166. package/vendor/ofd/dltech/ofd/pipeline.js +26 -0
@@ -0,0 +1,485 @@
1
+ import { resolvePrintAvailability } from './capabilities.js';
2
+ import { getExtension, normalizeFilename } from './source.js';
3
+ import { createFileViewerOriginalSourceState, hasFileViewerOriginalSource, } from './viewerOperations.js';
4
+ export const FILE_VIEWER_LIFECYCLE_HOOKS = {
5
+ 'load-start': 'onLoadStart',
6
+ 'load-complete': 'onLoadComplete',
7
+ 'unload-start': 'onUnloadStart',
8
+ 'unload-complete': 'onUnloadComplete',
9
+ };
10
+ export const FILE_VIEWER_OPERATION_LABELS = {
11
+ download: '下载原始文件',
12
+ print: '打印完整渲染内容',
13
+ 'export-html': '导出渲染 HTML',
14
+ 'zoom-in': '放大预览',
15
+ 'zoom-out': '缩小预览',
16
+ 'zoom-reset': '还原预览比例',
17
+ };
18
+ export const FILE_VIEWER_BEFORE_OPERATION_ERROR_PREFIX = '操作前置校验失败';
19
+ export const FILE_VIEWER_LIFECYCLE_HOOK_ERROR_MESSAGE_PREFIX = 'FileViewer';
20
+ export const buildFileViewerLifecycleContext = ({ phase, version, source, filename, file, url, size, bufferSize, startedAt, duration, timestamp, reason, }) => {
21
+ var _a;
22
+ const resolvedFilename = normalizeFilename((file === null || file === void 0 ? void 0 : file.name) || filename || url || '');
23
+ const now = timestamp !== null && timestamp !== void 0 ? timestamp : Date.now();
24
+ return {
25
+ phase,
26
+ type: getExtension(resolvedFilename),
27
+ filename: resolvedFilename,
28
+ source,
29
+ url,
30
+ file: file || undefined,
31
+ size: (_a = size !== null && size !== void 0 ? size : file === null || file === void 0 ? void 0 : file.size) !== null && _a !== void 0 ? _a : bufferSize,
32
+ version,
33
+ timestamp: now,
34
+ duration: duration !== null && duration !== void 0 ? duration : (phase === 'load-complete' && typeof startedAt === 'number' ? now - startedAt : undefined),
35
+ reason,
36
+ };
37
+ };
38
+ export const buildFileViewerLifecycleContextFromNormalizedSource = ({ phase, source, version, startedAt, timestamp, reason, }) => {
39
+ const now = timestamp !== null && timestamp !== void 0 ? timestamp : Date.now();
40
+ return buildFileViewerLifecycleContext({
41
+ phase,
42
+ filename: source.filename,
43
+ source: source.kind,
44
+ url: source.url,
45
+ file: typeof File !== 'undefined' && source.file instanceof File ? source.file : undefined,
46
+ size: source.size,
47
+ version,
48
+ timestamp: now,
49
+ duration: phase.endsWith('complete') && typeof startedAt === 'number' ? now - startedAt : undefined,
50
+ reason,
51
+ });
52
+ };
53
+ export const resolveFileViewerLifecycleFallbackSource = ({ file, url, } = {}) => {
54
+ if (file) {
55
+ return { source: 'file' };
56
+ }
57
+ if (url) {
58
+ return { source: 'url', sourceUrl: url };
59
+ }
60
+ return { source: 'empty' };
61
+ };
62
+ export const createFileViewerLifecycleStateController = () => {
63
+ let activeDocumentContext = null;
64
+ const loadStartedAt = new Map();
65
+ return {
66
+ markLoadStarted(version, timestamp = Date.now()) {
67
+ loadStartedAt.set(version, timestamp);
68
+ },
69
+ clearLoadStarted(version) {
70
+ loadStartedAt.delete(version);
71
+ },
72
+ getLoadStartedAt(version) {
73
+ return loadStartedAt.get(version);
74
+ },
75
+ getActiveDocumentContext() {
76
+ return activeDocumentContext;
77
+ },
78
+ setActiveDocumentContext(context) {
79
+ activeDocumentContext = context;
80
+ },
81
+ clearActiveDocumentContext() {
82
+ activeDocumentContext = null;
83
+ },
84
+ buildActiveUnloadContext(phase, context, reason = 'replace', timestamp = Date.now()) {
85
+ if (!context) {
86
+ return null;
87
+ }
88
+ return {
89
+ ...context,
90
+ phase,
91
+ timestamp,
92
+ reason,
93
+ };
94
+ },
95
+ };
96
+ };
97
+ export const buildFileViewerOperationContext = (operation, lifecycleContext, timestamp = Date.now()) => {
98
+ const { phase: _phase, ...context } = lifecycleContext;
99
+ return {
100
+ ...context,
101
+ operation,
102
+ label: FILE_VIEWER_OPERATION_LABELS[operation],
103
+ timestamp,
104
+ };
105
+ };
106
+ export const buildFileViewerOperationContextFromLifecycleState = ({ operation, lifecycleState, version, filename, bufferSize, currentFile, fallbackFile, fallbackUrl, timestamp, lifecycleTimestamp, }) => {
107
+ const activeContext = lifecycleState.getActiveDocumentContext();
108
+ const fallbackSource = resolveFileViewerLifecycleFallbackSource({
109
+ file: fallbackFile,
110
+ url: fallbackUrl,
111
+ });
112
+ const baseContext = activeContext || buildFileViewerLifecycleContext({
113
+ phase: 'load-complete',
114
+ version,
115
+ source: fallbackSource.source,
116
+ file: currentFile,
117
+ filename,
118
+ url: fallbackSource.sourceUrl,
119
+ bufferSize,
120
+ startedAt: lifecycleState.getLoadStartedAt(version),
121
+ timestamp: lifecycleTimestamp,
122
+ });
123
+ return buildFileViewerOperationContext(operation, baseContext, timestamp);
124
+ };
125
+ export const emitFileViewerComponentLifecycleEvent = (emit, context) => {
126
+ if (context.phase === 'load-start') {
127
+ emit('load-start', context);
128
+ return;
129
+ }
130
+ if (context.phase === 'load-complete') {
131
+ emit('load-complete', context);
132
+ return;
133
+ }
134
+ if (context.phase === 'unload-start') {
135
+ emit('unload-start', context);
136
+ return;
137
+ }
138
+ emit('unload-complete', context);
139
+ };
140
+ export const resolveFileViewerBeforeOperationErrorMessage = ({ error, formatErrorMessage, prefix = FILE_VIEWER_BEFORE_OPERATION_ERROR_PREFIX, }) => {
141
+ return formatErrorMessage(prefix, error);
142
+ };
143
+ export const resolveFileViewerLifecycleHookErrorMessage = ({ context, prefix = FILE_VIEWER_LIFECYCLE_HOOK_ERROR_MESSAGE_PREFIX, }) => {
144
+ return `${prefix} ${context.phase} hook failed`;
145
+ };
146
+ export const DEFAULT_FILE_VIEWER_LIFECYCLE_HOOK_ERROR_LOGGER = (message, error) => {
147
+ if (typeof console !== 'undefined' && typeof console.error === 'function') {
148
+ console.error(message, error);
149
+ }
150
+ };
151
+ export const reportFileViewerLifecycleHookError = ({ error, context, onLogError = DEFAULT_FILE_VIEWER_LIFECYCLE_HOOK_ERROR_LOGGER, prefix, }) => {
152
+ const message = resolveFileViewerLifecycleHookErrorMessage({ context, prefix });
153
+ onLogError === null || onLogError === void 0 ? void 0 : onLogError(message, error, context);
154
+ return message;
155
+ };
156
+ export const DEFAULT_FILE_VIEWER_OPERATION_ERROR_LOGGER = error => {
157
+ if (typeof console !== 'undefined' && typeof console.error === 'function') {
158
+ console.error(error);
159
+ }
160
+ };
161
+ export const reportFileViewerOperationError = ({ error, context, onLogError = DEFAULT_FILE_VIEWER_OPERATION_ERROR_LOGGER, }) => {
162
+ onLogError === null || onLogError === void 0 ? void 0 : onLogError(error, context);
163
+ return error;
164
+ };
165
+ export const runFileViewerActiveUnloadStart = ({ lifecycleState, reason = 'replace', onLifecycle, }) => {
166
+ const context = lifecycleState.getActiveDocumentContext();
167
+ const unloadContext = lifecycleState.buildActiveUnloadContext('unload-start', context, reason);
168
+ if (unloadContext) {
169
+ onLifecycle === null || onLifecycle === void 0 ? void 0 : onLifecycle(unloadContext);
170
+ }
171
+ return {
172
+ reason,
173
+ context,
174
+ unloadContext,
175
+ };
176
+ };
177
+ export const runFileViewerActiveUnloadComplete = ({ lifecycleState, context = null, reason = 'replace', onLifecycle, }) => {
178
+ const unloadContext = lifecycleState.buildActiveUnloadContext('unload-complete', context, reason);
179
+ if (unloadContext) {
180
+ onLifecycle === null || onLifecycle === void 0 ? void 0 : onLifecycle(unloadContext);
181
+ }
182
+ return {
183
+ reason,
184
+ context,
185
+ unloadContext,
186
+ };
187
+ };
188
+ export const getFileViewerLifecycleHookName = (phase) => {
189
+ return FILE_VIEWER_LIFECYCLE_HOOKS[phase];
190
+ };
191
+ export const runFileViewerLifecycleHook = async (context, hooks, onError) => {
192
+ const hook = hooks === null || hooks === void 0 ? void 0 : hooks[getFileViewerLifecycleHookName(context.phase)];
193
+ if (!hook) {
194
+ return;
195
+ }
196
+ try {
197
+ await hook(context);
198
+ }
199
+ catch (error) {
200
+ onError === null || onError === void 0 ? void 0 : onError(error, context);
201
+ }
202
+ };
203
+ export const getFileViewerBeforeOperationHooks = (options, operation) => {
204
+ const toolbar = options === null || options === void 0 ? void 0 : options.toolbar;
205
+ if (!toolbar || typeof toolbar !== 'object') {
206
+ return [options === null || options === void 0 ? void 0 : options.beforeOperation];
207
+ }
208
+ const specificHook = operation === 'download'
209
+ ? toolbar.beforeDownload
210
+ : operation === 'print'
211
+ ? toolbar.beforePrint
212
+ : operation === 'export-html'
213
+ ? toolbar.beforeExportHtml
214
+ : undefined;
215
+ return [options === null || options === void 0 ? void 0 : options.beforeOperation, toolbar.beforeOperation, specificHook];
216
+ };
217
+ export const runFileViewerBeforeOperation = async ({ context, options, onBefore, onCancel, onError, }) => {
218
+ onBefore === null || onBefore === void 0 ? void 0 : onBefore(context);
219
+ try {
220
+ for (const hook of getFileViewerBeforeOperationHooks(options, context.operation)) {
221
+ if (!hook) {
222
+ continue;
223
+ }
224
+ const result = await hook(context);
225
+ if (result === false) {
226
+ onCancel === null || onCancel === void 0 ? void 0 : onCancel(context);
227
+ return false;
228
+ }
229
+ }
230
+ }
231
+ catch (error) {
232
+ onError === null || onError === void 0 ? void 0 : onError(error, context);
233
+ onCancel === null || onCancel === void 0 ? void 0 : onCancel(context);
234
+ return false;
235
+ }
236
+ return true;
237
+ };
238
+ export const serializeFileViewerContext = (context) => {
239
+ const { file: _file, ...serializable } = context;
240
+ return {
241
+ ...serializable,
242
+ hasFile: !!context.file,
243
+ };
244
+ };
245
+ export const dispatchFileViewerLifecycleEvent = ({ context, hooks, onChange, onError, }) => {
246
+ onChange === null || onChange === void 0 ? void 0 : onChange(context.phase, context);
247
+ void runFileViewerLifecycleHook(context, hooks, onError);
248
+ return true;
249
+ };
250
+ export const dispatchFileViewerOperationContextEvent = ({ event, context, onChange, }) => {
251
+ onChange === null || onChange === void 0 ? void 0 : onChange(context);
252
+ return true;
253
+ };
254
+ export const createFileViewerLifecycleActions = ({ lifecycleState, getOptions = () => undefined, onLifecycleChange, onLifecycleError, onOperationBefore, onOperationCancel, onOperationError, }) => {
255
+ const notifyLifecycle = (context) => {
256
+ var _a;
257
+ return dispatchFileViewerLifecycleEvent({
258
+ context,
259
+ hooks: (_a = getOptions()) === null || _a === void 0 ? void 0 : _a.hooks,
260
+ onChange: onLifecycleChange,
261
+ onError: onLifecycleError,
262
+ });
263
+ };
264
+ return {
265
+ notifyLifecycle,
266
+ notifyActiveUnloadStart(reason = 'replace') {
267
+ return runFileViewerActiveUnloadStart({
268
+ lifecycleState,
269
+ reason,
270
+ onLifecycle: notifyLifecycle,
271
+ }).context;
272
+ },
273
+ notifyActiveUnloadComplete(context, reason = 'replace') {
274
+ return runFileViewerActiveUnloadComplete({
275
+ lifecycleState,
276
+ context,
277
+ reason,
278
+ onLifecycle: notifyLifecycle,
279
+ });
280
+ },
281
+ runBeforeOperation(context) {
282
+ return runFileViewerBeforeOperation({
283
+ context,
284
+ options: getOptions(),
285
+ onBefore: nextContext => {
286
+ dispatchFileViewerOperationContextEvent({
287
+ event: 'operation-before',
288
+ context: nextContext,
289
+ onChange: onOperationBefore,
290
+ });
291
+ },
292
+ onCancel: nextContext => {
293
+ dispatchFileViewerOperationContextEvent({
294
+ event: 'operation-cancel',
295
+ context: nextContext,
296
+ onChange: onOperationCancel,
297
+ });
298
+ },
299
+ onError: onOperationError,
300
+ });
301
+ },
302
+ };
303
+ };
304
+ export const dispatchFileViewerOperationAvailabilityChange = ({ availability, onChange, }) => {
305
+ const payload = cloneFileViewerOperationAvailability(availability);
306
+ onChange === null || onChange === void 0 ? void 0 : onChange(payload);
307
+ return true;
308
+ };
309
+ export const dispatchFileViewerZoomChange = ({ state, onChange, }) => {
310
+ onChange === null || onChange === void 0 ? void 0 : onChange(state);
311
+ return true;
312
+ };
313
+ export const createFileViewerToolbarActions = ({ getOperationAvailability, getToolbarDisabled = () => false, getZoomState, onOperationAvailabilityChange, onZoomChange, }) => {
314
+ return {
315
+ notifyOperationAvailabilityChange(availability = getOperationAvailability()) {
316
+ return dispatchFileViewerOperationAvailabilityChange({
317
+ availability,
318
+ onChange: onOperationAvailabilityChange,
319
+ });
320
+ },
321
+ notifyZoomChange(state = getZoomState()) {
322
+ return dispatchFileViewerZoomChange({
323
+ state,
324
+ onChange: onZoomChange,
325
+ });
326
+ },
327
+ isZoomButtonDisabled(action) {
328
+ return isFileViewerZoomButtonDisabled({
329
+ action,
330
+ availability: getOperationAvailability(),
331
+ toolbarDisabled: getToolbarDisabled(),
332
+ zoomState: getZoomState(),
333
+ });
334
+ },
335
+ };
336
+ };
337
+ export const createFileViewerPublicApi = ({ getOperationAvailability, ...api }) => {
338
+ return {
339
+ ...api,
340
+ getOperationAvailability: () => cloneFileViewerOperationAvailability(getOperationAvailability()),
341
+ };
342
+ };
343
+ export const createFileViewerToolbarZoomSyncSnapshot = (state) => [
344
+ state.scale,
345
+ state.label,
346
+ state.canZoomIn,
347
+ state.canZoomOut,
348
+ state.canReset,
349
+ ];
350
+ export const runFileViewerToolbarAvailabilitySync = ({ toolbarActions, availability, }) => {
351
+ return toolbarActions.notifyOperationAvailabilityChange(availability);
352
+ };
353
+ export const runFileViewerToolbarZoomSync = ({ toolbarActions, state, }) => {
354
+ return toolbarActions.notifyZoomChange(state);
355
+ };
356
+ export const createFileViewerToolbarControllerActionHandlers = ({ getAdapter = () => null, getBuffer = () => null, getExtension, getFile = () => null, getHasError = () => false, getLoading = () => false, getOptions, getSourceUrl = () => null, getToolbar, getRenderedReady, getZoomState, zoomSyncState, onOperationAvailabilityChange, onZoomChange, }) => {
357
+ let currentToolbarState = null;
358
+ const resolveToolbarState = () => {
359
+ var _a, _b, _c, _d;
360
+ currentToolbarState = resolveFileViewerToolbarState({
361
+ extension: getExtension(),
362
+ source: createFileViewerOriginalSourceState({
363
+ buffer: (_a = getBuffer()) !== null && _a !== void 0 ? _a : null,
364
+ file: (_b = getFile()) !== null && _b !== void 0 ? _b : null,
365
+ url: (_c = getSourceUrl()) !== null && _c !== void 0 ? _c : null,
366
+ }),
367
+ renderedReady: getRenderedReady(),
368
+ hasError: getHasError(),
369
+ adapter: (_d = getAdapter()) !== null && _d !== void 0 ? _d : null,
370
+ zoomState: getZoomState(),
371
+ toolbar: getToolbar(),
372
+ options: getOptions === null || getOptions === void 0 ? void 0 : getOptions(),
373
+ loading: getLoading(),
374
+ });
375
+ return currentToolbarState;
376
+ };
377
+ const getResolvedToolbarState = () => currentToolbarState !== null && currentToolbarState !== void 0 ? currentToolbarState : resolveToolbarState();
378
+ const toolbarActions = createFileViewerToolbarActions({
379
+ getOperationAvailability: () => getResolvedToolbarState().operationAvailability,
380
+ getToolbarDisabled: () => getResolvedToolbarState().toolbarDisabled,
381
+ getZoomState,
382
+ onOperationAvailabilityChange,
383
+ onZoomChange,
384
+ });
385
+ return {
386
+ resolveToolbarState,
387
+ createZoomSyncSnapshot: () => createFileViewerToolbarZoomSyncSnapshot(zoomSyncState !== null && zoomSyncState !== void 0 ? zoomSyncState : getZoomState()),
388
+ syncOperationAvailability: availability => runFileViewerToolbarAvailabilitySync({
389
+ toolbarActions,
390
+ availability,
391
+ }),
392
+ syncZoomChange: state => runFileViewerToolbarZoomSync({
393
+ toolbarActions,
394
+ state,
395
+ }),
396
+ isZoomButtonDisabled: toolbarActions.isZoomButtonDisabled,
397
+ };
398
+ };
399
+ export const normalizeFileViewerToolbar = (options) => {
400
+ const toolbar = options === null || options === void 0 ? void 0 : options.toolbar;
401
+ if (toolbar === false) {
402
+ return {
403
+ download: false,
404
+ print: false,
405
+ exportHtml: false,
406
+ zoom: false,
407
+ };
408
+ }
409
+ if (toolbar && typeof toolbar === 'object') {
410
+ return {
411
+ download: toolbar.download !== false,
412
+ print: toolbar.print !== false,
413
+ exportHtml: toolbar.exportHtml !== false,
414
+ zoom: toolbar.zoom !== false,
415
+ };
416
+ }
417
+ return {
418
+ download: true,
419
+ print: true,
420
+ exportHtml: true,
421
+ zoom: true,
422
+ };
423
+ };
424
+ export const resolveFileViewerOperationAvailability = ({ extension, hasOriginalSource, renderedReady, hasError = false, adapter, source, zoomState, }) => {
425
+ const hasRenderableOutput = renderedReady && !hasError;
426
+ const hasSource = hasOriginalSource !== null && hasOriginalSource !== void 0 ? hasOriginalSource : (source ? hasFileViewerOriginalSource(source) : false);
427
+ const zoomEnabled = hasRenderableOutput && (zoomState.canZoomIn || zoomState.canZoomOut || zoomState.canReset);
428
+ return {
429
+ download: hasSource,
430
+ print: hasRenderableOutput && resolvePrintAvailability(extension, adapter !== null && adapter !== void 0 ? adapter : null, renderedReady),
431
+ exportHtml: hasRenderableOutput && (adapter === null || adapter === void 0 ? void 0 : adapter.exportHtml) !== false,
432
+ zoom: zoomEnabled,
433
+ zoomIn: zoomEnabled && zoomState.canZoomIn,
434
+ zoomOut: zoomEnabled && zoomState.canZoomOut,
435
+ zoomReset: zoomEnabled && zoomState.canReset,
436
+ };
437
+ };
438
+ export const cloneFileViewerOperationAvailability = (availability) => ({
439
+ download: availability.download,
440
+ print: availability.print,
441
+ exportHtml: availability.exportHtml,
442
+ zoom: availability.zoom,
443
+ zoomIn: availability.zoomIn,
444
+ zoomOut: availability.zoomOut,
445
+ zoomReset: availability.zoomReset,
446
+ });
447
+ export const resolveVisibleFileViewerToolbar = (toolbar, availability) => {
448
+ return {
449
+ download: toolbar.download && availability.download,
450
+ print: toolbar.print && availability.print,
451
+ exportHtml: toolbar.exportHtml && availability.exportHtml,
452
+ zoom: toolbar.zoom && availability.zoom,
453
+ };
454
+ };
455
+ export const hasVisibleFileViewerToolbarActions = (toolbar) => {
456
+ return !!(toolbar.download || toolbar.print || toolbar.exportHtml || toolbar.zoom);
457
+ };
458
+ export const isFileViewerZoomButtonDisabled = ({ toolbarDisabled = false, availability, zoomState, action, }) => {
459
+ return toolbarDisabled || !availability.zoom || !zoomState[action];
460
+ };
461
+ export const isFileViewerToolbarDisabled = ({ loading = false, hasError = false, }) => {
462
+ return !!(loading || hasError);
463
+ };
464
+ export const resolveFileViewerToolbarState = ({ toolbar, options, loading = false, ...availabilityInput }) => {
465
+ const operationAvailability = resolveFileViewerOperationAvailability(availabilityInput);
466
+ const visibleToolbar = resolveVisibleFileViewerToolbar(toolbar, operationAvailability);
467
+ return {
468
+ operationAvailability,
469
+ visibleToolbar,
470
+ showToolbar: hasVisibleFileViewerToolbarActions(visibleToolbar),
471
+ toolbarPosition: resolveFileViewerToolbarPosition(options, availabilityInput.extension),
472
+ toolbarDisabled: isFileViewerToolbarDisabled({
473
+ loading,
474
+ hasError: availabilityInput.hasError,
475
+ }),
476
+ };
477
+ };
478
+ export const resolveFileViewerToolbarPosition = (options, extension) => {
479
+ const toolbar = options === null || options === void 0 ? void 0 : options.toolbar;
480
+ const position = toolbar && typeof toolbar === 'object' ? toolbar.position : 'auto';
481
+ if (position === 'top' || position === 'bottom-right') {
482
+ return position;
483
+ }
484
+ return extension === 'pdf' ? 'bottom-right' : 'top';
485
+ };
@@ -0,0 +1,16 @@
1
+ import type { FileViewerArchiveOptions, FileViewerCadOptions, FileViewerOptions, FileViewerThemeMode, FileViewerToolbarOptions } from './types';
2
+ export type FileViewerSerializableToolbarOptions = Omit<FileViewerToolbarOptions, 'beforeOperation' | 'beforeDownload' | 'beforePrint' | 'beforeExportHtml'>;
3
+ export type FileViewerSerializableCadOptions = Omit<FileViewerCadOptions, 'workerUrl'> & {
4
+ workerUrl?: string;
5
+ };
6
+ export interface FileViewerSerializableOptions extends Omit<FileViewerOptions, 'toolbar' | 'cad' | 'hooks' | 'beforeOperation'> {
7
+ toolbar?: boolean | FileViewerSerializableToolbarOptions;
8
+ archive?: FileViewerArchiveOptions;
9
+ cad?: FileViewerSerializableCadOptions;
10
+ }
11
+ export declare const normalizeFileViewerTheme: (theme: FileViewerThemeMode | undefined) => FileViewerThemeMode;
12
+ export declare const sanitizeFileViewerOptions: (options?: FileViewerOptions | FileViewerSerializableOptions | null) => FileViewerSerializableOptions | undefined;
13
+ export declare const serializeFileViewerOptions: (options?: FileViewerOptions | FileViewerSerializableOptions | null) => string | undefined;
14
+ export declare const parseFileViewerOptions: (value: unknown) => FileViewerSerializableOptions | undefined;
15
+ export declare const setFileViewerOptionsSearchParam: (searchParams: URLSearchParams, options?: FileViewerOptions | FileViewerSerializableOptions | null, key?: string) => void;
16
+ export declare const getFileViewerOptionsSearchParam: (searchParams: URLSearchParams, key?: string) => FileViewerSerializableOptions | undefined;
@@ -0,0 +1,92 @@
1
+ const isRecord = (value) => {
2
+ return !!value && typeof value === 'object' && !Array.isArray(value);
3
+ };
4
+ const isUrlLike = (value) => {
5
+ return typeof URL !== 'undefined' && value instanceof URL;
6
+ };
7
+ const sanitizeJsonValue = (value) => {
8
+ if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
9
+ return undefined;
10
+ }
11
+ if (value === null || typeof value === 'string' || typeof value === 'boolean') {
12
+ return value;
13
+ }
14
+ if (typeof value === 'number') {
15
+ return Number.isFinite(value) ? value : undefined;
16
+ }
17
+ if (typeof value === 'bigint') {
18
+ return value.toString();
19
+ }
20
+ if (value instanceof Date) {
21
+ return value.toISOString();
22
+ }
23
+ if (isUrlLike(value)) {
24
+ return value.toString();
25
+ }
26
+ if (Array.isArray(value)) {
27
+ return value
28
+ .map(item => sanitizeJsonValue(item))
29
+ .filter((item) => item !== undefined);
30
+ }
31
+ if (!isRecord(value)) {
32
+ return undefined;
33
+ }
34
+ const output = {};
35
+ Object.entries(value).forEach(([key, nextValue]) => {
36
+ const sanitized = sanitizeJsonValue(nextValue);
37
+ if (sanitized !== undefined) {
38
+ output[key] = sanitized;
39
+ }
40
+ });
41
+ return Object.keys(output).length ? output : undefined;
42
+ };
43
+ const stripExecutionOnlyOptions = (value) => {
44
+ const { beforeOperation: _beforeOperation, hooks: _hooks, ...rest } = value;
45
+ if (isRecord(rest.toolbar)) {
46
+ const { beforeOperation: _toolbarBeforeOperation, beforeDownload: _beforeDownload, beforePrint: _beforePrint, beforeExportHtml: _beforeExportHtml, ...toolbar } = rest.toolbar;
47
+ rest.toolbar = toolbar;
48
+ }
49
+ return rest;
50
+ };
51
+ export const normalizeFileViewerTheme = (theme) => {
52
+ return theme === 'light' || theme === 'dark' || theme === 'system' ? theme : 'system';
53
+ };
54
+ export const sanitizeFileViewerOptions = (options) => {
55
+ if (!isRecord(options)) {
56
+ return undefined;
57
+ }
58
+ const sanitized = sanitizeJsonValue(stripExecutionOnlyOptions(options));
59
+ if (!isRecord(sanitized)) {
60
+ return undefined;
61
+ }
62
+ return sanitized;
63
+ };
64
+ export const serializeFileViewerOptions = (options) => {
65
+ const sanitized = sanitizeFileViewerOptions(options);
66
+ return sanitized ? JSON.stringify(sanitized) : undefined;
67
+ };
68
+ export const parseFileViewerOptions = (value) => {
69
+ if (!value) {
70
+ return undefined;
71
+ }
72
+ if (typeof value === 'string') {
73
+ try {
74
+ return sanitizeFileViewerOptions(JSON.parse(value));
75
+ }
76
+ catch {
77
+ return undefined;
78
+ }
79
+ }
80
+ return sanitizeFileViewerOptions(value);
81
+ };
82
+ export const setFileViewerOptionsSearchParam = (searchParams, options, key = 'options') => {
83
+ const serialized = serializeFileViewerOptions(options);
84
+ if (!serialized) {
85
+ searchParams.delete(key);
86
+ return;
87
+ }
88
+ searchParams.set(key, serialized);
89
+ };
90
+ export const getFileViewerOptionsSearchParam = (searchParams, key = 'options') => {
91
+ return parseFileViewerOptions(searchParams.get(key));
92
+ };
@@ -0,0 +1,14 @@
1
+ import type { FileViewerFileRef, FileViewerOptions, FileViewerThemeMode, FileViewerToolbarOptions } from './types';
2
+ export interface ResolveFileViewerPresentationStateInput {
3
+ filename?: string;
4
+ file?: FileViewerFileRef;
5
+ url?: string;
6
+ options?: FileViewerOptions;
7
+ }
8
+ export interface FileViewerPresentationState {
9
+ displayFilename: string;
10
+ extension: string;
11
+ toolbar: FileViewerToolbarOptions;
12
+ theme: FileViewerThemeMode;
13
+ }
14
+ export declare const resolveFileViewerPresentationState: ({ filename, file, url, options, }: ResolveFileViewerPresentationStateInput) => FileViewerPresentationState;
@@ -0,0 +1,16 @@
1
+ import { normalizeFileViewerToolbar } from './operations.js';
2
+ import { normalizeFileViewerTheme } from './options.js';
3
+ import { getExtension, resolveFileViewerSourceFilename } from './source.js';
4
+ export const resolveFileViewerPresentationState = ({ filename, file, url, options, }) => {
5
+ const displayFilename = resolveFileViewerSourceFilename({
6
+ filename,
7
+ file,
8
+ url,
9
+ });
10
+ return {
11
+ displayFilename,
12
+ extension: getExtension(displayFilename),
13
+ toolbar: normalizeFileViewerToolbar(options),
14
+ theme: normalizeFileViewerTheme(options === null || options === void 0 ? void 0 : options.theme),
15
+ };
16
+ };
@@ -0,0 +1,19 @@
1
+ export interface PrintPageSize {
2
+ width: number;
3
+ height: number;
4
+ }
5
+ export interface ApplyPrintPageSizeOptions {
6
+ heightMode?: 'fixed' | 'min';
7
+ }
8
+ export interface BuildPrintPageStyleOptions extends PrintPageSize {
9
+ selector: string;
10
+ heightMode?: 'fixed' | 'min';
11
+ }
12
+ export declare const formatCssPixels: (value: number) => string;
13
+ /**
14
+ * Browser print helper. DOM measurement belongs in the core browser layer
15
+ * because it depends on CSS layout and HTMLElement.
16
+ */
17
+ export declare const getElementPrintPageSize: (element: HTMLElement, fallback?: Partial<PrintPageSize>) => PrintPageSize;
18
+ export declare const applyPrintPageSize: (element: HTMLElement, size: PrintPageSize, options?: ApplyPrintPageSizeOptions) => void;
19
+ export declare const buildPrintPageStyle: ({ selector, width, height, heightMode, }: BuildPrintPageStyleOptions) => string;