@veltra/desktop 1.0.10 → 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 (49) 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.vue.d.ts +2 -2
  5. package/dist/components/button/button.vue.d.ts +1 -1
  6. package/dist/components/cascade/cascade.vue.d.ts +6 -6
  7. package/dist/components/checkbox-group/checkbox-group.vue.d.ts +2 -2
  8. package/dist/components/code-editor/code-editor.js +2 -0
  9. package/dist/components/code-editor/code-editor.js.map +1 -1
  10. package/dist/components/date-panel/date-panel.vue.d.ts +1 -1
  11. package/dist/components/date-picker/date-picker.vue.d.ts +1 -1
  12. package/dist/components/date-range-picker/date-range-picker.vue.d.ts +1 -1
  13. package/dist/components/file-picker/file-picker.vue.d.ts +1 -1
  14. package/dist/components/file-viewer/file-viewer.js +195 -30
  15. package/dist/components/file-viewer/file-viewer.js.map +1 -1
  16. package/dist/components/file-viewer/previewers/docx-previewer.js +7 -5
  17. package/dist/components/file-viewer/previewers/docx-previewer.js.map +1 -1
  18. package/dist/components/file-viewer/previewers/image-previewer.js +6 -6
  19. package/dist/components/file-viewer/previewers/image-previewer.js.map +1 -1
  20. package/dist/components/file-viewer/previewers/pdf-previewer.js +5 -3
  21. package/dist/components/file-viewer/previewers/pdf-previewer.js.map +1 -1
  22. package/dist/components/file-viewer/style2.css +387 -136
  23. package/dist/components/grid-input/grid-input.vue.d.ts +1 -1
  24. package/dist/components/input/input.vue.d.ts +3 -3
  25. package/dist/components/multi-select/multi-select.vue.d.ts +4 -4
  26. package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +7 -7
  27. package/dist/components/notification/notification.vue.d.ts +1 -1
  28. package/dist/components/number-input/number-input.vue.d.ts +1 -1
  29. package/dist/components/number-range-input/number-range-input.vue.d.ts +1 -1
  30. package/dist/components/password-input/password-input.vue.d.ts +1 -1
  31. package/dist/components/pop-confirm/pop-confirm.vue.d.ts +2 -2
  32. package/dist/components/radio-group/radio-group.vue.d.ts +2 -2
  33. package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +1 -1
  34. package/dist/components/select/select.vue.d.ts +3 -3
  35. package/dist/components/table/table.vue.d.ts +2 -2
  36. package/dist/components/tabs/tabs-horizontal.vue.d.ts +2 -2
  37. package/dist/components/tabs/tabs-vertical.vue.d.ts +2 -2
  38. package/dist/components/tabs/tabs.vue.d.ts +2 -2
  39. package/dist/components/textarea/textarea.vue.d.ts +4 -4
  40. package/dist/components/tip/tip.vue.d.ts +2 -2
  41. package/dist/components/tree/tree.vue.d.ts +6 -6
  42. package/dist/components/tree-select/tree-select.vue.d.ts +7 -7
  43. package/package.json +13 -12
  44. package/src/components/code-editor/code-editor.vue +2 -0
  45. package/src/components/file-viewer/file-viewer.vue +250 -24
  46. package/src/components/file-viewer/previewers/docx-previewer.vue +4 -3
  47. package/src/components/file-viewer/previewers/image-previewer.vue +4 -5
  48. package/src/components/file-viewer/previewers/pdf-previewer.vue +4 -3
  49. package/src/components/file-viewer/style.scss +503 -161
@@ -8,8 +8,8 @@ type __VLS_Slots = {
8
8
  };
9
9
  declare const __VLS_base: _$vue.DefineComponent<ActionGroupProps, {}, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<ActionGroupProps> & Readonly<{}>, {
10
10
  max: number;
11
- circle: boolean;
12
11
  loading: boolean;
12
+ circle: boolean;
13
13
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
14
14
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
15
15
  declare const _default: typeof __VLS_export;
@@ -15,12 +15,12 @@ declare const __VLS_base: _$vue.DefineComponent<ActionProps, {}, {}, {}, {}, _$v
15
15
  }, string, _$vue.PublicProps, Readonly<ActionProps> & Readonly<{
16
16
  onRun?: (() => any) | undefined;
17
17
  }>, {
18
- size: _$_veltra_utils0.ComponentSize;
19
18
  type: ButtonType;
20
- circle: boolean;
21
- text: boolean;
19
+ size: _$_veltra_utils0.ComponentSize;
22
20
  loading: boolean;
21
+ circle: boolean;
23
22
  inDropdown: boolean;
23
+ text: boolean;
24
24
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
25
25
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
26
26
  declare const _default: typeof __VLS_export;
@@ -25,9 +25,9 @@ declare const __VLS_base: _$vue.DefineComponent<__VLS_PublicProps, {}, {}, {}, {
25
25
  onSelect?: ((value: string) => any) | undefined;
26
26
  }>, {
27
27
  disabled: boolean;
28
- readonly: boolean;
29
28
  placeholder: string;
30
29
  clearable: boolean;
30
+ readonly: boolean;
31
31
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
32
32
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
33
33
  declare const _default: typeof __VLS_export;
@@ -7,9 +7,9 @@ import * as _$_cat_kit_core0 from "@cat-kit/core";
7
7
  //#region src/components/batch-edit/batch-edit.vue.d.ts
8
8
  declare const __VLS_export: <Model extends FormModel>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
9
9
  props: _$vue.PublicProps & __VLS_PrettifyLocal<BatchEditProps<Model> & {
10
- "onUpdate:selected"?: ((value: Record<string, any> | undefined) => any) | undefined;
11
- "onUpdate:checked"?: ((value: Record<string, any>[]) => any) | undefined;
12
10
  "onUpdate:data"?: ((value: Record<string, any>[]) => any) | undefined;
11
+ "onUpdate:checked"?: ((value: Record<string, any>[]) => any) | undefined;
12
+ "onUpdate:selected"?: ((value: Record<string, any> | undefined) => any) | undefined;
13
13
  "onUpdate:rows"?: ((rows: TableRow[]) => any) | undefined;
14
14
  "onUpdate:forest"?: ((rows?: _$_cat_kit_core0.Forest<Record<string, unknown>, any> | undefined) => any) | undefined;
15
15
  "onUpdate:current"?: ((row?: TableRow | undefined) => any) | undefined;
@@ -11,8 +11,8 @@ declare const __VLS_base: _$vue.DefineComponent<ButtonProps, _ButtonExposed, {},
11
11
  }, string, _$vue.PublicProps, Readonly<ButtonProps> & Readonly<{
12
12
  onClick?: ((e: MouseEvent) => any) | undefined;
13
13
  }>, {
14
- disabled: boolean;
15
14
  loadingIcon: _$vue.Component;
15
+ disabled: boolean;
16
16
  iconPosition: "left" | "right";
17
17
  propagate: boolean;
18
18
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
@@ -3,22 +3,22 @@ import * as _$vue from "vue";
3
3
 
4
4
  //#region src/components/cascade/cascade.vue.d.ts
5
5
  declare const __VLS_export: _$vue.DefineComponent<CascadeProps, {}, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {} & {
6
+ clear: () => any;
6
7
  "update:modelValue": (value?: string | string[] | undefined) => any;
7
8
  change: (...args: [value?: string | undefined, label?: string | undefined, item?: Record<string, any> | undefined] | [value: string[], label: string[], data: Record<string, any>[]]) => any;
8
- clear: () => any;
9
9
  }, string, _$vue.PublicProps, Readonly<CascadeProps> & Readonly<{
10
+ onClear?: (() => any) | undefined;
10
11
  "onUpdate:modelValue"?: ((value?: string | string[] | undefined) => any) | undefined;
11
12
  onChange?: ((...args: [value?: string | undefined, label?: string | undefined, item?: Record<string, any> | undefined] | [value: string[], label: string[], data: Record<string, any>[]]) => any) | undefined;
12
- onClear?: (() => any) | undefined;
13
13
  }>, {
14
- labelKey: string;
15
- valueKey: string;
16
14
  disabled: boolean;
17
- readonly: boolean;
18
- separator: string;
19
15
  placeholder: string;
20
16
  clearable: boolean;
17
+ readonly: boolean;
21
18
  data: Record<string, any>[];
19
+ separator: string;
20
+ labelKey: string;
21
+ valueKey: string;
22
22
  childrenKey: string;
23
23
  filterable: boolean;
24
24
  visibilityLimit: number;
@@ -14,10 +14,10 @@ declare const __VLS_export: _$vue.DefineComponent<__VLS_PublicProps, {}, {}, {},
14
14
  }, string, _$vue.PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
15
15
  "onUpdate:modelValue"?: ((value: any[]) => any) | undefined;
16
16
  }>, {
17
- labelKey: string;
18
- valueKey: string;
19
17
  disabled: boolean;
20
18
  readonly: boolean;
19
+ labelKey: string;
20
+ valueKey: string;
21
21
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
22
22
  declare const _default: typeof __VLS_export;
23
23
  //#endregion
@@ -3,6 +3,7 @@ import { computed, createBlock, createElementVNode, defineComponent, mergeModels
3
3
  import { bem, zIndex } from "@veltra/utils";
4
4
  import { useFormComponent, useFormFallbackProps } from "@veltra/compositions";
5
5
  import { EditorState } from "@codemirror/state";
6
+ import { oneDark } from "@codemirror/theme-one-dark";
6
7
  import { tooltips } from "@codemirror/view";
7
8
  import { EditorView, basicSetup } from "codemirror";
8
9
  //#region src/components/code-editor/code-editor.vue
@@ -58,6 +59,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
58
59
  const { language } = props;
59
60
  const extensions = [
60
61
  basicSetup,
62
+ oneDark,
61
63
  tooltips({ parent: document.body }),
62
64
  EditorView.theme({ ".cm-tooltip": { zIndex: zIndex() } })
63
65
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"code-editor.js","names":[],"sources":["../../../src/components/code-editor/code-editor.vue"],"sourcesContent":["<template>\n <u-scroll :class=\"className\" @keyup.enter.stop>\n <div ref=\"container\"></div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { EditorState } from '@codemirror/state'\nimport { tooltips } from '@codemirror/view'\nimport { useFormComponent, useFormFallbackProps } from '@veltra/compositions'\nimport { bem, zIndex } from '@veltra/utils'\nimport { EditorView, basicSetup } from 'codemirror'\nimport { computed, onBeforeUnmount, shallowRef, useTemplateRef, watch } from 'vue'\n\nimport type { CodeEditorLang, CodeEditorProps } from '../../types'\nimport { UScroll } from '../scroll'\n\nconst props = withDefaults(defineProps<CodeEditorProps>(), {\n disabled: undefined,\n readonly: undefined\n})\n\nconst model = defineModel<string>()\n\nconst cls = bem('code-editor')\n\nconst { formProps } = useFormComponent()\n\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst className = computed<string[]>(() => {\n return [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n ]\n})\n\nconst containerRef = useTemplateRef('container')\n\nconst editor = shallowRef<EditorView | null>(null)\n\nconst langLoaders: Record<CodeEditorLang, () => Promise<any>> = {\n js: () => import('@codemirror/lang-javascript').then((m) => m.javascript({ typescript: true })),\n sql: () => import('@codemirror/lang-sql').then((m) => m.sql()),\n java: () => import('@codemirror/lang-java').then((m) => m.java()),\n json: () => import('@codemirror/lang-json').then((m) => m.json())\n}\n\nasync function renderEditor() {\n if (!containerRef.value) return\n editor.value?.destroy()\n\n const { language } = props\n\n const extensions = [\n basicSetup,\n tooltips({\n parent: document.body\n }),\n EditorView.theme({\n '.cm-tooltip': {\n zIndex: zIndex()\n }\n })\n ]\n\n if (disabled.value) {\n extensions.push(EditorView.editable.of(false))\n }\n if (readonly.value) {\n extensions.push(EditorState.readOnly.of(true))\n }\n if (language) {\n const lang = await langLoaders[language]()\n\n extensions.push(lang)\n }\n\n editor.value = new EditorView({\n doc: model.value,\n extensions,\n parent: containerRef.value,\n\n dispatch(tr) {\n editor.value?.update([tr])\n if (tr.changes.empty || !tr.docChanged) {\n return\n }\n model.value = tr.state.doc.toString()\n }\n })\n}\n\nwatch([containerRef, () => props.language, disabled, readonly], renderEditor)\n\nwatch(\n [() => props.modelValue, editor],\n ([v, e]) => {\n if (!e) return\n\n if (e.composing || e.state.doc.toJSON().join('\\n') === v) {\n return\n }\n const isSelectionOutOfRange = !e?.state.selection.ranges.every(\n (range) => range.anchor < (v?.length ?? 0) && range.head < (v?.length ?? 0)\n )\n e?.dispatch({\n changes: {\n from: 0,\n to: e?.state.doc.length,\n insert: v\n },\n selection: isSelectionOutOfRange ? { anchor: 0, head: 0 } : e?.state.selection,\n scrollIntoView: true\n })\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n editor.value?.destroy()\n})\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBA,MAAM,QAAQ;EAKd,MAAM,QAAQ,SAAmB,SAAA,aAAC;EAElC,MAAM,MAAM,IAAI,cAAa;EAE7B,MAAM,EAAE,cAAc,kBAAiB;EAEvC,MAAM,EAAE,MAAM,UAAU,aAAa,qBAAqB,CAAC,aAAa,EAAE,EAAE,MAAM,CAAA;EAElF,MAAM,YAAY,eAAyB;AACzC,UAAO;IACL,IAAI;IACJ,IAAI,EAAE,KAAK,MAAM;IACjB,IAAI,GAAG,YAAY,SAAS,MAAM;IAClC,IAAI,GAAG,YAAY,SAAS,MAAK;IACnC;IACD;EAED,MAAM,eAAe,eAAe,YAAW;EAE/C,MAAM,SAAS,WAA8B,KAAI;EAEjD,MAAM,cAA0D;GAC9D,UAAU,OAAO,+BAA+B,MAAM,MAAM,EAAE,WAAW,EAAE,YAAY,MAAM,CAAC,CAAC;GAC/F,WAAW,OAAO,wBAAwB,MAAM,MAAM,EAAE,KAAK,CAAC;GAC9D,YAAY,OAAO,yBAAyB,MAAM,MAAM,EAAE,MAAM,CAAC;GACjE,YAAY,OAAO,yBAAyB,MAAM,MAAM,EAAE,MAAM,CAAA;GAClE;EAEA,eAAe,eAAe;AAC5B,OAAI,CAAC,aAAa,MAAO;AACzB,UAAO,OAAO,SAAQ;GAEtB,MAAM,EAAE,aAAa;GAErB,MAAM,aAAa;IACjB;IACA,SAAS,EACP,QAAQ,SAAS,MAClB,CAAC;IACF,WAAW,MAAM,EACf,eAAe,EACb,QAAQ,QAAO,EACjB,EACD,CAAA;IACH;AAEA,OAAI,SAAS,MACX,YAAW,KAAK,WAAW,SAAS,GAAG,MAAM,CAAA;AAE/C,OAAI,SAAS,MACX,YAAW,KAAK,YAAY,SAAS,GAAG,KAAK,CAAA;AAE/C,OAAI,UAAU;IACZ,MAAM,OAAO,MAAM,YAAY,WAAU;AAEzC,eAAW,KAAK,KAAI;;AAGtB,UAAO,QAAQ,IAAI,WAAW;IAC5B,KAAK,MAAM;IACX;IACA,QAAQ,aAAa;IAErB,SAAS,IAAI;AACX,YAAO,OAAO,OAAO,CAAC,GAAG,CAAA;AACzB,SAAI,GAAG,QAAQ,SAAS,CAAC,GAAG,WAC1B;AAEF,WAAM,QAAQ,GAAG,MAAM,IAAI,UAAS;;IAEvC,CAAA;;AAGH,QAAM;GAAC;SAAoB,MAAM;GAAU;GAAU;GAAS,EAAE,aAAY;AAE5E,QACE,OAAO,MAAM,YAAY,OAAO,GAC/B,CAAC,GAAG,OAAO;AACV,OAAI,CAAC,EAAG;AAER,OAAI,EAAE,aAAa,EAAE,MAAM,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,EACrD;GAEF,MAAM,wBAAwB,CAAC,GAAG,MAAM,UAAU,OAAO,OACtD,UAAU,MAAM,UAAU,GAAG,UAAU,MAAM,MAAM,QAAQ,GAAG,UAAU,GAC3E;AACA,MAAG,SAAS;IACV,SAAS;KACP,MAAM;KACN,IAAI,GAAG,MAAM,IAAI;KACjB,QAAQ;KACT;IACD,WAAW,wBAAwB;KAAE,QAAQ;KAAG,MAAM;KAAG,GAAG,GAAG,MAAM;IACrE,gBAAgB;IACjB,CAAA;KAEH,EAAE,WAAW,MAAK,CACpB;AAEA,wBAAsB;AACpB,UAAO,OAAO,SAAQ;IACvB;;uBA1HC,YAEW,MAAA,YAAA,EAAA;IAFA,OAAK,eAAE,UAAA,MAAS;IAAG,SAAK,OAAA,OAAA,OAAA,KAAA,SAAA,oBAAN,IAAiB,CAAA,OAAA,CAAA,EAAA,CAAA,QAAA,CAAA;;2BACjB,CAA3B,mBAA2B,OAA3B,YAA2B,MAAA,IAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"code-editor.js","names":[],"sources":["../../../src/components/code-editor/code-editor.vue"],"sourcesContent":["<template>\n <u-scroll :class=\"className\" @keyup.enter.stop>\n <div ref=\"container\"></div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { EditorState } from '@codemirror/state'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { tooltips } from '@codemirror/view'\nimport { useFormComponent, useFormFallbackProps } from '@veltra/compositions'\nimport { bem, zIndex } from '@veltra/utils'\nimport { EditorView, basicSetup } from 'codemirror'\nimport { computed, onBeforeUnmount, shallowRef, useTemplateRef, watch } from 'vue'\n\nimport type { CodeEditorLang, CodeEditorProps } from '../../types'\nimport { UScroll } from '../scroll'\n\nconst props = withDefaults(defineProps<CodeEditorProps>(), {\n disabled: undefined,\n readonly: undefined\n})\n\nconst model = defineModel<string>()\n\nconst cls = bem('code-editor')\n\nconst { formProps } = useFormComponent()\n\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst className = computed<string[]>(() => {\n return [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n ]\n})\n\nconst containerRef = useTemplateRef('container')\n\nconst editor = shallowRef<EditorView | null>(null)\n\nconst langLoaders: Record<CodeEditorLang, () => Promise<any>> = {\n js: () => import('@codemirror/lang-javascript').then((m) => m.javascript({ typescript: true })),\n sql: () => import('@codemirror/lang-sql').then((m) => m.sql()),\n java: () => import('@codemirror/lang-java').then((m) => m.java()),\n json: () => import('@codemirror/lang-json').then((m) => m.json())\n}\n\nasync function renderEditor() {\n if (!containerRef.value) return\n editor.value?.destroy()\n\n const { language } = props\n\n const extensions = [\n basicSetup,\n oneDark,\n tooltips({\n parent: document.body\n }),\n EditorView.theme({\n '.cm-tooltip': {\n zIndex: zIndex()\n }\n })\n ]\n\n if (disabled.value) {\n extensions.push(EditorView.editable.of(false))\n }\n if (readonly.value) {\n extensions.push(EditorState.readOnly.of(true))\n }\n if (language) {\n const lang = await langLoaders[language]()\n\n extensions.push(lang)\n }\n\n editor.value = new EditorView({\n doc: model.value,\n extensions,\n parent: containerRef.value,\n\n dispatch(tr) {\n editor.value?.update([tr])\n if (tr.changes.empty || !tr.docChanged) {\n return\n }\n model.value = tr.state.doc.toString()\n }\n })\n}\n\nwatch([containerRef, () => props.language, disabled, readonly], renderEditor)\n\nwatch(\n [() => props.modelValue, editor],\n ([v, e]) => {\n if (!e) return\n\n if (e.composing || e.state.doc.toJSON().join('\\n') === v) {\n return\n }\n const isSelectionOutOfRange = !e?.state.selection.ranges.every(\n (range) => range.anchor < (v?.length ?? 0) && range.head < (v?.length ?? 0)\n )\n e?.dispatch({\n changes: {\n from: 0,\n to: e?.state.doc.length,\n insert: v\n },\n selection: isSelectionOutOfRange ? { anchor: 0, head: 0 } : e?.state.selection,\n scrollIntoView: true\n })\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n editor.value?.destroy()\n})\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBA,MAAM,QAAQ;EAKd,MAAM,QAAQ,SAAmB,SAAA,aAAC;EAElC,MAAM,MAAM,IAAI,cAAa;EAE7B,MAAM,EAAE,cAAc,kBAAiB;EAEvC,MAAM,EAAE,MAAM,UAAU,aAAa,qBAAqB,CAAC,aAAa,EAAE,EAAE,MAAM,CAAA;EAElF,MAAM,YAAY,eAAyB;AACzC,UAAO;IACL,IAAI;IACJ,IAAI,EAAE,KAAK,MAAM;IACjB,IAAI,GAAG,YAAY,SAAS,MAAM;IAClC,IAAI,GAAG,YAAY,SAAS,MAAK;IACnC;IACD;EAED,MAAM,eAAe,eAAe,YAAW;EAE/C,MAAM,SAAS,WAA8B,KAAI;EAEjD,MAAM,cAA0D;GAC9D,UAAU,OAAO,+BAA+B,MAAM,MAAM,EAAE,WAAW,EAAE,YAAY,MAAM,CAAC,CAAC;GAC/F,WAAW,OAAO,wBAAwB,MAAM,MAAM,EAAE,KAAK,CAAC;GAC9D,YAAY,OAAO,yBAAyB,MAAM,MAAM,EAAE,MAAM,CAAC;GACjE,YAAY,OAAO,yBAAyB,MAAM,MAAM,EAAE,MAAM,CAAA;GAClE;EAEA,eAAe,eAAe;AAC5B,OAAI,CAAC,aAAa,MAAO;AACzB,UAAO,OAAO,SAAQ;GAEtB,MAAM,EAAE,aAAa;GAErB,MAAM,aAAa;IACjB;IACA;IACA,SAAS,EACP,QAAQ,SAAS,MAClB,CAAC;IACF,WAAW,MAAM,EACf,eAAe,EACb,QAAQ,QAAO,EACjB,EACD,CAAA;IACH;AAEA,OAAI,SAAS,MACX,YAAW,KAAK,WAAW,SAAS,GAAG,MAAM,CAAA;AAE/C,OAAI,SAAS,MACX,YAAW,KAAK,YAAY,SAAS,GAAG,KAAK,CAAA;AAE/C,OAAI,UAAU;IACZ,MAAM,OAAO,MAAM,YAAY,WAAU;AAEzC,eAAW,KAAK,KAAI;;AAGtB,UAAO,QAAQ,IAAI,WAAW;IAC5B,KAAK,MAAM;IACX;IACA,QAAQ,aAAa;IAErB,SAAS,IAAI;AACX,YAAO,OAAO,OAAO,CAAC,GAAG,CAAA;AACzB,SAAI,GAAG,QAAQ,SAAS,CAAC,GAAG,WAC1B;AAEF,WAAM,QAAQ,GAAG,MAAM,IAAI,UAAS;;IAEvC,CAAA;;AAGH,QAAM;GAAC;SAAoB,MAAM;GAAU;GAAU;GAAS,EAAE,aAAY;AAE5E,QACE,OAAO,MAAM,YAAY,OAAO,GAC/B,CAAC,GAAG,OAAO;AACV,OAAI,CAAC,EAAG;AAER,OAAI,EAAE,aAAa,EAAE,MAAM,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,EACrD;GAEF,MAAM,wBAAwB,CAAC,GAAG,MAAM,UAAU,OAAO,OACtD,UAAU,MAAM,UAAU,GAAG,UAAU,MAAM,MAAM,QAAQ,GAAG,UAAU,GAC3E;AACA,MAAG,SAAS;IACV,SAAS;KACP,MAAM;KACN,IAAI,GAAG,MAAM,IAAI;KACjB,QAAQ;KACT;IACD,WAAW,wBAAwB;KAAE,QAAQ;KAAG,MAAM;KAAG,GAAG,GAAG,MAAM;IACrE,gBAAgB;IACjB,CAAA;KAEH,EAAE,WAAW,MAAK,CACpB;AAEA,wBAAsB;AACpB,UAAO,OAAO,SAAQ;IACvB;;uBA5HC,YAEW,MAAA,YAAA,EAAA;IAFA,OAAK,eAAE,UAAA,MAAS;IAAG,SAAK,OAAA,OAAA,OAAA,KAAA,SAAA,oBAAN,IAAiB,CAAA,OAAA,CAAA,EAAA,CAAA,QAAA,CAAA;;2BACjB,CAA3B,mBAA2B,OAA3B,YAA2B,MAAA,IAAA,CAAA,CAAA"}
@@ -11,8 +11,8 @@ declare const __VLS_export: _$vue.DefineComponent<DatePanelProps, {}, {}, {}, {}
11
11
  "onSelect:range-date"?: ((rangeDate?: [_$_cat_kit_core0.Dater, _$_cat_kit_core0.Dater] | undefined) => any) | undefined;
12
12
  "onSelect:date"?: ((date: _$_cat_kit_core0.Dater) => any) | undefined;
13
13
  }>, {
14
- size: _$_veltra_utils0.ComponentSize;
15
14
  type: "date" | "month" | "year";
15
+ size: _$_veltra_utils0.ComponentSize;
16
16
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
17
17
  declare const _default: typeof __VLS_export;
18
18
  //#endregion
@@ -9,9 +9,9 @@ declare const __VLS_export: _$vue.DefineComponent<DatePickerProps, {}, {}, {}, {
9
9
  }>, {
10
10
  type: "date" | "month" | "year";
11
11
  disabled: boolean;
12
- readonly: boolean;
13
12
  placeholder: string;
14
13
  clearable: boolean;
14
+ readonly: boolean;
15
15
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
16
16
  declare const _default: typeof __VLS_export;
17
17
  //#endregion
@@ -9,9 +9,9 @@ declare const __VLS_export: _$vue.DefineComponent<DateRangePickerProps, {}, {},
9
9
  }>, {
10
10
  type: "date" | "month" | "year";
11
11
  disabled: boolean;
12
- readonly: boolean;
13
12
  placeholder: [string, string];
14
13
  clearable: boolean;
14
+ readonly: boolean;
15
15
  }, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
16
16
  declare const _default: typeof __VLS_export;
17
17
  //#endregion
@@ -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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"}