@veltra/desktop 1.1.27 → 1.1.29

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 (316) hide show
  1. package/dist/components/action/action-group.vue.d.ts +5 -7
  2. package/dist/components/action/action-group.vue_vue_type_script_setup_true_lang.js +1 -1
  3. package/dist/components/action/action-group.vue_vue_type_script_setup_true_lang.js.map +1 -1
  4. package/dist/components/action/action.js.map +1 -1
  5. package/dist/components/action/action.vue.d.ts +5 -8
  6. package/dist/components/action/di.js.map +1 -1
  7. package/dist/components/auto-complete/auto-complete.js.map +1 -1
  8. package/dist/components/auto-complete/auto-complete.vue.d.ts +5 -7
  9. package/dist/components/auto-complete/use-keyboard.js.map +1 -1
  10. package/dist/components/auto-complete/use-suggestions.js.map +1 -1
  11. package/dist/components/badge/badge.js.map +1 -1
  12. package/dist/components/badge/badge.vue.d.ts +2 -4
  13. package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
  14. package/dist/components/batch-edit/batch-edit-list.js.map +1 -1
  15. package/dist/components/batch-edit/batch-edit.js.map +1 -1
  16. package/dist/components/batch-edit/batch-edit.vue.d.ts +6 -9
  17. package/dist/components/batch-edit/di.js.map +1 -1
  18. package/dist/components/batch-edit/helper.js.map +1 -1
  19. package/dist/components/batch-edit/use-edit.js.map +1 -1
  20. package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
  21. package/dist/components/breadcrumb/breadcrumb.vue.d.ts +3 -5
  22. package/dist/components/button/button-group.js.map +1 -1
  23. package/dist/components/button/button-group.vue.d.ts +1 -3
  24. package/dist/components/button/button.js.map +1 -1
  25. package/dist/components/button/button.vue.d.ts +4 -6
  26. package/dist/components/calendar/calendar.js.map +1 -1
  27. package/dist/components/calendar/calendar.vue.d.ts +3 -5
  28. package/dist/components/calendar/utils.js.map +1 -1
  29. package/dist/components/card/card-action.js.map +1 -1
  30. package/dist/components/card/card-action.vue.d.ts +1 -3
  31. package/dist/components/card/card-content.js.map +1 -1
  32. package/dist/components/card/card-content.vue.d.ts +1 -3
  33. package/dist/components/card/card-cover.js.map +1 -1
  34. package/dist/components/card/card-cover.vue.d.ts +1 -3
  35. package/dist/components/card/card-header.js.map +1 -1
  36. package/dist/components/card/card-header.vue.d.ts +1 -3
  37. package/dist/components/card/card.js.map +1 -1
  38. package/dist/components/card/card.vue.d.ts +1 -3
  39. package/dist/components/card/di.js.map +1 -1
  40. package/dist/components/cascade/cascade-panel-item.js.map +1 -1
  41. package/dist/components/cascade/cascade.js.map +1 -1
  42. package/dist/components/cascade/cascade.vue.d.ts +8 -10
  43. package/dist/components/cascade/di.js.map +1 -1
  44. package/dist/components/cascade/node.js.map +1 -1
  45. package/dist/components/cascade/use-check.js.map +1 -1
  46. package/dist/components/cascade/use-data-map.js.map +1 -1
  47. package/dist/components/cascade/use-select.js.map +1 -1
  48. package/dist/components/check-tag/check-tag.js.map +1 -1
  49. package/dist/components/check-tag/check-tag.vue.d.ts +3 -5
  50. package/dist/components/checkbox/checkbox-button.js.map +1 -1
  51. package/dist/components/checkbox/checkbox-button.vue.d.ts +4 -7
  52. package/dist/components/checkbox/checkbox.js.map +1 -1
  53. package/dist/components/checkbox/checkbox.vue.d.ts +3 -5
  54. package/dist/components/checkbox-group/checkbox-group.js.map +1 -1
  55. package/dist/components/checkbox-group/checkbox-group.vue.d.ts +5 -7
  56. package/dist/components/code-editor/code-editor.js.map +1 -1
  57. package/dist/components/code-editor/code-editor.vue.d.ts +3 -5
  58. package/dist/components/collapse/collapse-item.js.map +1 -1
  59. package/dist/components/collapse/collapse-item.vue.d.ts +1 -3
  60. package/dist/components/collapse/collapse.js.map +1 -1
  61. package/dist/components/collapse/collapse.vue.d.ts +3 -5
  62. package/dist/components/collapse/di.js.map +1 -1
  63. package/dist/components/condition-editor/components/condition-group.js.map +1 -1
  64. package/dist/components/condition-editor/components/condition-row.js.map +1 -1
  65. package/dist/components/condition-editor/condition-editor.js.map +1 -1
  66. package/dist/components/condition-editor/condition-editor.vue.d.ts +3 -5
  67. package/dist/components/condition-editor/core/evaluator.js.map +1 -1
  68. package/dist/components/condition-editor/core/operators.js.map +1 -1
  69. package/dist/components/context-menu/api.js.map +1 -1
  70. package/dist/components/context-menu/context-menu-item.js.map +1 -1
  71. package/dist/components/context-menu/context-menu.js.map +1 -1
  72. package/dist/components/context-menu/context-menu.vue.d.ts +3 -5
  73. package/dist/components/context-menu/di.js.map +1 -1
  74. package/dist/components/date-panel/date-panel.js.map +1 -1
  75. package/dist/components/date-panel/date-panel.vue.d.ts +8 -12
  76. package/dist/components/date-panel/di.js.map +1 -1
  77. package/dist/components/date-panel/headers/day.js.map +1 -1
  78. package/dist/components/date-panel/headers/month.js.map +1 -1
  79. package/dist/components/date-panel/headers/year.js.map +1 -1
  80. package/dist/components/date-panel/panels/day.js.map +1 -1
  81. package/dist/components/date-panel/panels/month.js.map +1 -1
  82. package/dist/components/date-panel/panels/year.js.map +1 -1
  83. package/dist/components/date-panel/use-date-select.js.map +1 -1
  84. package/dist/components/date-panel/use-panel-date.js.map +1 -1
  85. package/dist/components/date-panel/use-panel.js.map +1 -1
  86. package/dist/components/date-picker/date-picker.js.map +1 -1
  87. package/dist/components/date-picker/date-picker.vue.d.ts +5 -7
  88. package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
  89. package/dist/components/date-range-picker/date-range-picker.vue.d.ts +5 -7
  90. package/dist/components/dialog/di.js.map +1 -1
  91. package/dist/components/dialog/dialog.js.map +1 -1
  92. package/dist/components/dialog/dialog.vue.d.ts +3 -6
  93. package/dist/components/dialog/use-maximum.js.map +1 -1
  94. package/dist/components/drawer/drawer.js.map +1 -1
  95. package/dist/components/drawer/drawer.vue.d.ts +3 -5
  96. package/dist/components/dropdown/dropdown.js.map +1 -1
  97. package/dist/components/dropdown/dropdown.vue.d.ts +3 -6
  98. package/dist/components/empty/empty.js.map +1 -1
  99. package/dist/components/empty/empty.vue.d.ts +3 -5
  100. package/dist/components/expression-editor/components/path-preview.js.map +1 -1
  101. package/dist/components/expression-editor/components/variable-picker.js.map +1 -1
  102. package/dist/components/expression-editor/core/chip.js.map +1 -1
  103. package/dist/components/expression-editor/core/editor.js.map +1 -1
  104. package/dist/components/expression-editor/core/mention.js.map +1 -1
  105. package/dist/components/expression-editor/core/model.js.map +1 -1
  106. package/dist/components/expression-editor/di.js.map +1 -1
  107. package/dist/components/expression-editor/expression-editor.js.map +1 -1
  108. package/dist/components/expression-editor/expression-editor.vue.d.ts +3 -5
  109. package/dist/components/file-picker/file-picker.js.map +1 -1
  110. package/dist/components/file-picker/file-picker.vue.d.ts +3 -5
  111. package/dist/components/file-picker/helper.js.map +1 -1
  112. package/dist/components/file-viewer/file-viewer.js +1 -1
  113. package/dist/components/file-viewer/file-viewer.js.map +1 -1
  114. package/dist/components/file-viewer/file-viewer.vue.d.ts +5 -6
  115. package/dist/components/file-viewer/helper.js.map +1 -1
  116. package/dist/components/file-viewer/previewers/docx-previewer.js.map +1 -1
  117. package/dist/components/file-viewer/previewers/image-previewer.js.map +1 -1
  118. package/dist/components/file-viewer/previewers/pdf-previewer.js.map +1 -1
  119. package/dist/components/file-viewer/previewers/pdf-viewport-scroll.js.map +1 -1
  120. package/dist/components/file-viewer/previewers/pdf-zoom-bridge.js.map +1 -1
  121. package/dist/components/file-viewer/previewers/sheet-previewer.js.map +1 -1
  122. package/dist/components/file-viewer/previewers/text-previewer.js.map +1 -1
  123. package/dist/components/file-viewer/previewers/video-previewer.js.map +1 -1
  124. package/dist/components/float-button/float-button.js.map +1 -1
  125. package/dist/components/float-button/float-button.vue.d.ts +3 -5
  126. package/dist/components/form/dynamic-form-model.js.map +1 -1
  127. package/dist/components/form/form-model.d.ts +8 -8
  128. package/dist/components/form/form-model.js +2 -2
  129. package/dist/components/form/form-model.js.map +1 -1
  130. package/dist/components/form/form.vue.d.ts +3 -4
  131. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +1 -1
  132. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
  133. package/dist/components/form/helper.js.map +1 -1
  134. package/dist/components/form/use-node-interceptor.js.map +1 -1
  135. package/dist/components/form-item/form-item.vue.d.ts +2 -4
  136. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js +1 -1
  137. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
  138. package/dist/components/form-item/helper.js.map +1 -1
  139. package/dist/components/gantt-chart/gantt-chart.js.map +1 -1
  140. package/dist/components/gantt-chart/gantt-chart.vue.d.ts +1 -3
  141. package/dist/components/grid/breakpoint.js.map +1 -1
  142. package/dist/components/grid/di.js.map +1 -1
  143. package/dist/components/grid/grid-item.js.map +1 -1
  144. package/dist/components/grid/grid-item.vue.d.ts +2 -4
  145. package/dist/components/grid/grid.js.map +1 -1
  146. package/dist/components/grid/grid.vue.d.ts +3 -5
  147. package/dist/components/grid/use-responsive.js.map +1 -1
  148. package/dist/components/grid-input/grid-input.js.map +1 -1
  149. package/dist/components/grid-input/grid-input.vue.d.ts +3 -6
  150. package/dist/components/group-input/group-input.js.map +1 -1
  151. package/dist/components/group-input/group-input.vue.d.ts +2 -4
  152. package/dist/components/group-input/use-group-items.js.map +1 -1
  153. package/dist/components/icon/icon.js.map +1 -1
  154. package/dist/components/icon/icon.vue.d.ts +1 -3
  155. package/dist/components/input/input.vue.d.ts +7 -9
  156. package/dist/components/input/input.vue_vue_type_script_setup_true_lang.js +3 -3
  157. package/dist/components/input/input.vue_vue_type_script_setup_true_lang.js.map +1 -1
  158. package/dist/components/kbd/kbd.js.map +1 -1
  159. package/dist/components/kbd/kbd.vue.d.ts +1 -3
  160. package/dist/components/layout/di.js.map +1 -1
  161. package/dist/components/layout/layout-resizer.js.map +1 -1
  162. package/dist/components/layout/layout.js.map +1 -1
  163. package/dist/components/layout/layout.vue.d.ts +2 -4
  164. package/dist/components/list/list-item.js.map +1 -1
  165. package/dist/components/list/list-item.vue.d.ts +1 -3
  166. package/dist/components/list/list.js.map +1 -1
  167. package/dist/components/list/list.vue.d.ts +1 -3
  168. package/dist/components/loading/directive.js.map +1 -1
  169. package/dist/components/loading/loading.js.map +1 -1
  170. package/dist/components/loading/loading.vue.d.ts +2 -4
  171. package/dist/components/menu/di.js.map +1 -1
  172. package/dist/components/menu/helper.js.map +1 -1
  173. package/dist/components/menu/menu-icon.js.map +1 -1
  174. package/dist/components/menu/menu-item-collapsed.js.map +1 -1
  175. package/dist/components/menu/menu-item.js.map +1 -1
  176. package/dist/components/menu/menu-item.vue.d.ts +1 -3
  177. package/dist/components/menu/menu-sub-collapsed.js.map +1 -1
  178. package/dist/components/menu/menu-sub.js.map +1 -1
  179. package/dist/components/menu/menu-sub.vue.d.ts +1 -3
  180. package/dist/components/menu/menu.js.map +1 -1
  181. package/dist/components/menu/menu.vue.d.ts +3 -5
  182. package/dist/components/menu/use-menu-item.js.map +1 -1
  183. package/dist/components/menu/walk-menu-path.js.map +1 -1
  184. package/dist/components/message/helper.js.map +1 -1
  185. package/dist/components/message/message-box.js.map +1 -1
  186. package/dist/components/message/message.js.map +1 -1
  187. package/dist/components/message/message.vue.d.ts +3 -5
  188. package/dist/components/message/message2.js.map +1 -1
  189. package/dist/components/message-confirm/message-confirm.js.map +1 -1
  190. package/dist/components/message-confirm/message-confirm.vue.d.ts +2 -3
  191. package/dist/components/message-confirm/message-confirm2.js.map +1 -1
  192. package/dist/components/multi-select/di.js.map +1 -1
  193. package/dist/components/multi-select/multi-select-option.js.map +1 -1
  194. package/dist/components/multi-select/multi-select.js.map +1 -1
  195. package/dist/components/multi-select/multi-select.vue.d.ts +6 -8
  196. package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
  197. package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +8 -9
  198. package/dist/components/node-render/node-render.js.map +1 -1
  199. package/dist/components/notification/index.js.map +1 -1
  200. package/dist/components/notification/notification.js.map +1 -1
  201. package/dist/components/notification/notification.vue.d.ts +4 -7
  202. package/dist/components/number/number.js.map +1 -1
  203. package/dist/components/number/number.vue.d.ts +2 -4
  204. package/dist/components/number-input/number-input.js.map +1 -1
  205. package/dist/components/number-input/number-input.vue.d.ts +7 -9
  206. package/dist/components/number-range-input/number-range-input.js.map +1 -1
  207. package/dist/components/number-range-input/number-range-input.vue.d.ts +4 -6
  208. package/dist/components/paginator/paginator.js.map +1 -1
  209. package/dist/components/paginator/paginator.vue.d.ts +3 -5
  210. package/dist/components/palette/color-transform.js.map +1 -1
  211. package/dist/components/palette/di.js.map +1 -1
  212. package/dist/components/palette/palette-alpha.js.map +1 -1
  213. package/dist/components/palette/palette-color-switch.js.map +1 -1
  214. package/dist/components/palette/palette-hue.js.map +1 -1
  215. package/dist/components/palette/palette-sv.js.map +1 -1
  216. package/dist/components/palette/palette.js.map +1 -1
  217. package/dist/components/palette/palette.vue.d.ts +3 -5
  218. package/dist/components/palette/use-hsv.js.map +1 -1
  219. package/dist/components/password-input/password-input.js.map +1 -1
  220. package/dist/components/password-input/password-input.vue.d.ts +4 -6
  221. package/dist/components/pop-confirm/pop-confirm.js.map +1 -1
  222. package/dist/components/pop-confirm/pop-confirm.vue.d.ts +5 -7
  223. package/dist/components/progress/progress.js.map +1 -1
  224. package/dist/components/progress/progress.vue.d.ts +2 -3
  225. package/dist/components/progress-nodes/progress-nodes.js.map +1 -1
  226. package/dist/components/progress-nodes/progress-nodes.vue.d.ts +4 -7
  227. package/dist/components/radio/radio.js.map +1 -1
  228. package/dist/components/radio/radio.vue.d.ts +3 -5
  229. package/dist/components/radio-group/radio-group.js.map +1 -1
  230. package/dist/components/radio-group/radio-group.vue.d.ts +5 -7
  231. package/dist/components/rich-text-editor/rich-text-editor.js.map +1 -1
  232. package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +5 -7
  233. package/dist/components/rich-text-editor/toolbar.js.map +1 -1
  234. package/dist/components/scroll/di.js.map +1 -1
  235. package/dist/components/scroll/scroll-bar.js.map +1 -1
  236. package/dist/components/scroll/scroll.js.map +1 -1
  237. package/dist/components/scroll/scroll.vue.d.ts +3 -5
  238. package/dist/components/select/select.js.map +1 -1
  239. package/dist/components/select/select.vue.d.ts +5 -7
  240. package/dist/components/select/use-keyboard.js.map +1 -1
  241. package/dist/components/select/use-options.js.map +1 -1
  242. package/dist/components/slider/di.js.map +1 -1
  243. package/dist/components/slider/slider-thumb.js.map +1 -1
  244. package/dist/components/slider/slider.js.map +1 -1
  245. package/dist/components/slider/slider.vue.d.ts +2 -4
  246. package/dist/components/slider/use-slider.js.map +1 -1
  247. package/dist/components/steps/steps.js.map +1 -1
  248. package/dist/components/steps/steps.vue.d.ts +4 -7
  249. package/dist/components/switch/switch.js.map +1 -1
  250. package/dist/components/switch/switch.vue.d.ts +3 -5
  251. package/dist/components/table/di.js.map +1 -1
  252. package/dist/components/table/node/col.js.map +1 -1
  253. package/dist/components/table/node/row.js.map +1 -1
  254. package/dist/components/table/table-body.js.map +1 -1
  255. package/dist/components/table/table-cell.js.map +1 -1
  256. package/dist/components/table/table-foot.js.map +1 -1
  257. package/dist/components/table/table-head.js.map +1 -1
  258. package/dist/components/table/table-row.js.map +1 -1
  259. package/dist/components/table/table.js.map +1 -1
  260. package/dist/components/table/table.vue.d.ts +7 -10
  261. package/dist/components/table/use-check.js.map +1 -1
  262. package/dist/components/table/use-col-resize.js.map +1 -1
  263. package/dist/components/table/use-columns.js.map +1 -1
  264. package/dist/components/table/use-fixed-columns.js.map +1 -1
  265. package/dist/components/table/use-rows.js.map +1 -1
  266. package/dist/components/table/use-table.js.map +1 -1
  267. package/dist/components/table-editor/table-editor.js.map +1 -1
  268. package/dist/components/table-editor/table-editor.vue.d.ts +3 -5
  269. package/dist/components/tabs/tabs-horizontal.js +5 -2
  270. package/dist/components/tabs/tabs-horizontal.js.map +1 -1
  271. package/dist/components/tabs/tabs-horizontal.vue.d.ts +6 -8
  272. package/dist/components/tabs/tabs-vertical.js +5 -2
  273. package/dist/components/tabs/tabs-vertical.js.map +1 -1
  274. package/dist/components/tabs/tabs-vertical.vue.d.ts +11 -10
  275. package/dist/components/tabs/tabs.js.map +1 -1
  276. package/dist/components/tabs/tabs.vue.d.ts +12 -7
  277. package/dist/components/tabs/use-tabs-bar.js.map +1 -1
  278. package/dist/components/tag/tag.js.map +1 -1
  279. package/dist/components/tag/tag.vue.d.ts +3 -5
  280. package/dist/components/text/text.js.map +1 -1
  281. package/dist/components/text/text.vue.d.ts +2 -4
  282. package/dist/components/textarea/textarea.js.map +1 -1
  283. package/dist/components/textarea/textarea.vue.d.ts +7 -9
  284. package/dist/components/textarea/utils.js.map +1 -1
  285. package/dist/components/theme/schema.js.map +1 -1
  286. package/dist/components/theme/theme.js.map +1 -1
  287. package/dist/components/theme/theme.vue.d.ts +1 -3
  288. package/dist/components/tip/tip.js.map +1 -1
  289. package/dist/components/tip/tip.vue.d.ts +4 -6
  290. package/dist/components/tip/use-nest.js.map +1 -1
  291. package/dist/components/tree/di.js.map +1 -1
  292. package/dist/components/tree/tree-node.js.map +1 -1
  293. package/dist/components/tree/tree-node2.js.map +1 -1
  294. package/dist/components/tree/tree.js.map +1 -1
  295. package/dist/components/tree/tree.vue.d.ts +3 -5
  296. package/dist/components/tree/use-check.js.map +1 -1
  297. package/dist/components/tree/use-filter.js.map +1 -1
  298. package/dist/components/tree/use-select.js.map +1 -1
  299. package/dist/components/tree/use-tree-nodes.js.map +1 -1
  300. package/dist/components/tree-select/tree-select.js.map +1 -1
  301. package/dist/components/tree-select/tree-select.vue.d.ts +8 -9
  302. package/dist/components/watermark/watermark.js.map +1 -1
  303. package/dist/components/watermark/watermark.vue.d.ts +2 -4
  304. package/dist/index.d.ts +1 -1
  305. package/dist/install.js.map +1 -1
  306. package/dist/types/form.d.ts +7 -7
  307. package/dist/types/index.d.ts +1 -1
  308. package/package.json +8 -8
  309. package/src/components/batch-edit/batch-edit.vue +2 -2
  310. package/src/components/batch-edit/di.ts +2 -2
  311. package/src/components/form/form-model.ts +16 -20
  312. package/src/components/tabs/tabs-horizontal.vue +2 -2
  313. package/src/components/tabs/tabs-vertical.vue +1 -1
  314. package/src/components/tabs/tabs.vue +2 -2
  315. package/src/types/form.ts +7 -7
  316. package/dist/components/kbd/index.d.ts +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"expression-editor.js","names":[],"sources":["../../../src/components/expression-editor/expression-editor.vue"],"sourcesContent":["<template>\n <div :class=\"className\">\n <div\n ref=\"container\"\n :class=\"cls.e('container')\"\n :contenteditable=\"!readonly && !disabled\"\n :data-empty=\"isEmpty || undefined\"\n :data-placeholder=\"props.placeholder\"\n @keydown=\"onKeydown\"\n @blur=\"onBlur\"\n ></div>\n\n <div v-if=\"showPlaceholder\" :class=\"cls.e('placeholder')\">\n {{ props.placeholder }}\n </div>\n\n <VariablePicker\n ref=\"pickerRef\"\n :visible=\"pickerVisible\"\n :trigger-dom=\"pickerTriggerDom\"\n :variables=\"props.variables\"\n :filter=\"pickerFilter\"\n :selectable-levels=\"props.selectableLevels ?? 'leaf'\"\n @select=\"onPickerSelect\"\n @dismiss=\"onPickerDismiss\"\n @update:visible=\"onPickerVisibleChange\"\n />\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { bem } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch\n} from 'vue'\n\nimport type { ExpressionEditorProps, VariableItem } from '../../types'\nimport VariablePicker from './components/variable-picker.vue'\nimport { createEditor, type EditorAPI } from './core/editor'\nimport { createMention, type MentionAPI } from './core/mention'\nimport { parse, type Doc } from './core/model'\nimport { createVariableMap } from './di'\n\ndefineOptions({ name: 'ExpressionEditor' })\n\nconst props = withDefaults(defineProps<ExpressionEditorProps>(), {\n placeholder: '请输入表达式,输入 @ 可插入变量',\n selectableLevels: 'leaf'\n})\n\nconst emit = defineEmits<{ (e: 'update:modelValue', value: string): void }>()\n\nconst cls = bem('expression-editor')\nconst { formProps } = injectFormContext()\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst containerRef = useTemplateRef<HTMLDivElement>('container')\nconst pickerRef = useTemplateRef<{ handleKeydown: (e: KeyboardEvent) => boolean }>('pickerRef')\n\nconst className = computed(() => [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n])\n\nconst variableMap = computed(() => createVariableMap(props.variables))\n\nconst editorRef = shallowRef<EditorAPI | null>(null)\nconst mention: MentionAPI = createMention()\n\nconst currentDoc = shallowRef<Doc>([])\nconst isEmpty = computed(() => currentDoc.value.length === 0)\nconst showPlaceholder = computed(() => isEmpty.value && !disabled.value)\n\nconst pickerMode = shallowRef<'mention' | 'reselect' | null>(null)\nconst pickerTriggerDom = shallowRef<HTMLElement | undefined>(undefined)\nconst reselectingSegIdx = shallowRef<number | null>(null)\nconst pickerFilter = shallowRef('')\n\nconst pickerVisible = computed(() => pickerMode.value !== null)\n\nfunction syncMention() {\n const editor = editorRef.value\n if (!editor) return\n if (pickerMode.value === 'reselect') return\n const caret = editor.getCaretOffset()\n const state = mention.update(currentDoc.value, caret)\n if (state) {\n pickerMode.value = 'mention'\n pickerFilter.value = state.filter\n pickerTriggerDom.value = containerRef.value ?? undefined\n } else if (pickerMode.value === 'mention') {\n closePicker()\n }\n}\n\nfunction closePicker() {\n pickerMode.value = null\n reselectingSegIdx.value = null\n pickerFilter.value = ''\n}\n\nonMounted(() => {\n if (!containerRef.value) return\n const initialDoc = parse(props.modelValue ?? '', variableMap.value)\n currentDoc.value = initialDoc\n\n const editor = createEditor({\n container: containerRef.value,\n cls,\n initialDoc,\n getVariableMap: () => variableMap.value,\n onChange: (doc) => {\n currentDoc.value = doc\n const value = serializeFromDoc(doc)\n if (value !== (props.modelValue ?? '')) emit('update:modelValue', value)\n syncMention()\n },\n onSelectionChange: () => {\n syncMention()\n },\n onChipReselect: ({ chipEl, segIndex }) => {\n if (disabled.value || readonly.value) return\n mention.commit()\n pickerMode.value = 'reselect'\n pickerFilter.value = ''\n pickerTriggerDom.value = chipEl\n reselectingSegIdx.value = segIndex\n },\n onChipRemove: ({ segIndex }) => {\n if (disabled.value || readonly.value) return\n editor.removeVarAt(segIndex)\n }\n })\n editorRef.value = editor\n})\n\nonBeforeUnmount(() => {\n editorRef.value?.dispose()\n})\n\nfunction serializeFromDoc(doc: Doc): string {\n let s = ''\n for (const seg of doc) s += seg.kind === 'text' ? seg.value : `{${seg.value}}`\n return s\n}\n\nwatch(\n () => props.modelValue,\n (v) => {\n const editor = editorRef.value\n if (!editor) return\n if (v === editor.getValue()) return\n editor.setValue(v ?? '')\n }\n)\n\nwatch(variableMap, () => {\n // variables 变化:重渲染以刷新 chip label / type\n const editor = editorRef.value\n if (!editor) return\n editor.setValue(editor.getValue())\n})\n\nfunction onKeydown(e: KeyboardEvent) {\n if (disabled.value || readonly.value) return\n // mention / reselect 激活时,优先把箭头键 / Enter / Esc 转给 picker\n if (pickerMode.value !== null) {\n const handledByPicker = pickerRef.value?.handleKeydown(e)\n if (handledByPicker) {\n e.preventDefault()\n return\n }\n }\n\n if (pickerMode.value === 'mention') {\n // 这些键导致 mention 退出(保留 @filter 文本,光标继续移动)\n if (e.key === ' ' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n mention.dismiss()\n closePicker()\n }\n }\n}\n\nfunction onBlur() {\n if (pickerMode.value === 'mention') {\n mention.dismiss()\n // 下一帧再关闭,避免和 picker 内 click 冲突\n void nextTick(() => closePicker())\n }\n}\n\nfunction onPickerSelect(item: VariableItem) {\n const editor = editorRef.value\n if (!editor) return\n\n if (pickerMode.value === 'mention') {\n const state = mention.getState()\n if (!state) return\n const anchor = state.anchorOffset\n const caret = editor.getCaretOffset() ?? anchor + state.filter.length + 1\n editor.replaceRangeWithVar(anchor, caret, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n mention.commit()\n } else if (pickerMode.value === 'reselect') {\n const idx = reselectingSegIdx.value\n if (idx !== null) {\n editor.replaceVarAt(idx, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n }\n }\n closePicker()\n}\n\nfunction onPickerDismiss() {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n}\n\nfunction onPickerVisibleChange(v: boolean) {\n if (!v && pickerMode.value !== null) {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n }\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqDA,MAAM,QAAQ;EAKd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,oBAAmB;EACnC,MAAM,EAAE,cAAc,mBAAkB;EACxC,MAAM,EAAE,MAAM,UAAU,aAAa,qBAAqB,CAAC,aAAa,EAAC,EAAG,MAAM,CAAA;EAElF,MAAM,eAAe,eAA+B,YAAW;EAC/D,MAAM,YAAY,eAAiE,YAAW;EAE9F,MAAM,YAAY,eAAe;GAC/B,IAAI;GACJ,IAAI,EAAE,KAAK,MAAK;GAChB,IAAI,GAAG,YAAY,SAAS,MAAK;GACjC,IAAI,GAAG,YAAY,SAAS,MAAK;GAClC,CAAA;EAED,MAAM,cAAc,eAAe,kBAAkB,MAAM,UAAU,CAAA;EAErE,MAAM,YAAY,WAA6B,KAAI;EACnD,MAAM,UAAsB,eAAc;EAE1C,MAAM,aAAa,WAAgB,EAAE,CAAA;EACrC,MAAM,UAAU,eAAe,WAAW,MAAM,WAAW,EAAC;EAC5D,MAAM,kBAAkB,eAAe,QAAQ,SAAS,CAAC,SAAS,MAAK;EAEvE,MAAM,aAAa,WAA0C,KAAI;EACjE,MAAM,mBAAmB,WAAoC,KAAA,EAAS;EACtE,MAAM,oBAAoB,WAA0B,KAAI;EACxD,MAAM,eAAe,WAAW,GAAE;EAElC,MAAM,gBAAgB,eAAe,WAAW,UAAU,KAAI;EAE9D,SAAS,cAAc;GACrB,MAAM,SAAS,UAAU;GACzB,IAAI,CAAC,QAAQ;GACb,IAAI,WAAW,UAAU,YAAY;GACrC,MAAM,QAAQ,OAAO,gBAAe;GACpC,MAAM,QAAQ,QAAQ,OAAO,WAAW,OAAO,MAAK;GACpD,IAAI,OAAO;IACT,WAAW,QAAQ;IACnB,aAAa,QAAQ,MAAM;IAC3B,iBAAiB,QAAQ,aAAa,SAAS,KAAA;UAC1C,IAAI,WAAW,UAAU,WAC9B,aAAY;;EAIhB,SAAS,cAAc;GACrB,WAAW,QAAQ;GACnB,kBAAkB,QAAQ;GAC1B,aAAa,QAAQ;;EAGvB,gBAAgB;GACd,IAAI,CAAC,aAAa,OAAO;GACzB,MAAM,aAAa,MAAM,MAAM,cAAc,IAAI,YAAY,MAAK;GAClE,WAAW,QAAQ;GAEnB,MAAM,SAAS,aAAa;IAC1B,WAAW,aAAa;IACxB;IACA;IACA,sBAAsB,YAAY;IAClC,WAAW,QAAQ;KACjB,WAAW,QAAQ;KACnB,MAAM,QAAQ,iBAAiB,IAAG;KAClC,IAAI,WAAW,MAAM,cAAc,KAAK,KAAK,qBAAqB,MAAK;KACvE,aAAY;;IAEd,yBAAyB;KACvB,aAAY;;IAEd,iBAAiB,EAAE,QAAQ,eAAe;KACxC,IAAI,SAAS,SAAS,SAAS,OAAO;KACtC,QAAQ,QAAO;KACf,WAAW,QAAQ;KACnB,aAAa,QAAQ;KACrB,iBAAiB,QAAQ;KACzB,kBAAkB,QAAQ;;IAE5B,eAAe,EAAE,eAAe;KAC9B,IAAI,SAAS,SAAS,SAAS,OAAO;KACtC,OAAO,YAAY,SAAQ;;IAE9B,CAAA;GACD,UAAU,QAAQ;IACnB;EAED,sBAAsB;GACpB,UAAU,OAAO,SAAQ;IAC1B;EAED,SAAS,iBAAiB,KAAkB;GAC1C,IAAI,IAAI;GACR,KAAK,MAAM,OAAO,KAAK,KAAK,IAAI,SAAS,SAAS,IAAI,QAAQ,IAAI,IAAI,MAAM;GAC5E,OAAO;;EAGT,YACQ,MAAM,aACX,MAAM;GACL,MAAM,SAAS,UAAU;GACzB,IAAI,CAAC,QAAQ;GACb,IAAI,MAAM,OAAO,UAAS,EAAG;GAC7B,OAAO,SAAS,KAAK,GAAE;IAE3B;EAEA,MAAM,mBAAmB;GAEvB,MAAM,SAAS,UAAU;GACzB,IAAI,CAAC,QAAQ;GACb,OAAO,SAAS,OAAO,UAAU,CAAA;IAClC;EAED,SAAS,UAAU,GAAkB;GACnC,IAAI,SAAS,SAAS,SAAS,OAAO;GAEtC,IAAI,WAAW,UAAU;QACC,UAAU,OAAO,cAAc,EAAC,EACnC;KACnB,EAAE,gBAAe;KACjB;;;GAIJ,IAAI,WAAW,UAAU;QAEnB,EAAE,QAAQ,OAAO,EAAE,QAAQ,eAAe,EAAE,QAAQ,cAAc;KACpE,QAAQ,SAAQ;KAChB,aAAY;;;;EAKlB,SAAS,SAAS;GAChB,IAAI,WAAW,UAAU,WAAW;IAClC,QAAQ,SAAQ;IAEhB,eAAoB,aAAa,CAAA;;;EAIrC,SAAS,eAAe,MAAoB;GAC1C,MAAM,SAAS,UAAU;GACzB,IAAI,CAAC,QAAQ;GAEb,IAAI,WAAW,UAAU,WAAW;IAClC,MAAM,QAAQ,QAAQ,UAAS;IAC/B,IAAI,CAAC,OAAO;IACZ,MAAM,SAAS,MAAM;IACrB,MAAM,QAAQ,OAAO,gBAAe,IAAK,SAAS,MAAM,OAAO,SAAS;IACxE,OAAO,oBAAoB,QAAQ,OAAO;KACxC,OAAO,KAAK;KACZ,OAAO,KAAK;KACZ,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,MAAK,GAAI,EAAC;KACxC,CAAA;IACD,QAAQ,QAAO;UACV,IAAI,WAAW,UAAU,YAAY;IAC1C,MAAM,MAAM,kBAAkB;IAC9B,IAAI,QAAQ,MACV,OAAO,aAAa,KAAK;KACvB,OAAO,KAAK;KACZ,OAAO,KAAK;KACZ,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,MAAK,GAAI,EAAC;KACxC,CAAA;;GAGL,aAAY;;EAGd,SAAS,kBAAkB;GACzB,IAAI,WAAW,UAAU,WAAW,QAAQ,SAAQ;GACpD,aAAY;;EAGd,SAAS,sBAAsB,GAAY;GACzC,IAAI,CAAC,KAAK,WAAW,UAAU,MAAM;IACnC,IAAI,WAAW,UAAU,WAAW,QAAQ,SAAQ;IACpD,aAAY;;;;uBA5Od,mBA0BM,OAAA,EA1BA,OAAK,eAAE,UAAA,MAAS,EAAA,EAAA;IACpB,mBAQO,OAAA;KAPL,KAAI;KACH,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC,YAAA,CAAA;KACZ,iBAAe,CAAG,MAAA,SAAA,IAAQ,CAAK,MAAA,SAAA;KAC/B,cAAY,QAAA,SAAW,KAAA;KACvB,oBAAkB,MAAM;KACf;KACH;;IAGE,gBAAA,SAAA,WAAA,EAAX,mBAEM,OAAA;;KAFuB,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC,cAAA,CAAA;uBACpC,MAAM,YAAW,EAAA,EAAA,IAAA,mBAAA,QAAA,KAAA;IAGtB,YAUE,aAAA;cATI;KAAJ,KAAI;KACH,SAAS,cAAA;KACT,eAAa,iBAAA;KACb,WAAW,MAAM;KACjB,QAAQ,aAAA;KACR,qBAAmB,MAAM,oBAAgB;KACzC,UAAQ;KACR,WAAS;KACT,oBAAgB"}
1
+ {"version":3,"file":"expression-editor.js","names":[],"sources":["../../../src/components/expression-editor/expression-editor.vue"],"sourcesContent":["<template>\n <div :class=\"className\">\n <div\n ref=\"container\"\n :class=\"cls.e('container')\"\n :contenteditable=\"!readonly && !disabled\"\n :data-empty=\"isEmpty || undefined\"\n :data-placeholder=\"props.placeholder\"\n @keydown=\"onKeydown\"\n @blur=\"onBlur\"\n ></div>\n\n <div v-if=\"showPlaceholder\" :class=\"cls.e('placeholder')\">\n {{ props.placeholder }}\n </div>\n\n <VariablePicker\n ref=\"pickerRef\"\n :visible=\"pickerVisible\"\n :trigger-dom=\"pickerTriggerDom\"\n :variables=\"props.variables\"\n :filter=\"pickerFilter\"\n :selectable-levels=\"props.selectableLevels ?? 'leaf'\"\n @select=\"onPickerSelect\"\n @dismiss=\"onPickerDismiss\"\n @update:visible=\"onPickerVisibleChange\"\n />\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { bem } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch\n} from 'vue'\n\nimport type { ExpressionEditorProps, VariableItem } from '../../types'\nimport VariablePicker from './components/variable-picker.vue'\nimport { createEditor, type EditorAPI } from './core/editor'\nimport { createMention, type MentionAPI } from './core/mention'\nimport { parse, type Doc } from './core/model'\nimport { createVariableMap } from './di'\n\ndefineOptions({ name: 'ExpressionEditor' })\n\nconst props = withDefaults(defineProps<ExpressionEditorProps>(), {\n placeholder: '请输入表达式,输入 @ 可插入变量',\n selectableLevels: 'leaf'\n})\n\nconst emit = defineEmits<{ (e: 'update:modelValue', value: string): void }>()\n\nconst cls = bem('expression-editor')\nconst { formProps } = injectFormContext()\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst containerRef = useTemplateRef<HTMLDivElement>('container')\nconst pickerRef = useTemplateRef<{ handleKeydown: (e: KeyboardEvent) => boolean }>('pickerRef')\n\nconst className = computed(() => [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n])\n\nconst variableMap = computed(() => createVariableMap(props.variables))\n\nconst editorRef = shallowRef<EditorAPI | null>(null)\nconst mention: MentionAPI = createMention()\n\nconst currentDoc = shallowRef<Doc>([])\nconst isEmpty = computed(() => currentDoc.value.length === 0)\nconst showPlaceholder = computed(() => isEmpty.value && !disabled.value)\n\nconst pickerMode = shallowRef<'mention' | 'reselect' | null>(null)\nconst pickerTriggerDom = shallowRef<HTMLElement | undefined>(undefined)\nconst reselectingSegIdx = shallowRef<number | null>(null)\nconst pickerFilter = shallowRef('')\n\nconst pickerVisible = computed(() => pickerMode.value !== null)\n\nfunction syncMention() {\n const editor = editorRef.value\n if (!editor) return\n if (pickerMode.value === 'reselect') return\n const caret = editor.getCaretOffset()\n const state = mention.update(currentDoc.value, caret)\n if (state) {\n pickerMode.value = 'mention'\n pickerFilter.value = state.filter\n pickerTriggerDom.value = containerRef.value ?? undefined\n } else if (pickerMode.value === 'mention') {\n closePicker()\n }\n}\n\nfunction closePicker() {\n pickerMode.value = null\n reselectingSegIdx.value = null\n pickerFilter.value = ''\n}\n\nonMounted(() => {\n if (!containerRef.value) return\n const initialDoc = parse(props.modelValue ?? '', variableMap.value)\n currentDoc.value = initialDoc\n\n const editor = createEditor({\n container: containerRef.value,\n cls,\n initialDoc,\n getVariableMap: () => variableMap.value,\n onChange: (doc) => {\n currentDoc.value = doc\n const value = serializeFromDoc(doc)\n if (value !== (props.modelValue ?? '')) emit('update:modelValue', value)\n syncMention()\n },\n onSelectionChange: () => {\n syncMention()\n },\n onChipReselect: ({ chipEl, segIndex }) => {\n if (disabled.value || readonly.value) return\n mention.commit()\n pickerMode.value = 'reselect'\n pickerFilter.value = ''\n pickerTriggerDom.value = chipEl\n reselectingSegIdx.value = segIndex\n },\n onChipRemove: ({ segIndex }) => {\n if (disabled.value || readonly.value) return\n editor.removeVarAt(segIndex)\n }\n })\n editorRef.value = editor\n})\n\nonBeforeUnmount(() => {\n editorRef.value?.dispose()\n})\n\nfunction serializeFromDoc(doc: Doc): string {\n let s = ''\n for (const seg of doc) s += seg.kind === 'text' ? seg.value : `{${seg.value}}`\n return s\n}\n\nwatch(\n () => props.modelValue,\n (v) => {\n const editor = editorRef.value\n if (!editor) return\n if (v === editor.getValue()) return\n editor.setValue(v ?? '')\n }\n)\n\nwatch(variableMap, () => {\n // variables 变化:重渲染以刷新 chip label / type\n const editor = editorRef.value\n if (!editor) return\n editor.setValue(editor.getValue())\n})\n\nfunction onKeydown(e: KeyboardEvent) {\n if (disabled.value || readonly.value) return\n // mention / reselect 激活时,优先把箭头键 / Enter / Esc 转给 picker\n if (pickerMode.value !== null) {\n const handledByPicker = pickerRef.value?.handleKeydown(e)\n if (handledByPicker) {\n e.preventDefault()\n return\n }\n }\n\n if (pickerMode.value === 'mention') {\n // 这些键导致 mention 退出(保留 @filter 文本,光标继续移动)\n if (e.key === ' ' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n mention.dismiss()\n closePicker()\n }\n }\n}\n\nfunction onBlur() {\n if (pickerMode.value === 'mention') {\n mention.dismiss()\n // 下一帧再关闭,避免和 picker 内 click 冲突\n void nextTick(() => closePicker())\n }\n}\n\nfunction onPickerSelect(item: VariableItem) {\n const editor = editorRef.value\n if (!editor) return\n\n if (pickerMode.value === 'mention') {\n const state = mention.getState()\n if (!state) return\n const anchor = state.anchorOffset\n const caret = editor.getCaretOffset() ?? anchor + state.filter.length + 1\n editor.replaceRangeWithVar(anchor, caret, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n mention.commit()\n } else if (pickerMode.value === 'reselect') {\n const idx = reselectingSegIdx.value\n if (idx !== null) {\n editor.replaceVarAt(idx, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n }\n }\n closePicker()\n}\n\nfunction onPickerDismiss() {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n}\n\nfunction onPickerVisibleChange(v: boolean) {\n if (!v && pickerMode.value !== null) {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n }\n}\n</script>\n"],"mappings":"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"}
@@ -1,15 +1,13 @@
1
1
  import { ExpressionEditorProps, ExpressionSelectableLevels } from "../../types/expression-editor.js";
2
- import * as _$vue from "vue";
3
-
4
2
  //#region src/components/expression-editor/expression-editor.vue.d.ts
5
- declare const __VLS_export: _$vue.DefineComponent<ExpressionEditorProps, {}, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {} & {
3
+ declare const __VLS_export: import("vue").DefineComponent<ExpressionEditorProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
6
4
  "update:modelValue": (value: string) => any;
7
- }, string, _$vue.PublicProps, Readonly<ExpressionEditorProps> & Readonly<{
5
+ }, string, import("vue").PublicProps, Readonly<ExpressionEditorProps> & Readonly<{
8
6
  "onUpdate:modelValue"?: ((value: string) => any) | undefined;
9
7
  }>, {
10
8
  placeholder: string;
11
9
  selectableLevels: ExpressionSelectableLevels;
12
- }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
10
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
11
  declare const _default: typeof __VLS_export;
14
12
  //#endregion
15
13
  export { _default };
@@ -1 +1 @@
1
- {"version":3,"file":"file-picker.js","names":[],"sources":["../../../src/components/file-picker/file-picker.vue"],"sourcesContent":["<template>\n <component\n :is=\"tag\"\n :class=\"cls.b\"\n @click.stop=\"handleClickPicker\"\n @dragover.prevent=\"handleDragover\"\n @dragleave=\"handleDragLeave\"\n @drop.prevent=\"handleDrop\"\n >\n <input\n :multiple=\"multiple\"\n :class=\"cls.e('native')\"\n type=\"file\"\n :accept=\"accept\"\n hidden\n placeholder=\"选择文件\"\n ref=\"fileRef\"\n @change=\"handleChange\"\n capture=\"environment\"\n />\n <slot :is-dragover=\"isDragover\" />\n </component>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { shallowRef, ref } from 'vue'\n\nimport type { UploaderProps, UploaderEmits } from '../../types'\nimport { matchAccept } from './helper'\n\ndefineOptions({ name: 'FilePicker' })\n\nconst props = withDefaults(defineProps<UploaderProps>(), { tag: 'div', multiple: false })\n\nconst emit = defineEmits<UploaderEmits>()\n\nconst cls = bem('file-picker')\n\nconst fileRef = shallowRef<HTMLInputElement>()\nconst isDragover = ref(false)\n\nconst processFiles = (files: File[]) => {\n const filteredFiles = files.filter((file) => matchAccept(file, props.accept))\n emit('pick', filteredFiles)\n}\n\nconst handleChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n const files = Array.from(target.files || [])\n processFiles(files)\n target.value = ''\n}\n\nconst handleDragover = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = true\n}\n\nconst handleDragLeave = (e: DragEvent) => {\n if (props.disabled) return\n const currentTarget = e.currentTarget as HTMLElement\n const relatedTarget = e.relatedTarget as HTMLElement | null\n\n if (currentTarget.contains(relatedTarget)) return\n isDragover.value = false\n}\n\nconst handleDrop = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = false\n const files = Array.from(e.dataTransfer?.files || [])\n processFiles(files)\n}\n\nfunction handleClickPicker() {\n if (props.disabled) return\n fileRef.value?.click()\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;EAiCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,cAAa;EAE7B,MAAM,UAAU,YAA6B;EAC7C,MAAM,aAAa,IAAI,MAAK;EAE5B,MAAM,gBAAgB,UAAkB;GAEtC,KAAK,QADiB,MAAM,QAAQ,SAAS,YAAY,MAAM,MAAM,OAAO,CAClD,CAAA;;EAG5B,MAAM,gBAAgB,MAAa;GACjC,MAAM,SAAS,EAAE;GAEjB,aADc,MAAM,KAAK,OAAO,SAAS,EAAE,CACzB,CAAA;GAClB,OAAO,QAAQ;;EAGjB,MAAM,kBAAkB,MAAiB;GACvC,IAAI,MAAM,UAAU;GACpB,WAAW,QAAQ;;EAGrB,MAAM,mBAAmB,MAAiB;GACxC,IAAI,MAAM,UAAU;GACpB,MAAM,gBAAgB,EAAE;GACxB,MAAM,gBAAgB,EAAE;GAExB,IAAI,cAAc,SAAS,cAAa,EAAG;GAC3C,WAAW,QAAQ;;EAGrB,MAAM,cAAc,MAAiB;GACnC,IAAI,MAAM,UAAU;GACpB,WAAW,QAAQ;GAEnB,aADc,MAAM,KAAK,EAAE,cAAc,SAAS,EAAE,CAClC,CAAA;;EAGpB,SAAS,oBAAoB;GAC3B,IAAI,MAAM,UAAU;GACpB,QAAQ,OAAO,OAAM;;;uBA5ErB,YAoBY,wBAnBL,QAAA,IAAG,EAAA;IACP,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC;IACZ,SAAK,cAAO,mBAAiB,CAAA,OAAA,CAAA;IAC7B,YAAQ,cAAU,gBAAc,CAAA,UAAA,CAAA;IAChC,aAAW;IACX,QAAI,cAAU,YAAU,CAAA,UAAA,CAAA;;2BAYvB,CAVF,mBAUE,SAAA;KATC,UAAU,QAAA;KACV,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC,SAAA,CAAA;KACb,MAAK;KACJ,QAAQ,QAAA;KACT,QAAA;KACA,aAAY;cACR;KAAJ,KAAI;KACH,UAAQ;KACT,SAAQ;8BAEV,WAAkC,KAAA,QAAA,WAAA,EAA3B,YAAa,WAAA,OAAU,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"file-picker.js","names":[],"sources":["../../../src/components/file-picker/file-picker.vue"],"sourcesContent":["<template>\n <component\n :is=\"tag\"\n :class=\"cls.b\"\n @click.stop=\"handleClickPicker\"\n @dragover.prevent=\"handleDragover\"\n @dragleave=\"handleDragLeave\"\n @drop.prevent=\"handleDrop\"\n >\n <input\n :multiple=\"multiple\"\n :class=\"cls.e('native')\"\n type=\"file\"\n :accept=\"accept\"\n hidden\n placeholder=\"选择文件\"\n ref=\"fileRef\"\n @change=\"handleChange\"\n capture=\"environment\"\n />\n <slot :is-dragover=\"isDragover\" />\n </component>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { shallowRef, ref } from 'vue'\n\nimport type { UploaderProps, UploaderEmits } from '../../types'\nimport { matchAccept } from './helper'\n\ndefineOptions({ name: 'FilePicker' })\n\nconst props = withDefaults(defineProps<UploaderProps>(), { tag: 'div', multiple: false })\n\nconst emit = defineEmits<UploaderEmits>()\n\nconst cls = bem('file-picker')\n\nconst fileRef = shallowRef<HTMLInputElement>()\nconst isDragover = ref(false)\n\nconst processFiles = (files: File[]) => {\n const filteredFiles = files.filter((file) => matchAccept(file, props.accept))\n emit('pick', filteredFiles)\n}\n\nconst handleChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n const files = Array.from(target.files || [])\n processFiles(files)\n target.value = ''\n}\n\nconst handleDragover = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = true\n}\n\nconst handleDragLeave = (e: DragEvent) => {\n if (props.disabled) return\n const currentTarget = e.currentTarget as HTMLElement\n const relatedTarget = e.relatedTarget as HTMLElement | null\n\n if (currentTarget.contains(relatedTarget)) return\n isDragover.value = false\n}\n\nconst handleDrop = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = false\n const files = Array.from(e.dataTransfer?.files || [])\n processFiles(files)\n}\n\nfunction handleClickPicker() {\n if (props.disabled) return\n fileRef.value?.click()\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;EAiCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAE7B,MAAM,UAAU,WAA6B;EAC7C,MAAM,aAAa,IAAI,KAAK;EAE5B,MAAM,gBAAgB,UAAkB;GAEtC,KAAK,QADiB,MAAM,QAAQ,SAAS,YAAY,MAAM,MAAM,MAAM,CAC9D,CAAa;EAC5B;EAEA,MAAM,gBAAgB,MAAa;GACjC,MAAM,SAAS,EAAE;GAEjB,aADc,MAAM,KAAK,OAAO,SAAS,CAAC,CAC7B,CAAK;GAClB,OAAO,QAAQ;EACjB;EAEA,MAAM,kBAAkB,MAAiB;GACvC,IAAI,MAAM,UAAU;GACpB,WAAW,QAAQ;EACrB;EAEA,MAAM,mBAAmB,MAAiB;GACxC,IAAI,MAAM,UAAU;GACpB,MAAM,gBAAgB,EAAE;GACxB,MAAM,gBAAgB,EAAE;GAExB,IAAI,cAAc,SAAS,aAAa,GAAG;GAC3C,WAAW,QAAQ;EACrB;EAEA,MAAM,cAAc,MAAiB;GACnC,IAAI,MAAM,UAAU;GACpB,WAAW,QAAQ;GAEnB,aADc,MAAM,KAAK,EAAE,cAAc,SAAS,CAAC,CACtC,CAAK;EACpB;EAEA,SAAS,oBAAoB;GAC3B,IAAI,MAAM,UAAU;GACpB,QAAQ,OAAO,MAAM;EACvB;;uBA7EE,YAoBY,wBAnBL,QAAA,GAAG,GAAA;IACP,OAAK,eAAE,MAAA,GAAA,EAAI,CAAC;IACZ,SAAK,cAAO,mBAAiB,CAAA,MAAA,CAAA;IAC7B,YAAQ,cAAU,gBAAc,CAAA,SAAA,CAAA;IAChC,aAAW;IACX,QAAI,cAAU,YAAU,CAAA,SAAA,CAAA;;2BAYvB,CAVF,mBAUE,SAAA;KATC,UAAU,QAAA;KACV,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,QAAA,CAAA;KACb,MAAK;KACJ,QAAQ,QAAA;KACT,QAAA;KACA,aAAY;cACR;KAAJ,KAAI;KACH,UAAQ;KACT,SAAQ;8BAEV,WAAkC,KAAA,QAAA,WAAA,EAA3B,YAAa,WAAA,MAAU,CAAA,CAAA,CAAA"}
@@ -1,6 +1,4 @@
1
1
  import { UploaderProps } from "../../types/file-picker.js";
2
- import * as _$vue from "vue";
3
-
4
2
  //#region src/components/file-picker/file-picker.vue.d.ts
5
3
  declare var __VLS_13: {
6
4
  isDragover: boolean;
@@ -8,14 +6,14 @@ declare var __VLS_13: {
8
6
  type __VLS_Slots = {} & {
9
7
  default?: (props: typeof __VLS_13) => any;
10
8
  };
11
- declare const __VLS_base: _$vue.DefineComponent<UploaderProps, {}, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {} & {
9
+ declare const __VLS_base: import("vue").DefineComponent<UploaderProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
12
10
  pick: (files: File[]) => any;
13
- }, string, _$vue.PublicProps, Readonly<UploaderProps> & Readonly<{
11
+ }, string, import("vue").PublicProps, Readonly<UploaderProps> & Readonly<{
14
12
  onPick?: ((files: File[]) => any) | undefined;
15
13
  }>, {
16
14
  tag: string;
17
15
  multiple: boolean;
18
- }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
16
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
19
17
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
20
18
  declare const _default: typeof __VLS_export;
21
19
  type __VLS_WithSlots<T, S> = T & {
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","names":[],"sources":["../../../src/components/file-picker/helper.ts"],"sourcesContent":["/**\n * 校验文件是否匹配 accept 字符串(支持 MIME 类型与通配符)。\n *\n * 支持的形式:\n * - `*` / `*\\/*`:接受所有文件\n * - `image/*`:MIME 类型组匹配\n * - `application/pdf`:精确 MIME 类型\n * - `.pdf` / `.docx`:扩展名匹配(不区分大小写)\n *\n * 多个值以逗号分隔,命中任一即视为匹配。\n */\nexport function matchAccept(file: File, accept?: string): boolean {\n if (!accept) return true\n\n const fileType = file.type.toLowerCase()\n const fileName = file.name.toLowerCase()\n const acceptList = accept\n .split(',')\n .map((item) => item.trim().toLowerCase())\n .filter(Boolean)\n\n if (!acceptList.length) return true\n\n return acceptList.some((item) => {\n if (item === '*' || item === '*/*') return true\n if (item.startsWith('.')) return fileName.endsWith(item)\n if (item.endsWith('/*')) {\n const group = item.slice(0, -2)\n return fileType.startsWith(`${group}/`)\n }\n return fileType === item\n })\n}\n"],"mappings":";;;;;;;;;;;;AAWA,SAAgB,YAAY,MAAY,QAA0B;CAChE,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,WAAW,KAAK,KAAK,aAAa;CACxC,MAAM,WAAW,KAAK,KAAK,aAAa;CACxC,MAAM,aAAa,OAChB,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,MAAM,CAAC,aAAa,CAAC,CACxC,OAAO,QAAQ;CAElB,IAAI,CAAC,WAAW,QAAQ,OAAO;CAE/B,OAAO,WAAW,MAAM,SAAS;EAC/B,IAAI,SAAS,OAAO,SAAS,OAAO,OAAO;EAC3C,IAAI,KAAK,WAAW,IAAI,EAAE,OAAO,SAAS,SAAS,KAAK;EACxD,IAAI,KAAK,SAAS,KAAK,EAAE;GACvB,MAAM,QAAQ,KAAK,MAAM,GAAG,GAAG;GAC/B,OAAO,SAAS,WAAW,GAAG,MAAM,GAAG;;EAEzC,OAAO,aAAa;GACpB"}
1
+ {"version":3,"file":"helper.js","names":[],"sources":["../../../src/components/file-picker/helper.ts"],"sourcesContent":["/**\n * 校验文件是否匹配 accept 字符串(支持 MIME 类型与通配符)。\n *\n * 支持的形式:\n * - `*` / `*\\/*`:接受所有文件\n * - `image/*`:MIME 类型组匹配\n * - `application/pdf`:精确 MIME 类型\n * - `.pdf` / `.docx`:扩展名匹配(不区分大小写)\n *\n * 多个值以逗号分隔,命中任一即视为匹配。\n */\nexport function matchAccept(file: File, accept?: string): boolean {\n if (!accept) return true\n\n const fileType = file.type.toLowerCase()\n const fileName = file.name.toLowerCase()\n const acceptList = accept\n .split(',')\n .map((item) => item.trim().toLowerCase())\n .filter(Boolean)\n\n if (!acceptList.length) return true\n\n return acceptList.some((item) => {\n if (item === '*' || item === '*/*') return true\n if (item.startsWith('.')) return fileName.endsWith(item)\n if (item.endsWith('/*')) {\n const group = item.slice(0, -2)\n return fileType.startsWith(`${group}/`)\n }\n return fileType === item\n })\n}\n"],"mappings":";;;;;;;;;;;;AAWA,SAAgB,YAAY,MAAY,QAA0B;CAChE,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,WAAW,KAAK,KAAK,YAAY;CACvC,MAAM,WAAW,KAAK,KAAK,YAAY;CACvC,MAAM,aAAa,OAChB,MAAM,GAAG,EACT,KAAK,SAAS,KAAK,KAAK,EAAE,YAAY,CAAC,EACvC,OAAO,OAAO;CAEjB,IAAI,CAAC,WAAW,QAAQ,OAAO;CAE/B,OAAO,WAAW,MAAM,SAAS;EAC/B,IAAI,SAAS,OAAO,SAAS,OAAO,OAAO;EAC3C,IAAI,KAAK,WAAW,GAAG,GAAG,OAAO,SAAS,SAAS,IAAI;EACvD,IAAI,KAAK,SAAS,IAAI,GAAG;GACvB,MAAM,QAAQ,KAAK,MAAM,GAAG,EAAE;GAC9B,OAAO,SAAS,WAAW,GAAG,MAAM,EAAE;EACxC;EACA,OAAO,aAAa;CACtB,CAAC;AACH"}
@@ -196,7 +196,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
196
196
  if (!isZoomWheel(e)) return;
197
197
  if (isInteractiveTarget(e.target)) return;
198
198
  e.preventDefault();
199
- const delta = e.deltaY > 0 ? -SCALE_STEP : SCALE_STEP;
199
+ const delta = e.deltaY > 0 ? -.1 : SCALE_STEP;
200
200
  setScale(scale.value + delta);
201
201
  }
202
202
  function isInteractiveTarget(target) {
@@ -1 +1 @@
1
- {"version":3,"file":"file-viewer.js","names":[],"sources":["../../../src/components/file-viewer/file-viewer.vue"],"sourcesContent":["<template>\n <Teleport to=\"body\" :disabled=\"!isModal\">\n <transition :name=\"isModal ? 'u-file-viewer-modal' : ''\">\n <div\n v-if=\"!isModal || openModel\"\n :class=\"[cls.b, bem.is('modal', isModal)]\"\n :tabindex=\"isModal ? -1 : undefined\"\n ref=\"rootRef\"\n @mousedown.self=\"handleBackdropMousedown\"\n >\n <div v-if=\"isModal\" :class=\"cls.e('backdrop')\" @mousedown.self=\"handleBackdropMousedown\" />\n <div :class=\"cls.e('inner')\">\n <aside v-if=\"showSidebar\" :class=\"cls.e('sidebar')\" :style=\"{ width: sidebarWidthCss }\">\n <header :class=\"cls.e('sidebar-head')\">\n <span :class=\"cls.e('sidebar-title')\">文件</span>\n <span :class=\"cls.e('sidebar-count')\">{{ normalizedFiles.length }}</span>\n </header>\n <u-scroll tag=\"ul\" :class=\"cls.e('list')\">\n <li\n v-for=\"f in normalizedFiles\"\n :key=\"f.id\"\n :class=\"[cls.e('item'), bem.is('active', f.id === activeId)]\"\n :title=\"f.name\"\n @click=\"activate(f.id)\"\n >\n <span :class=\"cls.e('item-meta')\">\n <span :class=\"cls.e('item-name')\" :title=\"f.name\">{{ f.name }}</span>\n <span :class=\"cls.e('item-size')\">{{ formatBytes(f.size) }}</span>\n </span>\n <span :class=\"cls.e('item-kind')\">{{ label(f.kind) }}</span>\n </li>\n <li v-if=\"!normalizedFiles.length\" :class=\"cls.e('list-empty')\">\n <u-empty text=\"暂无文件\" :size=\"32\" />\n </li>\n </u-scroll>\n </aside>\n\n <section :class=\"cls.e('stage')\">\n <header :class=\"cls.e('stage-head')\">\n <div :class=\"cls.e('stage-title')\">\n <span v-if=\"activeFile\" :class=\"[cls.e('badge'), cls.em('badge', activeFile.kind)]\">\n {{ label(activeFile.kind) }}\n </span>\n <span :class=\"cls.e('stage-copy')\">\n <span :class=\"cls.e('stage-name')\" :title=\"activeFile?.name\">\n {{ activeFile?.name ?? '—' }}\n </span>\n <span v-if=\"activeFile\" :class=\"cls.e('stage-sub')\">\n <span>{{ activeIndexLabel }}</span>\n <span v-if=\"activeFile.size\">{{ formatBytes(activeFile.size) }}</span>\n </span>\n </span>\n </div>\n <div :class=\"cls.e('stage-actions')\">\n <span :class=\"cls.e('action-group')\">\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"!hasPrev\"\n type=\"button\"\n aria-label=\"上一个\"\n title=\"上一个\"\n @click=\"prev\"\n >\n <u-icon :size=\"15\">\n <ArrowLeft />\n </u-icon>\n </button>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"!hasNext\"\n type=\"button\"\n aria-label=\"下一个\"\n title=\"下一个\"\n @click=\"next\"\n >\n <u-icon :size=\"15\">\n <ArrowRight />\n </u-icon>\n </button>\n </span>\n <span v-if=\"isZoomable\" :class=\"cls.e('action-group')\">\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"zoomOutDisabled\"\n type=\"button\"\n aria-label=\"缩小\"\n title=\"缩小\"\n @click=\"zoomOut\"\n >\n <u-icon :size=\"15\">\n <ZoomOut />\n </u-icon>\n </button>\n <span :class=\"cls.e('zoom-value')\">{{ zoomPercent }}</span>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"zoomInDisabled\"\n type=\"button\"\n aria-label=\"放大\"\n title=\"放大\"\n @click=\"zoomIn\"\n >\n <u-icon :size=\"15\">\n <ZoomIn />\n </u-icon>\n </button>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"isTransformReset\"\n type=\"button\"\n aria-label=\"重置视图\"\n title=\"重置视图\"\n @click=\"resetTransform\"\n >\n <u-icon :size=\"15\">\n <Refresh />\n </u-icon>\n </button>\n </span>\n <button\n v-if=\"downloadable && activeFile\"\n :class=\"[cls.e('action'), cls.em('action', 'primary'), cls.em('action', 'icon')]\"\n type=\"button\"\n aria-label=\"下载\"\n title=\"下载\"\n @click=\"download\"\n >\n <u-icon :size=\"15\">\n <Download />\n </u-icon>\n </button>\n <button\n v-if=\"isModal\"\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n type=\"button\"\n aria-label=\"关闭预览\"\n title=\"关闭\"\n @click=\"handleClose\"\n >\n <u-icon :size=\"16\">\n <Close />\n </u-icon>\n </button>\n </div>\n </header>\n <div :class=\"cls.e('body')\">\n <transition name=\"u-file-viewer-fade\" mode=\"out-in\">\n <div\n v-if=\"activeFile\"\n :key=\"activeFile.id\"\n :class=\"[\n cls.e('viewport'),\n bem.is('transformable', isTransformable),\n bem.is('pannable', canPan),\n bem.is('dragging', isDragging)\n ]\"\n @pointerdown.capture=\"handleViewportPointerDown\"\n @pointermove.capture=\"handleViewportPointerMove\"\n @pointerup.capture=\"handleViewportPointerEnd\"\n @pointercancel.capture=\"handleViewportPointerEnd\"\n @wheel=\"handleViewportWheel\"\n @dblclick=\"handleViewportDblclick\"\n >\n <component\n :is=\"PreviewerMap[activeFile.kind]\"\n ref=\"previewerRef\"\n :file=\"activeFile\"\n :max-rows=\"sheetMaxRows\"\n :class=\"isTransformable ? cls.e('previewer') : undefined\"\n :style=\"previewerStyle\"\n @error=\"handleChildError\"\n @zoom-change=\"handlePdfZoomChange\"\n />\n </div>\n <div v-else :class=\"cls.e('empty')\">\n <u-empty text=\"暂无可预览文件\" />\n </div>\n </transition>\n </div>\n </section>\n </div>\n </div>\n </transition>\n </Teleport>\n</template>\n\n<script lang=\"ts\" setup>\nimport {\n ArrowLeft,\n ArrowRight,\n Close,\n Download,\n Refresh,\n ZoomIn,\n ZoomOut\n} from '@veltra/icons/normal'\nimport { bem, withUnit } from '@veltra/utils'\nimport {\n computed,\n defineAsyncComponent,\n nextTick,\n onBeforeUnmount,\n ref,\n shallowRef,\n watch\n} from 'vue'\nimport type { CSSProperties } from 'vue'\n\nimport type {\n _FileViewerExposed,\n FileViewerEmits,\n FileViewerItem,\n FileViewerKind,\n FileViewerProps\n} from '../../types/file-viewer'\nimport { UEmpty } from '../empty'\nimport { UIcon } from '../icon'\nimport { UScroll } from '../scroll'\nimport { FILE_VIEWER_KIND_LABEL, downloadFile, formatBytes, inferKind } from './helper'\n\ndefineOptions({ name: 'FileViewer', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FileViewerProps>(), {\n modelValue: undefined,\n sidebarWidth: '280px',\n sheetMaxRows: 50_000,\n downloadable: true,\n open: undefined,\n closeOnClickBackdrop: true,\n closeOnEsc: true\n})\n\nconst emit = defineEmits<FileViewerEmits>()\n\nconst cls = bem('file-viewer')\n\nconst MIN_SCALE = 0.5\nconst MAX_SCALE = 3\n/** 每次缩放固定增减 10% */\nconst SCALE_STEP = 0.1\n/** 使用 CSS transform 缩放的类型(PDF 由 EmbedPDF zoom 插件处理) */\nconst TRANSFORMABLE_KINDS = new Set<FileViewerKind>(['image'])\n/** 工具栏显示缩放控件的类型 */\nconst ZOOMABLE_KINDS = new Set<FileViewerKind>(['image', 'pdf'])\n\nconst activeId = defineModel<string | undefined>('modelValue', { default: undefined })\nconst openModel = defineModel<boolean | undefined>('open', { default: undefined })\n\nconst rootRef = shallowRef<HTMLDivElement>()\nconst previewerRef = shallowRef<{\n zoomIn?: () => void\n zoomOut?: () => void\n resetZoom?: () => void\n}>()\nconst scale = ref(1)\nconst pdfZoomLevel = ref(1)\nconst offsetX = ref(0)\nconst offsetY = ref(0)\nconst isDragging = ref(false)\n\nlet dragState:\n | { pointerId: number; startX: number; startY: number; originX: number; originY: number }\n | undefined\n\nconst PreviewerMap: Record<FileViewerKind, ReturnType<typeof defineAsyncComponent>> = {\n image: defineAsyncComponent(() => import('./previewers/image-previewer.vue')),\n video: defineAsyncComponent(() => import('./previewers/video-previewer.vue')),\n pdf: defineAsyncComponent(() => import('./previewers/pdf-previewer.vue')),\n sheet: defineAsyncComponent(() => import('./previewers/sheet-previewer.vue')),\n docx: defineAsyncComponent(() => import('./previewers/docx-previewer.vue')),\n text: defineAsyncComponent(() => import('./previewers/text-previewer.vue'))\n}\n\ninterface NormalizedFile extends FileViewerItem {\n id: string\n kind: FileViewerKind\n}\n\nconst normalizedFiles = computed<NormalizedFile[]>(() =>\n props.files.map((f, i) => ({ ...f, id: f.id ?? `file-${i}`, kind: inferKind(f.name, f.kind) }))\n)\n\nconst activeFile = computed<NormalizedFile | undefined>(() =>\n normalizedFiles.value.find((f) => f.id === activeId.value)\n)\n\nconst activeIndex = computed(() => normalizedFiles.value.findIndex((f) => f.id === activeId.value))\n\nconst hasPrev = computed(() => activeIndex.value > 0)\nconst hasNext = computed(\n () => activeIndex.value >= 0 && activeIndex.value < normalizedFiles.value.length - 1\n)\n\nconst showSidebar = computed(() => props.sidebarWidth !== false && props.sidebarWidth !== 0)\n\nconst sidebarWidthCss = computed(() => {\n const w = props.sidebarWidth\n if (w === false || w === 0) return undefined\n return withUnit(w ?? '280px', 'px')\n})\n\n/** 是否启用模态模式:只要父组件显式传入 open(含 v-model:open),即进入模态 */\nconst isModal = computed(() => openModel.value !== undefined)\n\nconst activeIndexLabel = computed(() =>\n activeIndex.value >= 0 ? `${activeIndex.value + 1} / ${normalizedFiles.value.length}` : ''\n)\n\nconst isTransformable = computed(\n () => !!activeFile.value && TRANSFORMABLE_KINDS.has(activeFile.value.kind)\n)\n\nconst isZoomable = computed(() => !!activeFile.value && ZOOMABLE_KINDS.has(activeFile.value.kind))\n\nconst isPdfActive = computed(() => activeFile.value?.kind === 'pdf')\n\nconst canPan = computed(() => isTransformable.value && scale.value > 1)\n\nconst displayZoomLevel = computed(() => (isPdfActive.value ? pdfZoomLevel.value : scale.value))\n\nconst zoomPercent = computed(() => `${Math.round(displayZoomLevel.value * 100)}%`)\n\nconst zoomInDisabled = computed(() => !isZoomable.value || displayZoomLevel.value >= MAX_SCALE)\n\nconst zoomOutDisabled = computed(() => !isZoomable.value || displayZoomLevel.value <= MIN_SCALE)\n\nconst isTransformReset = computed(() => {\n if (isPdfActive.value) {\n return Math.abs(pdfZoomLevel.value - 1) < 0.02\n }\n return scale.value === 1 && offsetX.value === 0 && offsetY.value === 0\n})\n\nconst previewerStyle = computed<CSSProperties | undefined>(() => {\n if (!isTransformable.value) return undefined\n return {\n transform: `translate3d(${offsetX.value}px, ${offsetY.value}px, 0) scale(${scale.value})`\n }\n})\n\nfunction label(kind: FileViewerKind): string {\n return FILE_VIEWER_KIND_LABEL[kind]\n}\n\nfunction activate(id: string) {\n if (activeId.value === id) return\n activeId.value = id\n const f = normalizedFiles.value.find((x) => x.id === id)\n if (f) emit('change', f)\n}\n\nfunction prev() {\n const i = activeIndex.value\n if (i <= 0) return\n const target = normalizedFiles.value[i - 1]\n if (target) activate(target.id)\n}\n\nfunction next() {\n const i = activeIndex.value\n if (i < 0 || i >= normalizedFiles.value.length - 1) return\n const target = normalizedFiles.value[i + 1]\n if (target) activate(target.id)\n}\n\nfunction normalizeScale(value: number): number {\n const clamped = Math.min(MAX_SCALE, Math.max(MIN_SCALE, value))\n return Math.round(clamped * 100) / 100\n}\n\nfunction setScale(value: number) {\n scale.value = normalizeScale(value)\n if (scale.value <= 1) {\n offsetX.value = 0\n offsetY.value = 0\n }\n}\n\nfunction zoomIn() {\n if (!isZoomable.value) return\n if (isPdfActive.value) {\n previewerRef.value?.zoomIn?.()\n return\n }\n setScale(scale.value + SCALE_STEP)\n}\n\nfunction zoomOut() {\n if (!isZoomable.value) return\n if (isPdfActive.value) {\n previewerRef.value?.zoomOut?.()\n return\n }\n setScale(scale.value - SCALE_STEP)\n}\n\nfunction resetTransform() {\n if (isPdfActive.value) {\n previewerRef.value?.resetZoom?.()\n pdfZoomLevel.value = 1\n return\n }\n scale.value = 1\n offsetX.value = 0\n offsetY.value = 0\n dragState = undefined\n isDragging.value = false\n}\n\nfunction handlePdfZoomChange(level: number) {\n pdfZoomLevel.value = level\n}\n\nfunction isZoomWheel(e: WheelEvent): boolean {\n return e.ctrlKey || e.metaKey\n}\n\nfunction handleViewportWheel(e: WheelEvent) {\n if (!activeFile.value || activeFile.value.kind !== 'image') return\n if (!isZoomWheel(e)) return\n if (isInteractiveTarget(e.target)) return\n e.preventDefault()\n const delta = e.deltaY > 0 ? -SCALE_STEP : SCALE_STEP\n setScale(scale.value + delta)\n}\n\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false\n return !!target.closest('button, a, input, textarea, select, video, [contenteditable=\"true\"]')\n}\n\nfunction handleViewportPointerDown(e: PointerEvent) {\n if (!canPan.value || e.button !== 0 || isInteractiveTarget(e.target)) return\n\n dragState = {\n pointerId: e.pointerId,\n startX: e.clientX,\n startY: e.clientY,\n originX: offsetX.value,\n originY: offsetY.value\n }\n isDragging.value = true\n const el = e.currentTarget as HTMLElement\n el.setPointerCapture(e.pointerId)\n e.preventDefault()\n}\n\nfunction handleViewportPointerMove(e: PointerEvent) {\n if (!dragState || dragState.pointerId !== e.pointerId) return\n offsetX.value = dragState.originX + e.clientX - dragState.startX\n offsetY.value = dragState.originY + e.clientY - dragState.startY\n}\n\nfunction handleViewportPointerEnd(e: PointerEvent) {\n if (!dragState || dragState.pointerId !== e.pointerId) return\n const el = e.currentTarget as HTMLElement\n if (el.hasPointerCapture(e.pointerId)) {\n el.releasePointerCapture(e.pointerId)\n }\n dragState = undefined\n isDragging.value = false\n}\n\nfunction handleViewportDblclick() {\n if (isPdfActive.value) return\n if (!isTransformable.value) return\n if (scale.value === 1) {\n setScale(2)\n } else {\n resetTransform()\n }\n}\n\nasync function download() {\n if (!activeFile.value) return\n try {\n await downloadFile(activeFile.value)\n } catch (err) {\n emit('error', { file: activeFile.value, error: err })\n }\n}\n\nfunction handleChildError(err: unknown) {\n if (!activeFile.value) return\n emit('error', { file: activeFile.value, error: err })\n}\n\nfunction handleClose() {\n if (!isModal.value) return\n openModel.value = false\n}\n\nfunction handleWindowKeydown(e: KeyboardEvent) {\n if (e.key !== 'Escape') return\n if (!isModal.value || !openModel.value) return\n if (props.closeOnEsc === false) return\n e.stopPropagation()\n handleClose()\n}\n\nfunction handleBackdropMousedown() {\n if (!isModal.value) return\n if (props.closeOnClickBackdrop === false) return\n handleClose()\n}\n\nwatch(\n normalizedFiles,\n (files) => {\n if (!files.length) {\n activeId.value = undefined\n return\n }\n if (!activeId.value || !files.some((f) => f.id === activeId.value)) {\n activeId.value = files[0]!.id\n }\n },\n { immediate: true }\n)\n\nwatch(\n () => activeFile.value?.id,\n async () => {\n pdfZoomLevel.value = 1\n await nextTick()\n resetTransform()\n }\n)\n\n// 模态打开时:锁定 body 滚动 + 让容器获得焦点以便接收 ESC\nlet previousBodyOverflow = ''\nlet isBodyLocked = false\n\nfunction lockBody() {\n if (isBodyLocked || typeof document === 'undefined') return\n previousBodyOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n isBodyLocked = true\n}\n\nfunction unlockBody() {\n if (!isBodyLocked || typeof document === 'undefined') return\n document.body.style.overflow = previousBodyOverflow\n isBodyLocked = false\n}\n\nwatch(\n [isModal, openModel],\n ([modal, open]) => {\n if (modal && open) {\n lockBody()\n nextTick(() => {\n rootRef.value?.focus()\n })\n if (typeof window !== 'undefined') {\n window.addEventListener('keydown', handleWindowKeydown, true)\n }\n } else {\n unlockBody()\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', handleWindowKeydown, true)\n }\n }\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n unlockBody()\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', handleWindowKeydown, true)\n }\n})\n\ndefineExpose<_FileViewerExposed>({ activeId, activate, next, prev })\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"file-viewer.js","names":[],"sources":["../../../src/components/file-viewer/file-viewer.vue"],"sourcesContent":["<template>\n <Teleport to=\"body\" :disabled=\"!isModal\">\n <transition :name=\"isModal ? 'u-file-viewer-modal' : ''\">\n <div\n v-if=\"!isModal || openModel\"\n :class=\"[cls.b, bem.is('modal', isModal)]\"\n :tabindex=\"isModal ? -1 : undefined\"\n ref=\"rootRef\"\n @mousedown.self=\"handleBackdropMousedown\"\n >\n <div v-if=\"isModal\" :class=\"cls.e('backdrop')\" @mousedown.self=\"handleBackdropMousedown\" />\n <div :class=\"cls.e('inner')\">\n <aside v-if=\"showSidebar\" :class=\"cls.e('sidebar')\" :style=\"{ width: sidebarWidthCss }\">\n <header :class=\"cls.e('sidebar-head')\">\n <span :class=\"cls.e('sidebar-title')\">文件</span>\n <span :class=\"cls.e('sidebar-count')\">{{ normalizedFiles.length }}</span>\n </header>\n <u-scroll tag=\"ul\" :class=\"cls.e('list')\">\n <li\n v-for=\"f in normalizedFiles\"\n :key=\"f.id\"\n :class=\"[cls.e('item'), bem.is('active', f.id === activeId)]\"\n :title=\"f.name\"\n @click=\"activate(f.id)\"\n >\n <span :class=\"cls.e('item-meta')\">\n <span :class=\"cls.e('item-name')\" :title=\"f.name\">{{ f.name }}</span>\n <span :class=\"cls.e('item-size')\">{{ formatBytes(f.size) }}</span>\n </span>\n <span :class=\"cls.e('item-kind')\">{{ label(f.kind) }}</span>\n </li>\n <li v-if=\"!normalizedFiles.length\" :class=\"cls.e('list-empty')\">\n <u-empty text=\"暂无文件\" :size=\"32\" />\n </li>\n </u-scroll>\n </aside>\n\n <section :class=\"cls.e('stage')\">\n <header :class=\"cls.e('stage-head')\">\n <div :class=\"cls.e('stage-title')\">\n <span v-if=\"activeFile\" :class=\"[cls.e('badge'), cls.em('badge', activeFile.kind)]\">\n {{ label(activeFile.kind) }}\n </span>\n <span :class=\"cls.e('stage-copy')\">\n <span :class=\"cls.e('stage-name')\" :title=\"activeFile?.name\">\n {{ activeFile?.name ?? '—' }}\n </span>\n <span v-if=\"activeFile\" :class=\"cls.e('stage-sub')\">\n <span>{{ activeIndexLabel }}</span>\n <span v-if=\"activeFile.size\">{{ formatBytes(activeFile.size) }}</span>\n </span>\n </span>\n </div>\n <div :class=\"cls.e('stage-actions')\">\n <span :class=\"cls.e('action-group')\">\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"!hasPrev\"\n type=\"button\"\n aria-label=\"上一个\"\n title=\"上一个\"\n @click=\"prev\"\n >\n <u-icon :size=\"15\">\n <ArrowLeft />\n </u-icon>\n </button>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"!hasNext\"\n type=\"button\"\n aria-label=\"下一个\"\n title=\"下一个\"\n @click=\"next\"\n >\n <u-icon :size=\"15\">\n <ArrowRight />\n </u-icon>\n </button>\n </span>\n <span v-if=\"isZoomable\" :class=\"cls.e('action-group')\">\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"zoomOutDisabled\"\n type=\"button\"\n aria-label=\"缩小\"\n title=\"缩小\"\n @click=\"zoomOut\"\n >\n <u-icon :size=\"15\">\n <ZoomOut />\n </u-icon>\n </button>\n <span :class=\"cls.e('zoom-value')\">{{ zoomPercent }}</span>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"zoomInDisabled\"\n type=\"button\"\n aria-label=\"放大\"\n title=\"放大\"\n @click=\"zoomIn\"\n >\n <u-icon :size=\"15\">\n <ZoomIn />\n </u-icon>\n </button>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"isTransformReset\"\n type=\"button\"\n aria-label=\"重置视图\"\n title=\"重置视图\"\n @click=\"resetTransform\"\n >\n <u-icon :size=\"15\">\n <Refresh />\n </u-icon>\n </button>\n </span>\n <button\n v-if=\"downloadable && activeFile\"\n :class=\"[cls.e('action'), cls.em('action', 'primary'), cls.em('action', 'icon')]\"\n type=\"button\"\n aria-label=\"下载\"\n title=\"下载\"\n @click=\"download\"\n >\n <u-icon :size=\"15\">\n <Download />\n </u-icon>\n </button>\n <button\n v-if=\"isModal\"\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n type=\"button\"\n aria-label=\"关闭预览\"\n title=\"关闭\"\n @click=\"handleClose\"\n >\n <u-icon :size=\"16\">\n <Close />\n </u-icon>\n </button>\n </div>\n </header>\n <div :class=\"cls.e('body')\">\n <transition name=\"u-file-viewer-fade\" mode=\"out-in\">\n <div\n v-if=\"activeFile\"\n :key=\"activeFile.id\"\n :class=\"[\n cls.e('viewport'),\n bem.is('transformable', isTransformable),\n bem.is('pannable', canPan),\n bem.is('dragging', isDragging)\n ]\"\n @pointerdown.capture=\"handleViewportPointerDown\"\n @pointermove.capture=\"handleViewportPointerMove\"\n @pointerup.capture=\"handleViewportPointerEnd\"\n @pointercancel.capture=\"handleViewportPointerEnd\"\n @wheel=\"handleViewportWheel\"\n @dblclick=\"handleViewportDblclick\"\n >\n <component\n :is=\"PreviewerMap[activeFile.kind]\"\n ref=\"previewerRef\"\n :file=\"activeFile\"\n :max-rows=\"sheetMaxRows\"\n :class=\"isTransformable ? cls.e('previewer') : undefined\"\n :style=\"previewerStyle\"\n @error=\"handleChildError\"\n @zoom-change=\"handlePdfZoomChange\"\n />\n </div>\n <div v-else :class=\"cls.e('empty')\">\n <u-empty text=\"暂无可预览文件\" />\n </div>\n </transition>\n </div>\n </section>\n </div>\n </div>\n </transition>\n </Teleport>\n</template>\n\n<script lang=\"ts\" setup>\nimport {\n ArrowLeft,\n ArrowRight,\n Close,\n Download,\n Refresh,\n ZoomIn,\n ZoomOut\n} from '@veltra/icons/normal'\nimport { bem, withUnit } from '@veltra/utils'\nimport {\n computed,\n defineAsyncComponent,\n nextTick,\n onBeforeUnmount,\n ref,\n shallowRef,\n watch\n} from 'vue'\nimport type { CSSProperties } from 'vue'\n\nimport type {\n _FileViewerExposed,\n FileViewerEmits,\n FileViewerItem,\n FileViewerKind,\n FileViewerProps\n} from '../../types/file-viewer'\nimport { UEmpty } from '../empty'\nimport { UIcon } from '../icon'\nimport { UScroll } from '../scroll'\nimport { FILE_VIEWER_KIND_LABEL, downloadFile, formatBytes, inferKind } from './helper'\n\ndefineOptions({ name: 'FileViewer', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FileViewerProps>(), {\n modelValue: undefined,\n sidebarWidth: '280px',\n sheetMaxRows: 50_000,\n downloadable: true,\n open: undefined,\n closeOnClickBackdrop: true,\n closeOnEsc: true\n})\n\nconst emit = defineEmits<FileViewerEmits>()\n\nconst cls = bem('file-viewer')\n\nconst MIN_SCALE = 0.5\nconst MAX_SCALE = 3\n/** 每次缩放固定增减 10% */\nconst SCALE_STEP = 0.1\n/** 使用 CSS transform 缩放的类型(PDF 由 EmbedPDF zoom 插件处理) */\nconst TRANSFORMABLE_KINDS = new Set<FileViewerKind>(['image'])\n/** 工具栏显示缩放控件的类型 */\nconst ZOOMABLE_KINDS = new Set<FileViewerKind>(['image', 'pdf'])\n\nconst activeId = defineModel<string | undefined>('modelValue', { default: undefined })\nconst openModel = defineModel<boolean | undefined>('open', { default: undefined })\n\nconst rootRef = shallowRef<HTMLDivElement>()\nconst previewerRef = shallowRef<{\n zoomIn?: () => void\n zoomOut?: () => void\n resetZoom?: () => void\n}>()\nconst scale = ref(1)\nconst pdfZoomLevel = ref(1)\nconst offsetX = ref(0)\nconst offsetY = ref(0)\nconst isDragging = ref(false)\n\nlet dragState:\n | { pointerId: number; startX: number; startY: number; originX: number; originY: number }\n | undefined\n\nconst PreviewerMap: Record<FileViewerKind, ReturnType<typeof defineAsyncComponent>> = {\n image: defineAsyncComponent(() => import('./previewers/image-previewer.vue')),\n video: defineAsyncComponent(() => import('./previewers/video-previewer.vue')),\n pdf: defineAsyncComponent(() => import('./previewers/pdf-previewer.vue')),\n sheet: defineAsyncComponent(() => import('./previewers/sheet-previewer.vue')),\n docx: defineAsyncComponent(() => import('./previewers/docx-previewer.vue')),\n text: defineAsyncComponent(() => import('./previewers/text-previewer.vue'))\n}\n\ninterface NormalizedFile extends FileViewerItem {\n id: string\n kind: FileViewerKind\n}\n\nconst normalizedFiles = computed<NormalizedFile[]>(() =>\n props.files.map((f, i) => ({ ...f, id: f.id ?? `file-${i}`, kind: inferKind(f.name, f.kind) }))\n)\n\nconst activeFile = computed<NormalizedFile | undefined>(() =>\n normalizedFiles.value.find((f) => f.id === activeId.value)\n)\n\nconst activeIndex = computed(() => normalizedFiles.value.findIndex((f) => f.id === activeId.value))\n\nconst hasPrev = computed(() => activeIndex.value > 0)\nconst hasNext = computed(\n () => activeIndex.value >= 0 && activeIndex.value < normalizedFiles.value.length - 1\n)\n\nconst showSidebar = computed(() => props.sidebarWidth !== false && props.sidebarWidth !== 0)\n\nconst sidebarWidthCss = computed(() => {\n const w = props.sidebarWidth\n if (w === false || w === 0) return undefined\n return withUnit(w ?? '280px', 'px')\n})\n\n/** 是否启用模态模式:只要父组件显式传入 open(含 v-model:open),即进入模态 */\nconst isModal = computed(() => openModel.value !== undefined)\n\nconst activeIndexLabel = computed(() =>\n activeIndex.value >= 0 ? `${activeIndex.value + 1} / ${normalizedFiles.value.length}` : ''\n)\n\nconst isTransformable = computed(\n () => !!activeFile.value && TRANSFORMABLE_KINDS.has(activeFile.value.kind)\n)\n\nconst isZoomable = computed(() => !!activeFile.value && ZOOMABLE_KINDS.has(activeFile.value.kind))\n\nconst isPdfActive = computed(() => activeFile.value?.kind === 'pdf')\n\nconst canPan = computed(() => isTransformable.value && scale.value > 1)\n\nconst displayZoomLevel = computed(() => (isPdfActive.value ? pdfZoomLevel.value : scale.value))\n\nconst zoomPercent = computed(() => `${Math.round(displayZoomLevel.value * 100)}%`)\n\nconst zoomInDisabled = computed(() => !isZoomable.value || displayZoomLevel.value >= MAX_SCALE)\n\nconst zoomOutDisabled = computed(() => !isZoomable.value || displayZoomLevel.value <= MIN_SCALE)\n\nconst isTransformReset = computed(() => {\n if (isPdfActive.value) {\n return Math.abs(pdfZoomLevel.value - 1) < 0.02\n }\n return scale.value === 1 && offsetX.value === 0 && offsetY.value === 0\n})\n\nconst previewerStyle = computed<CSSProperties | undefined>(() => {\n if (!isTransformable.value) return undefined\n return {\n transform: `translate3d(${offsetX.value}px, ${offsetY.value}px, 0) scale(${scale.value})`\n }\n})\n\nfunction label(kind: FileViewerKind): string {\n return FILE_VIEWER_KIND_LABEL[kind]\n}\n\nfunction activate(id: string) {\n if (activeId.value === id) return\n activeId.value = id\n const f = normalizedFiles.value.find((x) => x.id === id)\n if (f) emit('change', f)\n}\n\nfunction prev() {\n const i = activeIndex.value\n if (i <= 0) return\n const target = normalizedFiles.value[i - 1]\n if (target) activate(target.id)\n}\n\nfunction next() {\n const i = activeIndex.value\n if (i < 0 || i >= normalizedFiles.value.length - 1) return\n const target = normalizedFiles.value[i + 1]\n if (target) activate(target.id)\n}\n\nfunction normalizeScale(value: number): number {\n const clamped = Math.min(MAX_SCALE, Math.max(MIN_SCALE, value))\n return Math.round(clamped * 100) / 100\n}\n\nfunction setScale(value: number) {\n scale.value = normalizeScale(value)\n if (scale.value <= 1) {\n offsetX.value = 0\n offsetY.value = 0\n }\n}\n\nfunction zoomIn() {\n if (!isZoomable.value) return\n if (isPdfActive.value) {\n previewerRef.value?.zoomIn?.()\n return\n }\n setScale(scale.value + SCALE_STEP)\n}\n\nfunction zoomOut() {\n if (!isZoomable.value) return\n if (isPdfActive.value) {\n previewerRef.value?.zoomOut?.()\n return\n }\n setScale(scale.value - SCALE_STEP)\n}\n\nfunction resetTransform() {\n if (isPdfActive.value) {\n previewerRef.value?.resetZoom?.()\n pdfZoomLevel.value = 1\n return\n }\n scale.value = 1\n offsetX.value = 0\n offsetY.value = 0\n dragState = undefined\n isDragging.value = false\n}\n\nfunction handlePdfZoomChange(level: number) {\n pdfZoomLevel.value = level\n}\n\nfunction isZoomWheel(e: WheelEvent): boolean {\n return e.ctrlKey || e.metaKey\n}\n\nfunction handleViewportWheel(e: WheelEvent) {\n if (!activeFile.value || activeFile.value.kind !== 'image') return\n if (!isZoomWheel(e)) return\n if (isInteractiveTarget(e.target)) return\n e.preventDefault()\n const delta = e.deltaY > 0 ? -SCALE_STEP : SCALE_STEP\n setScale(scale.value + delta)\n}\n\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false\n return !!target.closest('button, a, input, textarea, select, video, [contenteditable=\"true\"]')\n}\n\nfunction handleViewportPointerDown(e: PointerEvent) {\n if (!canPan.value || e.button !== 0 || isInteractiveTarget(e.target)) return\n\n dragState = {\n pointerId: e.pointerId,\n startX: e.clientX,\n startY: e.clientY,\n originX: offsetX.value,\n originY: offsetY.value\n }\n isDragging.value = true\n const el = e.currentTarget as HTMLElement\n el.setPointerCapture(e.pointerId)\n e.preventDefault()\n}\n\nfunction handleViewportPointerMove(e: PointerEvent) {\n if (!dragState || dragState.pointerId !== e.pointerId) return\n offsetX.value = dragState.originX + e.clientX - dragState.startX\n offsetY.value = dragState.originY + e.clientY - dragState.startY\n}\n\nfunction handleViewportPointerEnd(e: PointerEvent) {\n if (!dragState || dragState.pointerId !== e.pointerId) return\n const el = e.currentTarget as HTMLElement\n if (el.hasPointerCapture(e.pointerId)) {\n el.releasePointerCapture(e.pointerId)\n }\n dragState = undefined\n isDragging.value = false\n}\n\nfunction handleViewportDblclick() {\n if (isPdfActive.value) return\n if (!isTransformable.value) return\n if (scale.value === 1) {\n setScale(2)\n } else {\n resetTransform()\n }\n}\n\nasync function download() {\n if (!activeFile.value) return\n try {\n await downloadFile(activeFile.value)\n } catch (err) {\n emit('error', { file: activeFile.value, error: err })\n }\n}\n\nfunction handleChildError(err: unknown) {\n if (!activeFile.value) return\n emit('error', { file: activeFile.value, error: err })\n}\n\nfunction handleClose() {\n if (!isModal.value) return\n openModel.value = false\n}\n\nfunction handleWindowKeydown(e: KeyboardEvent) {\n if (e.key !== 'Escape') return\n if (!isModal.value || !openModel.value) return\n if (props.closeOnEsc === false) return\n e.stopPropagation()\n handleClose()\n}\n\nfunction handleBackdropMousedown() {\n if (!isModal.value) return\n if (props.closeOnClickBackdrop === false) return\n handleClose()\n}\n\nwatch(\n normalizedFiles,\n (files) => {\n if (!files.length) {\n activeId.value = undefined\n return\n }\n if (!activeId.value || !files.some((f) => f.id === activeId.value)) {\n activeId.value = files[0]!.id\n }\n },\n { immediate: true }\n)\n\nwatch(\n () => activeFile.value?.id,\n async () => {\n pdfZoomLevel.value = 1\n await nextTick()\n resetTransform()\n }\n)\n\n// 模态打开时:锁定 body 滚动 + 让容器获得焦点以便接收 ESC\nlet previousBodyOverflow = ''\nlet isBodyLocked = false\n\nfunction lockBody() {\n if (isBodyLocked || typeof document === 'undefined') return\n previousBodyOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n isBodyLocked = true\n}\n\nfunction unlockBody() {\n if (!isBodyLocked || typeof document === 'undefined') return\n document.body.style.overflow = previousBodyOverflow\n isBodyLocked = false\n}\n\nwatch(\n [isModal, openModel],\n ([modal, open]) => {\n if (modal && open) {\n lockBody()\n nextTick(() => {\n rootRef.value?.focus()\n })\n if (typeof window !== 'undefined') {\n window.addEventListener('keydown', handleWindowKeydown, true)\n }\n } else {\n unlockBody()\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', handleWindowKeydown, true)\n }\n }\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n unlockBody()\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', handleWindowKeydown, true)\n }\n})\n\ndefineExpose<_FileViewerExposed>({ activeId, activate, next, prev })\n</script>\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { FileViewerItem, FileViewerProps, _FileViewerExposed } from "../../types/file-viewer.js";
2
- import * as _$vue from "vue";
3
2
 
4
3
  //#region src/components/file-viewer/file-viewer.vue.d.ts
5
4
  type __VLS_Props = FileViewerProps;
@@ -8,25 +7,25 @@ type __VLS_ModelProps = {
8
7
  'open'?: boolean | undefined;
9
8
  };
10
9
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
11
- declare const __VLS_export: _$vue.DefineComponent<__VLS_PublicProps, _FileViewerExposed, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {
10
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, _FileViewerExposed, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
11
  "update:modelValue": (value: string | undefined) => any;
13
12
  "update:open": (value: boolean | undefined) => any;
14
13
  } & {
15
14
  "update:modelValue": (id: string) => any;
16
15
  change: (file: FileViewerItem) => any;
16
+ "update:open": (value: boolean) => any;
17
17
  error: (err: {
18
18
  file: FileViewerItem;
19
19
  error: unknown;
20
20
  }) => any;
21
- "update:open": (value: boolean) => any;
22
- }, string, _$vue.PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
21
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
23
22
  "onUpdate:modelValue"?: ((id: string) => any) | undefined;
24
23
  onChange?: ((file: FileViewerItem) => any) | undefined;
24
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
25
25
  onError?: ((err: {
26
26
  file: FileViewerItem;
27
27
  error: unknown;
28
28
  }) => any) | undefined;
29
- "onUpdate:open"?: ((value: boolean) => any) | undefined;
30
29
  }>, {
31
30
  modelValue: string;
32
31
  open: boolean;
@@ -35,7 +34,7 @@ declare const __VLS_export: _$vue.DefineComponent<__VLS_PublicProps, _FileViewer
35
34
  downloadable: boolean;
36
35
  closeOnClickBackdrop: boolean;
37
36
  closeOnEsc: boolean;
38
- }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
37
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
39
38
  declare const _default: typeof __VLS_export;
40
39
  //#endregion
41
40
  export { _default };
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","names":[],"sources":["../../../src/components/file-viewer/helper.ts"],"sourcesContent":["import type { FileViewerItem, FileViewerKind } from '../../types/file-viewer'\n\nconst IMAGE_EXTS = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg', 'avif', 'ico'])\n\nconst VIDEO_EXTS = new Set(['mp4', 'webm', 'mov', 'm4v', 'ogv', 'mkv'])\n\nconst SHEET_EXTS = new Set(['xlsx', 'xlsm', 'xlsb', 'csv'])\n\nconst TEXT_EXTS = new Set([\n 'txt',\n 'log',\n 'md',\n 'markdown',\n 'json',\n 'yml',\n 'yaml',\n 'xml',\n 'js',\n 'ts',\n 'tsx',\n 'jsx',\n 'css',\n 'scss',\n 'sass',\n 'less',\n 'html',\n 'htm',\n 'ini',\n 'toml',\n 'sh',\n 'bash',\n 'zsh',\n 'env',\n 'sql'\n])\n\nexport function getExtension(name: string): string {\n const idx = name.lastIndexOf('.')\n return idx === -1 ? '' : name.slice(idx + 1).toLowerCase()\n}\n\nexport function inferKind(name: string, explicit?: FileViewerKind): FileViewerKind {\n if (explicit) return explicit\n const ext = getExtension(name)\n if (IMAGE_EXTS.has(ext)) return 'image'\n if (VIDEO_EXTS.has(ext)) return 'video'\n if (ext === 'pdf') return 'pdf'\n if (SHEET_EXTS.has(ext)) return 'sheet'\n if (ext === 'docx') return 'docx'\n if (TEXT_EXTS.has(ext)) return 'text'\n return 'text'\n}\n\nexport const FILE_VIEWER_KIND_LABEL: Record<FileViewerKind, string> = {\n image: 'IMG',\n video: 'MP4',\n pdf: 'PDF',\n sheet: 'XLS',\n docx: 'DOC',\n text: 'TXT'\n}\n\n/** 规范化数据源为 ArrayBuffer,可被 AbortController 中断(仅 URL fetch 场景生效) */\nexport async function toArrayBuffer(\n src: FileViewerItem['src'],\n signal?: AbortSignal\n): Promise<ArrayBuffer> {\n if (typeof src === 'string') {\n const res = await fetch(src, { signal })\n if (!res.ok) {\n throw new Error(`Fetch failed: ${res.status} ${res.statusText}`)\n }\n return await res.arrayBuffer()\n }\n if (src instanceof ArrayBuffer) return src\n if (src instanceof Uint8Array) {\n // 复制底层以切断共享引用,防止外部修改影响预览\n return src.slice().buffer as ArrayBuffer\n }\n // File/Blob\n return await src.arrayBuffer()\n}\n\n/** 返回用于 <img> / <video> 等标签 src 的 URL;二进制会创建 ObjectURL 并返回 revoke 钩子 */\nexport function toBlobUrl(\n src: FileViewerItem['src'],\n mime?: string\n): { url: string; revoke: () => void } {\n if (typeof src === 'string') {\n return { url: src, revoke: () => {} }\n }\n let blob: Blob\n if (src instanceof Blob) {\n blob = src\n } else if (src instanceof ArrayBuffer) {\n blob = new Blob([src], { type: mime ?? 'application/octet-stream' })\n } else {\n // Uint8Array: 复制到新的 ArrayBuffer,避免与外部共享底层\n const copy = new Uint8Array(src.byteLength)\n copy.set(src)\n blob = new Blob([copy.buffer], { type: mime ?? 'application/octet-stream' })\n }\n const url = URL.createObjectURL(blob)\n return { url, revoke: () => URL.revokeObjectURL(url) }\n}\n\n/**\n * RFC-4180 子集 CSV 解析:支持 \"\" 转义、\\r\\n 与 \\n 换行、, 分隔。\n * 为性能起见采用状态机而非 split。\n */\nexport function parseCsv(text: string): string[][] {\n const rows: string[][] = []\n let row: string[] = []\n let field = ''\n let inQuotes = false\n const len = text.length\n\n for (let i = 0; i < len; i++) {\n const ch = text[i]\n\n if (inQuotes) {\n if (ch === '\"') {\n if (text[i + 1] === '\"') {\n field += '\"'\n i++\n } else {\n inQuotes = false\n }\n } else {\n field += ch\n }\n continue\n }\n\n if (ch === '\"') {\n inQuotes = true\n } else if (ch === ',') {\n row.push(field)\n field = ''\n } else if (ch === '\\n') {\n row.push(field)\n rows.push(row)\n row = []\n field = ''\n } else if (ch === '\\r') {\n // swallow CR; LF will commit the row\n } else {\n field += ch\n }\n }\n\n // 最后一行\n if (field.length > 0 || row.length > 0) {\n row.push(field)\n rows.push(row)\n }\n return rows\n}\n\nexport function formatBytes(bytes?: number): string {\n if (bytes === undefined || bytes === null || Number.isNaN(bytes)) return '-'\n if (bytes < 1024) return `${bytes} B`\n const units = ['KB', 'MB', 'GB', 'TB']\n let v = bytes / 1024\n let i = 0\n while (v >= 1024 && i < units.length - 1) {\n v /= 1024\n i++\n }\n return `${v.toFixed(v >= 10 ? 0 : 1)} ${units[i]}`\n}\n\n/** 触发浏览器下载 */\nexport async function downloadFile(file: FileViewerItem): Promise<void> {\n let href: string\n let revoke: (() => void) | undefined\n if (typeof file.src === 'string') {\n href = file.src\n } else {\n const url = toBlobUrl(file.src, file.mime)\n href = url.url\n revoke = url.revoke\n }\n const a = document.createElement('a')\n a.href = href\n a.download = file.name\n a.rel = 'noopener'\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n if (revoke) setTimeout(revoke, 4000)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"helper.js","names":[],"sources":["../../../src/components/file-viewer/helper.ts"],"sourcesContent":["import type { FileViewerItem, FileViewerKind } from '../../types/file-viewer'\n\nconst IMAGE_EXTS = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg', 'avif', 'ico'])\n\nconst VIDEO_EXTS = new Set(['mp4', 'webm', 'mov', 'm4v', 'ogv', 'mkv'])\n\nconst SHEET_EXTS = new Set(['xlsx', 'xlsm', 'xlsb', 'csv'])\n\nconst TEXT_EXTS = new Set([\n 'txt',\n 'log',\n 'md',\n 'markdown',\n 'json',\n 'yml',\n 'yaml',\n 'xml',\n 'js',\n 'ts',\n 'tsx',\n 'jsx',\n 'css',\n 'scss',\n 'sass',\n 'less',\n 'html',\n 'htm',\n 'ini',\n 'toml',\n 'sh',\n 'bash',\n 'zsh',\n 'env',\n 'sql'\n])\n\nexport function getExtension(name: string): string {\n const idx = name.lastIndexOf('.')\n return idx === -1 ? '' : name.slice(idx + 1).toLowerCase()\n}\n\nexport function inferKind(name: string, explicit?: FileViewerKind): FileViewerKind {\n if (explicit) return explicit\n const ext = getExtension(name)\n if (IMAGE_EXTS.has(ext)) return 'image'\n if (VIDEO_EXTS.has(ext)) return 'video'\n if (ext === 'pdf') return 'pdf'\n if (SHEET_EXTS.has(ext)) return 'sheet'\n if (ext === 'docx') return 'docx'\n if (TEXT_EXTS.has(ext)) return 'text'\n return 'text'\n}\n\nexport const FILE_VIEWER_KIND_LABEL: Record<FileViewerKind, string> = {\n image: 'IMG',\n video: 'MP4',\n pdf: 'PDF',\n sheet: 'XLS',\n docx: 'DOC',\n text: 'TXT'\n}\n\n/** 规范化数据源为 ArrayBuffer,可被 AbortController 中断(仅 URL fetch 场景生效) */\nexport async function toArrayBuffer(\n src: FileViewerItem['src'],\n signal?: AbortSignal\n): Promise<ArrayBuffer> {\n if (typeof src === 'string') {\n const res = await fetch(src, { signal })\n if (!res.ok) {\n throw new Error(`Fetch failed: ${res.status} ${res.statusText}`)\n }\n return await res.arrayBuffer()\n }\n if (src instanceof ArrayBuffer) return src\n if (src instanceof Uint8Array) {\n // 复制底层以切断共享引用,防止外部修改影响预览\n return src.slice().buffer as ArrayBuffer\n }\n // File/Blob\n return await src.arrayBuffer()\n}\n\n/** 返回用于 <img> / <video> 等标签 src 的 URL;二进制会创建 ObjectURL 并返回 revoke 钩子 */\nexport function toBlobUrl(\n src: FileViewerItem['src'],\n mime?: string\n): { url: string; revoke: () => void } {\n if (typeof src === 'string') {\n return { url: src, revoke: () => {} }\n }\n let blob: Blob\n if (src instanceof Blob) {\n blob = src\n } else if (src instanceof ArrayBuffer) {\n blob = new Blob([src], { type: mime ?? 'application/octet-stream' })\n } else {\n // Uint8Array: 复制到新的 ArrayBuffer,避免与外部共享底层\n const copy = new Uint8Array(src.byteLength)\n copy.set(src)\n blob = new Blob([copy.buffer], { type: mime ?? 'application/octet-stream' })\n }\n const url = URL.createObjectURL(blob)\n return { url, revoke: () => URL.revokeObjectURL(url) }\n}\n\n/**\n * RFC-4180 子集 CSV 解析:支持 \"\" 转义、\\r\\n 与 \\n 换行、, 分隔。\n * 为性能起见采用状态机而非 split。\n */\nexport function parseCsv(text: string): string[][] {\n const rows: string[][] = []\n let row: string[] = []\n let field = ''\n let inQuotes = false\n const len = text.length\n\n for (let i = 0; i < len; i++) {\n const ch = text[i]\n\n if (inQuotes) {\n if (ch === '\"') {\n if (text[i + 1] === '\"') {\n field += '\"'\n i++\n } else {\n inQuotes = false\n }\n } else {\n field += ch\n }\n continue\n }\n\n if (ch === '\"') {\n inQuotes = true\n } else if (ch === ',') {\n row.push(field)\n field = ''\n } else if (ch === '\\n') {\n row.push(field)\n rows.push(row)\n row = []\n field = ''\n } else if (ch === '\\r') {\n // swallow CR; LF will commit the row\n } else {\n field += ch\n }\n }\n\n // 最后一行\n if (field.length > 0 || row.length > 0) {\n row.push(field)\n rows.push(row)\n }\n return rows\n}\n\nexport function formatBytes(bytes?: number): string {\n if (bytes === undefined || bytes === null || Number.isNaN(bytes)) return '-'\n if (bytes < 1024) return `${bytes} B`\n const units = ['KB', 'MB', 'GB', 'TB']\n let v = bytes / 1024\n let i = 0\n while (v >= 1024 && i < units.length - 1) {\n v /= 1024\n i++\n }\n return `${v.toFixed(v >= 10 ? 0 : 1)} ${units[i]}`\n}\n\n/** 触发浏览器下载 */\nexport async function downloadFile(file: FileViewerItem): Promise<void> {\n let href: string\n let revoke: (() => void) | undefined\n if (typeof file.src === 'string') {\n href = file.src\n } else {\n const url = toBlobUrl(file.src, file.mime)\n href = url.url\n revoke = url.revoke\n }\n const a = document.createElement('a')\n a.href = href\n a.download = file.name\n a.rel = 'noopener'\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n if (revoke) setTimeout(revoke, 4000)\n}\n"],"mappings":";AAEA,MAAM,aAAa,IAAI,IAAI;CAAC;CAAO;CAAO;CAAQ;CAAO;CAAQ;CAAO;CAAO;CAAQ;AAAK,CAAC;AAE7F,MAAM,aAAa,IAAI,IAAI;CAAC;CAAO;CAAQ;CAAO;CAAO;CAAO;AAAK,CAAC;AAEtE,MAAM,aAAa,IAAI,IAAI;CAAC;CAAQ;CAAQ;CAAQ;AAAK,CAAC;AAE1D,MAAM,YAAY,IAAI,IAAI;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAgB,aAAa,MAAsB;CACjD,MAAM,MAAM,KAAK,YAAY,GAAG;CAChC,OAAO,QAAQ,KAAK,KAAK,KAAK,MAAM,MAAM,CAAC,EAAE,YAAY;AAC3D;AAEA,SAAgB,UAAU,MAAc,UAA2C;CACjF,IAAI,UAAU,OAAO;CACrB,MAAM,MAAM,aAAa,IAAI;CAC7B,IAAI,WAAW,IAAI,GAAG,GAAG,OAAO;CAChC,IAAI,WAAW,IAAI,GAAG,GAAG,OAAO;CAChC,IAAI,QAAQ,OAAO,OAAO;CAC1B,IAAI,WAAW,IAAI,GAAG,GAAG,OAAO;CAChC,IAAI,QAAQ,QAAQ,OAAO;CAC3B,IAAI,UAAU,IAAI,GAAG,GAAG,OAAO;CAC/B,OAAO;AACT;AAEA,MAAa,yBAAyD;CACpE,OAAO;CACP,OAAO;CACP,KAAK;CACL,OAAO;CACP,MAAM;CACN,MAAM;AACR;;AAGA,eAAsB,cACpB,KACA,QACsB;CACtB,IAAI,OAAO,QAAQ,UAAU;EAC3B,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,OAAO,CAAC;EACvC,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,MAAM,iBAAiB,IAAI,OAAO,GAAG,IAAI,YAAY;EAEjE,OAAO,MAAM,IAAI,YAAY;CAC/B;CACA,IAAI,eAAe,aAAa,OAAO;CACvC,IAAI,eAAe,YAEjB,OAAO,IAAI,MAAM,EAAE;CAGrB,OAAO,MAAM,IAAI,YAAY;AAC/B;;AAGA,SAAgB,UACd,KACA,MACqC;CACrC,IAAI,OAAO,QAAQ,UACjB,OAAO;EAAE,KAAK;EAAK,cAAc,CAAC;CAAE;CAEtC,IAAI;CACJ,IAAI,eAAe,MACjB,OAAO;MACF,IAAI,eAAe,aACxB,OAAO,IAAI,KAAK,CAAC,GAAG,GAAG,EAAE,MAAM,QAAQ,2BAA2B,CAAC;MAC9D;EAEL,MAAM,OAAO,IAAI,WAAW,IAAI,UAAU;EAC1C,KAAK,IAAI,GAAG;EACZ,OAAO,IAAI,KAAK,CAAC,KAAK,MAAM,GAAG,EAAE,MAAM,QAAQ,2BAA2B,CAAC;CAC7E;CACA,MAAM,MAAM,IAAI,gBAAgB,IAAI;CACpC,OAAO;EAAE;EAAK,cAAc,IAAI,gBAAgB,GAAG;CAAE;AACvD;;;;;AAMA,SAAgB,SAAS,MAA0B;CACjD,MAAM,OAAmB,CAAC;CAC1B,IAAI,MAAgB,CAAC;CACrB,IAAI,QAAQ;CACZ,IAAI,WAAW;CACf,MAAM,MAAM,KAAK;CAEjB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK;EAC5B,MAAM,KAAK,KAAK;EAEhB,IAAI,UAAU;GACZ,IAAI,OAAO,MACT,IAAI,KAAK,IAAI,OAAO,MAAK;IACvB,SAAS;IACT;GACF,OACE,WAAW;QAGb,SAAS;GAEX;EACF;EAEA,IAAI,OAAO,MACT,WAAW;OACN,IAAI,OAAO,KAAK;GACrB,IAAI,KAAK,KAAK;GACd,QAAQ;EACV,OAAO,IAAI,OAAO,MAAM;GACtB,IAAI,KAAK,KAAK;GACd,KAAK,KAAK,GAAG;GACb,MAAM,CAAC;GACP,QAAQ;EACV,OAAO,IAAI,OAAO,MAAM,CAExB,OACE,SAAS;CAEb;CAGA,IAAI,MAAM,SAAS,KAAK,IAAI,SAAS,GAAG;EACtC,IAAI,KAAK,KAAK;EACd,KAAK,KAAK,GAAG;CACf;CACA,OAAO;AACT;AAEA,SAAgB,YAAY,OAAwB;CAClD,IAAI,UAAU,KAAA,KAAa,UAAU,QAAQ,OAAO,MAAM,KAAK,GAAG,OAAO;CACzE,IAAI,QAAQ,MAAM,OAAO,GAAG,MAAM;CAClC,MAAM,QAAQ;EAAC;EAAM;EAAM;EAAM;CAAI;CACrC,IAAI,IAAI,QAAQ;CAChB,IAAI,IAAI;CACR,OAAO,KAAK,QAAQ,IAAI,MAAM,SAAS,GAAG;EACxC,KAAK;EACL;CACF;CACA,OAAO,GAAG,EAAE,QAAQ,KAAK,KAAK,IAAI,CAAC,EAAE,GAAG,MAAM;AAChD;;AAGA,eAAsB,aAAa,MAAqC;CACtE,IAAI;CACJ,IAAI;CACJ,IAAI,OAAO,KAAK,QAAQ,UACtB,OAAO,KAAK;MACP;EACL,MAAM,MAAM,UAAU,KAAK,KAAK,KAAK,IAAI;EACzC,OAAO,IAAI;EACX,SAAS,IAAI;CACf;CACA,MAAM,IAAI,SAAS,cAAc,GAAG;CACpC,EAAE,OAAO;CACT,EAAE,WAAW,KAAK;CAClB,EAAE,MAAM;CACR,EAAE,MAAM,UAAU;CAClB,SAAS,KAAK,YAAY,CAAC;CAC3B,EAAE,MAAM;CACR,SAAS,KAAK,YAAY,CAAC;CAC3B,IAAI,QAAQ,WAAW,QAAQ,GAAI;AACrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"docx-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/docx-previewer.vue"],"sourcesContent":["<template>\n <u-scroll tag=\"div\" :class=\"cls.e('docx')\" v-bind=\"attrs\">\n <div ref=\"container\" :class=\"cls.e('docx-body')\" />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, useAttrs, useTemplateRef, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { UScroll } from '../../scroll'\n\ndefineOptions({ name: 'FileViewerDocxPreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst container = useTemplateRef<HTMLDivElement>('container')\nconst loading = ref(true)\n\nlet controller: AbortController | undefined\n\nasync function load() {\n controller?.abort()\n controller = new AbortController()\n const signal = controller.signal\n loading.value = true\n\n try {\n const [{ toArrayBuffer }, docx] = await Promise.all([\n import('../helper'),\n import('docx-preview')\n ])\n\n const buf = await toArrayBuffer(props.file.src, signal)\n if (signal.aborted) return\n const el = container.value\n if (!el) return\n el.innerHTML = ''\n\n await docx.renderAsync(buf, el, undefined, {\n className: 'u-file-viewer__docx-doc',\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n ignoreFonts: false,\n breakPages: true,\n experimental: false,\n useBase64URL: false,\n renderChanges: false,\n renderHeaders: true,\n renderFooters: true,\n renderFootnotes: true\n })\n } catch (err) {\n if ((err as { name?: string })?.name === 'AbortError') return\n emit('error', err)\n } finally {\n loading.value = false\n }\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n controller?.abort()\n if (container.value) container.value.innerHTML = ''\n})\n</script>\n"],"mappings":";;;;;;;;;;;EAgBA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,cAAa;EAC7B,MAAM,QAAQ,UAAS;EAEvB,MAAM,YAAY,eAA+B,YAAW;EAC5D,MAAM,UAAU,IAAI,KAAI;EAExB,IAAI;EAEJ,eAAe,OAAO;GACpB,YAAY,OAAM;GAClB,aAAa,IAAI,iBAAgB;GACjC,MAAM,SAAS,WAAW;GAC1B,QAAQ,QAAQ;GAEhB,IAAI;IACF,MAAM,CAAC,EAAE,iBAAiB,QAAQ,MAAM,QAAQ,IAAI,CAClD,OAAO,iBACP,OAAO,gBACR,CAAA;IAED,MAAM,MAAM,MAAM,cAAc,MAAM,KAAK,KAAK,OAAM;IACtD,IAAI,OAAO,SAAS;IACpB,MAAM,KAAK,UAAU;IACrB,IAAI,CAAC,IAAI;IACT,GAAG,YAAY;IAEf,MAAM,KAAK,YAAY,KAAK,IAAI,KAAA,GAAW;KACzC,WAAW;KACX,WAAW;KACX,aAAa;KACb,cAAc;KACd,aAAa;KACb,YAAY;KACZ,cAAc;KACd,cAAc;KACd,eAAe;KACf,eAAe;KACf,eAAe;KACf,iBAAiB;KAClB,CAAA;YACM,KAAK;IACZ,IAAK,KAA2B,SAAS,cAAc;IACvD,KAAK,SAAS,IAAG;aACT;IACR,QAAQ,QAAQ;;;EAIpB,YACQ,MAAM,YACN,MAAK,EACX,EAAE,WAAW,MACf,CAAA;EAEA,sBAAsB;GACpB,YAAY,OAAM;GAClB,IAAI,UAAU,OAAO,UAAU,MAAM,YAAY;IAClD;;uBA5EC,YAGW,MAAA,YAAA,EAHX,WAGW;IAHD,KAAI;IAAO,OAAO,MAAA,IAAA,CAAI,EAAC,OAAA;MAAkB,MAAA,MAAK,CAAA,EAAA;2BACH,CAAnD,mBAAmD,OAAA;cAA1C;KAAJ,KAAI;KAAa,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC,YAAA,CAAA;iBACvB,QAAA,SAAA,WAAA,EAAX,mBAAwD,OAAA;;KAAnC,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC,UAAA,CAAA;OAAa,QAAI,EAAA,IAAA,mBAAA,QAAA,KAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"docx-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/docx-previewer.vue"],"sourcesContent":["<template>\n <u-scroll tag=\"div\" :class=\"cls.e('docx')\" v-bind=\"attrs\">\n <div ref=\"container\" :class=\"cls.e('docx-body')\" />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, useAttrs, useTemplateRef, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { UScroll } from '../../scroll'\n\ndefineOptions({ name: 'FileViewerDocxPreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst container = useTemplateRef<HTMLDivElement>('container')\nconst loading = ref(true)\n\nlet controller: AbortController | undefined\n\nasync function load() {\n controller?.abort()\n controller = new AbortController()\n const signal = controller.signal\n loading.value = true\n\n try {\n const [{ toArrayBuffer }, docx] = await Promise.all([\n import('../helper'),\n import('docx-preview')\n ])\n\n const buf = await toArrayBuffer(props.file.src, signal)\n if (signal.aborted) return\n const el = container.value\n if (!el) return\n el.innerHTML = ''\n\n await docx.renderAsync(buf, el, undefined, {\n className: 'u-file-viewer__docx-doc',\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n ignoreFonts: false,\n breakPages: true,\n experimental: false,\n useBase64URL: false,\n renderChanges: false,\n renderHeaders: true,\n renderFooters: true,\n renderFootnotes: true\n })\n } catch (err) {\n if ((err as { name?: string })?.name === 'AbortError') return\n emit('error', err)\n } finally {\n loading.value = false\n }\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n controller?.abort()\n if (container.value) container.value.innerHTML = ''\n})\n</script>\n"],"mappings":";;;;;;;;;;;EAgBA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAC7B,MAAM,QAAQ,SAAS;EAEvB,MAAM,YAAY,eAA+B,WAAW;EAC5D,MAAM,UAAU,IAAI,IAAI;EAExB,IAAI;EAEJ,eAAe,OAAO;GACpB,YAAY,MAAM;GAClB,aAAa,IAAI,gBAAgB;GACjC,MAAM,SAAS,WAAW;GAC1B,QAAQ,QAAQ;GAEhB,IAAI;IACF,MAAM,CAAC,EAAE,iBAAiB,QAAQ,MAAM,QAAQ,IAAI,CAClD,OAAO,iBACP,OAAO,eACT,CAAC;IAED,MAAM,MAAM,MAAM,cAAc,MAAM,KAAK,KAAK,MAAM;IACtD,IAAI,OAAO,SAAS;IACpB,MAAM,KAAK,UAAU;IACrB,IAAI,CAAC,IAAI;IACT,GAAG,YAAY;IAEf,MAAM,KAAK,YAAY,KAAK,IAAI,KAAA,GAAW;KACzC,WAAW;KACX,WAAW;KACX,aAAa;KACb,cAAc;KACd,aAAa;KACb,YAAY;KACZ,cAAc;KACd,cAAc;KACd,eAAe;KACf,eAAe;KACf,eAAe;KACf,iBAAiB;IACnB,CAAC;GACH,SAAS,KAAK;IACZ,IAAK,KAA2B,SAAS,cAAc;IACvD,KAAK,SAAS,GAAG;GACnB,UAAU;IACR,QAAQ,QAAQ;GAClB;EACF;EAEA,YACQ,MAAM,YACN,KAAK,GACX,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,YAAY,MAAM;GAClB,IAAI,UAAU,OAAO,UAAU,MAAM,YAAY;EACnD,CAAC;;uBA5EC,YAGW,MAAA,WAAA,GAHX,WAGW;IAHD,KAAI;IAAO,OAAO,MAAA,GAAA,EAAI,EAAC,MAAA;MAAkB,MAAA,KAAA,CAAK,GAAA;2BACH,CAAnD,mBAAmD,OAAA;cAA1C;KAAJ,KAAI;KAAa,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,WAAA,CAAA;iBACvB,QAAA,SAAA,UAAA,GAAX,mBAAwD,OAAA;;KAAnC,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,SAAA,CAAA;OAAa,QAAI,CAAA,KAAA,mBAAA,QAAA,IAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"image-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/image-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('image')\" v-bind=\"attrs\">\n <img\n v-if=\"url\"\n :src=\"url\"\n :alt=\"file.name\"\n draggable=\"false\"\n @dragstart.prevent\n @load=\"loading = false\"\n @error=\"onImgError\"\n />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n <div v-if=\"failed\" :class=\"cls.e('loading')\">图片加载失败</div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, shallowRef, useAttrs, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { toBlobUrl } from '../helper'\n\ndefineOptions({ name: 'FileViewerImagePreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst url = shallowRef<string>('')\nconst loading = ref(true)\nconst failed = ref(false)\n\nlet revoke: (() => void) | undefined\n\nfunction load() {\n loading.value = true\n failed.value = false\n revoke?.()\n const r = toBlobUrl(props.file.src, props.file.mime)\n url.value = r.url\n revoke = r.revoke\n}\n\nfunction onImgError(e: Event) {\n loading.value = false\n failed.value = true\n emit('error', e)\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n revoke?.()\n url.value = ''\n})\n</script>\n"],"mappings":";;;;;;;;;;;;EAyBA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,cAAa;EAC7B,MAAM,QAAQ,UAAS;EAEvB,MAAM,MAAM,WAAmB,GAAE;EACjC,MAAM,UAAU,IAAI,KAAI;EACxB,MAAM,SAAS,IAAI,MAAK;EAExB,IAAI;EAEJ,SAAS,OAAO;GACd,QAAQ,QAAQ;GAChB,OAAO,QAAQ;GACf,UAAS;GACT,MAAM,IAAI,UAAU,MAAM,KAAK,KAAK,MAAM,KAAK,KAAI;GACnD,IAAI,QAAQ,EAAE;GACd,SAAS,EAAE;;EAGb,SAAS,WAAW,GAAU;GAC5B,QAAQ,QAAQ;GAChB,OAAO,QAAQ;GACf,KAAK,SAAS,EAAC;;EAGjB,YACQ,MAAM,YACN,MAAK,EACX,EAAE,WAAW,MACf,CAAA;EAEA,sBAAsB;GACpB,UAAS;GACT,IAAI,QAAQ;IACb;;uBA7DC,mBAYM,OAZN,WAYM,EAZA,OAAO,MAAA,IAAA,CAAI,EAAC,QAAA,EAAA,EAAmB,MAAA,MAAK,CAAA,EAAA;IAEhC,IAAA,SAAA,WAAA,EADR,mBAQE,OAAA;;KANC,KAAK,IAAA;KACL,KAAK,QAAA,KAAK;KACX,WAAU;KACT,aAAS,OAAA,OAAA,OAAA,KAAA,oBAAV,IAAkB,CAAA,UAAA,CAAA;KACjB,QAAI,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,QAAO;KACb,SAAO;;IAEC,QAAA,SAAA,WAAA,EAAX,mBAAwD,OAAA;;KAAnC,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC,UAAA,CAAA;OAAa,QAAI,EAAA,IAAA,mBAAA,QAAA,KAAA;IACvC,OAAA,SAAA,WAAA,EAAX,mBAAyD,OAAA;;KAArC,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC,UAAA,CAAA;OAAa,UAAM,EAAA,IAAA,mBAAA,QAAA,KAAA"}
1
+ {"version":3,"file":"image-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/image-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('image')\" v-bind=\"attrs\">\n <img\n v-if=\"url\"\n :src=\"url\"\n :alt=\"file.name\"\n draggable=\"false\"\n @dragstart.prevent\n @load=\"loading = false\"\n @error=\"onImgError\"\n />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n <div v-if=\"failed\" :class=\"cls.e('loading')\">图片加载失败</div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, shallowRef, useAttrs, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { toBlobUrl } from '../helper'\n\ndefineOptions({ name: 'FileViewerImagePreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst url = shallowRef<string>('')\nconst loading = ref(true)\nconst failed = ref(false)\n\nlet revoke: (() => void) | undefined\n\nfunction load() {\n loading.value = true\n failed.value = false\n revoke?.()\n const r = toBlobUrl(props.file.src, props.file.mime)\n url.value = r.url\n revoke = r.revoke\n}\n\nfunction onImgError(e: Event) {\n loading.value = false\n failed.value = true\n emit('error', e)\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n revoke?.()\n url.value = ''\n})\n</script>\n"],"mappings":";;;;;;;;;;;;EAyBA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAC7B,MAAM,QAAQ,SAAS;EAEvB,MAAM,MAAM,WAAmB,EAAE;EACjC,MAAM,UAAU,IAAI,IAAI;EACxB,MAAM,SAAS,IAAI,KAAK;EAExB,IAAI;EAEJ,SAAS,OAAO;GACd,QAAQ,QAAQ;GAChB,OAAO,QAAQ;GACf,SAAS;GACT,MAAM,IAAI,UAAU,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI;GACnD,IAAI,QAAQ,EAAE;GACd,SAAS,EAAE;EACb;EAEA,SAAS,WAAW,GAAU;GAC5B,QAAQ,QAAQ;GAChB,OAAO,QAAQ;GACf,KAAK,SAAS,CAAC;EACjB;EAEA,YACQ,MAAM,YACN,KAAK,GACX,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,SAAS;GACT,IAAI,QAAQ;EACd,CAAC;;uBA7DC,mBAYM,OAZN,WAYM,EAZA,OAAO,MAAA,GAAA,EAAI,EAAC,OAAA,EAAA,GAAmB,MAAA,KAAA,CAAK,GAAA;IAEhC,IAAA,SAAA,UAAA,GADR,mBAQE,OAAA;;KANC,KAAK,IAAA;KACL,KAAK,QAAA,KAAK;KACX,WAAU;KACT,aAAS,OAAA,OAAA,OAAA,KAAA,oBAAV,CAAA,GAAkB,CAAA,SAAA,CAAA;KACjB,QAAI,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,QAAO;KACb,SAAO;;IAEC,QAAA,SAAA,UAAA,GAAX,mBAAwD,OAAA;;KAAnC,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,SAAA,CAAA;OAAa,QAAI,CAAA,KAAA,mBAAA,QAAA,IAAA;IACvC,OAAA,SAAA,UAAA,GAAX,mBAAyD,OAAA;;KAArC,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,SAAA,CAAA;OAAa,UAAM,CAAA,KAAA,mBAAA,QAAA,IAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('pdf')\" v-bind=\"attrs\">\n <div v-if=\"!engine || isLoading\" :class=\"cls.e('loading')\">正在加载 PDF 引擎…</div>\n <EmbedPDF v-else-if=\"pdfUrl\" :engine=\"engine\" :plugins=\"plugins\" v-slot=\"{ activeDocumentId }\">\n <PdfZoomBridge\n v-if=\"activeDocumentId\"\n :document-id=\"activeDocumentId\"\n @zoom-change=\"onZoomChange\"\n />\n <DocumentContent\n v-if=\"activeDocumentId\"\n :document-id=\"activeDocumentId\"\n v-slot=\"{ isLoaded }\"\n >\n <Viewport v-if=\"isLoaded\" :document-id=\"activeDocumentId\" :class=\"cls.e('pdf-viewport')\">\n <PdfViewportScroll>\n <ZoomGestureWrapper :document-id=\"activeDocumentId\" :enable-wheel=\"true\">\n <Scroller :document-id=\"activeDocumentId\">\n <template #default=\"{ page }\">\n <div\n :class=\"cls.e('pdf-page')\"\n :style=\"{ width: page.width + 'px', height: page.height + 'px' }\"\n >\n <RenderLayer :document-id=\"activeDocumentId\" :page-index=\"page.pageIndex\" />\n </div>\n </template>\n </Scroller>\n </ZoomGestureWrapper>\n </PdfViewportScroll>\n </Viewport>\n </DocumentContent>\n </EmbedPDF>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { createPluginRegistration } from '@embedpdf/core'\nimport { EmbedPDF } from '@embedpdf/core/vue'\nimport { usePdfiumEngine } from '@embedpdf/engines/vue'\nimport {\n DocumentContent,\n DocumentManagerPluginPackage\n} from '@embedpdf/plugin-document-manager/vue'\nimport { RenderLayer, RenderPluginPackage } from '@embedpdf/plugin-render/vue'\nimport { ScrollPluginPackage, Scroller } from '@embedpdf/plugin-scroll/vue'\nimport { ViewportPluginPackage, Viewport } from '@embedpdf/plugin-viewport/vue'\nimport {\n ZoomGestureWrapper,\n ZoomMode,\n ZoomPluginPackage,\n type ZoomScope\n} from '@embedpdf/plugin-zoom/vue'\nimport { bem } from '@veltra/utils'\nimport { computed, onBeforeUnmount, shallowRef, useAttrs, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { toBlobUrl } from '../helper'\nimport PdfViewportScroll from './pdf-viewport-scroll.vue'\nimport PdfZoomBridge from './pdf-zoom-bridge.vue'\n\ndefineOptions({ name: 'FileViewerPdfPreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{\n (e: 'error', err: unknown): void\n (e: 'zoom-change', level: number): void\n}>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst { engine, isLoading, error } = usePdfiumEngine()\n\nconst pdfUrl = shallowRef<string>('')\nlet revoke: (() => void) | undefined\n\n/** 当前文档的 zoom API(由 PdfZoomBridge 注入) */\nlet zoomScope: ZoomScope | null = null\n\nfunction load() {\n revoke?.()\n const r = toBlobUrl(props.file.src, props.file.mime ?? 'application/pdf')\n pdfUrl.value = r.url\n revoke = r.revoke\n}\n\nconst plugins = computed(() => {\n if (!pdfUrl.value) return []\n return [\n createPluginRegistration(DocumentManagerPluginPackage, {\n initialDocuments: [{ url: pdfUrl.value }]\n }),\n createPluginRegistration(ViewportPluginPackage, { viewportGap: 0 }),\n createPluginRegistration(ScrollPluginPackage, { defaultBufferSize: 2 }),\n createPluginRegistration(RenderPluginPackage),\n createPluginRegistration(ZoomPluginPackage, {\n defaultZoomLevel: ZoomMode.FitPage,\n minZoom: 0.5,\n maxZoom: 3,\n zoomStep: 0.1\n })\n ]\n})\n\nfunction onZoomChange(payload: { level: number; scope: ZoomScope | null }) {\n zoomScope = payload.scope\n emit('zoom-change', payload.level)\n}\n\nfunction zoomIn() {\n zoomScope?.zoomIn()\n}\n\nfunction zoomOut() {\n zoomScope?.zoomOut()\n}\n\nfunction resetZoom() {\n zoomScope?.requestZoom(ZoomMode.FitPage)\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nwatch(error, (err) => {\n if (err) emit('error', err)\n})\n\nonBeforeUnmount(() => {\n revoke?.()\n pdfUrl.value = ''\n zoomScope = null\n})\n\ndefineExpose({ zoomIn, zoomOut, resetZoom })\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EA8DA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAKb,MAAM,MAAM,IAAI,cAAa;EAC7B,MAAM,QAAQ,UAAS;EAEvB,MAAM,EAAE,QAAQ,WAAW,UAAU,iBAAgB;EAErD,MAAM,SAAS,WAAmB,GAAE;EACpC,IAAI;;EAGJ,IAAI,YAA8B;EAElC,SAAS,OAAO;GACd,UAAS;GACT,MAAM,IAAI,UAAU,MAAM,KAAK,KAAK,MAAM,KAAK,QAAQ,kBAAiB;GACxE,OAAO,QAAQ,EAAE;GACjB,SAAS,EAAE;;EAGb,MAAM,UAAU,eAAe;GAC7B,IAAI,CAAC,OAAO,OAAO,OAAO,EAAC;GAC3B,OAAO;IACL,yBAAyB,8BAA8B,EACrD,kBAAkB,CAAC,EAAE,KAAK,OAAO,OAAO,CAAA,EACzC,CAAA;IACD,yBAAyB,uBAAuB,EAAE,aAAa,GAAG,CAAA;IAClE,yBAAyB,qBAAqB,EAAE,mBAAmB,GAAG,CAAA;IACtE,yBAAyB,oBAAmB;IAC5C,yBAAyB,mBAAmB;KAC1C,kBAAkB,SAAS;KAC3B,SAAS;KACT,SAAS;KACT,UAAU;KACX,CAAA;IACH;IACD;EAED,SAAS,aAAa,SAAqD;GACzE,YAAY,QAAQ;GACpB,KAAK,eAAe,QAAQ,MAAK;;EAGnC,SAAS,SAAS;GAChB,WAAW,QAAO;;EAGpB,SAAS,UAAU;GACjB,WAAW,SAAQ;;EAGrB,SAAS,YAAY;GACnB,WAAW,YAAY,SAAS,QAAO;;EAGzC,YACQ,MAAM,YACN,MAAK,EACX,EAAE,WAAW,MACf,CAAA;EAEA,MAAM,QAAQ,QAAQ;GACpB,IAAI,KAAK,KAAK,SAAS,IAAG;IAC3B;EAED,sBAAsB;GACpB,UAAS;GACT,OAAO,QAAQ;GACf,YAAY;IACb;EAED,SAAa;GAAE;GAAQ;GAAS;GAAW,CAAA;;uBAzIzC,mBA+BM,OA/BN,WA+BM,EA/BA,OAAO,MAAA,IAAA,CAAI,EAAC,MAAA,EAAA,EAAiB,MAAA,MAAK,CAAA,EAAA,CAAA,CAC1B,MAAA,OAAA,IAAU,MAAA,UAAA,IAAA,WAAA,EAAtB,mBAA6E,OAAA;;IAA3C,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC,UAAA,CAAA;MAAa,gBAAY,EAAA,IAClD,OAAA,SAAA,WAAA,EAArB,YA4BW,MAAA,SAAA,EAAA;;IA5BmB,QAAQ,MAAA,OAAA;IAAS,SAAS,QAAA;;sBAKpD,EALuE,uBAAgB,CAEjF,oBAAA,WAAA,EADR,YAIE,aAAA;;KAFC,eAAa;KACA;sEAGR,oBAAA,WAAA,EADR,YAqBkB,MAAA,gBAAA,EAAA;;KAnBf,eAAa;;uBAkBH,EAjBD,eAAQ,CAEF,YAAA,WAAA,EAAhB,YAeW,MAAA,SAAA,EAAA;;MAfgB,eAAa;MAAmB,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC,eAAA,CAAA;;6BAcjD,CAbpB,YAaoB,aAAA,MAAA;8BADG,CAXrB,YAWqB,MAAA,mBAAA,EAAA;QAXA,eAAa;QAAmB,gBAAc;;+BAUtD,CATX,YASW,MAAA,SAAA,EAAA,EATA,eAAa,kBAAgB,EAAA;SAC3B,SAAO,SAMV,EANc,WAAI,CACxB,mBAKM,OAAA;UAJH,OAAK,eAAE,MAAA,IAAA,CAAI,EAAC,WAAA,CAAA;UACZ,OAAK,eAAA;WAAA,OAAW,KAAK,QAAK;WAAA,QAAiB,KAAK,SAAM;WAAA,CAAA;aAEvD,YAA4E,MAAA,YAAA,EAAA;UAA9D,eAAa;UAAmB,cAAY,KAAK"}
1
+ {"version":3,"file":"pdf-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('pdf')\" v-bind=\"attrs\">\n <div v-if=\"!engine || isLoading\" :class=\"cls.e('loading')\">正在加载 PDF 引擎…</div>\n <EmbedPDF v-else-if=\"pdfUrl\" :engine=\"engine\" :plugins=\"plugins\" v-slot=\"{ activeDocumentId }\">\n <PdfZoomBridge\n v-if=\"activeDocumentId\"\n :document-id=\"activeDocumentId\"\n @zoom-change=\"onZoomChange\"\n />\n <DocumentContent\n v-if=\"activeDocumentId\"\n :document-id=\"activeDocumentId\"\n v-slot=\"{ isLoaded }\"\n >\n <Viewport v-if=\"isLoaded\" :document-id=\"activeDocumentId\" :class=\"cls.e('pdf-viewport')\">\n <PdfViewportScroll>\n <ZoomGestureWrapper :document-id=\"activeDocumentId\" :enable-wheel=\"true\">\n <Scroller :document-id=\"activeDocumentId\">\n <template #default=\"{ page }\">\n <div\n :class=\"cls.e('pdf-page')\"\n :style=\"{ width: page.width + 'px', height: page.height + 'px' }\"\n >\n <RenderLayer :document-id=\"activeDocumentId\" :page-index=\"page.pageIndex\" />\n </div>\n </template>\n </Scroller>\n </ZoomGestureWrapper>\n </PdfViewportScroll>\n </Viewport>\n </DocumentContent>\n </EmbedPDF>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { createPluginRegistration } from '@embedpdf/core'\nimport { EmbedPDF } from '@embedpdf/core/vue'\nimport { usePdfiumEngine } from '@embedpdf/engines/vue'\nimport {\n DocumentContent,\n DocumentManagerPluginPackage\n} from '@embedpdf/plugin-document-manager/vue'\nimport { RenderLayer, RenderPluginPackage } from '@embedpdf/plugin-render/vue'\nimport { ScrollPluginPackage, Scroller } from '@embedpdf/plugin-scroll/vue'\nimport { ViewportPluginPackage, Viewport } from '@embedpdf/plugin-viewport/vue'\nimport {\n ZoomGestureWrapper,\n ZoomMode,\n ZoomPluginPackage,\n type ZoomScope\n} from '@embedpdf/plugin-zoom/vue'\nimport { bem } from '@veltra/utils'\nimport { computed, onBeforeUnmount, shallowRef, useAttrs, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { toBlobUrl } from '../helper'\nimport PdfViewportScroll from './pdf-viewport-scroll.vue'\nimport PdfZoomBridge from './pdf-zoom-bridge.vue'\n\ndefineOptions({ name: 'FileViewerPdfPreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{\n (e: 'error', err: unknown): void\n (e: 'zoom-change', level: number): void\n}>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst { engine, isLoading, error } = usePdfiumEngine()\n\nconst pdfUrl = shallowRef<string>('')\nlet revoke: (() => void) | undefined\n\n/** 当前文档的 zoom API(由 PdfZoomBridge 注入) */\nlet zoomScope: ZoomScope | null = null\n\nfunction load() {\n revoke?.()\n const r = toBlobUrl(props.file.src, props.file.mime ?? 'application/pdf')\n pdfUrl.value = r.url\n revoke = r.revoke\n}\n\nconst plugins = computed(() => {\n if (!pdfUrl.value) return []\n return [\n createPluginRegistration(DocumentManagerPluginPackage, {\n initialDocuments: [{ url: pdfUrl.value }]\n }),\n createPluginRegistration(ViewportPluginPackage, { viewportGap: 0 }),\n createPluginRegistration(ScrollPluginPackage, { defaultBufferSize: 2 }),\n createPluginRegistration(RenderPluginPackage),\n createPluginRegistration(ZoomPluginPackage, {\n defaultZoomLevel: ZoomMode.FitPage,\n minZoom: 0.5,\n maxZoom: 3,\n zoomStep: 0.1\n })\n ]\n})\n\nfunction onZoomChange(payload: { level: number; scope: ZoomScope | null }) {\n zoomScope = payload.scope\n emit('zoom-change', payload.level)\n}\n\nfunction zoomIn() {\n zoomScope?.zoomIn()\n}\n\nfunction zoomOut() {\n zoomScope?.zoomOut()\n}\n\nfunction resetZoom() {\n zoomScope?.requestZoom(ZoomMode.FitPage)\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nwatch(error, (err) => {\n if (err) emit('error', err)\n})\n\nonBeforeUnmount(() => {\n revoke?.()\n pdfUrl.value = ''\n zoomScope = null\n})\n\ndefineExpose({ zoomIn, zoomOut, resetZoom })\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EA8DA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAKb,MAAM,MAAM,IAAI,aAAa;EAC7B,MAAM,QAAQ,SAAS;EAEvB,MAAM,EAAE,QAAQ,WAAW,UAAU,gBAAgB;EAErD,MAAM,SAAS,WAAmB,EAAE;EACpC,IAAI;;EAGJ,IAAI,YAA8B;EAElC,SAAS,OAAO;GACd,SAAS;GACT,MAAM,IAAI,UAAU,MAAM,KAAK,KAAK,MAAM,KAAK,QAAQ,iBAAiB;GACxE,OAAO,QAAQ,EAAE;GACjB,SAAS,EAAE;EACb;EAEA,MAAM,UAAU,eAAe;GAC7B,IAAI,CAAC,OAAO,OAAO,OAAO,CAAC;GAC3B,OAAO;IACL,yBAAyB,8BAA8B,EACrD,kBAAkB,CAAC,EAAE,KAAK,OAAO,MAAM,CAAC,EAC1C,CAAC;IACD,yBAAyB,uBAAuB,EAAE,aAAa,EAAE,CAAC;IAClE,yBAAyB,qBAAqB,EAAE,mBAAmB,EAAE,CAAC;IACtE,yBAAyB,mBAAmB;IAC5C,yBAAyB,mBAAmB;KAC1C,kBAAkB,SAAS;KAC3B,SAAS;KACT,SAAS;KACT,UAAU;IACZ,CAAC;GACH;EACF,CAAC;EAED,SAAS,aAAa,SAAqD;GACzE,YAAY,QAAQ;GACpB,KAAK,eAAe,QAAQ,KAAK;EACnC;EAEA,SAAS,SAAS;GAChB,WAAW,OAAO;EACpB;EAEA,SAAS,UAAU;GACjB,WAAW,QAAQ;EACrB;EAEA,SAAS,YAAY;GACnB,WAAW,YAAY,SAAS,OAAO;EACzC;EAEA,YACQ,MAAM,YACN,KAAK,GACX,EAAE,WAAW,KAAK,CACpB;EAEA,MAAM,QAAQ,QAAQ;GACpB,IAAI,KAAK,KAAK,SAAS,GAAG;EAC5B,CAAC;EAED,sBAAsB;GACpB,SAAS;GACT,OAAO,QAAQ;GACf,YAAY;EACd,CAAC;EAED,SAAa;GAAE;GAAQ;GAAS;EAAU,CAAC;;uBAzIzC,mBA+BM,OA/BN,WA+BM,EA/BA,OAAO,MAAA,GAAA,EAAI,EAAC,KAAA,EAAA,GAAiB,MAAA,KAAA,CAAK,GAAA,CAAA,CAC1B,MAAA,MAAA,KAAU,MAAA,SAAA,KAAA,UAAA,GAAtB,mBAA6E,OAAA;;IAA3C,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,SAAA,CAAA;MAAa,gBAAY,CAAA,KAClD,OAAA,SAAA,UAAA,GAArB,YA4BW,MAAA,QAAA,GAAA;;IA5BmB,QAAQ,MAAA,MAAA;IAAS,SAAS,QAAA;;sBAKpD,EALuE,uBAAgB,CAEjF,oBAAA,UAAA,GADR,YAIE,aAAA;;KAFC,eAAa;KACA;sEAGR,oBAAA,UAAA,GADR,YAqBkB,MAAA,eAAA,GAAA;;KAnBf,eAAa;;uBAkBH,EAjBD,eAAQ,CAEF,YAAA,UAAA,GAAhB,YAeW,MAAA,QAAA,GAAA;;MAfgB,eAAa;MAAmB,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,cAAA,CAAA;;6BAcjD,CAbpB,YAaoB,aAAA,MAAA;8BADG,CAXrB,YAWqB,MAAA,kBAAA,GAAA;QAXA,eAAa;QAAmB,gBAAc;;+BAUtD,CATX,YASW,MAAA,QAAA,GAAA,EATA,eAAa,iBAAgB,GAAA;SAC3B,SAAO,SAMV,EANc,WAAI,CACxB,mBAKM,OAAA;UAJH,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,UAAA,CAAA;UACZ,OAAK,eAAA;WAAA,OAAW,KAAK,QAAK;WAAA,QAAiB,KAAK,SAAM;UAAA,CAAA;aAEvD,YAA4E,MAAA,WAAA,GAAA;UAA9D,eAAa;UAAmB,cAAY,KAAK"}
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-viewport-scroll.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-viewport-scroll.vue"],"sourcesContent":["<template>\n <slot />\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, inject, onBeforeUnmount, type Ref, watch } from 'vue'\n\ndefineOptions({ name: 'FileViewerPdfViewportScroll' })\n\n/** EmbedPDF Viewport 向子树注入的滚动容器 ref */\nconst VIEWPORT_ELEMENT_KEY = 'viewport-element'\n\nconst viewportRef = inject<Ref<HTMLDivElement | null>>(VIEWPORT_ELEMENT_KEY)\nconst viewportEl = computed(() => viewportRef?.value ?? null)\n\nlet panState:\n | { pointerId: number; startX: number; startY: number; scrollLeft: number; scrollTop: number }\n | undefined\n\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false\n return !!target.closest(\n 'button, a, input, textarea, select, video, [contenteditable=\"true\"], .u-scroll__bar-x, .u-scroll__bar-y'\n )\n}\n\nfunction handlePointerDown(e: PointerEvent) {\n if (e.button !== 0 || isInteractiveTarget(e.target)) return\n\n const el = viewportEl.value\n if (!el) return\n\n panState = {\n pointerId: e.pointerId,\n startX: e.clientX,\n startY: e.clientY,\n scrollLeft: el.scrollLeft,\n scrollTop: el.scrollTop\n }\n el.classList.add('is-panning')\n el.setPointerCapture(e.pointerId)\n e.preventDefault()\n}\n\nfunction handlePointerMove(e: PointerEvent) {\n if (!panState || panState.pointerId !== e.pointerId) return\n\n const el = viewportEl.value\n if (!el) return\n\n el.scrollLeft = panState.scrollLeft - (e.clientX - panState.startX)\n el.scrollTop = panState.scrollTop - (e.clientY - panState.startY)\n}\n\nfunction endPan(e: PointerEvent) {\n if (!panState || panState.pointerId !== e.pointerId) return\n\n const el = viewportEl.value\n if (el?.hasPointerCapture(e.pointerId)) {\n el.releasePointerCapture(e.pointerId)\n }\n el?.classList.remove('is-panning')\n panState = undefined\n}\n\nlet detachPan: (() => void) | undefined\n\nwatch(\n viewportEl,\n (el, _, onCleanup) => {\n detachPan?.()\n detachPan = undefined\n if (!el) return\n\n el.addEventListener('pointerdown', handlePointerDown, { capture: true })\n el.addEventListener('pointermove', handlePointerMove, { capture: true })\n el.addEventListener('pointerup', endPan, { capture: true })\n el.addEventListener('pointercancel', endPan, { capture: true })\n\n detachPan = () => {\n el.removeEventListener('pointerdown', handlePointerDown, { capture: true })\n el.removeEventListener('pointermove', handlePointerMove, { capture: true })\n el.removeEventListener('pointerup', endPan, { capture: true })\n el.removeEventListener('pointercancel', endPan, { capture: true })\n el.classList.remove('is-panning')\n panState = undefined\n }\n\n onCleanup(() => {\n detachPan?.()\n detachPan = undefined\n })\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n detachPan?.()\n detachPan = undefined\n})\n</script>\n"],"mappings":";;AAUA,MAAM,uBAAuB;;;;;;EAE7B,MAAM,cAAc,OAAmC,qBAAoB;EAC3E,MAAM,aAAa,eAAe,aAAa,SAAS,KAAI;EAE5D,IAAI;EAIJ,SAAS,oBAAoB,QAAqC;GAChE,IAAI,EAAE,kBAAkB,cAAc,OAAO;GAC7C,OAAO,CAAC,CAAC,OAAO,QACd,4GACF;;EAGF,SAAS,kBAAkB,GAAiB;GAC1C,IAAI,EAAE,WAAW,KAAK,oBAAoB,EAAE,OAAM,EAAG;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,CAAC,IAAI;GAET,WAAW;IACT,WAAW,EAAE;IACb,QAAQ,EAAE;IACV,QAAQ,EAAE;IACV,YAAY,GAAG;IACf,WAAW,GAAG;IAChB;GACA,GAAG,UAAU,IAAI,aAAY;GAC7B,GAAG,kBAAkB,EAAE,UAAS;GAChC,EAAE,gBAAe;;EAGnB,SAAS,kBAAkB,GAAiB;GAC1C,IAAI,CAAC,YAAY,SAAS,cAAc,EAAE,WAAW;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,CAAC,IAAI;GAET,GAAG,aAAa,SAAS,cAAc,EAAE,UAAU,SAAS;GAC5D,GAAG,YAAY,SAAS,aAAa,EAAE,UAAU,SAAS;;EAG5D,SAAS,OAAO,GAAiB;GAC/B,IAAI,CAAC,YAAY,SAAS,cAAc,EAAE,WAAW;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,IAAI,kBAAkB,EAAE,UAAS,EACnC,GAAG,sBAAsB,EAAE,UAAS;GAEtC,IAAI,UAAU,OAAO,aAAY;GACjC,WAAW,KAAA;;EAGb,IAAI;EAEJ,MACE,aACC,IAAI,GAAG,cAAc;GACpB,aAAY;GACZ,YAAY,KAAA;GACZ,IAAI,CAAC,IAAI;GAET,GAAG,iBAAiB,eAAe,mBAAmB,EAAE,SAAS,MAAM,CAAA;GACvE,GAAG,iBAAiB,eAAe,mBAAmB,EAAE,SAAS,MAAM,CAAA;GACvE,GAAG,iBAAiB,aAAa,QAAQ,EAAE,SAAS,MAAM,CAAA;GAC1D,GAAG,iBAAiB,iBAAiB,QAAQ,EAAE,SAAS,MAAM,CAAA;GAE9D,kBAAkB;IAChB,GAAG,oBAAoB,eAAe,mBAAmB,EAAE,SAAS,MAAM,CAAA;IAC1E,GAAG,oBAAoB,eAAe,mBAAmB,EAAE,SAAS,MAAM,CAAA;IAC1E,GAAG,oBAAoB,aAAa,QAAQ,EAAE,SAAS,MAAM,CAAA;IAC7D,GAAG,oBAAoB,iBAAiB,QAAQ,EAAE,SAAS,MAAM,CAAA;IACjE,GAAG,UAAU,OAAO,aAAY;IAChC,WAAW,KAAA;;GAGb,gBAAgB;IACd,aAAY;IACZ,YAAY,KAAA;KACb;KAEH,EAAE,WAAW,MACf,CAAA;EAEA,sBAAsB;GACpB,aAAY;GACZ,YAAY,KAAA;IACb;;UAlGC,WAAQ,KAAA,QAAA,UAAA"}
1
+ {"version":3,"file":"pdf-viewport-scroll.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-viewport-scroll.vue"],"sourcesContent":["<template>\n <slot />\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, inject, onBeforeUnmount, type Ref, watch } from 'vue'\n\ndefineOptions({ name: 'FileViewerPdfViewportScroll' })\n\n/** EmbedPDF Viewport 向子树注入的滚动容器 ref */\nconst VIEWPORT_ELEMENT_KEY = 'viewport-element'\n\nconst viewportRef = inject<Ref<HTMLDivElement | null>>(VIEWPORT_ELEMENT_KEY)\nconst viewportEl = computed(() => viewportRef?.value ?? null)\n\nlet panState:\n | { pointerId: number; startX: number; startY: number; scrollLeft: number; scrollTop: number }\n | undefined\n\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false\n return !!target.closest(\n 'button, a, input, textarea, select, video, [contenteditable=\"true\"], .u-scroll__bar-x, .u-scroll__bar-y'\n )\n}\n\nfunction handlePointerDown(e: PointerEvent) {\n if (e.button !== 0 || isInteractiveTarget(e.target)) return\n\n const el = viewportEl.value\n if (!el) return\n\n panState = {\n pointerId: e.pointerId,\n startX: e.clientX,\n startY: e.clientY,\n scrollLeft: el.scrollLeft,\n scrollTop: el.scrollTop\n }\n el.classList.add('is-panning')\n el.setPointerCapture(e.pointerId)\n e.preventDefault()\n}\n\nfunction handlePointerMove(e: PointerEvent) {\n if (!panState || panState.pointerId !== e.pointerId) return\n\n const el = viewportEl.value\n if (!el) return\n\n el.scrollLeft = panState.scrollLeft - (e.clientX - panState.startX)\n el.scrollTop = panState.scrollTop - (e.clientY - panState.startY)\n}\n\nfunction endPan(e: PointerEvent) {\n if (!panState || panState.pointerId !== e.pointerId) return\n\n const el = viewportEl.value\n if (el?.hasPointerCapture(e.pointerId)) {\n el.releasePointerCapture(e.pointerId)\n }\n el?.classList.remove('is-panning')\n panState = undefined\n}\n\nlet detachPan: (() => void) | undefined\n\nwatch(\n viewportEl,\n (el, _, onCleanup) => {\n detachPan?.()\n detachPan = undefined\n if (!el) return\n\n el.addEventListener('pointerdown', handlePointerDown, { capture: true })\n el.addEventListener('pointermove', handlePointerMove, { capture: true })\n el.addEventListener('pointerup', endPan, { capture: true })\n el.addEventListener('pointercancel', endPan, { capture: true })\n\n detachPan = () => {\n el.removeEventListener('pointerdown', handlePointerDown, { capture: true })\n el.removeEventListener('pointermove', handlePointerMove, { capture: true })\n el.removeEventListener('pointerup', endPan, { capture: true })\n el.removeEventListener('pointercancel', endPan, { capture: true })\n el.classList.remove('is-panning')\n panState = undefined\n }\n\n onCleanup(() => {\n detachPan?.()\n detachPan = undefined\n })\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n detachPan?.()\n detachPan = undefined\n})\n</script>\n"],"mappings":";;AAUA,MAAM,uBAAuB;;;;;;EAE7B,MAAM,cAAc,OAAmC,oBAAoB;EAC3E,MAAM,aAAa,eAAe,aAAa,SAAS,IAAI;EAE5D,IAAI;EAIJ,SAAS,oBAAoB,QAAqC;GAChE,IAAI,EAAE,kBAAkB,cAAc,OAAO;GAC7C,OAAO,CAAC,CAAC,OAAO,QACd,2GACF;EACF;EAEA,SAAS,kBAAkB,GAAiB;GAC1C,IAAI,EAAE,WAAW,KAAK,oBAAoB,EAAE,MAAM,GAAG;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,CAAC,IAAI;GAET,WAAW;IACT,WAAW,EAAE;IACb,QAAQ,EAAE;IACV,QAAQ,EAAE;IACV,YAAY,GAAG;IACf,WAAW,GAAG;GAChB;GACA,GAAG,UAAU,IAAI,YAAY;GAC7B,GAAG,kBAAkB,EAAE,SAAS;GAChC,EAAE,eAAe;EACnB;EAEA,SAAS,kBAAkB,GAAiB;GAC1C,IAAI,CAAC,YAAY,SAAS,cAAc,EAAE,WAAW;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,CAAC,IAAI;GAET,GAAG,aAAa,SAAS,cAAc,EAAE,UAAU,SAAS;GAC5D,GAAG,YAAY,SAAS,aAAa,EAAE,UAAU,SAAS;EAC5D;EAEA,SAAS,OAAO,GAAiB;GAC/B,IAAI,CAAC,YAAY,SAAS,cAAc,EAAE,WAAW;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,IAAI,kBAAkB,EAAE,SAAS,GACnC,GAAG,sBAAsB,EAAE,SAAS;GAEtC,IAAI,UAAU,OAAO,YAAY;GACjC,WAAW,KAAA;EACb;EAEA,IAAI;EAEJ,MACE,aACC,IAAI,GAAG,cAAc;GACpB,YAAY;GACZ,YAAY,KAAA;GACZ,IAAI,CAAC,IAAI;GAET,GAAG,iBAAiB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;GACvE,GAAG,iBAAiB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;GACvE,GAAG,iBAAiB,aAAa,QAAQ,EAAE,SAAS,KAAK,CAAC;GAC1D,GAAG,iBAAiB,iBAAiB,QAAQ,EAAE,SAAS,KAAK,CAAC;GAE9D,kBAAkB;IAChB,GAAG,oBAAoB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;IAC1E,GAAG,oBAAoB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;IAC1E,GAAG,oBAAoB,aAAa,QAAQ,EAAE,SAAS,KAAK,CAAC;IAC7D,GAAG,oBAAoB,iBAAiB,QAAQ,EAAE,SAAS,KAAK,CAAC;IACjE,GAAG,UAAU,OAAO,YAAY;IAChC,WAAW,KAAA;GACb;GAEA,gBAAgB;IACd,YAAY;IACZ,YAAY,KAAA;GACd,CAAC;EACH,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,YAAY;GACZ,YAAY,KAAA;EACd,CAAC;;UAlGC,WAAQ,KAAA,QAAA,SAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-zoom-bridge.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-zoom-bridge.vue"],"sourcesContent":["<template>\n <span hidden aria-hidden=\"true\" />\n</template>\n\n<script lang=\"ts\" setup>\nimport { useZoom, ZoomMode, type ZoomScope } from '@embedpdf/plugin-zoom/vue'\nimport { watch } from 'vue'\n\ndefineOptions({ name: 'FileViewerPdfZoomBridge' })\n\nconst props = defineProps<{ documentId: string }>()\n\nconst emit = defineEmits<{\n (e: 'zoom-change', payload: { level: number; scope: ZoomScope | null }): void\n}>()\n\nconst { provides: zoom, state } = useZoom(() => props.documentId)\n\nwatch(\n [zoom, () => state.value.currentZoomLevel],\n () => {\n emit('zoom-change', { level: state.value.currentZoomLevel, scope: zoom.value })\n },\n { immediate: true }\n)\n\ndefineExpose({ resetZoom: () => zoom.value?.requestZoom(ZoomMode.FitPage) })\n</script>\n"],"mappings":";;;;;;;;;;;;;EAUA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAIb,MAAM,EAAE,UAAU,MAAM,UAAU,cAAc,MAAM,WAAU;EAEhE,MACE,CAAC,YAAY,MAAM,MAAM,iBAAgB,QACnC;GACJ,KAAK,eAAe;IAAE,OAAO,MAAM,MAAM;IAAkB,OAAO,KAAK;IAAO,CAAA;KAEhF,EAAE,WAAW,MACf,CAAA;EAEA,SAAa,EAAE,iBAAiB,KAAK,OAAO,YAAY,SAAS,QAAO,EAAG,CAAA;;uBAzBzE,mBAAkC,QAAlC,WAAkC"}
1
+ {"version":3,"file":"pdf-zoom-bridge.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-zoom-bridge.vue"],"sourcesContent":["<template>\n <span hidden aria-hidden=\"true\" />\n</template>\n\n<script lang=\"ts\" setup>\nimport { useZoom, ZoomMode, type ZoomScope } from '@embedpdf/plugin-zoom/vue'\nimport { watch } from 'vue'\n\ndefineOptions({ name: 'FileViewerPdfZoomBridge' })\n\nconst props = defineProps<{ documentId: string }>()\n\nconst emit = defineEmits<{\n (e: 'zoom-change', payload: { level: number; scope: ZoomScope | null }): void\n}>()\n\nconst { provides: zoom, state } = useZoom(() => props.documentId)\n\nwatch(\n [zoom, () => state.value.currentZoomLevel],\n () => {\n emit('zoom-change', { level: state.value.currentZoomLevel, scope: zoom.value })\n },\n { immediate: true }\n)\n\ndefineExpose({ resetZoom: () => zoom.value?.requestZoom(ZoomMode.FitPage) })\n</script>\n"],"mappings":";;;;;;;;;;;;;EAUA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAIb,MAAM,EAAE,UAAU,MAAM,UAAU,cAAc,MAAM,UAAU;EAEhE,MACE,CAAC,YAAY,MAAM,MAAM,gBAAgB,SACnC;GACJ,KAAK,eAAe;IAAE,OAAO,MAAM,MAAM;IAAkB,OAAO,KAAK;GAAM,CAAC;EAChF,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,SAAa,EAAE,iBAAiB,KAAK,OAAO,YAAY,SAAS,OAAO,EAAE,CAAC;;uBAzBzE,mBAAkC,QAAlC,UAAkC"}
@@ -1 +1 @@
1
- {"version":3,"file":"sheet-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/sheet-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('sheet')\">\n <div v-if=\"truncated\" :class=\"cls.e('sheet-note')\">\n 仅展示前 {{ renderedRows.toLocaleString() }} 行(共 {{ totalRows.toLocaleString() }} 行)\n </div>\n <div v-if=\"sheets.length > 1\" :class=\"cls.e('sheet-tabs')\">\n <button\n v-for=\"(s, i) in sheets\"\n :key=\"s.name\"\n :class=\"[cls.e('sheet-tab'), bem.is('active', i === activeSheetIndex)]\"\n @click=\"activeSheetIndex = i\"\n >\n {{ s.name }}\n </button>\n </div>\n <div ref=\"container\" :class=\"cls.e('sheet-stage')\" />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, shallowRef, useTemplateRef, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\n\ndefineOptions({ name: 'FileViewerSheetPreviewer' })\n\nconst props = withDefaults(defineProps<{ file: FileViewerItem; maxRows?: number }>(), {\n maxRows: 50_000\n})\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\n\nconst container = useTemplateRef<HTMLDivElement>('container')\nconst loading = ref(true)\nconst truncated = ref(false)\nconst totalRows = ref(0)\nconst renderedRows = ref(0)\n\ninterface SheetData {\n name: string\n headers: string[]\n rows: string[][]\n totalCount: number\n}\n\nconst sheets = shallowRef<SheetData[]>([])\nconst activeSheetIndex = ref(0)\n\nlet controller: AbortController | undefined\nlet instance: { release?: () => void; resize?: () => void } | undefined\nlet resizeObserver: ResizeObserver | undefined\n\nasync function load() {\n controller?.abort()\n controller = new AbortController()\n const signal = controller.signal\n loading.value = true\n sheets.value = []\n activeSheetIndex.value = 0\n\n try {\n const ext = props.file.name.slice(props.file.name.lastIndexOf('.') + 1).toLowerCase()\n const { toArrayBuffer, parseCsv } = await import('../helper')\n const buf = await toArrayBuffer(props.file.src, signal)\n if (signal.aborted) return\n\n if (ext === 'csv') {\n const text = new TextDecoder('utf-8', { fatal: false }).decode(buf)\n const parsed = parseCsv(text).filter((row) => row.some((c) => c.length > 0))\n const headers = parsed[0] ?? []\n const rows = parsed.slice(1)\n sheets.value = [\n {\n name: props.file.name,\n headers: headers.map((h, i) => String(h) || `Column ${i + 1}`),\n rows,\n totalCount: rows.length\n }\n ]\n } else {\n const { readWorkbook } = await import('@cat-kit/excel')\n const workbook = await readWorkbook(new Uint8Array(buf))\n if (signal.aborted) return\n sheets.value = workbook.worksheets.map((ws) => {\n const wsRows = ws.getRows()\n const firstRow = wsRows[0]\n const headers = firstRow ? firstRow.toValues().map((v) => cellToString(v)) : []\n const rows = wsRows.slice(1).map((r) => r.toValues().map(cellToString))\n return {\n name: ws.name,\n headers: headers.map((h, i) => h || `Column ${i + 1}`),\n rows,\n totalCount: rows.length\n }\n })\n }\n\n await renderActive()\n } catch (err) {\n if ((err as { name?: string })?.name === 'AbortError') return\n emit('error', err)\n } finally {\n loading.value = false\n }\n}\n\nfunction cellToString(v: unknown): string {\n if (v === null || v === undefined) return ''\n if (typeof v === 'string') return v\n if (typeof v === 'number' || typeof v === 'boolean') return String(v)\n if (v instanceof Date) return v.toLocaleString()\n if (typeof v === 'object' && v !== null && 'formula' in v) {\n const f = v as { formula: string; result?: unknown }\n if (f.result !== undefined && f.result !== null) return cellToString(f.result)\n return `=${f.formula}`\n }\n return String(v)\n}\n\nasync function renderActive() {\n const sheet = sheets.value[activeSheetIndex.value]\n if (!sheet || !container.value) return\n\n releaseInstance()\n\n const limit = props.maxRows > 0 ? Math.min(props.maxRows, sheet.rows.length) : sheet.rows.length\n totalRows.value = sheet.totalCount\n renderedRows.value = limit\n truncated.value = props.maxRows > 0 && sheet.rows.length > props.maxRows\n\n const columns = sheet.headers.map((h, i) => ({\n field: 'c' + i,\n title: h,\n width: 'auto' as const\n }))\n\n const records: Record<string, string>[] = []\n for (let i = 0; i < limit; i++) {\n const row = sheet.rows[i]\n if (!row) continue\n const record: Record<string, string> = {}\n for (let j = 0; j < columns.length; j++) {\n record['c' + j] = row[j] ?? ''\n }\n records.push(record)\n }\n\n const VTable = await import('@visactor/vtable')\n if (!container.value) return\n\n instance = new VTable.ListTable(container.value, {\n records,\n columns,\n widthMode: 'standard',\n heightMode: 'standard',\n defaultRowHeight: 32,\n defaultHeaderRowHeight: 36,\n autoFillWidth: true,\n frozenColCount: 0,\n theme: (VTable.themes.ARCO ?? VTable.themes.DEFAULT).extends({\n defaultStyle: { borderLineWidth: 1 }\n })\n })\n}\n\nfunction releaseInstance() {\n if (instance && typeof instance.release === 'function') {\n try {\n instance.release()\n } catch {\n /* noop */\n }\n }\n instance = undefined\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nwatch(activeSheetIndex, () => renderActive())\n\nwatch(container, (el) => {\n resizeObserver?.disconnect()\n if (!el) return\n resizeObserver = new ResizeObserver(() => {\n instance?.resize?.()\n })\n resizeObserver.observe(el)\n})\n\nonBeforeUnmount(() => {\n controller?.abort()\n resizeObserver?.disconnect()\n releaseInstance()\n sheets.value = []\n})\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"sheet-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/sheet-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('sheet')\">\n <div v-if=\"truncated\" :class=\"cls.e('sheet-note')\">\n 仅展示前 {{ renderedRows.toLocaleString() }} 行(共 {{ totalRows.toLocaleString() }} 行)\n </div>\n <div v-if=\"sheets.length > 1\" :class=\"cls.e('sheet-tabs')\">\n <button\n v-for=\"(s, i) in sheets\"\n :key=\"s.name\"\n :class=\"[cls.e('sheet-tab'), bem.is('active', i === activeSheetIndex)]\"\n @click=\"activeSheetIndex = i\"\n >\n {{ s.name }}\n </button>\n </div>\n <div ref=\"container\" :class=\"cls.e('sheet-stage')\" />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, shallowRef, useTemplateRef, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\n\ndefineOptions({ name: 'FileViewerSheetPreviewer' })\n\nconst props = withDefaults(defineProps<{ file: FileViewerItem; maxRows?: number }>(), {\n maxRows: 50_000\n})\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\n\nconst container = useTemplateRef<HTMLDivElement>('container')\nconst loading = ref(true)\nconst truncated = ref(false)\nconst totalRows = ref(0)\nconst renderedRows = ref(0)\n\ninterface SheetData {\n name: string\n headers: string[]\n rows: string[][]\n totalCount: number\n}\n\nconst sheets = shallowRef<SheetData[]>([])\nconst activeSheetIndex = ref(0)\n\nlet controller: AbortController | undefined\nlet instance: { release?: () => void; resize?: () => void } | undefined\nlet resizeObserver: ResizeObserver | undefined\n\nasync function load() {\n controller?.abort()\n controller = new AbortController()\n const signal = controller.signal\n loading.value = true\n sheets.value = []\n activeSheetIndex.value = 0\n\n try {\n const ext = props.file.name.slice(props.file.name.lastIndexOf('.') + 1).toLowerCase()\n const { toArrayBuffer, parseCsv } = await import('../helper')\n const buf = await toArrayBuffer(props.file.src, signal)\n if (signal.aborted) return\n\n if (ext === 'csv') {\n const text = new TextDecoder('utf-8', { fatal: false }).decode(buf)\n const parsed = parseCsv(text).filter((row) => row.some((c) => c.length > 0))\n const headers = parsed[0] ?? []\n const rows = parsed.slice(1)\n sheets.value = [\n {\n name: props.file.name,\n headers: headers.map((h, i) => String(h) || `Column ${i + 1}`),\n rows,\n totalCount: rows.length\n }\n ]\n } else {\n const { readWorkbook } = await import('@cat-kit/excel')\n const workbook = await readWorkbook(new Uint8Array(buf))\n if (signal.aborted) return\n sheets.value = workbook.worksheets.map((ws) => {\n const wsRows = ws.getRows()\n const firstRow = wsRows[0]\n const headers = firstRow ? firstRow.toValues().map((v) => cellToString(v)) : []\n const rows = wsRows.slice(1).map((r) => r.toValues().map(cellToString))\n return {\n name: ws.name,\n headers: headers.map((h, i) => h || `Column ${i + 1}`),\n rows,\n totalCount: rows.length\n }\n })\n }\n\n await renderActive()\n } catch (err) {\n if ((err as { name?: string })?.name === 'AbortError') return\n emit('error', err)\n } finally {\n loading.value = false\n }\n}\n\nfunction cellToString(v: unknown): string {\n if (v === null || v === undefined) return ''\n if (typeof v === 'string') return v\n if (typeof v === 'number' || typeof v === 'boolean') return String(v)\n if (v instanceof Date) return v.toLocaleString()\n if (typeof v === 'object' && v !== null && 'formula' in v) {\n const f = v as { formula: string; result?: unknown }\n if (f.result !== undefined && f.result !== null) return cellToString(f.result)\n return `=${f.formula}`\n }\n return String(v)\n}\n\nasync function renderActive() {\n const sheet = sheets.value[activeSheetIndex.value]\n if (!sheet || !container.value) return\n\n releaseInstance()\n\n const limit = props.maxRows > 0 ? Math.min(props.maxRows, sheet.rows.length) : sheet.rows.length\n totalRows.value = sheet.totalCount\n renderedRows.value = limit\n truncated.value = props.maxRows > 0 && sheet.rows.length > props.maxRows\n\n const columns = sheet.headers.map((h, i) => ({\n field: 'c' + i,\n title: h,\n width: 'auto' as const\n }))\n\n const records: Record<string, string>[] = []\n for (let i = 0; i < limit; i++) {\n const row = sheet.rows[i]\n if (!row) continue\n const record: Record<string, string> = {}\n for (let j = 0; j < columns.length; j++) {\n record['c' + j] = row[j] ?? ''\n }\n records.push(record)\n }\n\n const VTable = await import('@visactor/vtable')\n if (!container.value) return\n\n instance = new VTable.ListTable(container.value, {\n records,\n columns,\n widthMode: 'standard',\n heightMode: 'standard',\n defaultRowHeight: 32,\n defaultHeaderRowHeight: 36,\n autoFillWidth: true,\n frozenColCount: 0,\n theme: (VTable.themes.ARCO ?? VTable.themes.DEFAULT).extends({\n defaultStyle: { borderLineWidth: 1 }\n })\n })\n}\n\nfunction releaseInstance() {\n if (instance && typeof instance.release === 'function') {\n try {\n instance.release()\n } catch {\n /* noop */\n }\n }\n instance = undefined\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nwatch(activeSheetIndex, () => renderActive())\n\nwatch(container, (el) => {\n resizeObserver?.disconnect()\n if (!el) return\n resizeObserver = new ResizeObserver(() => {\n instance?.resize?.()\n })\n resizeObserver.observe(el)\n})\n\nonBeforeUnmount(() => {\n controller?.abort()\n resizeObserver?.disconnect()\n releaseInstance()\n sheets.value = []\n})\n</script>\n"],"mappings":"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"}