@veltra/desktop 1.0.9 → 1.0.11

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 (109) hide show
  1. package/dist/components/action/action-group.vue.d.ts +1 -1
  2. package/dist/components/action/action.vue.d.ts +3 -3
  3. package/dist/components/auto-complete/auto-complete.vue.d.ts +1 -1
  4. package/dist/components/batch-edit/batch-edit.js.map +1 -1
  5. package/dist/components/batch-edit/style.js +2 -2
  6. package/dist/components/batch-edit/use-edit.js.map +1 -1
  7. package/dist/components/button/button.js.map +1 -1
  8. package/dist/components/button/button.vue.d.ts +1 -1
  9. package/dist/components/cascade/cascade.vue.d.ts +6 -6
  10. package/dist/components/cascade/use-select.js.map +1 -1
  11. package/dist/components/checkbox-group/checkbox-group.js.map +1 -1
  12. package/dist/components/code-editor/code-editor.js +2 -0
  13. package/dist/components/code-editor/code-editor.js.map +1 -1
  14. package/dist/components/date-panel/date-panel.js.map +1 -1
  15. package/dist/components/date-panel/date-panel.vue.d.ts +1 -1
  16. package/dist/components/date-picker/date-picker.vue.d.ts +1 -1
  17. package/dist/components/date-range-picker/date-range-picker.vue.d.ts +1 -1
  18. package/dist/components/drawer/drawer.js.map +1 -1
  19. package/dist/components/expression-editor/expression-editor.js.map +1 -1
  20. package/dist/components/expression-editor/internal/editor-runtime/create-runtime.js.map +1 -1
  21. package/dist/components/expression-editor/internal/features/commands/register-command-packs.js.map +1 -1
  22. package/dist/components/expression-editor/internal/features/insertion/insertion-service.js.map +1 -1
  23. package/dist/components/expression-editor/use-decorators.js.map +1 -1
  24. package/dist/components/expression-editor/use-expression-drag-drop.js.map +1 -1
  25. package/dist/components/file-picker/file-picker.js.map +1 -1
  26. package/dist/components/file-picker/file-picker.vue.d.ts +1 -1
  27. package/dist/components/file-viewer/file-viewer.js +195 -30
  28. package/dist/components/file-viewer/file-viewer.js.map +1 -1
  29. package/dist/components/file-viewer/previewers/docx-previewer.js +7 -5
  30. package/dist/components/file-viewer/previewers/docx-previewer.js.map +1 -1
  31. package/dist/components/file-viewer/previewers/image-previewer.js +6 -6
  32. package/dist/components/file-viewer/previewers/image-previewer.js.map +1 -1
  33. package/dist/components/file-viewer/previewers/pdf-previewer.js +5 -3
  34. package/dist/components/file-viewer/previewers/pdf-previewer.js.map +1 -1
  35. package/dist/components/file-viewer/previewers/sheet-previewer.js.map +1 -1
  36. package/dist/components/file-viewer/style2.css +387 -136
  37. package/dist/components/form/form-model.js +2 -1
  38. package/dist/components/form/form-model.js.map +1 -1
  39. package/dist/components/grid/grid.js.map +1 -1
  40. package/dist/components/grid/use-responsive.js.map +1 -1
  41. package/dist/components/grid-input/grid-input.vue.d.ts +1 -1
  42. package/dist/components/input/input.vue.d.ts +3 -3
  43. package/dist/components/list/list.js.map +1 -1
  44. package/dist/components/loading/directive.js.map +1 -1
  45. package/dist/components/menu/menu-item.js.map +1 -1
  46. package/dist/components/message/message2.js.map +1 -1
  47. package/dist/components/multi-select/multi-select.js.map +1 -1
  48. package/dist/components/multi-select/multi-select.vue.d.ts +3 -3
  49. package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +6 -6
  50. package/dist/components/notification/index.js.map +1 -1
  51. package/dist/components/notification/notification.vue.d.ts +1 -1
  52. package/dist/components/number-input/number-input.js.map +1 -1
  53. package/dist/components/number-input/number-input.vue.d.ts +1 -1
  54. package/dist/components/number-range-input/number-range-input.vue.d.ts +2 -2
  55. package/dist/components/palette/color-transform.js.map +1 -1
  56. package/dist/components/palette/palette-sv.js.map +1 -1
  57. package/dist/components/password-input/password-input.vue.d.ts +1 -1
  58. package/dist/components/pop-confirm/pop-confirm.vue.d.ts +1 -1
  59. package/dist/components/progress/progress.js +1 -1
  60. package/dist/components/progress/progress.js.map +1 -1
  61. package/dist/components/progress-nodes/progress-nodes.js.map +1 -1
  62. package/dist/components/progress-nodes/progress-nodes.vue.d.ts +3 -3
  63. package/dist/components/rich-text-editor/rich-text-editor.js.map +1 -1
  64. package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +2 -2
  65. package/dist/components/rich-text-editor/toolbar.js.map +1 -1
  66. package/dist/components/scroll/scroll.js.map +1 -1
  67. package/dist/components/select/select.vue.d.ts +2 -2
  68. package/dist/components/slider/slider-thumb.js.map +1 -1
  69. package/dist/components/table/di.js.map +1 -1
  70. package/dist/components/table/style.js +1 -1
  71. package/dist/components/table/table-row.js +1 -2
  72. package/dist/components/table/table-row.js.map +1 -1
  73. package/dist/components/table/table.js +1 -2
  74. package/dist/components/table/table.js.map +1 -1
  75. package/dist/components/table/use-columns.js +4 -0
  76. package/dist/components/table/use-columns.js.map +1 -1
  77. package/dist/components/table/use-table.js +25 -0
  78. package/dist/components/table/use-table.js.map +1 -1
  79. package/dist/components/tabs/style2.css +3 -2
  80. package/dist/components/tabs/tabs-horizontal.js +2 -2
  81. package/dist/components/tabs/tabs-horizontal.js.map +1 -1
  82. package/dist/components/tabs/tabs-horizontal.vue.d.ts +14 -3
  83. package/dist/components/tabs/tabs-vertical.js +2 -2
  84. package/dist/components/tabs/tabs-vertical.js.map +1 -1
  85. package/dist/components/tabs/tabs-vertical.vue.d.ts +13 -3
  86. package/dist/components/tabs/tabs.vue.d.ts +2 -2
  87. package/dist/components/text/text.js.map +1 -1
  88. package/dist/components/textarea/textarea.js.map +1 -1
  89. package/dist/components/textarea/textarea.vue.d.ts +3 -3
  90. package/dist/components/theme/theme.js.map +1 -1
  91. package/dist/components/tip/tip.vue.d.ts +2 -2
  92. package/dist/components/tree/tree-node2.js.map +1 -1
  93. package/dist/components/tree/tree.vue.d.ts +2 -2
  94. package/dist/components/tree/use-tree-nodes.js.map +1 -1
  95. package/dist/components/tree-select/tree-select.vue.d.ts +4 -4
  96. package/dist/components/watermark/watermark.vue.d.ts +1 -1
  97. package/package.json +13 -12
  98. package/src/components/code-editor/code-editor.vue +2 -0
  99. package/src/components/file-viewer/file-viewer.vue +250 -24
  100. package/src/components/file-viewer/previewers/docx-previewer.vue +4 -3
  101. package/src/components/file-viewer/previewers/image-previewer.vue +4 -5
  102. package/src/components/file-viewer/previewers/pdf-previewer.vue +4 -3
  103. package/src/components/file-viewer/style.scss +503 -161
  104. package/src/components/progress/progress.vue +1 -1
  105. package/src/components/table/di.ts +51 -53
  106. package/src/components/table/table.vue +0 -1
  107. package/src/components/tabs/style.scss +7 -4
  108. package/src/components/tabs/tabs-horizontal.vue +10 -7
  109. package/src/components/tabs/tabs-vertical.vue +3 -1
@@ -1 +1 @@
1
- {"version":3,"file":"use-expression-drag-drop.js","names":[],"sources":["../../../src/components/expression-editor/use-expression-drag-drop.ts"],"sourcesContent":["import { $getNodeByKey, $getRoot, type LexicalEditor, type LexicalNode } from 'lexical'\n\nimport {\n EXPRESSION_DROP_SCOPE_ATTR,\n EXPRESSION_VARIABLE_DRAG_KEY_ATTR,\n EXPRESSION_VARIABLE_DRAG_MARKER_ATTR,\n EXPRESSION_VARIABLE_DRAG_TYPE\n} from './constants'\nimport { VariableNode } from './nodes/variable-node'\n\ntype Direction = -1 | 1\n\ninterface DragVisualState {\n indicatorEl: HTMLDivElement | null\n sourceEl: HTMLElement | null\n cleanupDragEnd: (() => void) | null\n activePayload: InternalDragPayload | null\n}\n\ninterface DropAnchor {\n x: number\n y: number\n height: number\n}\n\nexport interface VariableNodeDescriptor {\n key: string\n variable: string\n label: string\n}\n\nexport interface InternalDragPayload {\n sourceKey: string\n scopeId: string\n action: 'move-variable'\n}\n\nexport interface ApplyDropReorderOptions {\n payloadText: string | null\n scopeId: string\n targetSlot: number\n focusMovedNode?: boolean\n}\n\nconst DROP_INDICATOR_CLASS = 'expression-editor__drop-indicator'\nconst DRAG_SOURCE_CLASS = 'is-dragging'\n\nconst dragVisualStateMap = new WeakMap<LexicalEditor, DragVisualState>()\n\nfunction getDragVisualState(editor: LexicalEditor): DragVisualState {\n const existing = dragVisualStateMap.get(editor)\n if (existing) return existing\n\n const created: DragVisualState = {\n indicatorEl: null,\n sourceEl: null,\n cleanupDragEnd: null,\n activePayload: null\n }\n dragVisualStateMap.set(editor, created)\n return created\n}\n\nfunction isHTMLElement(target: EventTarget | null): target is HTMLElement {\n return target instanceof HTMLElement\n}\n\nfunction hasChildren(\n node: LexicalNode\n): node is LexicalNode & { getChildren: () => LexicalNode[] } {\n return typeof (node as { getChildren?: unknown }).getChildren === 'function'\n}\n\nfunction traverseVariableNodes(node: LexicalNode, collector: VariableNodeDescriptor[]): void {\n if (node instanceof VariableNode) {\n collector.push({ key: node.getKey(), variable: node.getVariable(), label: node.getLabel() })\n return\n }\n\n if (!hasChildren(node)) return\n node.getChildren().forEach((child) => traverseVariableNodes(child, collector))\n}\n\nfunction $collectVariableNodeDescriptors(): VariableNodeDescriptor[] {\n const collector: VariableNodeDescriptor[] = []\n const root = $getRoot()\n traverseVariableNodes(root, collector)\n return collector\n}\n\nfunction getDropIndicator(rootElement: HTMLElement): HTMLDivElement {\n const existing = rootElement.querySelector<HTMLDivElement>(`.${DROP_INDICATOR_CLASS}`)\n if (existing) return existing\n\n const indicator = document.createElement('div')\n indicator.className = DROP_INDICATOR_CLASS\n indicator.style.opacity = '0'\n rootElement.appendChild(indicator)\n return indicator\n}\n\nfunction getDropAnchors(editor: LexicalEditor): DropAnchor[] {\n const descriptors = collectVariableNodeDescriptors(editor)\n if (descriptors.length === 0) return []\n\n const rects = descriptors\n .map((descriptor) => editor.getElementByKey(descriptor.key))\n .filter((element): element is HTMLElement => element instanceof HTMLElement)\n .map((element) => element.getBoundingClientRect())\n\n if (rects.length === 0) return []\n\n const anchors: DropAnchor[] = []\n const first = rects[0]!\n anchors.push({ x: first.left, y: first.top, height: first.height })\n\n for (let index = 0; index < rects.length - 1; index++) {\n const currentRect = rects[index]!\n const nextRect = rects[index + 1]!\n anchors.push({\n x: (currentRect.right + nextRect.left) / 2,\n y: (currentRect.top + nextRect.top) / 2,\n height: Math.max(currentRect.height, nextRect.height)\n })\n }\n\n const last = rects[rects.length - 1]!\n anchors.push({ x: last.right, y: last.top, height: last.height })\n\n return anchors\n}\n\nfunction getDistance(pointerX: number, pointerY: number, anchor: DropAnchor): number {\n const dx = pointerX - anchor.x\n const dy = pointerY - (anchor.y + anchor.height / 2)\n return dx * dx + dy * dy\n}\n\nexport function supportsNativeDnD(): boolean {\n if (typeof window === 'undefined') return false\n\n const probe = document.createElement('span')\n const hasDragApi = 'draggable' in probe && typeof DataTransfer !== 'undefined'\n const coarsePointer = window.matchMedia?.('(pointer: coarse)').matches ?? false\n\n return hasDragApi && !coarsePointer\n}\n\nexport function collectVariableNodeDescriptors(editor: LexicalEditor): VariableNodeDescriptor[] {\n let descriptors: VariableNodeDescriptor[] = []\n editor.getEditorState().read(() => {\n descriptors = $collectVariableNodeDescriptors()\n })\n return descriptors\n}\n\nexport function ensureDropScopeId(editor: LexicalEditor): string {\n const rootElement = editor.getRootElement()\n if (!rootElement) return ''\n\n const existing = rootElement.getAttribute(EXPRESSION_DROP_SCOPE_ATTR)\n if (existing) return existing\n\n const generated = `scope-${Math.random().toString(36).slice(2)}`\n rootElement.setAttribute(EXPRESSION_DROP_SCOPE_ATTR, generated)\n return generated\n}\n\nexport function findVariableDragSource(target: EventTarget | null): HTMLElement | null {\n if (!isHTMLElement(target)) return null\n\n return target.closest<HTMLElement>(`[${EXPRESSION_VARIABLE_DRAG_MARKER_ATTR}=\"true\"]`)\n}\n\nexport function readDragSourceKey(target: EventTarget | null): string | null {\n const source = findVariableDragSource(target)\n if (!source) return null\n\n return source.getAttribute(EXPRESSION_VARIABLE_DRAG_KEY_ATTR)\n}\n\nexport function createInternalDragPayload(payload: InternalDragPayload): string {\n return JSON.stringify(payload)\n}\n\nexport function writeInternalDragPayload(\n dataTransfer: DataTransfer | null,\n payload: InternalDragPayload\n): void {\n if (!dataTransfer) return\n dataTransfer.setData(EXPRESSION_VARIABLE_DRAG_TYPE, createInternalDragPayload(payload))\n}\n\nexport function parseInternalDragPayload(payloadText: string | null): InternalDragPayload | null {\n if (!payloadText) return null\n\n try {\n const parsed = JSON.parse(payloadText) as Partial<InternalDragPayload>\n if (\n parsed.action !== 'move-variable' ||\n typeof parsed.scopeId !== 'string' ||\n parsed.scopeId.length === 0 ||\n typeof parsed.sourceKey !== 'string' ||\n parsed.sourceKey.length === 0\n ) {\n return null\n }\n\n return { action: parsed.action, scopeId: parsed.scopeId, sourceKey: parsed.sourceKey }\n } catch {\n return null\n }\n}\n\nexport function readInternalDragPayload(\n dataTransfer: DataTransfer | null\n): InternalDragPayload | null {\n if (!dataTransfer) return null\n return parseInternalDragPayload(dataTransfer.getData(EXPRESSION_VARIABLE_DRAG_TYPE))\n}\n\nexport function beginDragVisualState(\n editor: LexicalEditor,\n sourceEl: HTMLElement | null,\n payload?: InternalDragPayload\n): void {\n const state = getDragVisualState(editor)\n clearDragVisualState(editor)\n state.activePayload = payload ?? null\n\n if (!sourceEl) return\n sourceEl.classList.add(DRAG_SOURCE_CLASS)\n state.sourceEl = sourceEl\n\n const onDragEnd = () => {\n clearDragVisualState(editor)\n }\n window.addEventListener('dragend', onDragEnd, true)\n state.cleanupDragEnd = () => {\n window.removeEventListener('dragend', onDragEnd, true)\n }\n}\n\nexport function getActiveInternalDragPayload(editor: LexicalEditor): InternalDragPayload | null {\n return getDragVisualState(editor).activePayload\n}\n\nexport function showDropIndicator(editor: LexicalEditor, slot: number): void {\n const rootElement = editor.getRootElement()\n if (!rootElement) return\n\n const anchors = getDropAnchors(editor)\n if (slot < 0 || slot >= anchors.length) {\n clearDropIndicator(editor)\n return\n }\n\n const anchor = anchors[slot]!\n const indicator = getDropIndicator(rootElement)\n const rootRect = rootElement.getBoundingClientRect()\n\n indicator.style.left = `${anchor.x - rootRect.left}px`\n indicator.style.top = `${anchor.y - rootRect.top}px`\n indicator.style.height = `${anchor.height}px`\n indicator.style.opacity = '1'\n\n const state = getDragVisualState(editor)\n state.indicatorEl = indicator\n}\n\nexport function clearDropIndicator(editor: LexicalEditor): void {\n const state = getDragVisualState(editor)\n if (!state.indicatorEl) return\n state.indicatorEl.style.opacity = '0'\n}\n\nexport function clearDragVisualState(editor: LexicalEditor): void {\n const state = getDragVisualState(editor)\n\n if (state.sourceEl) {\n state.sourceEl.classList.remove(DRAG_SOURCE_CLASS)\n state.sourceEl = null\n }\n\n if (state.indicatorEl) {\n state.indicatorEl.style.opacity = '0'\n state.indicatorEl = null\n }\n\n if (state.cleanupDragEnd) {\n state.cleanupDragEnd()\n state.cleanupDragEnd = null\n }\n\n state.activePayload = null\n}\n\nexport function autoScrollWhenNearEdge(container: HTMLElement, pointerY: number): void {\n const rect = container.getBoundingClientRect()\n const threshold = 24\n const step = 10\n\n if (pointerY < rect.top + threshold) {\n container.scrollBy({ top: -step, behavior: 'auto' })\n return\n }\n\n if (pointerY > rect.bottom - threshold) {\n container.scrollBy({ top: step, behavior: 'auto' })\n }\n}\n\nexport function resolveDropSlot(editor: LexicalEditor, event: DragEvent): number | null {\n const rootElement = editor.getRootElement()\n if (!rootElement || !isHTMLElement(event.target)) return null\n if (!rootElement.contains(event.target)) return null\n\n const anchors = getDropAnchors(editor)\n if (anchors.length === 0) return null\n\n let nearestSlot = 0\n let nearestDistance = Number.POSITIVE_INFINITY\n for (let slot = 0; slot < anchors.length; slot++) {\n const anchor = anchors[slot]!\n const distance = getDistance(event.clientX, event.clientY, anchor)\n if (distance < nearestDistance) {\n nearestDistance = distance\n nearestSlot = slot\n }\n }\n\n return nearestSlot\n}\n\nexport function reorderVariableNode(\n sourceKey: string,\n targetSlot: number,\n focusMovedNode = true\n): boolean {\n const nodes = $collectVariableNodeDescriptors()\n if (nodes.length <= 1) return false\n\n const sourceIndex = nodes.findIndex((item) => item.key === sourceKey)\n if (sourceIndex < 0) return false\n if (targetSlot < 0 || targetSlot > nodes.length) return false\n if (targetSlot === sourceIndex || targetSlot === sourceIndex + 1) return false\n\n const sourceNode = $getNodeByKey(sourceKey)\n if (!(sourceNode instanceof VariableNode)) return false\n\n const remaining = nodes.filter((item) => item.key !== sourceKey)\n const insertionIndex = targetSlot > sourceIndex ? targetSlot - 1 : targetSlot\n const reference = remaining[insertionIndex]\n\n if (reference) {\n const referenceNode = $getNodeByKey(reference.key)\n if (!(referenceNode instanceof VariableNode)) return false\n referenceNode.insertBefore(sourceNode)\n } else {\n const last = remaining[remaining.length - 1]\n if (!last) return false\n const lastNode = $getNodeByKey(last.key)\n if (!(lastNode instanceof VariableNode)) return false\n lastNode.insertAfter(sourceNode)\n }\n\n if (focusMovedNode) {\n sourceNode.selectEnd()\n }\n\n return true\n}\n\nexport function moveVariableByDirection(\n sourceKey: string,\n direction: Direction,\n focusMovedNode = true\n): boolean {\n const nodes = $collectVariableNodeDescriptors()\n const sourceIndex = nodes.findIndex((item) => item.key === sourceKey)\n if (sourceIndex < 0) return false\n\n const targetIndex = sourceIndex + direction\n if (targetIndex < 0 || targetIndex >= nodes.length) return false\n\n const targetSlot = direction === -1 ? targetIndex : targetIndex + 1\n return reorderVariableNode(sourceKey, targetSlot, focusMovedNode)\n}\n\nexport function applyDropReorder(options: ApplyDropReorderOptions): boolean {\n const payload = parseInternalDragPayload(options.payloadText)\n if (!payload) return false\n if (payload.scopeId !== options.scopeId) return false\n\n return reorderVariableNode(payload.sourceKey, options.targetSlot, options.focusMovedNode ?? true)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-expression-drag-drop.js","names":[],"sources":["../../../src/components/expression-editor/use-expression-drag-drop.ts"],"sourcesContent":["import { $getNodeByKey, $getRoot, type LexicalEditor, type LexicalNode } from 'lexical'\n\nimport {\n EXPRESSION_DROP_SCOPE_ATTR,\n EXPRESSION_VARIABLE_DRAG_KEY_ATTR,\n EXPRESSION_VARIABLE_DRAG_MARKER_ATTR,\n EXPRESSION_VARIABLE_DRAG_TYPE\n} from './constants'\nimport { VariableNode } from './nodes/variable-node'\n\ntype Direction = -1 | 1\n\ninterface DragVisualState {\n indicatorEl: HTMLDivElement | null\n sourceEl: HTMLElement | null\n cleanupDragEnd: (() => void) | null\n activePayload: InternalDragPayload | null\n}\n\ninterface DropAnchor {\n x: number\n y: number\n height: number\n}\n\nexport interface VariableNodeDescriptor {\n key: string\n variable: string\n label: string\n}\n\nexport interface InternalDragPayload {\n sourceKey: string\n scopeId: string\n action: 'move-variable'\n}\n\nexport interface ApplyDropReorderOptions {\n payloadText: string | null\n scopeId: string\n targetSlot: number\n focusMovedNode?: boolean\n}\n\nconst DROP_INDICATOR_CLASS = 'expression-editor__drop-indicator'\nconst DRAG_SOURCE_CLASS = 'is-dragging'\n\nconst dragVisualStateMap = new WeakMap<LexicalEditor, DragVisualState>()\n\nfunction getDragVisualState(editor: LexicalEditor): DragVisualState {\n const existing = dragVisualStateMap.get(editor)\n if (existing) return existing\n\n const created: DragVisualState = {\n indicatorEl: null,\n sourceEl: null,\n cleanupDragEnd: null,\n activePayload: null\n }\n dragVisualStateMap.set(editor, created)\n return created\n}\n\nfunction isHTMLElement(target: EventTarget | null): target is HTMLElement {\n return target instanceof HTMLElement\n}\n\nfunction hasChildren(\n node: LexicalNode\n): node is LexicalNode & { getChildren: () => LexicalNode[] } {\n return typeof (node as { getChildren?: unknown }).getChildren === 'function'\n}\n\nfunction traverseVariableNodes(node: LexicalNode, collector: VariableNodeDescriptor[]): void {\n if (node instanceof VariableNode) {\n collector.push({ key: node.getKey(), variable: node.getVariable(), label: node.getLabel() })\n return\n }\n\n if (!hasChildren(node)) return\n node.getChildren().forEach((child) => traverseVariableNodes(child, collector))\n}\n\nfunction $collectVariableNodeDescriptors(): VariableNodeDescriptor[] {\n const collector: VariableNodeDescriptor[] = []\n const root = $getRoot()\n traverseVariableNodes(root, collector)\n return collector\n}\n\nfunction getDropIndicator(rootElement: HTMLElement): HTMLDivElement {\n const existing = rootElement.querySelector<HTMLDivElement>(`.${DROP_INDICATOR_CLASS}`)\n if (existing) return existing\n\n const indicator = document.createElement('div')\n indicator.className = DROP_INDICATOR_CLASS\n indicator.style.opacity = '0'\n rootElement.appendChild(indicator)\n return indicator\n}\n\nfunction getDropAnchors(editor: LexicalEditor): DropAnchor[] {\n const descriptors = collectVariableNodeDescriptors(editor)\n if (descriptors.length === 0) return []\n\n const rects = descriptors\n .map((descriptor) => editor.getElementByKey(descriptor.key))\n .filter((element): element is HTMLElement => element instanceof HTMLElement)\n .map((element) => element.getBoundingClientRect())\n\n if (rects.length === 0) return []\n\n const anchors: DropAnchor[] = []\n const first = rects[0]!\n anchors.push({ x: first.left, y: first.top, height: first.height })\n\n for (let index = 0; index < rects.length - 1; index++) {\n const currentRect = rects[index]!\n const nextRect = rects[index + 1]!\n anchors.push({\n x: (currentRect.right + nextRect.left) / 2,\n y: (currentRect.top + nextRect.top) / 2,\n height: Math.max(currentRect.height, nextRect.height)\n })\n }\n\n const last = rects[rects.length - 1]!\n anchors.push({ x: last.right, y: last.top, height: last.height })\n\n return anchors\n}\n\nfunction getDistance(pointerX: number, pointerY: number, anchor: DropAnchor): number {\n const dx = pointerX - anchor.x\n const dy = pointerY - (anchor.y + anchor.height / 2)\n return dx * dx + dy * dy\n}\n\nexport function supportsNativeDnD(): boolean {\n if (typeof window === 'undefined') return false\n\n const probe = document.createElement('span')\n const hasDragApi = 'draggable' in probe && typeof DataTransfer !== 'undefined'\n const coarsePointer = window.matchMedia?.('(pointer: coarse)').matches ?? false\n\n return hasDragApi && !coarsePointer\n}\n\nexport function collectVariableNodeDescriptors(editor: LexicalEditor): VariableNodeDescriptor[] {\n let descriptors: VariableNodeDescriptor[] = []\n editor.getEditorState().read(() => {\n descriptors = $collectVariableNodeDescriptors()\n })\n return descriptors\n}\n\nexport function ensureDropScopeId(editor: LexicalEditor): string {\n const rootElement = editor.getRootElement()\n if (!rootElement) return ''\n\n const existing = rootElement.getAttribute(EXPRESSION_DROP_SCOPE_ATTR)\n if (existing) return existing\n\n const generated = `scope-${Math.random().toString(36).slice(2)}`\n rootElement.setAttribute(EXPRESSION_DROP_SCOPE_ATTR, generated)\n return generated\n}\n\nexport function findVariableDragSource(target: EventTarget | null): HTMLElement | null {\n if (!isHTMLElement(target)) return null\n\n return target.closest<HTMLElement>(`[${EXPRESSION_VARIABLE_DRAG_MARKER_ATTR}=\"true\"]`)\n}\n\nexport function readDragSourceKey(target: EventTarget | null): string | null {\n const source = findVariableDragSource(target)\n if (!source) return null\n\n return source.getAttribute(EXPRESSION_VARIABLE_DRAG_KEY_ATTR)\n}\n\nexport function createInternalDragPayload(payload: InternalDragPayload): string {\n return JSON.stringify(payload)\n}\n\nexport function writeInternalDragPayload(\n dataTransfer: DataTransfer | null,\n payload: InternalDragPayload\n): void {\n if (!dataTransfer) return\n dataTransfer.setData(EXPRESSION_VARIABLE_DRAG_TYPE, createInternalDragPayload(payload))\n}\n\nexport function parseInternalDragPayload(payloadText: string | null): InternalDragPayload | null {\n if (!payloadText) return null\n\n try {\n const parsed = JSON.parse(payloadText) as Partial<InternalDragPayload>\n if (\n parsed.action !== 'move-variable' ||\n typeof parsed.scopeId !== 'string' ||\n parsed.scopeId.length === 0 ||\n typeof parsed.sourceKey !== 'string' ||\n parsed.sourceKey.length === 0\n ) {\n return null\n }\n\n return { action: parsed.action, scopeId: parsed.scopeId, sourceKey: parsed.sourceKey }\n } catch {\n return null\n }\n}\n\nexport function readInternalDragPayload(\n dataTransfer: DataTransfer | null\n): InternalDragPayload | null {\n if (!dataTransfer) return null\n return parseInternalDragPayload(dataTransfer.getData(EXPRESSION_VARIABLE_DRAG_TYPE))\n}\n\nexport function beginDragVisualState(\n editor: LexicalEditor,\n sourceEl: HTMLElement | null,\n payload?: InternalDragPayload\n): void {\n const state = getDragVisualState(editor)\n clearDragVisualState(editor)\n state.activePayload = payload ?? null\n\n if (!sourceEl) return\n sourceEl.classList.add(DRAG_SOURCE_CLASS)\n state.sourceEl = sourceEl\n\n const onDragEnd = () => {\n clearDragVisualState(editor)\n }\n window.addEventListener('dragend', onDragEnd, true)\n state.cleanupDragEnd = () => {\n window.removeEventListener('dragend', onDragEnd, true)\n }\n}\n\nexport function getActiveInternalDragPayload(editor: LexicalEditor): InternalDragPayload | null {\n return getDragVisualState(editor).activePayload\n}\n\nexport function showDropIndicator(editor: LexicalEditor, slot: number): void {\n const rootElement = editor.getRootElement()\n if (!rootElement) return\n\n const anchors = getDropAnchors(editor)\n if (slot < 0 || slot >= anchors.length) {\n clearDropIndicator(editor)\n return\n }\n\n const anchor = anchors[slot]!\n const indicator = getDropIndicator(rootElement)\n const rootRect = rootElement.getBoundingClientRect()\n\n indicator.style.left = `${anchor.x - rootRect.left}px`\n indicator.style.top = `${anchor.y - rootRect.top}px`\n indicator.style.height = `${anchor.height}px`\n indicator.style.opacity = '1'\n\n const state = getDragVisualState(editor)\n state.indicatorEl = indicator\n}\n\nexport function clearDropIndicator(editor: LexicalEditor): void {\n const state = getDragVisualState(editor)\n if (!state.indicatorEl) return\n state.indicatorEl.style.opacity = '0'\n}\n\nexport function clearDragVisualState(editor: LexicalEditor): void {\n const state = getDragVisualState(editor)\n\n if (state.sourceEl) {\n state.sourceEl.classList.remove(DRAG_SOURCE_CLASS)\n state.sourceEl = null\n }\n\n if (state.indicatorEl) {\n state.indicatorEl.style.opacity = '0'\n state.indicatorEl = null\n }\n\n if (state.cleanupDragEnd) {\n state.cleanupDragEnd()\n state.cleanupDragEnd = null\n }\n\n state.activePayload = null\n}\n\nexport function autoScrollWhenNearEdge(container: HTMLElement, pointerY: number): void {\n const rect = container.getBoundingClientRect()\n const threshold = 24\n const step = 10\n\n if (pointerY < rect.top + threshold) {\n container.scrollBy({ top: -step, behavior: 'auto' })\n return\n }\n\n if (pointerY > rect.bottom - threshold) {\n container.scrollBy({ top: step, behavior: 'auto' })\n }\n}\n\nexport function resolveDropSlot(editor: LexicalEditor, event: DragEvent): number | null {\n const rootElement = editor.getRootElement()\n if (!rootElement || !isHTMLElement(event.target)) return null\n if (!rootElement.contains(event.target)) return null\n\n const anchors = getDropAnchors(editor)\n if (anchors.length === 0) return null\n\n let nearestSlot = 0\n let nearestDistance = Number.POSITIVE_INFINITY\n for (let slot = 0; slot < anchors.length; slot++) {\n const anchor = anchors[slot]!\n const distance = getDistance(event.clientX, event.clientY, anchor)\n if (distance < nearestDistance) {\n nearestDistance = distance\n nearestSlot = slot\n }\n }\n\n return nearestSlot\n}\n\nexport function reorderVariableNode(\n sourceKey: string,\n targetSlot: number,\n focusMovedNode = true\n): boolean {\n const nodes = $collectVariableNodeDescriptors()\n if (nodes.length <= 1) return false\n\n const sourceIndex = nodes.findIndex((item) => item.key === sourceKey)\n if (sourceIndex < 0) return false\n if (targetSlot < 0 || targetSlot > nodes.length) return false\n if (targetSlot === sourceIndex || targetSlot === sourceIndex + 1) return false\n\n const sourceNode = $getNodeByKey(sourceKey)\n if (!(sourceNode instanceof VariableNode)) return false\n\n const remaining = nodes.filter((item) => item.key !== sourceKey)\n const insertionIndex = targetSlot > sourceIndex ? targetSlot - 1 : targetSlot\n const reference = remaining[insertionIndex]\n\n if (reference) {\n const referenceNode = $getNodeByKey(reference.key)\n if (!(referenceNode instanceof VariableNode)) return false\n referenceNode.insertBefore(sourceNode)\n } else {\n const last = remaining[remaining.length - 1]\n if (!last) return false\n const lastNode = $getNodeByKey(last.key)\n if (!(lastNode instanceof VariableNode)) return false\n lastNode.insertAfter(sourceNode)\n }\n\n if (focusMovedNode) {\n sourceNode.selectEnd()\n }\n\n return true\n}\n\nexport function moveVariableByDirection(\n sourceKey: string,\n direction: Direction,\n focusMovedNode = true\n): boolean {\n const nodes = $collectVariableNodeDescriptors()\n const sourceIndex = nodes.findIndex((item) => item.key === sourceKey)\n if (sourceIndex < 0) return false\n\n const targetIndex = sourceIndex + direction\n if (targetIndex < 0 || targetIndex >= nodes.length) return false\n\n const targetSlot = direction === -1 ? targetIndex : targetIndex + 1\n return reorderVariableNode(sourceKey, targetSlot, focusMovedNode)\n}\n\nexport function applyDropReorder(options: ApplyDropReorderOptions): boolean {\n const payload = parseInternalDragPayload(options.payloadText)\n if (!payload) return false\n if (payload.scopeId !== options.scopeId) return false\n\n return reorderVariableNode(payload.sourceKey, options.targetSlot, options.focusMovedNode ?? true)\n}\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({\n name: 'FilePicker'\n})\n\nconst props = withDefaults(defineProps<UploaderProps>(), {\n tag: 'div',\n multiple: false\n})\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":";;;;;;;;;;;;;;;;;;;;;;;;;EAmCA,MAAM,QAAQ;EAKd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,cAAa;EAE7B,MAAM,UAAU,YAA6B;EAC7C,MAAM,aAAa,IAAI,MAAK;EAE5B,MAAM,gBAAgB,UAAkB;AAEtC,QAAK,QADiB,MAAM,QAAQ,SAAS,YAAY,MAAM,MAAM,OAAO,CAAA,CAClD;;EAG5B,MAAM,gBAAgB,MAAa;GACjC,MAAM,SAAS,EAAE;AAEjB,gBADc,MAAM,KAAK,OAAO,SAAS,EAAE,CAAA,CACzB;AAClB,UAAO,QAAQ;;EAGjB,MAAM,kBAAkB,MAAiB;AACvC,OAAI,MAAM,SAAU;AACpB,cAAW,QAAQ;;EAGrB,MAAM,mBAAmB,MAAiB;AACxC,OAAI,MAAM,SAAU;GACpB,MAAM,gBAAgB,EAAE;GACxB,MAAM,gBAAgB,EAAE;AAExB,OAAI,cAAc,SAAS,cAAc,CAAE;AAC3C,cAAW,QAAQ;;EAGrB,MAAM,cAAc,MAAiB;AACnC,OAAI,MAAM,SAAU;AACpB,cAAW,QAAQ;AAEnB,gBADc,MAAM,KAAK,EAAE,cAAc,SAAS,EAAE,CAAA,CAClC;;EAGpB,SAAS,oBAAoB;AAC3B,OAAI,MAAM,SAAU;AACpB,WAAQ,OAAO,OAAM;;;uBAjFrB,YAoBY,wBAnBL,QAAA,IAAG,EAAA;IACP,OAAK,eAAE,MAAA,IAAG,CAAC,EAAC;IACZ,SAAK,cAAO,mBAAiB,CAAA,OAAA,CAAA;IAC7B,YAAQ,cAAU,gBAAc,CAAA,UAAA,CAAA;IAChC,aAAW;IACX,QAAI,cAAU,YAAU,CAAA,UAAA,CAAA;;2BAYvB,CAVF,mBAUE,SAAA;KATC,UAAU,QAAA;KACV,OAAK,eAAE,MAAA,IAAG,CAAC,EAAC,SAAA,CAAA;KACb,MAAK;KACJ,QAAQ,QAAA;KACT,QAAA;KACA,aAAY;cACR;KAAJ,KAAI;KACH,UAAQ;KACT,SAAQ;8BAEV,WAAkC,KAAA,QAAA,WAAA,EAA3B,YAAa,WAAA,OAAU,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"file-picker.js","names":[],"sources":["../../../src/components/file-picker/file-picker.vue"],"sourcesContent":["<template>\n <component\n :is=\"tag\"\n :class=\"cls.b\"\n @click.stop=\"handleClickPicker\"\n @dragover.prevent=\"handleDragover\"\n @dragleave=\"handleDragLeave\"\n @drop.prevent=\"handleDrop\"\n >\n <input\n :multiple=\"multiple\"\n :class=\"cls.e('native')\"\n type=\"file\"\n :accept=\"accept\"\n hidden\n placeholder=\"选择文件\"\n ref=\"fileRef\"\n @change=\"handleChange\"\n capture=\"environment\"\n />\n <slot :is-dragover=\"isDragover\" />\n </component>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { shallowRef, ref } from 'vue'\n\nimport type { UploaderProps, UploaderEmits } from '../../types'\nimport { matchAccept } from './helper'\n\ndefineOptions({\n name: 'FilePicker'\n})\n\nconst props = withDefaults(defineProps<UploaderProps>(), {\n tag: 'div',\n multiple: false\n})\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":";;;;;;;;;;;;;;;;;;;;;;;;;EAmCA,MAAM,QAAQ;EAKd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,cAAa;EAE7B,MAAM,UAAU,YAA6B;EAC7C,MAAM,aAAa,IAAI,MAAK;EAE5B,MAAM,gBAAgB,UAAkB;AAEtC,QAAK,QADiB,MAAM,QAAQ,SAAS,YAAY,MAAM,MAAM,OAAO,CAC/D,CAAa;;EAG5B,MAAM,gBAAgB,MAAa;GACjC,MAAM,SAAS,EAAE;AAEjB,gBADc,MAAM,KAAK,OAAO,SAAS,EAAE,CAC9B,CAAK;AAClB,UAAO,QAAQ;;EAGjB,MAAM,kBAAkB,MAAiB;AACvC,OAAI,MAAM,SAAU;AACpB,cAAW,QAAQ;;EAGrB,MAAM,mBAAmB,MAAiB;AACxC,OAAI,MAAM,SAAU;GACpB,MAAM,gBAAgB,EAAE;GACxB,MAAM,gBAAgB,EAAE;AAExB,OAAI,cAAc,SAAS,cAAc,CAAE;AAC3C,cAAW,QAAQ;;EAGrB,MAAM,cAAc,MAAiB;AACnC,OAAI,MAAM,SAAU;AACpB,cAAW,QAAQ;AAEnB,gBADc,MAAM,KAAK,EAAE,cAAc,SAAS,EAAE,CACvC,CAAK;;EAGpB,SAAS,oBAAoB;AAC3B,OAAI,MAAM,SAAU;AACpB,WAAQ,OAAO,OAAM;;;uBAjFrB,YAoBY,wBAnBL,QAAA,IAAG,EAAA;IACP,OAAK,eAAE,MAAA,IAAG,CAAC,EAAC;IACZ,SAAK,cAAO,mBAAiB,CAAA,OAAA,CAAA;IAC7B,YAAQ,cAAU,gBAAc,CAAA,UAAA,CAAA;IAChC,aAAW;IACX,QAAI,cAAU,YAAU,CAAA,UAAA,CAAA;;2BAYvB,CAVF,mBAUE,SAAA;KATC,UAAU,QAAA;KACV,OAAK,eAAE,MAAA,IAAG,CAAC,EAAC,SAAA,CAAA;KACb,MAAK;KACJ,QAAQ,QAAA;KACT,QAAA;KACA,aAAY;cACR;KAAJ,KAAI;KACH,UAAQ;KACT,SAAQ;8BAEV,WAAkC,KAAA,QAAA,WAAA,EAA3B,YAAa,WAAA,OAAU,CAAA,CAAA,CAAA"}
@@ -13,8 +13,8 @@ declare const __VLS_base: _$vue.DefineComponent<UploaderProps, {}, {}, {}, {}, _
13
13
  }, string, _$vue.PublicProps, Readonly<UploaderProps> & Readonly<{
14
14
  onPick?: ((files: File[]) => any) | undefined;
15
15
  }>, {
16
- tag: string;
17
16
  multiple: boolean;
17
+ tag: string;
18
18
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
19
19
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
20
20
  declare const _default: typeof __VLS_export;
@@ -2,15 +2,23 @@ import _sfc_main$1 from "../icon/icon.js";
2
2
  import _sfc_main$2 from "../scroll/scroll.js";
3
3
  import _sfc_main$3 from "../empty/empty.js";
4
4
  import { FILE_VIEWER_KIND_LABEL, downloadFile, formatBytes, inferKind } from "./helper.js";
5
- import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineAsyncComponent, defineComponent, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, renderList, resolveDynamicComponent, shallowRef, toDisplayString, unref, useModel, watch, withCtx, withModifiers } from "vue";
5
+ import { Fragment, Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineAsyncComponent, defineComponent, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, ref, renderList, resolveDynamicComponent, shallowRef, toDisplayString, unref, useModel, watch, withCtx, withModifiers } from "vue";
6
6
  import { bem, withUnit } from "@veltra/utils";
7
- import { Close } from "@veltra/icons/normal";
7
+ import { ArrowLeft, ArrowRight, Close, Download, Refresh, ZoomIn, ZoomOut } from "@veltra/icons/normal";
8
8
  //#region src/components/file-viewer/file-viewer.vue
9
9
  const _hoisted_1 = ["tabindex"];
10
- const _hoisted_2 = ["onClick"];
10
+ const _hoisted_2 = ["title", "onClick"];
11
11
  const _hoisted_3 = ["title"];
12
- const _hoisted_4 = ["disabled"];
13
- const _hoisted_5 = ["disabled"];
12
+ const _hoisted_4 = ["title"];
13
+ const _hoisted_5 = { key: 0 };
14
+ const _hoisted_6 = ["disabled"];
15
+ const _hoisted_7 = ["disabled"];
16
+ const _hoisted_8 = ["disabled"];
17
+ const _hoisted_9 = ["disabled"];
18
+ const _hoisted_10 = ["disabled"];
19
+ const MIN_SCALE = .5;
20
+ const MAX_SCALE = 3;
21
+ const SCALE_STEP = .25;
14
22
  const _sfc_main = /* @__PURE__ */ defineComponent({
15
23
  name: "FileViewer",
16
24
  inheritAttrs: false,
@@ -62,9 +70,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
62
70
  const props = __props;
63
71
  const emit = __emit;
64
72
  const cls = bem("file-viewer");
73
+ const TRANSFORMABLE_KINDS = new Set([
74
+ "image",
75
+ "pdf",
76
+ "docx"
77
+ ]);
65
78
  const activeId = useModel(__props, "modelValue");
66
79
  const openModel = useModel(__props, "open");
67
80
  const rootRef = shallowRef();
81
+ const scale = ref(1);
82
+ const offsetX = ref(0);
83
+ const offsetY = ref(0);
84
+ const isDragging = ref(false);
85
+ let dragState;
68
86
  const PreviewerMap = {
69
87
  image: defineAsyncComponent(() => import("./previewers/image-previewer.js")),
70
88
  video: defineAsyncComponent(() => import("./previewers/video-previewer.js")),
@@ -90,6 +108,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
90
108
  });
91
109
  /** 是否启用模态模式:只要父组件显式传入 open(含 v-model:open),即进入模态 */
92
110
  const isModal = computed(() => openModel.value !== void 0);
111
+ const activeIndexLabel = computed(() => activeIndex.value >= 0 ? `${activeIndex.value + 1} / ${normalizedFiles.value.length}` : "");
112
+ const isTransformable = computed(() => !!activeFile.value && TRANSFORMABLE_KINDS.has(activeFile.value.kind));
113
+ const canPan = computed(() => isTransformable.value && scale.value > 1);
114
+ const zoomPercent = computed(() => `${Math.round(scale.value * 100)}%`);
115
+ const zoomInDisabled = computed(() => !isTransformable.value || scale.value >= MAX_SCALE);
116
+ const zoomOutDisabled = computed(() => !isTransformable.value || scale.value <= MIN_SCALE);
117
+ const isTransformReset = computed(() => scale.value === 1 && offsetX.value === 0 && offsetY.value === 0);
118
+ const previewerStyle = computed(() => {
119
+ if (!isTransformable.value) return void 0;
120
+ return { transform: `translate3d(${offsetX.value}px, ${offsetY.value}px, 0) scale(${scale.value})` };
121
+ });
93
122
  function label(kind) {
94
123
  return FILE_VIEWER_KIND_LABEL[kind];
95
124
  }
@@ -111,6 +140,65 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
111
140
  const target = normalizedFiles.value[i + 1];
112
141
  if (target) activate(target.id);
113
142
  }
143
+ function normalizeScale(value) {
144
+ return Math.round(Math.min(MAX_SCALE, Math.max(MIN_SCALE, value)) * 100) / 100;
145
+ }
146
+ function setScale(value) {
147
+ scale.value = normalizeScale(value);
148
+ if (scale.value <= 1) {
149
+ offsetX.value = 0;
150
+ offsetY.value = 0;
151
+ }
152
+ }
153
+ function zoomIn() {
154
+ if (!isTransformable.value) return;
155
+ setScale(scale.value + SCALE_STEP);
156
+ }
157
+ function zoomOut() {
158
+ if (!isTransformable.value) return;
159
+ setScale(scale.value - SCALE_STEP);
160
+ }
161
+ function resetTransform() {
162
+ scale.value = 1;
163
+ offsetX.value = 0;
164
+ offsetY.value = 0;
165
+ dragState = void 0;
166
+ isDragging.value = false;
167
+ }
168
+ function isInteractiveTarget(target) {
169
+ if (!(target instanceof HTMLElement)) return false;
170
+ return !!target.closest("button, a, input, textarea, select, video, [contenteditable=\"true\"]");
171
+ }
172
+ function handleViewportPointerDown(e) {
173
+ if (!canPan.value || e.button !== 0 || isInteractiveTarget(e.target)) return;
174
+ dragState = {
175
+ pointerId: e.pointerId,
176
+ startX: e.clientX,
177
+ startY: e.clientY,
178
+ originX: offsetX.value,
179
+ originY: offsetY.value
180
+ };
181
+ isDragging.value = true;
182
+ e.currentTarget.setPointerCapture(e.pointerId);
183
+ e.preventDefault();
184
+ }
185
+ function handleViewportPointerMove(e) {
186
+ if (!dragState || dragState.pointerId !== e.pointerId) return;
187
+ offsetX.value = dragState.originX + e.clientX - dragState.startX;
188
+ offsetY.value = dragState.originY + e.clientY - dragState.startY;
189
+ }
190
+ function handleViewportPointerEnd(e) {
191
+ if (!dragState || dragState.pointerId !== e.pointerId) return;
192
+ const el = e.currentTarget;
193
+ if (el.hasPointerCapture(e.pointerId)) el.releasePointerCapture(e.pointerId);
194
+ dragState = void 0;
195
+ isDragging.value = false;
196
+ }
197
+ function handleViewportDblclick() {
198
+ if (!isTransformable.value) return;
199
+ if (scale.value === 1) setScale(2);
200
+ else resetTransform();
201
+ }
114
202
  async function download() {
115
203
  if (!activeFile.value) return;
116
204
  try {
@@ -152,6 +240,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
152
240
  }
153
241
  if (!activeId.value || !files.some((f) => f.id === activeId.value)) activeId.value = files[0].id;
154
242
  }, { immediate: true });
243
+ watch(() => activeFile.value?.id, () => resetTransform());
155
244
  let previousBodyOverflow = "";
156
245
  let isBodyLocked = false;
157
246
  function lockBody() {
@@ -215,11 +304,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
215
304
  return openBlock(), createElementBlock("li", {
216
305
  key: f.id,
217
306
  class: normalizeClass([unref(cls).e("item"), unref(bem).is("active", f.id === activeId.value)]),
307
+ title: f.name,
218
308
  onClick: ($event) => activate(f.id)
219
- }, [createElementVNode("span", { class: normalizeClass([unref(cls).e("badge"), unref(cls).em("badge", f.kind)]) }, toDisplayString(label(f.kind)), 3), createElementVNode("span", { class: normalizeClass(unref(cls).e("item-meta")) }, [createElementVNode("span", {
309
+ }, [createElementVNode("span", { class: normalizeClass(unref(cls).e("item-meta")) }, [createElementVNode("span", {
220
310
  class: normalizeClass(unref(cls).e("item-name")),
221
311
  title: f.name
222
- }, toDisplayString(f.name), 11, _hoisted_3), createElementVNode("span", { class: normalizeClass(unref(cls).e("item-size")) }, toDisplayString(unref(formatBytes)(f.size)), 3)], 2)], 10, _hoisted_2);
312
+ }, toDisplayString(f.name), 11, _hoisted_3), createElementVNode("span", { class: normalizeClass(unref(cls).e("item-size")) }, toDisplayString(unref(formatBytes)(f.size)), 3)], 2), createElementVNode("span", { class: normalizeClass(unref(cls).e("item-kind")) }, toDisplayString(label(f.kind)), 3)], 10, _hoisted_2);
223
313
  }), 128)), !normalizedFiles.value.length ? (openBlock(), createElementBlock("li", {
224
314
  key: 0,
225
315
  class: normalizeClass(unref(cls).e("list-empty"))
@@ -228,37 +318,93 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
228
318
  size: 32
229
319
  })], 2)) : createCommentVNode("v-if", true)]),
230
320
  _: 1
231
- }, 8, ["class"])], 6)) : createCommentVNode("v-if", true), createElementVNode("section", { class: normalizeClass(unref(cls).e("stage")) }, [createElementVNode("header", { class: normalizeClass(unref(cls).e("stage-head")) }, [createElementVNode("div", { class: normalizeClass(unref(cls).e("stage-title")) }, [
232
- activeFile.value ? (openBlock(), createElementBlock("span", {
233
- key: 0,
234
- class: normalizeClass([unref(cls).e("badge"), unref(cls).em("badge", activeFile.value.kind)])
235
- }, toDisplayString(label(activeFile.value.kind)), 3)) : createCommentVNode("v-if", true),
236
- createElementVNode("span", { class: normalizeClass(unref(cls).e("stage-name")) }, toDisplayString(activeFile.value?.name ?? "—"), 3),
237
- activeFile.value?.size ? (openBlock(), createElementBlock("span", {
238
- key: 1,
239
- class: normalizeClass(unref(cls).e("stage-sub"))
240
- }, toDisplayString(unref(formatBytes)(activeFile.value.size)), 3)) : createCommentVNode("v-if", true)
241
- ], 2), createElementVNode("div", { class: normalizeClass(unref(cls).e("stage-actions")) }, [
242
- createElementVNode("button", {
243
- class: normalizeClass(unref(cls).e("action")),
321
+ }, 8, ["class"])], 6)) : createCommentVNode("v-if", true), createElementVNode("section", { class: normalizeClass(unref(cls).e("stage")) }, [createElementVNode("header", { class: normalizeClass(unref(cls).e("stage-head")) }, [createElementVNode("div", { class: normalizeClass(unref(cls).e("stage-title")) }, [activeFile.value ? (openBlock(), createElementBlock("span", {
322
+ key: 0,
323
+ class: normalizeClass([unref(cls).e("badge"), unref(cls).em("badge", activeFile.value.kind)])
324
+ }, toDisplayString(label(activeFile.value.kind)), 3)) : createCommentVNode("v-if", true), createElementVNode("span", { class: normalizeClass(unref(cls).e("stage-copy")) }, [createElementVNode("span", {
325
+ class: normalizeClass(unref(cls).e("stage-name")),
326
+ title: activeFile.value?.name
327
+ }, toDisplayString(activeFile.value?.name ?? "—"), 11, _hoisted_4), activeFile.value ? (openBlock(), createElementBlock("span", {
328
+ key: 0,
329
+ class: normalizeClass(unref(cls).e("stage-sub"))
330
+ }, [createElementVNode("span", null, toDisplayString(activeIndexLabel.value), 1), activeFile.value.size ? (openBlock(), createElementBlock("span", _hoisted_5, toDisplayString(unref(formatBytes)(activeFile.value.size)), 1)) : createCommentVNode("v-if", true)], 2)) : createCommentVNode("v-if", true)], 2)], 2), createElementVNode("div", { class: normalizeClass(unref(cls).e("stage-actions")) }, [
331
+ createElementVNode("span", { class: normalizeClass(unref(cls).e("action-group")) }, [createElementVNode("button", {
332
+ class: normalizeClass([unref(cls).e("action"), unref(cls).em("action", "icon")]),
244
333
  disabled: !hasPrev.value,
245
334
  type: "button",
335
+ "aria-label": "上一个",
336
+ title: "上一个",
246
337
  onClick: prev
247
- }, " 上一个 ", 10, _hoisted_4),
248
- createElementVNode("button", {
249
- class: normalizeClass(unref(cls).e("action")),
338
+ }, [createVNode(unref(_sfc_main$1), { size: 15 }, {
339
+ default: withCtx(() => [createVNode(unref(ArrowLeft))]),
340
+ _: 1
341
+ })], 10, _hoisted_6), createElementVNode("button", {
342
+ class: normalizeClass([unref(cls).e("action"), unref(cls).em("action", "icon")]),
250
343
  disabled: !hasNext.value,
251
344
  type: "button",
345
+ "aria-label": "下一个",
346
+ title: "下一个",
252
347
  onClick: next
253
- }, " 下一个 ", 10, _hoisted_5),
254
- __props.downloadable && activeFile.value ? (openBlock(), createElementBlock("button", {
348
+ }, [createVNode(unref(_sfc_main$1), { size: 15 }, {
349
+ default: withCtx(() => [createVNode(unref(ArrowRight))]),
350
+ _: 1
351
+ })], 10, _hoisted_7)], 2),
352
+ isTransformable.value ? (openBlock(), createElementBlock("span", {
255
353
  key: 0,
256
- class: normalizeClass([unref(cls).e("action"), unref(cls).em("action", "primary")]),
354
+ class: normalizeClass(unref(cls).e("action-group"))
355
+ }, [
356
+ createElementVNode("button", {
357
+ class: normalizeClass([unref(cls).e("action"), unref(cls).em("action", "icon")]),
358
+ disabled: zoomOutDisabled.value,
359
+ type: "button",
360
+ "aria-label": "缩小",
361
+ title: "缩小",
362
+ onClick: zoomOut
363
+ }, [createVNode(unref(_sfc_main$1), { size: 15 }, {
364
+ default: withCtx(() => [createVNode(unref(ZoomOut))]),
365
+ _: 1
366
+ })], 10, _hoisted_8),
367
+ createElementVNode("span", { class: normalizeClass(unref(cls).e("zoom-value")) }, toDisplayString(zoomPercent.value), 3),
368
+ createElementVNode("button", {
369
+ class: normalizeClass([unref(cls).e("action"), unref(cls).em("action", "icon")]),
370
+ disabled: zoomInDisabled.value,
371
+ type: "button",
372
+ "aria-label": "放大",
373
+ title: "放大",
374
+ onClick: zoomIn
375
+ }, [createVNode(unref(_sfc_main$1), { size: 15 }, {
376
+ default: withCtx(() => [createVNode(unref(ZoomIn))]),
377
+ _: 1
378
+ })], 10, _hoisted_9),
379
+ createElementVNode("button", {
380
+ class: normalizeClass([unref(cls).e("action"), unref(cls).em("action", "icon")]),
381
+ disabled: isTransformReset.value,
382
+ type: "button",
383
+ "aria-label": "重置视图",
384
+ title: "重置视图",
385
+ onClick: resetTransform
386
+ }, [createVNode(unref(_sfc_main$1), { size: 15 }, {
387
+ default: withCtx(() => [createVNode(unref(Refresh))]),
388
+ _: 1
389
+ })], 10, _hoisted_10)
390
+ ], 2)) : createCommentVNode("v-if", true),
391
+ __props.downloadable && activeFile.value ? (openBlock(), createElementBlock("button", {
392
+ key: 1,
393
+ class: normalizeClass([
394
+ unref(cls).e("action"),
395
+ unref(cls).em("action", "primary"),
396
+ unref(cls).em("action", "icon")
397
+ ]),
257
398
  type: "button",
399
+ "aria-label": "下载",
400
+ title: "下载",
258
401
  onClick: download
259
- }, " 下载 ", 2)) : createCommentVNode("v-if", true),
402
+ }, [createVNode(unref(_sfc_main$1), { size: 15 }, {
403
+ default: withCtx(() => [createVNode(unref(Download))]),
404
+ _: 1
405
+ })], 2)) : createCommentVNode("v-if", true),
260
406
  isModal.value ? (openBlock(), createElementBlock("button", {
261
- key: 1,
407
+ key: 2,
262
408
  class: normalizeClass([unref(cls).e("action"), unref(cls).em("action", "icon")]),
263
409
  type: "button",
264
410
  "aria-label": "关闭预览",
@@ -272,12 +418,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
272
418
  name: "u-file-viewer-fade",
273
419
  mode: "out-in"
274
420
  }, {
275
- default: withCtx(() => [activeFile.value ? (openBlock(), createBlock(resolveDynamicComponent(PreviewerMap[activeFile.value.kind]), {
421
+ default: withCtx(() => [activeFile.value ? (openBlock(), createElementBlock("div", {
276
422
  key: activeFile.value.id,
423
+ class: normalizeClass([
424
+ unref(cls).e("viewport"),
425
+ unref(bem).is("transformable", isTransformable.value),
426
+ unref(bem).is("pannable", canPan.value),
427
+ unref(bem).is("dragging", isDragging.value)
428
+ ]),
429
+ onPointerdown: handleViewportPointerDown,
430
+ onPointermove: handleViewportPointerMove,
431
+ onPointerup: handleViewportPointerEnd,
432
+ onPointercancel: handleViewportPointerEnd,
433
+ onDblclick: handleViewportDblclick
434
+ }, [(openBlock(), createBlock(resolveDynamicComponent(PreviewerMap[activeFile.value.kind]), {
277
435
  file: activeFile.value,
278
436
  "max-rows": __props.sheetMaxRows,
437
+ class: normalizeClass(isTransformable.value ? unref(cls).e("previewer") : void 0),
438
+ style: normalizeStyle(previewerStyle.value),
279
439
  onError: handleChildError
280
- }, null, 40, ["file", "max-rows"])) : (openBlock(), createElementBlock("div", {
440
+ }, null, 40, [
441
+ "file",
442
+ "max-rows",
443
+ "class",
444
+ "style"
445
+ ]))], 34)) : (openBlock(), createElementBlock("div", {
281
446
  key: 1,
282
447
  class: normalizeClass(unref(cls).e("empty"))
283
448
  }, [createVNode(unref(_sfc_main$3), { text: "暂无可预览文件" })], 2))]),
@@ -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 @click=\"activate(f.id)\"\n >\n <span :class=\"[cls.e('badge'), cls.em('badge', f.kind)]\">\n {{ label(f.kind) }}\n </span>\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 </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-name')\">\n {{ activeFile?.name ?? '—' }}\n </span>\n <span v-if=\"activeFile?.size\" :class=\"cls.e('stage-sub')\">\n {{ formatBytes(activeFile.size) }}\n </span>\n </div>\n <div :class=\"cls.e('stage-actions')\">\n <button :class=\"cls.e('action')\" :disabled=\"!hasPrev\" type=\"button\" @click=\"prev\">\n 上一个\n </button>\n <button :class=\"cls.e('action')\" :disabled=\"!hasNext\" type=\"button\" @click=\"next\">\n 下一个\n </button>\n <button\n v-if=\"downloadable && activeFile\"\n :class=\"[cls.e('action'), cls.em('action', 'primary')]\"\n type=\"button\"\n @click=\"download\"\n >\n 下载\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 <component\n :is=\"PreviewerMap[activeFile.kind]\"\n v-if=\"activeFile\"\n :key=\"activeFile.id\"\n :file=\"activeFile\"\n :max-rows=\"sheetMaxRows\"\n @error=\"handleChildError\"\n />\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 { Close } from '@veltra/icons/normal'\nimport { bem, withUnit } from '@veltra/utils'\nimport { computed, defineAsyncComponent, nextTick, onBeforeUnmount, shallowRef, watch } 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({\n name: 'FileViewer',\n inheritAttrs: false\n})\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 activeId = defineModel<string | undefined>('modelValue', { default: undefined })\nconst openModel = defineModel<boolean | undefined>('open', { default: undefined })\n\nconst rootRef = shallowRef<HTMLDivElement>()\n\nconst PreviewerMap: Record<FileViewerKind, ReturnType<typeof defineAsyncComponent>> = {\n image: defineAsyncComponent(() => import('./previewers/image-previewer.vue')),\n video: defineAsyncComponent(() => import('./previewers/video-previewer.vue')),\n pdf: defineAsyncComponent(() => import('./previewers/pdf-previewer.vue')),\n sheet: defineAsyncComponent(() => import('./previewers/sheet-previewer.vue')),\n docx: defineAsyncComponent(() => import('./previewers/docx-previewer.vue')),\n text: defineAsyncComponent(() => import('./previewers/text-previewer.vue'))\n}\n\ninterface NormalizedFile extends FileViewerItem {\n id: string\n kind: FileViewerKind\n}\n\nconst normalizedFiles = computed<NormalizedFile[]>(() =>\n props.files.map((f, i) => ({\n ...f,\n id: f.id ?? `file-${i}`,\n kind: inferKind(f.name, f.kind)\n }))\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\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\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\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>({\n activeId,\n activate,\n next,\n prev\n})\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"file-viewer.js","names":[],"sources":["../../../src/components/file-viewer/file-viewer.vue"],"sourcesContent":["<template>\n <Teleport to=\"body\" :disabled=\"!isModal\">\n <transition :name=\"isModal ? 'u-file-viewer-modal' : ''\">\n <div\n v-if=\"!isModal || openModel\"\n :class=\"[cls.b, bem.is('modal', isModal)]\"\n :tabindex=\"isModal ? -1 : undefined\"\n ref=\"rootRef\"\n @mousedown.self=\"handleBackdropMousedown\"\n >\n <div v-if=\"isModal\" :class=\"cls.e('backdrop')\" @mousedown.self=\"handleBackdropMousedown\" />\n <div :class=\"cls.e('inner')\">\n <aside v-if=\"showSidebar\" :class=\"cls.e('sidebar')\" :style=\"{ width: sidebarWidthCss }\">\n <header :class=\"cls.e('sidebar-head')\">\n <span :class=\"cls.e('sidebar-title')\">文件</span>\n <span :class=\"cls.e('sidebar-count')\">{{ normalizedFiles.length }}</span>\n </header>\n <u-scroll tag=\"ul\" :class=\"cls.e('list')\">\n <li\n v-for=\"f in normalizedFiles\"\n :key=\"f.id\"\n :class=\"[cls.e('item'), bem.is('active', f.id === activeId)]\"\n :title=\"f.name\"\n @click=\"activate(f.id)\"\n >\n <span :class=\"cls.e('item-meta')\">\n <span :class=\"cls.e('item-name')\" :title=\"f.name\">{{ f.name }}</span>\n <span :class=\"cls.e('item-size')\">{{ formatBytes(f.size) }}</span>\n </span>\n <span :class=\"cls.e('item-kind')\">{{ label(f.kind) }}</span>\n </li>\n <li v-if=\"!normalizedFiles.length\" :class=\"cls.e('list-empty')\">\n <u-empty text=\"暂无文件\" :size=\"32\" />\n </li>\n </u-scroll>\n </aside>\n\n <section :class=\"cls.e('stage')\">\n <header :class=\"cls.e('stage-head')\">\n <div :class=\"cls.e('stage-title')\">\n <span v-if=\"activeFile\" :class=\"[cls.e('badge'), cls.em('badge', activeFile.kind)]\">\n {{ label(activeFile.kind) }}\n </span>\n <span :class=\"cls.e('stage-copy')\">\n <span :class=\"cls.e('stage-name')\" :title=\"activeFile?.name\">\n {{ activeFile?.name ?? '—' }}\n </span>\n <span v-if=\"activeFile\" :class=\"cls.e('stage-sub')\">\n <span>{{ activeIndexLabel }}</span>\n <span v-if=\"activeFile.size\">{{ formatBytes(activeFile.size) }}</span>\n </span>\n </span>\n </div>\n <div :class=\"cls.e('stage-actions')\">\n <span :class=\"cls.e('action-group')\">\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"!hasPrev\"\n type=\"button\"\n aria-label=\"上一个\"\n title=\"上一个\"\n @click=\"prev\"\n >\n <u-icon :size=\"15\">\n <ArrowLeft />\n </u-icon>\n </button>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"!hasNext\"\n type=\"button\"\n aria-label=\"下一个\"\n title=\"下一个\"\n @click=\"next\"\n >\n <u-icon :size=\"15\">\n <ArrowRight />\n </u-icon>\n </button>\n </span>\n <span v-if=\"isTransformable\" :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=\"handleViewportPointerDown\"\n @pointermove=\"handleViewportPointerMove\"\n @pointerup=\"handleViewportPointerEnd\"\n @pointercancel=\"handleViewportPointerEnd\"\n @dblclick=\"handleViewportDblclick\"\n >\n <component\n :is=\"PreviewerMap[activeFile.kind]\"\n :file=\"activeFile\"\n :max-rows=\"sheetMaxRows\"\n :class=\"isTransformable ? cls.e('previewer') : undefined\"\n :style=\"previewerStyle\"\n @error=\"handleChildError\"\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({\n name: 'FileViewer',\n inheritAttrs: false\n})\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\nconst SCALE_STEP = 0.25\nconst TRANSFORMABLE_KINDS = new Set<FileViewerKind>(['image', 'pdf', 'docx'])\n\nconst activeId = defineModel<string | undefined>('modelValue', { default: undefined })\nconst openModel = defineModel<boolean | undefined>('open', { default: undefined })\n\nconst rootRef = shallowRef<HTMLDivElement>()\nconst scale = ref(1)\nconst offsetX = ref(0)\nconst offsetY = ref(0)\nconst isDragging = ref(false)\n\nlet dragState:\n | {\n pointerId: number\n startX: number\n startY: number\n originX: number\n originY: number\n }\n | undefined\n\nconst PreviewerMap: Record<FileViewerKind, ReturnType<typeof defineAsyncComponent>> = {\n image: defineAsyncComponent(() => import('./previewers/image-previewer.vue')),\n video: defineAsyncComponent(() => import('./previewers/video-previewer.vue')),\n pdf: defineAsyncComponent(() => import('./previewers/pdf-previewer.vue')),\n sheet: defineAsyncComponent(() => import('./previewers/sheet-previewer.vue')),\n docx: defineAsyncComponent(() => import('./previewers/docx-previewer.vue')),\n text: defineAsyncComponent(() => import('./previewers/text-previewer.vue'))\n}\n\ninterface NormalizedFile extends FileViewerItem {\n id: string\n kind: FileViewerKind\n}\n\nconst normalizedFiles = computed<NormalizedFile[]>(() =>\n props.files.map((f, i) => ({\n ...f,\n id: f.id ?? `file-${i}`,\n kind: inferKind(f.name, f.kind)\n }))\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 canPan = computed(() => isTransformable.value && scale.value > 1)\n\nconst zoomPercent = computed(() => `${Math.round(scale.value * 100)}%`)\n\nconst zoomInDisabled = computed(() => !isTransformable.value || scale.value >= MAX_SCALE)\n\nconst zoomOutDisabled = computed(() => !isTransformable.value || scale.value <= MIN_SCALE)\n\nconst isTransformReset = computed(\n () => 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 (!isTransformable.value) return\n setScale(scale.value + SCALE_STEP)\n}\n\nfunction zoomOut() {\n if (!isTransformable.value) return\n setScale(scale.value - SCALE_STEP)\n}\n\nfunction resetTransform() {\n scale.value = 1\n offsetX.value = 0\n offsetY.value = 0\n dragState = undefined\n isDragging.value = false\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 (!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 () => resetTransform()\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>({\n activeId,\n activate,\n next,\n prev\n})\n</script>\n"],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  import _sfc_main$1 from "../../scroll/scroll.js";
2
- import { createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, onBeforeUnmount, openBlock, ref, unref, useTemplateRef, watch, withCtx } from "vue";
2
+ import { createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeProps, normalizeClass, onBeforeUnmount, openBlock, ref, unref, useAttrs, useTemplateRef, watch, withCtx } from "vue";
3
3
  import { bem } from "@veltra/utils";
4
4
  //#region src/components/file-viewer/previewers/docx-previewer.vue
5
5
  const _sfc_main = /* @__PURE__ */ defineComponent({
6
6
  name: "FileViewerDocxPreviewer",
7
+ inheritAttrs: false,
7
8
  __name: "docx-previewer",
8
9
  props: { file: {} },
9
10
  emits: ["error"],
@@ -11,6 +12,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
11
12
  const props = __props;
12
13
  const emit = __emit;
13
14
  const cls = bem("file-viewer");
15
+ const attrs = useAttrs();
14
16
  const container = useTemplateRef("container");
15
17
  const loading = ref(true);
16
18
  let controller;
@@ -53,10 +55,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
53
55
  if (container.value) container.value.innerHTML = "";
54
56
  });
55
57
  return (_ctx, _cache) => {
56
- return openBlock(), createBlock(unref(_sfc_main$1), {
58
+ return openBlock(), createBlock(unref(_sfc_main$1), mergeProps({
57
59
  tag: "div",
58
- class: normalizeClass(unref(cls).e("docx"))
59
- }, {
60
+ class: unref(cls).e("docx")
61
+ }, unref(attrs)), {
60
62
  default: withCtx(() => [createElementVNode("div", {
61
63
  ref_key: "container",
62
64
  ref: container,
@@ -66,7 +68,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
66
68
  class: normalizeClass(unref(cls).e("loading"))
67
69
  }, "加载中…", 2)) : createCommentVNode("v-if", true)]),
68
70
  _: 1
69
- }, 8, ["class"]);
71
+ }, 16, ["class"]);
70
72
  };
71
73
  }
72
74
  });
@@ -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')\">\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, useTemplateRef, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { UScroll } from '../../scroll'\n\ndefineOptions({ name: 'FileViewerDocxPreviewer' })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\n\nconst container = useTemplateRef<HTMLDivElement>('container')\nconst loading = ref(true)\n\nlet controller: AbortController | undefined\n\nasync function load() {\n controller?.abort()\n controller = new AbortController()\n const signal = controller.signal\n loading.value = true\n\n try {\n const [{ toArrayBuffer }, docx] = await Promise.all([\n import('../helper'),\n import('docx-preview')\n ])\n\n const buf = await toArrayBuffer(props.file.src, signal)\n if (signal.aborted) return\n const el = container.value\n if (!el) return\n el.innerHTML = ''\n\n await docx.renderAsync(buf, el, undefined, {\n className: 'u-file-viewer__docx-doc',\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n ignoreFonts: false,\n breakPages: true,\n experimental: false,\n useBase64URL: false,\n renderChanges: false,\n renderHeaders: true,\n renderFooters: true,\n renderFootnotes: true\n })\n } catch (err) {\n if ((err as { name?: string })?.name === 'AbortError') return\n emit('error', err)\n } finally {\n loading.value = false\n }\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n controller?.abort()\n if (container.value) container.value.innerHTML = ''\n})\n</script>\n"],"mappings":";;;;;;;;;;EAgBA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,cAAa;EAE7B,MAAM,YAAY,eAA+B,YAAW;EAC5D,MAAM,UAAU,IAAI,KAAI;EAExB,IAAI;EAEJ,eAAe,OAAO;AACpB,eAAY,OAAM;AAClB,gBAAa,IAAI,iBAAgB;GACjC,MAAM,SAAS,WAAW;AAC1B,WAAQ,QAAQ;AAEhB,OAAI;IACF,MAAM,CAAC,EAAE,iBAAiB,QAAQ,MAAM,QAAQ,IAAI,CAClD,OAAO,iBACP,OAAO,gBACR,CAAA;IAED,MAAM,MAAM,MAAM,cAAc,MAAM,KAAK,KAAK,OAAM;AACtD,QAAI,OAAO,QAAS;IACpB,MAAM,KAAK,UAAU;AACrB,QAAI,CAAC,GAAI;AACT,OAAG,YAAY;AAEf,UAAM,KAAK,YAAY,KAAK,IAAI,KAAA,GAAW;KACzC,WAAW;KACX,WAAW;KACX,aAAa;KACb,cAAc;KACd,aAAa;KACb,YAAY;KACZ,cAAc;KACd,cAAc;KACd,eAAe;KACf,eAAe;KACf,eAAe;KACf,iBAAiB;KAClB,CAAA;YACM,KAAK;AACZ,QAAK,KAA2B,SAAS,aAAc;AACvD,SAAK,SAAS,IAAG;aACT;AACR,YAAQ,QAAQ;;;AAIpB,cACQ,MAAM,YACN,MAAM,EACZ,EAAE,WAAW,MAAK,CACpB;AAEA,wBAAsB;AACpB,eAAY,OAAM;AAClB,OAAI,UAAU,MAAO,WAAU,MAAM,YAAY;IAClD;;uBA3EC,YAGW,MAAA,YAAA,EAAA;IAHD,KAAI;IAAO,OAAK,eAAE,MAAA,IAAG,CAAC,EAAC,OAAA,CAAA;;2BACoB,CAAnD,mBAAmD,OAAA;cAA1C;KAAJ,KAAI;KAAa,OAAK,eAAE,MAAA,IAAG,CAAC,EAAC,YAAA,CAAA;iBACvB,QAAA,SAAA,WAAA,EAAX,mBAAwD,OAAA;;KAAnC,OAAK,eAAE,MAAA,IAAG,CAAC,EAAC,UAAA,CAAA;OAAa,QAAI,EAAA,IAAA,mBAAA,QAAA,KAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"docx-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/docx-previewer.vue"],"sourcesContent":["<template>\n <u-scroll tag=\"div\" :class=\"cls.e('docx')\" v-bind=\"attrs\">\n <div ref=\"container\" :class=\"cls.e('docx-body')\" />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, useAttrs, useTemplateRef, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { UScroll } from '../../scroll'\n\ndefineOptions({ name: 'FileViewerDocxPreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst container = useTemplateRef<HTMLDivElement>('container')\nconst loading = ref(true)\n\nlet controller: AbortController | undefined\n\nasync function load() {\n controller?.abort()\n controller = new AbortController()\n const signal = controller.signal\n loading.value = true\n\n try {\n const [{ toArrayBuffer }, docx] = await Promise.all([\n import('../helper'),\n import('docx-preview')\n ])\n\n const buf = await toArrayBuffer(props.file.src, signal)\n if (signal.aborted) return\n const el = container.value\n if (!el) return\n el.innerHTML = ''\n\n await docx.renderAsync(buf, el, undefined, {\n className: 'u-file-viewer__docx-doc',\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n ignoreFonts: false,\n breakPages: true,\n experimental: false,\n useBase64URL: false,\n renderChanges: false,\n renderHeaders: true,\n renderFooters: true,\n renderFootnotes: true\n })\n } catch (err) {\n if ((err as { name?: string })?.name === 'AbortError') return\n emit('error', err)\n } finally {\n loading.value = false\n }\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n controller?.abort()\n if (container.value) container.value.innerHTML = ''\n})\n</script>\n"],"mappings":";;;;;;;;;;;EAgBA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,cAAa;EAC7B,MAAM,QAAQ,UAAS;EAEvB,MAAM,YAAY,eAA+B,YAAW;EAC5D,MAAM,UAAU,IAAI,KAAI;EAExB,IAAI;EAEJ,eAAe,OAAO;AACpB,eAAY,OAAM;AAClB,gBAAa,IAAI,iBAAgB;GACjC,MAAM,SAAS,WAAW;AAC1B,WAAQ,QAAQ;AAEhB,OAAI;IACF,MAAM,CAAC,EAAE,iBAAiB,QAAQ,MAAM,QAAQ,IAAI,CAClD,OAAO,iBACP,OAAO,gBACR,CAAA;IAED,MAAM,MAAM,MAAM,cAAc,MAAM,KAAK,KAAK,OAAM;AACtD,QAAI,OAAO,QAAS;IACpB,MAAM,KAAK,UAAU;AACrB,QAAI,CAAC,GAAI;AACT,OAAG,YAAY;AAEf,UAAM,KAAK,YAAY,KAAK,IAAI,KAAA,GAAW;KACzC,WAAW;KACX,WAAW;KACX,aAAa;KACb,cAAc;KACd,aAAa;KACb,YAAY;KACZ,cAAc;KACd,cAAc;KACd,eAAe;KACf,eAAe;KACf,eAAe;KACf,iBAAiB;KAClB,CAAA;YACM,KAAK;AACZ,QAAK,KAA2B,SAAS,aAAc;AACvD,SAAK,SAAS,IAAG;aACT;AACR,YAAQ,QAAQ;;;AAIpB,cACQ,MAAM,YACN,MAAM,EACZ,EAAE,WAAW,MAAK,CACpB;AAEA,wBAAsB;AACpB,eAAY,OAAM;AAClB,OAAI,UAAU,MAAO,WAAU,MAAM,YAAY;IAClD;;uBA5EC,YAGW,MAAA,YAAA,EAHX,WAGW;IAHD,KAAI;IAAO,OAAO,MAAA,IAAG,CAAC,EAAC,OAAA;MAAkB,MAAA,MAAK,CAAA,EAAA;2BACH,CAAnD,mBAAmD,OAAA;cAA1C;KAAJ,KAAI;KAAa,OAAK,eAAE,MAAA,IAAG,CAAC,EAAC,YAAA,CAAA;iBACvB,QAAA,SAAA,WAAA,EAAX,mBAAwD,OAAA;;KAAnC,OAAK,eAAE,MAAA,IAAG,CAAC,EAAC,UAAA,CAAA;OAAa,QAAI,EAAA,IAAA,mBAAA,QAAA,KAAA,CAAA,CAAA"}