@veltra/desktop 1.8.2 → 1.8.4

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 (207) hide show
  1. package/dist/components/action/action-group.js.map +1 -1
  2. package/dist/components/action/action-group.vue_vue_type_script_setup_true_lang.js.map +1 -1
  3. package/dist/components/action/action.js.map +1 -1
  4. package/dist/components/auto-complete/auto-complete.js.map +1 -1
  5. package/dist/components/badge/badge.js.map +1 -1
  6. package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
  7. package/dist/components/batch-edit/batch-edit-list.js.map +1 -1
  8. package/dist/components/batch-edit/batch-edit.js.map +1 -1
  9. package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
  10. package/dist/components/button/button-group.js.map +1 -1
  11. package/dist/components/button/button.js.map +1 -1
  12. package/dist/components/calendar/calendar.js.map +1 -1
  13. package/dist/components/card/card-action.js.map +1 -1
  14. package/dist/components/card/card-content.js.map +1 -1
  15. package/dist/components/card/card-cover.js.map +1 -1
  16. package/dist/components/card/card-header.js.map +1 -1
  17. package/dist/components/card/card.js.map +1 -1
  18. package/dist/components/cascade/cascade-panel-item.js.map +1 -1
  19. package/dist/components/cascade/cascade.js +1 -0
  20. package/dist/components/cascade/cascade.js.map +1 -1
  21. package/dist/components/cascade/use-select.js +6 -2
  22. package/dist/components/cascade/use-select.js.map +1 -1
  23. package/dist/components/check-tag/check-tag.js.map +1 -1
  24. package/dist/components/checkbox/checkbox-button.js.map +1 -1
  25. package/dist/components/checkbox/checkbox.js.map +1 -1
  26. package/dist/components/checkbox-group/checkbox-group.js.map +1 -1
  27. package/dist/components/code-editor/code-editor.js.map +1 -1
  28. package/dist/components/collapse/collapse-item.js.map +1 -1
  29. package/dist/components/collapse/collapse.js.map +1 -1
  30. package/dist/components/condition-editor/components/condition-group.js.map +1 -1
  31. package/dist/components/condition-editor/components/condition-row.js.map +1 -1
  32. package/dist/components/condition-editor/condition-editor.js.map +1 -1
  33. package/dist/components/contextmenu/contextmenu-item.js.map +1 -1
  34. package/dist/components/contextmenu/contextmenu-panel.js.map +1 -1
  35. package/dist/components/contextmenu/contextmenu-sub.js.map +1 -1
  36. package/dist/components/contextmenu/contextmenu.js.map +1 -1
  37. package/dist/components/date-panel/date-panel.js.map +1 -1
  38. package/dist/components/date-panel/headers/day.js.map +1 -1
  39. package/dist/components/date-panel/headers/month.js.map +1 -1
  40. package/dist/components/date-panel/headers/year.js.map +1 -1
  41. package/dist/components/date-panel/panels/day.js.map +1 -1
  42. package/dist/components/date-panel/panels/month.js.map +1 -1
  43. package/dist/components/date-panel/panels/year.js.map +1 -1
  44. package/dist/components/date-picker/date-picker.js.map +1 -1
  45. package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
  46. package/dist/components/dialog/dialog.js.map +1 -1
  47. package/dist/components/drawer/drawer.js.map +1 -1
  48. package/dist/components/dropdown/dropdown.js.map +1 -1
  49. package/dist/components/dual-nav/dual-nav-app.js.map +1 -1
  50. package/dist/components/dual-nav/dual-nav.js.map +1 -1
  51. package/dist/components/empty/empty.js.map +1 -1
  52. package/dist/components/expression-editor/components/path-preview.js.map +1 -1
  53. package/dist/components/expression-editor/components/variable-picker.js.map +1 -1
  54. package/dist/components/expression-editor/expression-editor.js.map +1 -1
  55. package/dist/components/file-picker/file-picker.js.map +1 -1
  56. package/dist/components/file-viewer/file-viewer.js.map +1 -1
  57. package/dist/components/file-viewer/previewers/docx-previewer.js.map +1 -1
  58. package/dist/components/file-viewer/previewers/image-previewer.js.map +1 -1
  59. package/dist/components/file-viewer/previewers/ofd-previewer.js.map +1 -1
  60. package/dist/components/file-viewer/previewers/pdf-previewer.js.map +1 -1
  61. package/dist/components/file-viewer/previewers/pdf-viewport-scroll.js.map +1 -1
  62. package/dist/components/file-viewer/previewers/pdf-zoom-bridge.js.map +1 -1
  63. package/dist/components/file-viewer/previewers/sheet-previewer.js.map +1 -1
  64. package/dist/components/file-viewer/previewers/text-previewer.js.map +1 -1
  65. package/dist/components/file-viewer/previewers/video-previewer.js.map +1 -1
  66. package/dist/components/float-button/float-button.js.map +1 -1
  67. package/dist/components/form/form.js.map +1 -1
  68. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
  69. package/dist/components/form-item/form-item.js.map +1 -1
  70. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
  71. package/dist/components/gantt-chart/gantt-chart.js.map +1 -1
  72. package/dist/components/grid/grid-item.js.map +1 -1
  73. package/dist/components/grid/grid.js.map +1 -1
  74. package/dist/components/grid-input/grid-input.js.map +1 -1
  75. package/dist/components/group-input/group-input.js.map +1 -1
  76. package/dist/components/group-nav/group-nav-item.js.map +1 -1
  77. package/dist/components/group-nav/group-nav.js.map +1 -1
  78. package/dist/components/icon/icon.js.map +1 -1
  79. package/dist/components/image-cropper/image-cropper.js.map +1 -1
  80. package/dist/components/input/input.js.map +1 -1
  81. package/dist/components/input/input.vue_vue_type_script_setup_true_lang.js.map +1 -1
  82. package/dist/components/kanban/kanban-column.js.map +1 -1
  83. package/dist/components/kanban/kanban.js.map +1 -1
  84. package/dist/components/kbd/kbd.js.map +1 -1
  85. package/dist/components/layout/layout-resizer.js.map +1 -1
  86. package/dist/components/layout/layout.js.map +1 -1
  87. package/dist/components/list/list-item.js.map +1 -1
  88. package/dist/components/list/list.js.map +1 -1
  89. package/dist/components/loading/loading.js.map +1 -1
  90. package/dist/components/message/message-box.js.map +1 -1
  91. package/dist/components/message/message.js.map +1 -1
  92. package/dist/components/message-confirm/message-confirm-box.js.map +1 -1
  93. package/dist/components/message-confirm/message-confirm.js.map +1 -1
  94. package/dist/components/multi-select/multi-select-option.js.map +1 -1
  95. package/dist/components/multi-select/multi-select.js.map +1 -1
  96. package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
  97. package/dist/components/nav/nav-icon.js.map +1 -1
  98. package/dist/components/nav/nav-item-collapsed.js.map +1 -1
  99. package/dist/components/nav/nav-item.js.map +1 -1
  100. package/dist/components/nav/nav-sub-collapsed.js.map +1 -1
  101. package/dist/components/nav/nav-sub.js.map +1 -1
  102. package/dist/components/nav/nav.js.map +1 -1
  103. package/dist/components/notification/notification-box.js.map +1 -1
  104. package/dist/components/notification/notification.js.map +1 -1
  105. package/dist/components/number/number.js.map +1 -1
  106. package/dist/components/number-input/number-input.js.map +1 -1
  107. package/dist/components/number-range-input/number-range-input.js.map +1 -1
  108. package/dist/components/paginator/paginator.js.map +1 -1
  109. package/dist/components/palette/palette-alpha.js.map +1 -1
  110. package/dist/components/palette/palette-color-switch.js.map +1 -1
  111. package/dist/components/palette/palette-hue.js.map +1 -1
  112. package/dist/components/palette/palette-sv.js.map +1 -1
  113. package/dist/components/palette/palette.js.map +1 -1
  114. package/dist/components/password-input/password-input.js.map +1 -1
  115. package/dist/components/pop-confirm/pop-confirm.js.map +1 -1
  116. package/dist/components/progress/progress.js.map +1 -1
  117. package/dist/components/progress-nodes/progress-nodes.js.map +1 -1
  118. package/dist/components/radio/radio.js.map +1 -1
  119. package/dist/components/radio-group/radio-group.js.map +1 -1
  120. package/dist/components/rich-text-editor/image-node.js +53 -14
  121. package/dist/components/rich-text-editor/image-node.js.map +1 -1
  122. package/dist/components/rich-text-editor/rich-text-editor.js +9 -3
  123. package/dist/components/rich-text-editor/rich-text-editor.js.map +1 -1
  124. package/dist/components/rich-text-editor/style2.css +31 -0
  125. package/dist/components/rich-text-editor/toolbar.js.map +1 -1
  126. package/dist/components/rich-text-editor/use-image-resize.js +118 -0
  127. package/dist/components/rich-text-editor/use-image-resize.js.map +1 -0
  128. package/dist/components/scroll/scroll-bar.js.map +1 -1
  129. package/dist/components/scroll/scroll.js.map +1 -1
  130. package/dist/components/segment/segment.js.map +1 -1
  131. package/dist/components/select/select.js +9 -5
  132. package/dist/components/select/select.js.map +1 -1
  133. package/dist/components/slider/slider-thumb.js.map +1 -1
  134. package/dist/components/slider/slider.js.map +1 -1
  135. package/dist/components/steps/steps.js.map +1 -1
  136. package/dist/components/switch/switch.js.map +1 -1
  137. package/dist/components/table/table-body.js.map +1 -1
  138. package/dist/components/table/table-cell.js.map +1 -1
  139. package/dist/components/table/table-foot.js.map +1 -1
  140. package/dist/components/table/table-head.js.map +1 -1
  141. package/dist/components/table/table-row.js.map +1 -1
  142. package/dist/components/table/table.js.map +1 -1
  143. package/dist/components/table-editor/table-editor.js.map +1 -1
  144. package/dist/components/tabs/tabs-horizontal.js.map +1 -1
  145. package/dist/components/tabs/tabs-vertical.js.map +1 -1
  146. package/dist/components/tabs/tabs.js.map +1 -1
  147. package/dist/components/tag/tag.js.map +1 -1
  148. package/dist/components/text/text.js.map +1 -1
  149. package/dist/components/textarea/textarea.js.map +1 -1
  150. package/dist/components/theme/theme.js.map +1 -1
  151. package/dist/components/tip/tip.js.map +1 -1
  152. package/dist/components/tree/tree-node.js.map +1 -1
  153. package/dist/components/tree/tree.js.map +1 -1
  154. package/dist/components/tree-select/tree-select.js +19 -10
  155. package/dist/components/tree-select/tree-select.js.map +1 -1
  156. package/dist/components/watermark/watermark.js.map +1 -1
  157. package/dist/types/cascade.d.ts +5 -0
  158. package/dist/types/select.d.ts +8 -2
  159. package/dist/types/tree-select.d.ts +8 -2
  160. package/package.json +18 -18
  161. package/src/components/batch-edit/__test__/batch-edit.test.ts +1 -1
  162. package/src/components/button/__test__/button.test.ts +1 -1
  163. package/src/components/cascade/__test__/cascade.test.ts +26 -1
  164. package/src/components/cascade/use-select.ts +5 -5
  165. package/src/components/collapse/__test__/collapse.test.ts +1 -1
  166. package/src/components/condition-editor/__test__/condition-editor.test.ts +1 -1
  167. package/src/components/contextmenu/__test__/contextmenu.test.ts +1 -1
  168. package/src/components/date-picker/__test__/date-picker.test.ts +1 -1
  169. package/src/components/date-range-picker/__test__/date-range-picker.test.ts +1 -1
  170. package/src/components/drawer/__test__/drawer.test.ts +1 -1
  171. package/src/components/expression-editor/__test__/chip.test.ts +1 -1
  172. package/src/components/expression-editor/__test__/editor.test.ts +1 -1
  173. package/src/components/expression-editor/__test__/expression-editor.test.ts +1 -1
  174. package/src/components/expression-editor/__test__/mention.test.ts +1 -1
  175. package/src/components/expression-editor/__test__/model.test.ts +1 -1
  176. package/src/components/file-viewer/__test__/helper.test.ts +1 -1
  177. package/src/components/form/__test__/form.test.ts +1 -1
  178. package/src/components/form/__test__/is-field-modified.test.ts +1 -1
  179. package/src/components/form-item/__test__/form-item.test.ts +1 -1
  180. package/src/components/image-cropper/__test__/draw-crop.test.ts +1 -1
  181. package/src/components/image-cropper/__test__/image-cropper.test.ts +1 -1
  182. package/src/components/image-cropper/__test__/use-transform.test.ts +1 -1
  183. package/src/components/kanban/__test__/kanban.test.ts +1 -1
  184. package/src/components/message-confirm/__test__/message-confirm.test.ts +1 -1
  185. package/src/components/multi-tree-select/__test__/multi-tree-select.test.ts +1 -1
  186. package/src/components/number-input/__test__/number-input.test.ts +1 -1
  187. package/src/components/number-range-input/__test__/number-range-input.test.ts +1 -1
  188. package/src/components/palette/__test__/color-transform.test.ts +1 -1
  189. package/src/components/palette/__test__/palette.test.ts +1 -1
  190. package/src/components/password-input/__test__/password-input.test.ts +1 -1
  191. package/src/components/radio-group/__test__/radio-group.test.ts +1 -1
  192. package/src/components/rich-text-editor/__test__/image-node.test.ts +140 -0
  193. package/src/components/rich-text-editor/image-node.ts +84 -15
  194. package/src/components/rich-text-editor/rich-text-editor.vue +15 -4
  195. package/src/components/rich-text-editor/style.scss +35 -0
  196. package/src/components/rich-text-editor/use-image-resize.ts +168 -0
  197. package/src/components/segment/__test__/segment.test.ts +1 -1
  198. package/src/components/select/__test__/select.test.ts +68 -1
  199. package/src/components/select/select.vue +15 -5
  200. package/src/components/table/__test__/col-width.test.ts +1 -1
  201. package/src/components/table/__test__/column-style.test.ts +1 -1
  202. package/src/components/table-editor/__test__/table-editor.test.ts +1 -1
  203. package/src/components/tree-select/__test__/tree-select.test.ts +50 -1
  204. package/src/components/tree-select/tree-select.vue +28 -11
  205. package/src/types/cascade.ts +5 -0
  206. package/src/types/select.ts +8 -2
  207. package/src/types/tree-select.ts +9 -2
@@ -1 +1 @@
1
- {"version":3,"file":"variable-picker.js","names":[],"sources":["../../../../src/components/expression-editor/components/variable-picker.vue"],"sourcesContent":["<template>\n <u-tip\n hide-arrow\n alignment=\"start\"\n direction=\"bottom\"\n trigger=\"click\"\n :trigger-dom=\"triggerDom\"\n :visible=\"visible\"\n @update:visible=\"handleVisibleChange($event)\"\n >\n <template #content>\n <div ref=\"root\" :class=\"cls.e('picker')\" @mousedown.prevent>\n <!-- 面包屑:仅逐级模式且非根级显示 -->\n <div v-if=\"!isFlat && navPath.length > 0\" :class=\"cls.e('breadcrumbs')\">\n <span :class=\"cls.e('breadcrumb-item')\">\n <span :class=\"cls.e('breadcrumb-link')\" @click=\"navigateTo(0)\">全部变量</span>\n <u-icon :class=\"cls.e('breadcrumb-separator')\">\n <ArrowRight />\n </u-icon>\n </span>\n <span\n v-for=\"(crumb, i) in navPath\"\n :key=\"`${i}-${crumb.value}`\"\n :class=\"cls.e('breadcrumb-item')\"\n >\n <span\n :class=\"[\n cls.e('breadcrumb-link'),\n { [cls.em('breadcrumb-link', 'active')]: i === navPath.length - 1 }\n ]\"\n @click=\"navigateTo(i + 1)\"\n >{{ crumb.label }}</span\n >\n <u-icon v-if=\"i < navPath.length - 1\" :class=\"cls.e('breadcrumb-separator')\">\n <ArrowRight />\n </u-icon>\n </span>\n </div>\n\n <div :class=\"cls.e('picker-body')\">\n <div :class=\"cls.e('panel')\" v-if=\"currentList.length > 0\">\n <u-scroll\n ref=\"listScroll\"\n tag=\"ul\"\n :class=\"cls.e('panel-list')\"\n :content-class=\"cls.e('panel-content')\"\n >\n <li\n v-for=\"(item, idx) in currentList\"\n :key=\"`${idx}-${item.value}`\"\n :data-idx=\"idx\"\n :class=\"getItemCls(item, idx)\"\n @click=\"handleItemClick(item, idx)\"\n @mouseenter=\"activeIndex = idx\"\n >\n <span :class=\"cls.e('item-label')\">{{ item.label }}</span>\n <u-icon\n v-if=\"!isFlat && hasChildren(item)\"\n :class=\"cls.e('item-expand')\"\n title=\"展开下一级\"\n @click.stop=\"expandInto(item)\"\n >\n <ArrowRight />\n </u-icon>\n </li>\n </u-scroll>\n </div>\n <div v-else :class=\"cls.e('empty')\">\n <UEmpty description=\"暂无可用变量\" />\n </div>\n\n <PathPreview v-if=\"isFlat && activePath.length > 0\" :path=\"activePath\" />\n </div>\n\n <div v-if=\"currentList.length > 0\" :class=\"cls.e('picker-hint')\">\n <template v-if=\"isFlat\">\n <span><kbd>↑</kbd><kbd>↓</kbd> 选择</span>\n <span><kbd>Enter</kbd> 确认</span>\n <span><kbd>Esc</kbd> 关闭</span>\n </template>\n <template v-else>\n <span><kbd>↑</kbd><kbd>↓</kbd> 选择</span>\n <span><kbd>→</kbd> 展开</span>\n <span><kbd>←</kbd> 返回</span>\n <span><kbd>Enter</kbd> 确认</span>\n <span><kbd>Esc</kbd> 关闭</span>\n </template>\n </div>\n </div>\n </template>\n </u-tip>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ArrowRight } from '@veltra/icons/normal'\nimport { bem } from '@veltra/utils'\nimport { computed, nextTick, ref, useTemplateRef, watch } from 'vue'\n\nimport type { VariableItem } from '../../../types'\nimport { UEmpty } from '../../empty'\nimport { UIcon } from '../../icon'\nimport { UScroll } from '../../scroll'\nimport { UTip } from '../../tip'\nimport PathPreview from './path-preview.vue'\n\ndefineOptions({ name: 'UVariablePicker' })\n\ninterface FlatItem extends VariableItem {\n /** 仅扁平模式使用:从根到当前节点的路径 */\n __path: VariableItem[]\n}\n\nconst props = defineProps<{\n visible: boolean\n triggerDom?: HTMLElement\n /** 顶层变量树 */\n variables?: VariableItem[]\n /** 来自编辑器 mention 状态的过滤字符串。空 = 逐级模式;非空 = 扁平模式。 */\n filter: string\n /** 是否允许选中分支节点 */\n selectableLevels: 'leaf' | 'any'\n}>()\n\nconst emit = defineEmits<{\n (e: 'select', item: VariableItem): void\n (e: 'update:visible', visible: boolean): void\n /** 用户主动取消(按 Esc)。编辑器据此把 mention 状态置为 dismissed。 */\n (e: 'dismiss'): void\n}>()\n\nconst cls = bem('expression-editor')\n\nconst navPath = ref<VariableItem[]>([])\nconst activeIndex = ref(0)\nconst root = useTemplateRef('root')\nconst listScroll = useTemplateRef<InstanceType<typeof UScroll>>('listScroll')\n\nconst isFlat = computed(() => props.filter !== '')\n\nfunction hasChildren(item: VariableItem): boolean {\n return !!item.children && item.children.length > 0\n}\n\nfunction isLeaf(item: VariableItem): boolean {\n return !hasChildren(item)\n}\n\n/** 当前层级展示的列表(来源依模式而定) */\nconst currentList = computed<VariableItem[]>(() => {\n const variables = props.variables ?? []\n if (isFlat.value) return flatList.value\n let level: VariableItem[] = variables\n for (const node of navPath.value) {\n const found = level.find((it) => it.value === node.value)\n if (!found || !found.children) break\n level = found.children\n }\n return level\n})\n\n/** 扁平模式下:根据 selectableLevels 拍平 + 过滤 */\nconst flatList = computed<FlatItem[]>(() => {\n const variables = props.variables ?? []\n const out: FlatItem[] = []\n const includeBranches = props.selectableLevels === 'any'\n function walk(items: VariableItem[], path: VariableItem[]) {\n for (const it of items) {\n const nextPath = [...path, it]\n if (isLeaf(it)) {\n out.push({ ...it, __path: nextPath })\n } else {\n if (includeBranches) out.push({ ...it, __path: nextPath })\n walk(it.children!, nextPath)\n }\n }\n }\n walk(variables, [])\n const q = props.filter.toLowerCase()\n return out.filter((it) => it.label.toLowerCase().includes(q))\n})\n\n/** 当前 active 项;扁平模式下用于驱动路径预览 */\nconst activePath = computed<VariableItem[]>(() => {\n if (!isFlat.value) return []\n const item = flatList.value[activeIndex.value] as FlatItem | undefined\n return item ? item.__path : []\n})\n\nfunction getItemCls(_item: VariableItem, idx: number) {\n return [cls.e('item'), bem.is('active', idx === activeIndex.value)]\n}\n\nfunction navigateTo(i: number) {\n // 0 = 全部变量;i 之后表示进入到 navPath[i-1]\n navPath.value = navPath.value.slice(0, i)\n activeIndex.value = 0\n}\n\nfunction handleItemClick(item: VariableItem, idx: number) {\n activeIndex.value = idx\n selectActive()\n}\n\nfunction selectActive() {\n const item = currentList.value[activeIndex.value]\n if (!item) return\n\n if (isFlat.value) {\n // 扁平模式始终是「选中并替换」\n emit('select', flattenSourceFor(item))\n return\n }\n\n // 逐级模式\n if (hasChildren(item)) {\n if (props.selectableLevels === 'any') {\n // Enter 在分支项上:选中分支本身\n emit('select', item)\n return\n }\n // 默认 'leaf':进入下一级\n expandInto(item)\n return\n }\n emit('select', item)\n}\n\n/** 进入 item 的下一级(点击展开图标 / leaf 模式点击分支项共用) */\nfunction expandInto(item: VariableItem) {\n if (!hasChildren(item)) return\n navPath.value = [...navPath.value, item]\n activeIndex.value = 0\n}\n\nfunction flattenSourceFor(it: VariableItem): VariableItem {\n const flat = it as FlatItem\n // 还原为「不带 __path 的纯 VariableItem」,避免泄漏内部字段\n const out: VariableItem = { value: flat.value, label: flat.label }\n if (flat.type) out.type = flat.type\n if (flat.children) out.children = flat.children\n return out\n}\n\nfunction moveActive(delta: -1 | 1) {\n const max = currentList.value.length - 1\n if (max < 0) return\n let next = activeIndex.value + delta\n if (next < 0) next = 0\n if (next > max) next = max\n activeIndex.value = next\n scrollActiveIntoView()\n}\n\nfunction scrollActiveIntoView() {\n void nextTick(() => {\n // 在面板根节点内查找,避免同页多个编辑器时滚错列表\n const item = root.value?.querySelector(`[data-idx=\"${activeIndex.value}\"]`)\n // expose 代理运行时会解包 ref,类型上按 unknown 收窄\n const scroller = listScroll.value?.containerRef as unknown\n if (!(item instanceof HTMLElement) || !(scroller instanceof HTMLElement)) return\n // 只滚面板列表自身:原生 scrollIntoView 会沿所有滚动祖先链滚动,\n // 面板贴近视口边缘时会连带滚动页面,导致面板与触发器错位抖动\n const top =\n item.getBoundingClientRect().top - scroller.getBoundingClientRect().top + scroller.scrollTop\n const bottom = top + item.offsetHeight\n if (top < scroller.scrollTop) {\n scroller.scrollTop = top\n } else if (bottom > scroller.scrollTop + scroller.clientHeight) {\n scroller.scrollTop = bottom - scroller.clientHeight\n }\n })\n}\n\nfunction handleVisibleChange(v: boolean) {\n emit('update:visible', v)\n if (!v) reset()\n}\n\nfunction reset() {\n navPath.value = []\n activeIndex.value = 0\n}\n\nwatch(\n () => props.visible,\n (v) => {\n if (!v) reset()\n else activeIndex.value = 0\n }\n)\n\nwatch(\n () => props.filter,\n () => {\n // 过滤词变化:重置 active;逐级 → 扁平时清空 navPath\n activeIndex.value = 0\n if (isFlat.value) navPath.value = []\n }\n)\n\n/**\n * 由父级 forward 进来的键盘事件。\n * 返回 true 表示已处理(外部应 preventDefault)。\n */\nfunction handleKeydown(e: KeyboardEvent): boolean {\n if (!props.visible) return false\n\n switch (e.key) {\n case 'Escape':\n emit('dismiss')\n emit('update:visible', false)\n reset()\n return true\n case 'ArrowDown':\n moveActive(1)\n return true\n case 'ArrowUp':\n moveActive(-1)\n return true\n case 'ArrowLeft':\n // 仅逐级模式:返回上一级;扁平模式下不拦截,让光标正常移动并触发 mention dismiss\n if (!isFlat.value && navPath.value.length > 0) {\n navPath.value = navPath.value.slice(0, -1)\n activeIndex.value = 0\n return true\n }\n return false\n case 'ArrowRight': {\n if (isFlat.value) return false\n const item = currentList.value[activeIndex.value]\n if (item && hasChildren(item)) {\n expandInto(item)\n return true\n }\n return false\n }\n case 'Enter':\n selectActive()\n return true\n default:\n return false\n }\n}\n\ndefineExpose({ handleKeydown })\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"variable-picker.js","names":["_openBlock","_createBlock","_unref","UTip","_withCtx","_createElementVNode","_normalizeClass","_withModifiers","_createCommentVNode","_createElementBlock","_createVNode","UIcon","_Fragment","_renderList","_toDisplayString","UScroll","UEmpty","PathPreview","_createTextVNode"],"sources":["../../../../src/components/expression-editor/components/variable-picker.vue"],"sourcesContent":["<template>\n <u-tip\n hide-arrow\n alignment=\"start\"\n direction=\"bottom\"\n trigger=\"click\"\n :trigger-dom=\"triggerDom\"\n :visible=\"visible\"\n @update:visible=\"handleVisibleChange($event)\"\n >\n <template #content>\n <div ref=\"root\" :class=\"cls.e('picker')\" @mousedown.prevent>\n <!-- 面包屑:仅逐级模式且非根级显示 -->\n <div v-if=\"!isFlat && navPath.length > 0\" :class=\"cls.e('breadcrumbs')\">\n <span :class=\"cls.e('breadcrumb-item')\">\n <span :class=\"cls.e('breadcrumb-link')\" @click=\"navigateTo(0)\">全部变量</span>\n <u-icon :class=\"cls.e('breadcrumb-separator')\">\n <ArrowRight />\n </u-icon>\n </span>\n <span\n v-for=\"(crumb, i) in navPath\"\n :key=\"`${i}-${crumb.value}`\"\n :class=\"cls.e('breadcrumb-item')\"\n >\n <span\n :class=\"[\n cls.e('breadcrumb-link'),\n { [cls.em('breadcrumb-link', 'active')]: i === navPath.length - 1 }\n ]\"\n @click=\"navigateTo(i + 1)\"\n >{{ crumb.label }}</span\n >\n <u-icon v-if=\"i < navPath.length - 1\" :class=\"cls.e('breadcrumb-separator')\">\n <ArrowRight />\n </u-icon>\n </span>\n </div>\n\n <div :class=\"cls.e('picker-body')\">\n <div :class=\"cls.e('panel')\" v-if=\"currentList.length > 0\">\n <u-scroll\n ref=\"listScroll\"\n tag=\"ul\"\n :class=\"cls.e('panel-list')\"\n :content-class=\"cls.e('panel-content')\"\n >\n <li\n v-for=\"(item, idx) in currentList\"\n :key=\"`${idx}-${item.value}`\"\n :data-idx=\"idx\"\n :class=\"getItemCls(item, idx)\"\n @click=\"handleItemClick(item, idx)\"\n @mouseenter=\"activeIndex = idx\"\n >\n <span :class=\"cls.e('item-label')\">{{ item.label }}</span>\n <u-icon\n v-if=\"!isFlat && hasChildren(item)\"\n :class=\"cls.e('item-expand')\"\n title=\"展开下一级\"\n @click.stop=\"expandInto(item)\"\n >\n <ArrowRight />\n </u-icon>\n </li>\n </u-scroll>\n </div>\n <div v-else :class=\"cls.e('empty')\">\n <UEmpty description=\"暂无可用变量\" />\n </div>\n\n <PathPreview v-if=\"isFlat && activePath.length > 0\" :path=\"activePath\" />\n </div>\n\n <div v-if=\"currentList.length > 0\" :class=\"cls.e('picker-hint')\">\n <template v-if=\"isFlat\">\n <span><kbd>↑</kbd><kbd>↓</kbd> 选择</span>\n <span><kbd>Enter</kbd> 确认</span>\n <span><kbd>Esc</kbd> 关闭</span>\n </template>\n <template v-else>\n <span><kbd>↑</kbd><kbd>↓</kbd> 选择</span>\n <span><kbd>→</kbd> 展开</span>\n <span><kbd>←</kbd> 返回</span>\n <span><kbd>Enter</kbd> 确认</span>\n <span><kbd>Esc</kbd> 关闭</span>\n </template>\n </div>\n </div>\n </template>\n </u-tip>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ArrowRight } from '@veltra/icons/normal'\nimport { bem } from '@veltra/utils'\nimport { computed, nextTick, ref, useTemplateRef, watch } from 'vue'\n\nimport type { VariableItem } from '../../../types'\nimport { UEmpty } from '../../empty'\nimport { UIcon } from '../../icon'\nimport { UScroll } from '../../scroll'\nimport { UTip } from '../../tip'\nimport PathPreview from './path-preview.vue'\n\ndefineOptions({ name: 'UVariablePicker' })\n\ninterface FlatItem extends VariableItem {\n /** 仅扁平模式使用:从根到当前节点的路径 */\n __path: VariableItem[]\n}\n\nconst props = defineProps<{\n visible: boolean\n triggerDom?: HTMLElement\n /** 顶层变量树 */\n variables?: VariableItem[]\n /** 来自编辑器 mention 状态的过滤字符串。空 = 逐级模式;非空 = 扁平模式。 */\n filter: string\n /** 是否允许选中分支节点 */\n selectableLevels: 'leaf' | 'any'\n}>()\n\nconst emit = defineEmits<{\n (e: 'select', item: VariableItem): void\n (e: 'update:visible', visible: boolean): void\n /** 用户主动取消(按 Esc)。编辑器据此把 mention 状态置为 dismissed。 */\n (e: 'dismiss'): void\n}>()\n\nconst cls = bem('expression-editor')\n\nconst navPath = ref<VariableItem[]>([])\nconst activeIndex = ref(0)\nconst root = useTemplateRef('root')\nconst listScroll = useTemplateRef<InstanceType<typeof UScroll>>('listScroll')\n\nconst isFlat = computed(() => props.filter !== '')\n\nfunction hasChildren(item: VariableItem): boolean {\n return !!item.children && item.children.length > 0\n}\n\nfunction isLeaf(item: VariableItem): boolean {\n return !hasChildren(item)\n}\n\n/** 当前层级展示的列表(来源依模式而定) */\nconst currentList = computed<VariableItem[]>(() => {\n const variables = props.variables ?? []\n if (isFlat.value) return flatList.value\n let level: VariableItem[] = variables\n for (const node of navPath.value) {\n const found = level.find((it) => it.value === node.value)\n if (!found || !found.children) break\n level = found.children\n }\n return level\n})\n\n/** 扁平模式下:根据 selectableLevels 拍平 + 过滤 */\nconst flatList = computed<FlatItem[]>(() => {\n const variables = props.variables ?? []\n const out: FlatItem[] = []\n const includeBranches = props.selectableLevels === 'any'\n function walk(items: VariableItem[], path: VariableItem[]) {\n for (const it of items) {\n const nextPath = [...path, it]\n if (isLeaf(it)) {\n out.push({ ...it, __path: nextPath })\n } else {\n if (includeBranches) out.push({ ...it, __path: nextPath })\n walk(it.children!, nextPath)\n }\n }\n }\n walk(variables, [])\n const q = props.filter.toLowerCase()\n return out.filter((it) => it.label.toLowerCase().includes(q))\n})\n\n/** 当前 active 项;扁平模式下用于驱动路径预览 */\nconst activePath = computed<VariableItem[]>(() => {\n if (!isFlat.value) return []\n const item = flatList.value[activeIndex.value] as FlatItem | undefined\n return item ? item.__path : []\n})\n\nfunction getItemCls(_item: VariableItem, idx: number) {\n return [cls.e('item'), bem.is('active', idx === activeIndex.value)]\n}\n\nfunction navigateTo(i: number) {\n // 0 = 全部变量;i 之后表示进入到 navPath[i-1]\n navPath.value = navPath.value.slice(0, i)\n activeIndex.value = 0\n}\n\nfunction handleItemClick(item: VariableItem, idx: number) {\n activeIndex.value = idx\n selectActive()\n}\n\nfunction selectActive() {\n const item = currentList.value[activeIndex.value]\n if (!item) return\n\n if (isFlat.value) {\n // 扁平模式始终是「选中并替换」\n emit('select', flattenSourceFor(item))\n return\n }\n\n // 逐级模式\n if (hasChildren(item)) {\n if (props.selectableLevels === 'any') {\n // Enter 在分支项上:选中分支本身\n emit('select', item)\n return\n }\n // 默认 'leaf':进入下一级\n expandInto(item)\n return\n }\n emit('select', item)\n}\n\n/** 进入 item 的下一级(点击展开图标 / leaf 模式点击分支项共用) */\nfunction expandInto(item: VariableItem) {\n if (!hasChildren(item)) return\n navPath.value = [...navPath.value, item]\n activeIndex.value = 0\n}\n\nfunction flattenSourceFor(it: VariableItem): VariableItem {\n const flat = it as FlatItem\n // 还原为「不带 __path 的纯 VariableItem」,避免泄漏内部字段\n const out: VariableItem = { value: flat.value, label: flat.label }\n if (flat.type) out.type = flat.type\n if (flat.children) out.children = flat.children\n return out\n}\n\nfunction moveActive(delta: -1 | 1) {\n const max = currentList.value.length - 1\n if (max < 0) return\n let next = activeIndex.value + delta\n if (next < 0) next = 0\n if (next > max) next = max\n activeIndex.value = next\n scrollActiveIntoView()\n}\n\nfunction scrollActiveIntoView() {\n void nextTick(() => {\n // 在面板根节点内查找,避免同页多个编辑器时滚错列表\n const item = root.value?.querySelector(`[data-idx=\"${activeIndex.value}\"]`)\n // expose 代理运行时会解包 ref,类型上按 unknown 收窄\n const scroller = listScroll.value?.containerRef as unknown\n if (!(item instanceof HTMLElement) || !(scroller instanceof HTMLElement)) return\n // 只滚面板列表自身:原生 scrollIntoView 会沿所有滚动祖先链滚动,\n // 面板贴近视口边缘时会连带滚动页面,导致面板与触发器错位抖动\n const top =\n item.getBoundingClientRect().top - scroller.getBoundingClientRect().top + scroller.scrollTop\n const bottom = top + item.offsetHeight\n if (top < scroller.scrollTop) {\n scroller.scrollTop = top\n } else if (bottom > scroller.scrollTop + scroller.clientHeight) {\n scroller.scrollTop = bottom - scroller.clientHeight\n }\n })\n}\n\nfunction handleVisibleChange(v: boolean) {\n emit('update:visible', v)\n if (!v) reset()\n}\n\nfunction reset() {\n navPath.value = []\n activeIndex.value = 0\n}\n\nwatch(\n () => props.visible,\n (v) => {\n if (!v) reset()\n else activeIndex.value = 0\n }\n)\n\nwatch(\n () => props.filter,\n () => {\n // 过滤词变化:重置 active;逐级 → 扁平时清空 navPath\n activeIndex.value = 0\n if (isFlat.value) navPath.value = []\n }\n)\n\n/**\n * 由父级 forward 进来的键盘事件。\n * 返回 true 表示已处理(外部应 preventDefault)。\n */\nfunction handleKeydown(e: KeyboardEvent): boolean {\n if (!props.visible) return false\n\n switch (e.key) {\n case 'Escape':\n emit('dismiss')\n emit('update:visible', false)\n reset()\n return true\n case 'ArrowDown':\n moveActive(1)\n return true\n case 'ArrowUp':\n moveActive(-1)\n return true\n case 'ArrowLeft':\n // 仅逐级模式:返回上一级;扁平模式下不拦截,让光标正常移动并触发 mention dismiss\n if (!isFlat.value && navPath.value.length > 0) {\n navPath.value = navPath.value.slice(0, -1)\n activeIndex.value = 0\n return true\n }\n return false\n case 'ArrowRight': {\n if (isFlat.value) return false\n const item = currentList.value[activeIndex.value]\n if (item && hasChildren(item)) {\n expandInto(item)\n return true\n }\n return false\n }\n case 'Enter':\n selectActive()\n return true\n default:\n return false\n }\n}\n\ndefineExpose({ handleKeydown })\n</script>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"expression-editor.js","names":[],"sources":["../../../src/components/expression-editor/expression-editor.vue"],"sourcesContent":["<template>\n <div ref=\"rootEl\" :class=\"cls.b\">\n <!-- 提示行独立在边框盒(shell)之外 -->\n <div v-if=\"showHint\" :class=\"cls.e('hint')\">输入 <kbd>@</kbd> 唤起变量面板</div>\n\n <div :class=\"shellClass\">\n <div :class=\"cls.e('body')\">\n <div\n ref=\"container\"\n :class=\"cls.e('container')\"\n :contenteditable=\"!readonly && !disabled\"\n :data-empty=\"visualEmpty || 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 </div>\n\n <!-- mention 面板的定位锚点:跟随 `@` 字符位置(见 positionMentionAnchor) -->\n <span ref=\"mentionAnchor\" :class=\"cls.e('mention-anchor')\" aria-hidden=\"true\"></span>\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: 'UExpressionEditor' })\n\nconst props = withDefaults(defineProps<ExpressionEditorProps>(), {\n placeholder: '请输入表达式,输入 @ 可插入变量',\n selectableLevels: 'leaf',\n // Boolean prop 缺省会被 Vue 归一成 false,挡住 UForm 下发的 disabled / readonly,须显式留 undefined\n disabled: undefined,\n readonly: undefined\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 rootElRef = useTemplateRef<HTMLDivElement>('rootEl')\nconst mentionAnchorRef = useTemplateRef<HTMLSpanElement>('mentionAnchor')\nconst pickerRef = useTemplateRef<{ handleKeydown: (e: KeyboardEvent) => boolean }>('pickerRef')\n\n/** 视觉盒(边框 / 背景 / 聚焦光晕 / 尺寸态)挂在 shell 上,根节点只做布局 */\nconst shellClass = computed(() => [\n cls.e('shell'),\n cls.em('shell', 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>([])\n/** 框内视觉空态:与 IME 合成状态无关,由 editor 在 DOM 变化时上报 */\nconst visualEmpty = shallowRef(true)\nconst showPlaceholder = computed(() => visualEmpty.value && !disabled.value)\n/** 上方 `@` 使用提示常驻:只跟可编辑状态走,不随内容增减隐藏 */\nconst showHint = computed(() => !disabled.value && !readonly.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\n/** 把 mention 锚点移到 `@` 字符下方,面板据此定位 */\nfunction positionMentionAnchor(anchorOffset: number) {\n const rootEl = rootElRef.value\n const anchor = mentionAnchorRef.value\n const rect = editorRef.value?.getRectAtOffset(anchorOffset)\n if (!rootEl || !anchor || !rect) return\n // absolute 定位以 padding box 为基准,需扣除根节点边框宽度\n const rootRect = rootEl.getBoundingClientRect()\n anchor.style.left = `${rect.left - rootRect.left - rootEl.clientLeft}px`\n anchor.style.top = `${rect.bottom - rootRect.top - rootEl.clientTop}px`\n}\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 positionMentionAnchor(state.anchorOffset)\n pickerTriggerDom.value = mentionAnchorRef.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 onVisualEmptyChange: (empty) => {\n visualEmpty.value = empty\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 // chip 的 mousedown 被 preventDefault,编辑器没有焦点时点击 chip 焦点不会转移,\n // 键盘导航依赖 container 的 keydown,这里主动把焦点拉回编辑器\n containerRef.value?.focus()\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
+ {"version":3,"file":"expression-editor.js","names":["_openBlock","_createElementBlock","_normalizeClass","_unref","_createCommentVNode","_createTextVNode","_createElementVNode","_toDisplayString","_createVNode","VariablePicker"],"sources":["../../../src/components/expression-editor/expression-editor.vue"],"sourcesContent":["<template>\n <div ref=\"rootEl\" :class=\"cls.b\">\n <!-- 提示行独立在边框盒(shell)之外 -->\n <div v-if=\"showHint\" :class=\"cls.e('hint')\">输入 <kbd>@</kbd> 唤起变量面板</div>\n\n <div :class=\"shellClass\">\n <div :class=\"cls.e('body')\">\n <div\n ref=\"container\"\n :class=\"cls.e('container')\"\n :contenteditable=\"!readonly && !disabled\"\n :data-empty=\"visualEmpty || 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 </div>\n\n <!-- mention 面板的定位锚点:跟随 `@` 字符位置(见 positionMentionAnchor) -->\n <span ref=\"mentionAnchor\" :class=\"cls.e('mention-anchor')\" aria-hidden=\"true\"></span>\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: 'UExpressionEditor' })\n\nconst props = withDefaults(defineProps<ExpressionEditorProps>(), {\n placeholder: '请输入表达式,输入 @ 可插入变量',\n selectableLevels: 'leaf',\n // Boolean prop 缺省会被 Vue 归一成 false,挡住 UForm 下发的 disabled / readonly,须显式留 undefined\n disabled: undefined,\n readonly: undefined\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 rootElRef = useTemplateRef<HTMLDivElement>('rootEl')\nconst mentionAnchorRef = useTemplateRef<HTMLSpanElement>('mentionAnchor')\nconst pickerRef = useTemplateRef<{ handleKeydown: (e: KeyboardEvent) => boolean }>('pickerRef')\n\n/** 视觉盒(边框 / 背景 / 聚焦光晕 / 尺寸态)挂在 shell 上,根节点只做布局 */\nconst shellClass = computed(() => [\n cls.e('shell'),\n cls.em('shell', 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>([])\n/** 框内视觉空态:与 IME 合成状态无关,由 editor 在 DOM 变化时上报 */\nconst visualEmpty = shallowRef(true)\nconst showPlaceholder = computed(() => visualEmpty.value && !disabled.value)\n/** 上方 `@` 使用提示常驻:只跟可编辑状态走,不随内容增减隐藏 */\nconst showHint = computed(() => !disabled.value && !readonly.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\n/** 把 mention 锚点移到 `@` 字符下方,面板据此定位 */\nfunction positionMentionAnchor(anchorOffset: number) {\n const rootEl = rootElRef.value\n const anchor = mentionAnchorRef.value\n const rect = editorRef.value?.getRectAtOffset(anchorOffset)\n if (!rootEl || !anchor || !rect) return\n // absolute 定位以 padding box 为基准,需扣除根节点边框宽度\n const rootRect = rootEl.getBoundingClientRect()\n anchor.style.left = `${rect.left - rootRect.left - rootEl.clientLeft}px`\n anchor.style.top = `${rect.bottom - rootRect.top - rootEl.clientTop}px`\n}\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 positionMentionAnchor(state.anchorOffset)\n pickerTriggerDom.value = mentionAnchorRef.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 onVisualEmptyChange: (empty) => {\n visualEmpty.value = empty\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 // chip 的 mousedown 被 preventDefault,编辑器没有焦点时点击 chip 焦点不会转移,\n // 键盘导航依赖 container 的 keydown,这里主动把焦点拉回编辑器\n containerRef.value?.focus()\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 +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: 'UFilePicker' })\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;GACtC,MAAM,gBAAgB,MAAM,QAAQ,SAAS,YAAY,MAAM,MAAM,MAAM,CAAC;GAC5E,KAAK,QAAQ,aAAa;EAC5B;EAEA,MAAM,gBAAgB,MAAa;GACjC,MAAM,SAAS,EAAE;GACjB,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,CAAC,CAAC;GAC3C,aAAa,KAAK;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;GACnB,MAAM,QAAQ,MAAM,KAAK,EAAE,cAAc,SAAS,CAAC,CAAC;GACpD,aAAa,KAAK;EACpB;EAEA,SAAS,oBAAoB;GAC3B,IAAI,MAAM,UAAU;GACpB,QAAQ,OAAO,MAAM;EACvB;;GA7EE,OAAA,UAAA,GAAA,YAoBY,wBAnBL,QAAA,GAAG,GAAA;IACP,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,CAAC;IACZ,SAAK,cAAO,mBAAiB,CAAA,MAAA,CAAA;IAC7B,YAAQ,cAAU,gBAAc,CAAA,SAAA,CAAA;IAChC,aAAW;IACX,QAAI,cAAU,YAAU,CAAA,SAAA,CAAA;;IAEzB,SAAA,cAUE,CAVF,mBAUE,SAAA;KATC,UAAU,QAAA;KACV,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA,CAAA;KACb,MAAK;KACJ,QAAQ,QAAA;KACT,QAAA;KACA,aAAY;KACR,SAAA;KAAJ,KAAI;KACH,UAAQ;KACT,SAAQ;IAEV,GAAA,MAAA,IAAA,UAAA,GAAA,WAAkC,KAAA,QAAA,WAAA,EAA3B,YAAa,WAAA,MAAU,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"file-picker.js","names":["_openBlock","_createBlock","_resolveDynamicComponent","_normalizeClass","_unref","_withModifiers","_withCtx","_createElementVNode","_renderSlot"],"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: 'UFilePicker' })\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;GACtC,MAAM,gBAAgB,MAAM,QAAQ,SAAS,YAAY,MAAM,MAAM,MAAM,CAAC;GAC5E,KAAK,QAAQ,aAAa;EAC5B;EAEA,MAAM,gBAAgB,MAAa;GACjC,MAAM,SAAS,EAAE;GACjB,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,CAAC,CAAC;GAC3C,aAAa,KAAK;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;GACnB,MAAM,QAAQ,MAAM,KAAK,EAAE,cAAc,SAAS,CAAC,CAAC;GACpD,aAAa,KAAK;EACpB;EAEA,SAAS,oBAAoB;GAC3B,IAAI,MAAM,UAAU;GACpB,QAAQ,OAAO,MAAM;EACvB;;GA7EE,OAAAA,UAAA,GAAAC,YAoBYC,wBAnBL,QAAA,GAAG,GAAA;IACP,OAAKC,eAAEC,MAAA,GAAA,CAAG,CAAC,CAAC;IACZ,SAAKC,cAAO,mBAAiB,CAAA,MAAA,CAAA;IAC7B,YAAQA,cAAU,gBAAc,CAAA,SAAA,CAAA;IAChC,aAAW;IACX,QAAIA,cAAU,YAAU,CAAA,SAAA,CAAA;;IAEzB,SAAAC,cAUE,CAVFC,mBAUE,SAAA;KATC,UAAU,QAAA;KACV,OAAKJ,eAAEC,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA,CAAA;KACb,MAAK;KACJ,QAAQ,QAAA;KACT,QAAA;KACA,aAAY;KACR,SAAA;KAAJ,KAAI;KACH,UAAQ;KACT,SAAQ;IAEV,GAAA,MAAA,IAAA,UAAA,GAAAI,WAAkC,KAAA,QAAA,WAAA,EAA3B,YAAa,WAAA,MAAU,CAAA,CAAA,CAAA"}
@@ -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=\"handlePreviewerZoomChange\"\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: 'UFileViewer', 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 / OFD 由各自 previewer 内部缩放) */\nconst TRANSFORMABLE_KINDS = new Set<FileViewerKind>(['image'])\n/** 工具栏显示缩放控件的类型 */\nconst ZOOMABLE_KINDS = new Set<FileViewerKind>(['image', 'pdf', 'ofd'])\n/** 缩放由 previewer 内部实现、组件只透传命令并回显级别的类型 */\nconst DELEGATED_ZOOM_KINDS = new Set<FileViewerKind>(['pdf', 'ofd'])\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 previewerZoomLevel = 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 ofd: defineAsyncComponent(() => import('./previewers/ofd-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 isDelegatedZoom = computed(\n () => !!activeFile.value && DELEGATED_ZOOM_KINDS.has(activeFile.value.kind)\n)\n\nconst canPan = computed(() => isTransformable.value && scale.value > 1)\n\nconst displayZoomLevel = computed(() =>\n isDelegatedZoom.value ? previewerZoomLevel.value : scale.value\n)\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 (isDelegatedZoom.value) {\n return Math.abs(previewerZoomLevel.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 (isDelegatedZoom.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 (isDelegatedZoom.value) {\n previewerRef.value?.zoomOut?.()\n return\n }\n setScale(scale.value - SCALE_STEP)\n}\n\nfunction resetTransform() {\n if (isDelegatedZoom.value) {\n previewerRef.value?.resetZoom?.()\n previewerZoomLevel.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 handlePreviewerZoomChange(level: number) {\n previewerZoomLevel.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 (isDelegatedZoom.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 previewerZoomLevel.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":["_useModel","_openBlock","_createBlock","_Teleport","_createVNode","_Transition","_withCtx","_createElementBlock","_normalizeClass","_unref","_withModifiers","_createCommentVNode","_createElementVNode","_normalizeStyle","_toDisplayString","UScroll","_Fragment","_renderList","UEmpty","UIcon","_resolveDynamicComponent"],"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=\"handlePreviewerZoomChange\"\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: 'UFileViewer', 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 / OFD 由各自 previewer 内部缩放) */\nconst TRANSFORMABLE_KINDS = new Set<FileViewerKind>(['image'])\n/** 工具栏显示缩放控件的类型 */\nconst ZOOMABLE_KINDS = new Set<FileViewerKind>(['image', 'pdf', 'ofd'])\n/** 缩放由 previewer 内部实现、组件只透传命令并回显级别的类型 */\nconst DELEGATED_ZOOM_KINDS = new Set<FileViewerKind>(['pdf', 'ofd'])\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 previewerZoomLevel = 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 ofd: defineAsyncComponent(() => import('./previewers/ofd-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 isDelegatedZoom = computed(\n () => !!activeFile.value && DELEGATED_ZOOM_KINDS.has(activeFile.value.kind)\n)\n\nconst canPan = computed(() => isTransformable.value && scale.value > 1)\n\nconst displayZoomLevel = computed(() =>\n isDelegatedZoom.value ? previewerZoomLevel.value : scale.value\n)\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 (isDelegatedZoom.value) {\n return Math.abs(previewerZoomLevel.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 (isDelegatedZoom.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 (isDelegatedZoom.value) {\n previewerRef.value?.zoomOut?.()\n return\n }\n setScale(scale.value - SCALE_STEP)\n}\n\nfunction resetTransform() {\n if (isDelegatedZoom.value) {\n previewerRef.value?.resetZoom?.()\n previewerZoomLevel.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 handlePreviewerZoomChange(level: number) {\n previewerZoomLevel.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 (isDelegatedZoom.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 previewerZoomLevel.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 +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: 'UFileViewerDocxPreviewer', 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;;GA5EC,OAAA,UAAA,GAAA,YAGW,MAAA,WAAA,GAHX,WAGW;IAHD,KAAI;IAAO,OAAO,MAAA,GAAA,CAAG,CAAC,EAAC,MAAA;GAAkB,GAAA,MAAA,KAAA,CAAK,GAAA;IACtD,SAAA,cAAmD,CAAnD,mBAAmD,OAAA;KAA1C,SAAA;KAAJ,KAAI;KAAa,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA;IACvB,GAAA,MAAA,CAAA,GAAA,QAAA,SAAX,UAAA,GAAA,mBAAwD,OAAA;;KAAnC,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;IAAa,GAAA,QAAI,CAAA,KAAA,mBAAA,QAAA,IAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"docx-previewer.js","names":["_openBlock","_createBlock","_unref","UScroll","_mergeProps","_withCtx","_createElementVNode","_normalizeClass","_createElementBlock","_createCommentVNode"],"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: 'UFileViewerDocxPreviewer', 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;;GA5EC,OAAAA,UAAA,GAAAC,YAGWC,MAAAC,WAAA,GAHXC,WAGW;IAHD,KAAI;IAAO,OAAOF,MAAA,GAAA,CAAG,CAAC,EAAC,MAAA;GAAkB,GAAAA,MAAA,KAAA,CAAK,GAAA;IACtD,SAAAG,cAAmD,CAAnDC,mBAAmD,OAAA;KAA1C,SAAA;KAAJ,KAAI;KAAa,OAAKC,eAAEL,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA;IACvB,GAAA,MAAA,CAAA,GAAA,QAAA,SAAXF,UAAA,GAAAQ,mBAAwD,OAAA;;KAAnC,OAAKD,eAAEL,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;IAAa,GAAA,QAAI,CAAA,KAAAO,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: 'UFileViewerImagePreviewer', 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;;GA7DC,OAAA,UAAA,GAAA,mBAYM,OAZN,WAYM,EAZA,OAAO,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,EAAmB,GAAA,MAAA,KAAA,CAAK,GAAA;IAEhC,IAAA,SADR,UAAA,GAAA,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,SAAX,UAAA,GAAA,mBAAwD,OAAA;;KAAnC,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;IAAa,GAAA,QAAI,CAAA,KAAA,mBAAA,QAAA,IAAA;IACvC,OAAA,SAAX,UAAA,GAAA,mBAAyD,OAAA;;KAArC,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;IAAa,GAAA,UAAM,CAAA,KAAA,mBAAA,QAAA,IAAA"}
1
+ {"version":3,"file":"image-previewer.js","names":["_openBlock","_createElementBlock","_mergeProps","_unref","_withModifiers","_createCommentVNode","_normalizeClass"],"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: 'UFileViewerImagePreviewer', 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;;GA7DC,OAAAA,UAAA,GAAAC,mBAYM,OAZNC,WAYM,EAZA,OAAOC,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,EAAmB,GAAAA,MAAA,KAAA,CAAK,GAAA;IAEhC,IAAA,SADRH,UAAA,GAAAC,mBAQE,OAAA;;KANC,KAAK,IAAA;KACL,KAAK,QAAA,KAAK;KACX,WAAU;KACT,aAAS,OAAA,OAAA,OAAA,KAAAG,oBAAV,CAAA,GAAkB,CAAA,SAAA,CAAA;KACjB,QAAI,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,QAAO;KACb,SAAO;;IAEC,QAAA,SAAXJ,UAAA,GAAAC,mBAAwD,OAAA;;KAAnC,OAAKK,eAAEH,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;IAAa,GAAA,QAAI,CAAA,KAAAE,mBAAA,QAAA,IAAA;IACvC,OAAA,SAAXL,UAAA,GAAAC,mBAAyD,OAAA;;KAArC,OAAKK,eAAEH,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;IAAa,GAAA,UAAM,CAAA,KAAAE,mBAAA,QAAA,IAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ofd-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/ofd-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('ofd')\">\n <div ref=\"scroll\" :class=\"cls.e('ofd-scroll')\">\n <div\n v-for=\"(page, i) in pages\"\n :key=\"i\"\n :data-index=\"i\"\n :class=\"cls.e('ofd-page')\"\n :style=\"{\n width: page.widthPx * zoomLevel + 'px',\n height: page.heightPx * zoomLevel + 'px'\n }\"\n >\n <div v-if=\"page.svg\" :class=\"cls.e('ofd-page-body')\" v-html=\"page.svg\" />\n </div>\n <div v-if=\"!pages.length && !loading\" :class=\"cls.e('empty')\">\n <u-empty text=\"该文件没有可预览的页面\" :size=\"32\" />\n </div>\n </div>\n <div v-if=\"loading\" :class=\"cls.e('loading')\">正在解析 OFD…</div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { nextTick, onBeforeUnmount, ref, useTemplateRef, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { UEmpty } from '../../empty'\nimport { toArrayBuffer } from '../helper'\n\ndefineOptions({ name: 'UFileViewerOfdPreviewer' })\n\n/** 仅类型查询;运行时动态 import 按需加载,构建时随 alwaysBundle 内联进 dist */\ntype OfdCoreModule = typeof import('@veltra/ofd-core')\ntype OfdContainer = import('@veltra/ofd-core').OfdContainer\ntype OfdZip = import('@veltra/ofd-core').OfdZip\n\n/** OFD 毫米 → CSS 像素(96dpi),与内核 SVG 输出的换算一致 */\nconst PX_PER_MM = 96 / 25.4\n\nconst MIN_ZOOM = 0.5\nconst MAX_ZOOM = 3\n/** 每次缩放固定增减 10%,对齐 pdf 缩放配置 */\nconst ZOOM_STEP = 0.1\n/** 可视区上下各预渲染一个视口高度的页 */\nconst RENDER_MARGIN = '100% 0px'\n\ninterface OfdPageView {\n docIndex: number\n pageIndex: number\n /** 页面基准尺寸(缩放 1 时),毫米按 96dpi 换算为像素 */\n widthPx: number\n heightPx: number\n /** null = 未渲染;'' = 已尝试但渲染失败,不再重试 */\n svg: string | null\n}\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 scrollEl = useTemplateRef<HTMLDivElement>('scroll')\nconst loading = ref(true)\nconst pages = ref<OfdPageView[]>([])\nconst zoomLevel = ref(1)\n\nlet controller: AbortController | undefined\n/** 递增 token:防止切文件后旧解析/渲染结果落地 */\nlet loadToken = 0\nlet ofdCore: OfdCoreModule | undefined\nlet observer: IntersectionObserver | undefined\nlet activeZip: OfdZip | undefined\nlet activeContainer: OfdContainer | undefined\n/** 已进入渲染流程(进行中或已完成)的页,防止滚动重复触发 */\nconst scheduledPages = new Set<number>()\n\n// ---- 缩放:作用于页面容器尺寸,滚动高度随之自适应 ----\n\nfunction clampZoom(value: number): number {\n return Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, Math.round(value * 100) / 100))\n}\n\nfunction setZoom(value: number) {\n const next = clampZoom(value)\n if (zoomLevel.value === next) return\n zoomLevel.value = next\n emit('zoom-change', next)\n}\n\nfunction zoomIn() {\n setZoom(zoomLevel.value + ZOOM_STEP)\n}\n\nfunction zoomOut() {\n setZoom(zoomLevel.value - ZOOM_STEP)\n}\n\nfunction resetZoom() {\n setZoom(1)\n}\n\ndefineExpose({ zoomIn, zoomOut, resetZoom })\n\n// ---- 解析与懒渲染 ----\n\n/** 动态加载 ofd-core chunk;首次加载后缓存模块复用 */\nasync function resolveOfdCore(): Promise<OfdCoreModule> {\n const mod = ofdCore ?? (await import('@veltra/ofd-core'))\n ofdCore = mod\n return mod\n}\n\nfunction teardownRender() {\n observer?.disconnect()\n observer = undefined\n activeZip = undefined\n activeContainer = undefined\n scheduledPages.clear()\n}\n\nfunction observePages() {\n const root = scrollEl.value\n if (!root || typeof IntersectionObserver === 'undefined') return\n observer = new IntersectionObserver(\n (entries) => {\n const token = loadToken\n for (const entry of entries) {\n if (!entry.isIntersecting) continue\n observer?.unobserve(entry.target)\n const index = Number((entry.target as HTMLElement).dataset.index)\n if (Number.isNaN(index) || scheduledPages.has(index)) continue\n scheduledPages.add(index)\n void renderPage(index, token)\n }\n },\n { root, rootMargin: RENDER_MARGIN }\n )\n for (const el of root.querySelectorAll<HTMLElement>('[data-index]')) {\n observer.observe(el)\n }\n}\n\n/** 渲染单页 SVG;失败置空串避免滚动时反复重试同一页 */\nasync function renderPage(index: number, token: number) {\n const page = pages.value[index]\n const core = ofdCore\n if (!page || page.svg !== null || !core || !activeZip || !activeContainer) return\n try {\n const svg = await core.pageToSvg(activeZip, activeContainer, page.docIndex, page.pageIndex)\n if (token !== loadToken) return\n pages.value[index] = { ...page, svg }\n } catch (err) {\n if (token !== loadToken) return\n pages.value[index] = { ...page, svg: '' }\n emit('error', err)\n }\n}\n\nasync function load() {\n const token = ++loadToken\n controller?.abort()\n controller = new AbortController()\n teardownRender()\n loading.value = true\n pages.value = []\n\n try {\n const core = await resolveOfdCore()\n if (token !== loadToken) return\n\n const buf = await toArrayBuffer(props.file.src, controller.signal)\n if (token !== loadToken) return\n const zip = core.openOfdZip(new Uint8Array(buf))\n const container = await core.parseOfdContainer(zip)\n if (token !== loadToken) return\n\n activeZip = zip\n activeContainer = container\n // 未声明尺寸时按 A4 兜底,与内核 pageToSvg 的兜底一致\n pages.value = container.docs.flatMap((doc, docIndex) =>\n doc.pages.map((page) => {\n const size = page.size ?? doc.pageSize ?? { width: 210, height: 297 }\n return {\n docIndex,\n pageIndex: page.index,\n widthPx: Math.round(size.width * PX_PER_MM),\n heightPx: Math.round(size.height * PX_PER_MM),\n svg: null\n }\n })\n )\n await nextTick()\n if (token !== loadToken) return\n observePages()\n } catch (err) {\n if (token !== loadToken) return\n if ((err as { name?: string })?.name === 'AbortError') return\n emit('error', err)\n } finally {\n if (token === loadToken) loading.value = false\n }\n}\n\nwatch(() => props.file, load, { immediate: true })\n\nonBeforeUnmount(() => {\n controller?.abort()\n teardownRender()\n pages.value = []\n})\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"ofd-previewer.js","names":["_openBlock","_createElementBlock","_normalizeClass","_unref","_createElementVNode","_Fragment","_renderList","_normalizeStyle","_createCommentVNode","_createVNode","UEmpty"],"sources":["../../../../src/components/file-viewer/previewers/ofd-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('ofd')\">\n <div ref=\"scroll\" :class=\"cls.e('ofd-scroll')\">\n <div\n v-for=\"(page, i) in pages\"\n :key=\"i\"\n :data-index=\"i\"\n :class=\"cls.e('ofd-page')\"\n :style=\"{\n width: page.widthPx * zoomLevel + 'px',\n height: page.heightPx * zoomLevel + 'px'\n }\"\n >\n <div v-if=\"page.svg\" :class=\"cls.e('ofd-page-body')\" v-html=\"page.svg\" />\n </div>\n <div v-if=\"!pages.length && !loading\" :class=\"cls.e('empty')\">\n <u-empty text=\"该文件没有可预览的页面\" :size=\"32\" />\n </div>\n </div>\n <div v-if=\"loading\" :class=\"cls.e('loading')\">正在解析 OFD…</div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { nextTick, onBeforeUnmount, ref, useTemplateRef, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { UEmpty } from '../../empty'\nimport { toArrayBuffer } from '../helper'\n\ndefineOptions({ name: 'UFileViewerOfdPreviewer' })\n\n/** 仅类型查询;运行时动态 import 按需加载,构建时随 alwaysBundle 内联进 dist */\ntype OfdCoreModule = typeof import('@veltra/ofd-core')\ntype OfdContainer = import('@veltra/ofd-core').OfdContainer\ntype OfdZip = import('@veltra/ofd-core').OfdZip\n\n/** OFD 毫米 → CSS 像素(96dpi),与内核 SVG 输出的换算一致 */\nconst PX_PER_MM = 96 / 25.4\n\nconst MIN_ZOOM = 0.5\nconst MAX_ZOOM = 3\n/** 每次缩放固定增减 10%,对齐 pdf 缩放配置 */\nconst ZOOM_STEP = 0.1\n/** 可视区上下各预渲染一个视口高度的页 */\nconst RENDER_MARGIN = '100% 0px'\n\ninterface OfdPageView {\n docIndex: number\n pageIndex: number\n /** 页面基准尺寸(缩放 1 时),毫米按 96dpi 换算为像素 */\n widthPx: number\n heightPx: number\n /** null = 未渲染;'' = 已尝试但渲染失败,不再重试 */\n svg: string | null\n}\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 scrollEl = useTemplateRef<HTMLDivElement>('scroll')\nconst loading = ref(true)\nconst pages = ref<OfdPageView[]>([])\nconst zoomLevel = ref(1)\n\nlet controller: AbortController | undefined\n/** 递增 token:防止切文件后旧解析/渲染结果落地 */\nlet loadToken = 0\nlet ofdCore: OfdCoreModule | undefined\nlet observer: IntersectionObserver | undefined\nlet activeZip: OfdZip | undefined\nlet activeContainer: OfdContainer | undefined\n/** 已进入渲染流程(进行中或已完成)的页,防止滚动重复触发 */\nconst scheduledPages = new Set<number>()\n\n// ---- 缩放:作用于页面容器尺寸,滚动高度随之自适应 ----\n\nfunction clampZoom(value: number): number {\n return Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, Math.round(value * 100) / 100))\n}\n\nfunction setZoom(value: number) {\n const next = clampZoom(value)\n if (zoomLevel.value === next) return\n zoomLevel.value = next\n emit('zoom-change', next)\n}\n\nfunction zoomIn() {\n setZoom(zoomLevel.value + ZOOM_STEP)\n}\n\nfunction zoomOut() {\n setZoom(zoomLevel.value - ZOOM_STEP)\n}\n\nfunction resetZoom() {\n setZoom(1)\n}\n\ndefineExpose({ zoomIn, zoomOut, resetZoom })\n\n// ---- 解析与懒渲染 ----\n\n/** 动态加载 ofd-core chunk;首次加载后缓存模块复用 */\nasync function resolveOfdCore(): Promise<OfdCoreModule> {\n const mod = ofdCore ?? (await import('@veltra/ofd-core'))\n ofdCore = mod\n return mod\n}\n\nfunction teardownRender() {\n observer?.disconnect()\n observer = undefined\n activeZip = undefined\n activeContainer = undefined\n scheduledPages.clear()\n}\n\nfunction observePages() {\n const root = scrollEl.value\n if (!root || typeof IntersectionObserver === 'undefined') return\n observer = new IntersectionObserver(\n (entries) => {\n const token = loadToken\n for (const entry of entries) {\n if (!entry.isIntersecting) continue\n observer?.unobserve(entry.target)\n const index = Number((entry.target as HTMLElement).dataset.index)\n if (Number.isNaN(index) || scheduledPages.has(index)) continue\n scheduledPages.add(index)\n void renderPage(index, token)\n }\n },\n { root, rootMargin: RENDER_MARGIN }\n )\n for (const el of root.querySelectorAll<HTMLElement>('[data-index]')) {\n observer.observe(el)\n }\n}\n\n/** 渲染单页 SVG;失败置空串避免滚动时反复重试同一页 */\nasync function renderPage(index: number, token: number) {\n const page = pages.value[index]\n const core = ofdCore\n if (!page || page.svg !== null || !core || !activeZip || !activeContainer) return\n try {\n const svg = await core.pageToSvg(activeZip, activeContainer, page.docIndex, page.pageIndex)\n if (token !== loadToken) return\n pages.value[index] = { ...page, svg }\n } catch (err) {\n if (token !== loadToken) return\n pages.value[index] = { ...page, svg: '' }\n emit('error', err)\n }\n}\n\nasync function load() {\n const token = ++loadToken\n controller?.abort()\n controller = new AbortController()\n teardownRender()\n loading.value = true\n pages.value = []\n\n try {\n const core = await resolveOfdCore()\n if (token !== loadToken) return\n\n const buf = await toArrayBuffer(props.file.src, controller.signal)\n if (token !== loadToken) return\n const zip = core.openOfdZip(new Uint8Array(buf))\n const container = await core.parseOfdContainer(zip)\n if (token !== loadToken) return\n\n activeZip = zip\n activeContainer = container\n // 未声明尺寸时按 A4 兜底,与内核 pageToSvg 的兜底一致\n pages.value = container.docs.flatMap((doc, docIndex) =>\n doc.pages.map((page) => {\n const size = page.size ?? doc.pageSize ?? { width: 210, height: 297 }\n return {\n docIndex,\n pageIndex: page.index,\n widthPx: Math.round(size.width * PX_PER_MM),\n heightPx: Math.round(size.height * PX_PER_MM),\n svg: null\n }\n })\n )\n await nextTick()\n if (token !== loadToken) return\n observePages()\n } catch (err) {\n if (token !== loadToken) return\n if ((err as { name?: string })?.name === 'AbortError') return\n emit('error', err)\n } finally {\n if (token === loadToken) loading.value = false\n }\n}\n\nwatch(() => props.file, load, { immediate: true })\n\nonBeforeUnmount(() => {\n controller?.abort()\n teardownRender()\n pages.value = []\n})\n</script>\n"],"mappings":"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"}
@@ -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: 'UFileViewerPdfPreviewer', 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":"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"}
1
+ {"version":3,"file":"pdf-previewer.js","names":["_openBlock","_createElementBlock","_mergeProps","_unref","_normalizeClass","_createBlock","_withCtx","PdfZoomBridge","_createCommentVNode","_createVNode","PdfViewportScroll","_createElementVNode","_normalizeStyle"],"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: 'UFileViewerPdfPreviewer', 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":"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"}
@@ -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: 'UFileViewerPdfViewportScroll' })\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;;GAlGC,OAAA,WAAQ,KAAA,QAAA,SAAA"}
1
+ {"version":3,"file":"pdf-viewport-scroll.js","names":["_renderSlot"],"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: 'UFileViewerPdfViewportScroll' })\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;;GAlGC,OAAAA,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: 'UFileViewerPdfZoomBridge' })\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;;GAzBzE,OAAA,UAAA,GAAA,mBAAkC,QAAlC,UAAkC"}
1
+ {"version":3,"file":"pdf-zoom-bridge.js","names":["_openBlock","_createElementBlock"],"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: 'UFileViewerPdfZoomBridge' })\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;;GAzBzE,OAAAA,UAAA,GAAAC,mBAAkC,QAAlC,UAAkC"}