@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.
- package/dist/components/action/action-group.vue.d.ts +1 -1
- package/dist/components/action/action.vue.d.ts +3 -3
- package/dist/components/auto-complete/auto-complete.vue.d.ts +1 -1
- package/dist/components/batch-edit/batch-edit.vue.d.ts +2 -2
- package/dist/components/button/button.vue.d.ts +1 -1
- package/dist/components/cascade/cascade.vue.d.ts +6 -6
- package/dist/components/checkbox-group/checkbox-group.vue.d.ts +2 -2
- package/dist/components/code-editor/code-editor.js +2 -0
- package/dist/components/code-editor/code-editor.js.map +1 -1
- package/dist/components/date-panel/date-panel.vue.d.ts +1 -1
- package/dist/components/date-picker/date-picker.vue.d.ts +1 -1
- package/dist/components/date-range-picker/date-range-picker.vue.d.ts +1 -1
- package/dist/components/file-picker/file-picker.vue.d.ts +1 -1
- package/dist/components/file-viewer/file-viewer.js +195 -30
- package/dist/components/file-viewer/file-viewer.js.map +1 -1
- package/dist/components/file-viewer/previewers/docx-previewer.js +7 -5
- package/dist/components/file-viewer/previewers/docx-previewer.js.map +1 -1
- package/dist/components/file-viewer/previewers/image-previewer.js +6 -6
- package/dist/components/file-viewer/previewers/image-previewer.js.map +1 -1
- package/dist/components/file-viewer/previewers/pdf-previewer.js +5 -3
- package/dist/components/file-viewer/previewers/pdf-previewer.js.map +1 -1
- package/dist/components/file-viewer/style2.css +387 -136
- package/dist/components/grid-input/grid-input.vue.d.ts +1 -1
- package/dist/components/input/input.vue.d.ts +3 -3
- package/dist/components/multi-select/multi-select.vue.d.ts +4 -4
- package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +7 -7
- package/dist/components/notification/notification.vue.d.ts +1 -1
- package/dist/components/number-input/number-input.vue.d.ts +1 -1
- package/dist/components/number-range-input/number-range-input.vue.d.ts +1 -1
- package/dist/components/password-input/password-input.vue.d.ts +1 -1
- package/dist/components/pop-confirm/pop-confirm.vue.d.ts +2 -2
- package/dist/components/radio-group/radio-group.vue.d.ts +2 -2
- package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +1 -1
- package/dist/components/select/select.vue.d.ts +3 -3
- package/dist/components/table/table.vue.d.ts +2 -2
- package/dist/components/tabs/tabs-horizontal.vue.d.ts +2 -2
- package/dist/components/tabs/tabs-vertical.vue.d.ts +2 -2
- package/dist/components/tabs/tabs.vue.d.ts +2 -2
- package/dist/components/textarea/textarea.vue.d.ts +4 -4
- package/dist/components/tip/tip.vue.d.ts +2 -2
- package/dist/components/tree/tree.vue.d.ts +6 -6
- package/dist/components/tree-select/tree-select.vue.d.ts +7 -7
- package/package.json +13 -12
- package/src/components/code-editor/code-editor.vue +2 -0
- package/src/components/file-viewer/file-viewer.vue +250 -24
- package/src/components/file-viewer/previewers/docx-previewer.vue +4 -3
- package/src/components/file-viewer/previewers/image-previewer.vue +4 -5
- package/src/components/file-viewer/previewers/pdf-previewer.vue +4 -3
- 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
|
-
|
|
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":"
|
|
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 = ["
|
|
13
|
-
const _hoisted_5 =
|
|
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(
|
|
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
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
-
},
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
},
|
|
254
|
-
|
|
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(
|
|
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
|
-
},
|
|
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:
|
|
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(),
|
|
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, [
|
|
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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"}
|