@veltra/desktop 1.4.0 → 1.6.0
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_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/action/action.js.map +1 -1
- package/dist/components/auto-complete/auto-complete.js.map +1 -1
- package/dist/components/badge/badge.js.map +1 -1
- package/dist/components/badge/style.d.ts +1 -1
- package/dist/components/batch-edit/batch-edit-form.js +8 -12
- package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
- package/dist/components/batch-edit/batch-edit-list.js.map +1 -1
- package/dist/components/batch-edit/batch-edit.js +2 -1
- package/dist/components/batch-edit/batch-edit.js.map +1 -1
- package/dist/components/batch-edit/di.js.map +1 -1
- package/dist/components/batch-edit/index.d.ts +2 -2
- package/dist/components/batch-edit/use-edit-state.js +11 -9
- package/dist/components/batch-edit/use-edit-state.js.map +1 -1
- package/dist/components/batch-edit/use-handlers.js.map +1 -1
- package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/breadcrumb/style.d.ts +1 -1
- package/dist/components/button/button-group.js.map +1 -1
- package/dist/components/button/button.js +2 -2
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/button/style2.css +85 -92
- package/dist/components/calendar/calendar.js.map +1 -1
- package/dist/components/calendar/style.d.ts +1 -1
- package/dist/components/card/card-action.js.map +1 -1
- package/dist/components/card/card-content.js.map +1 -1
- package/dist/components/card/card-cover.js.map +1 -1
- package/dist/components/card/card-header.js.map +1 -1
- package/dist/components/card/card.js.map +1 -1
- package/dist/components/card/style.d.ts +1 -1
- package/dist/components/cascade/cascade-panel-item.js.map +1 -1
- package/dist/components/cascade/cascade.js.map +1 -1
- package/dist/components/check-tag/check-tag.js.map +1 -1
- package/dist/components/check-tag/style.d.ts +1 -1
- package/dist/components/checkbox/checkbox-button.js.map +1 -1
- package/dist/components/checkbox/checkbox.js.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.js.map +1 -1
- package/dist/components/code-editor/basic-setup.js +2 -2
- package/dist/components/code-editor/code-editor.js +2 -2
- package/dist/components/code-editor/code-editor.js.map +1 -1
- package/dist/components/code-editor/lang-loaders.js +1 -1
- package/dist/components/code-editor/shell-extension.js +2 -2
- package/dist/components/collapse/collapse-item.js +24 -7
- package/dist/components/collapse/collapse-item.js.map +1 -1
- package/dist/components/collapse/collapse.js.map +1 -1
- package/dist/components/collapse/style.d.ts +1 -1
- package/dist/components/condition-editor/components/condition-group.js.map +1 -1
- package/dist/components/condition-editor/components/condition-row.js.map +1 -1
- package/dist/components/condition-editor/condition-editor.js.map +1 -1
- package/dist/components/condition-editor/index.d.ts +2 -2
- package/dist/components/contextmenu/contextmenu-item.js +13 -6
- package/dist/components/contextmenu/contextmenu-item.js.map +1 -1
- package/dist/components/contextmenu/contextmenu-panel.js +12 -6
- package/dist/components/contextmenu/contextmenu-panel.js.map +1 -1
- package/dist/components/contextmenu/contextmenu-sub.js.map +1 -1
- package/dist/components/contextmenu/contextmenu.js.map +1 -1
- package/dist/components/contextmenu/di.d.ts +15 -0
- package/dist/components/contextmenu/index.d.ts +3 -2
- package/dist/components/contextmenu/style2.css +13 -0
- package/dist/components/date-panel/date-panel.js.map +1 -1
- package/dist/components/date-panel/headers/day.js.map +1 -1
- package/dist/components/date-panel/headers/month.js.map +1 -1
- package/dist/components/date-panel/headers/year.js.map +1 -1
- package/dist/components/date-panel/panels/day.js.map +1 -1
- package/dist/components/date-panel/panels/month.js.map +1 -1
- package/dist/components/date-panel/panels/year.js.map +1 -1
- package/dist/components/date-panel/style.d.ts +1 -1
- package/dist/components/date-picker/date-picker.js.map +1 -1
- package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/components/dialog/dialog.js.map +1 -1
- package/dist/components/dialog/style2.css +3 -1
- package/dist/components/drawer/drawer.js.map +1 -1
- package/dist/components/dropdown/dropdown.js.map +1 -1
- package/dist/components/dual-nav/dual-nav-app.js.map +1 -1
- package/dist/components/dual-nav/dual-nav.js.map +1 -1
- package/dist/components/empty/empty.js.map +1 -1
- package/dist/components/empty/style.d.ts +1 -1
- package/dist/components/expression-editor/components/path-preview.js.map +1 -1
- package/dist/components/expression-editor/components/variable-picker.js.map +1 -1
- package/dist/components/expression-editor/core/editor.js.map +1 -1
- package/dist/components/expression-editor/expression-editor.js.map +1 -1
- package/dist/components/expression-editor/style.d.ts +1 -1
- package/dist/components/file-picker/file-picker.js.map +1 -1
- package/dist/components/file-picker/style.d.ts +1 -1
- package/dist/components/file-viewer/file-viewer.js.map +1 -1
- package/dist/components/file-viewer/helper.js +1 -38
- package/dist/components/file-viewer/helper.js.map +1 -1
- package/dist/components/file-viewer/previewers/docx-previewer.js.map +1 -1
- package/dist/components/file-viewer/previewers/image-previewer.js.map +1 -1
- package/dist/components/file-viewer/previewers/pdf-previewer.js.map +1 -1
- package/dist/components/file-viewer/previewers/pdf-viewport-scroll.js.map +1 -1
- package/dist/components/file-viewer/previewers/pdf-zoom-bridge.js.map +1 -1
- package/dist/components/file-viewer/previewers/sheet-previewer.js +68 -37
- package/dist/components/file-viewer/previewers/sheet-previewer.js.map +1 -1
- package/dist/components/file-viewer/previewers/text-previewer.js +2 -2
- package/dist/components/file-viewer/previewers/text-previewer.js.map +1 -1
- package/dist/components/file-viewer/previewers/video-previewer.js.map +1 -1
- package/dist/components/file-viewer/style.d.ts +1 -1
- package/dist/components/float-button/float-button.js.map +1 -1
- package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form/style.d.ts +1 -1
- package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form-item/style.d.ts +1 -1
- package/dist/components/gantt-chart/gantt-chart.js.map +1 -1
- package/dist/components/gantt-chart/style.d.ts +1 -1
- package/dist/components/grid/grid-item.js.map +1 -1
- package/dist/components/grid/grid.js +3 -2
- package/dist/components/grid/grid.js.map +1 -1
- package/dist/components/grid/style.d.ts +1 -1
- package/dist/components/grid-input/grid-input.js.map +1 -1
- package/dist/components/grid-input/style.d.ts +1 -1
- package/dist/components/group-input/group-input.js.map +1 -1
- package/dist/components/group-nav/group-nav-item.js.map +1 -1
- package/dist/components/group-nav/group-nav.js.map +1 -1
- package/dist/components/group-nav/style.d.ts +1 -1
- package/dist/components/icon/icon.js.map +1 -1
- package/dist/components/icon/style.d.ts +1 -1
- package/dist/components/index.d.ts +91 -156
- package/dist/components/index.js +4 -1
- package/dist/components/input/input.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/kbd/kbd.js.map +1 -1
- package/dist/components/kbd/style.d.ts +1 -1
- package/dist/components/layout/layout-resizer.js.map +1 -1
- package/dist/components/layout/layout.js +22 -10
- package/dist/components/layout/layout.js.map +1 -1
- package/dist/components/layout/style.d.ts +1 -1
- package/dist/components/list/list-item.js.map +1 -1
- package/dist/components/list/list.js.map +1 -1
- package/dist/components/loading/directive.js +2 -1
- package/dist/components/loading/directive.js.map +1 -1
- package/dist/components/loading/index.d.ts +2 -2
- package/dist/components/loading/loading.js.map +1 -1
- package/dist/components/message/index.d.ts +2 -2
- package/dist/components/message/message-box.js.map +1 -1
- package/dist/components/message/message.js.map +1 -1
- package/dist/components/message/style.d.ts +1 -1
- package/dist/components/message-confirm/index.d.ts +2 -2
- package/dist/components/message-confirm/message-confirm-box.js.map +1 -1
- package/dist/components/message-confirm/message-confirm.js.map +1 -1
- package/dist/components/message-confirm/style.d.ts +1 -1
- package/dist/components/message-confirm/style2.css +18 -0
- package/dist/components/multi-select/multi-select-option.js.map +1 -1
- package/dist/components/multi-select/multi-select.js +6 -3
- package/dist/components/multi-select/multi-select.js.map +1 -1
- package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
- package/dist/components/nav/nav-icon.js.map +1 -1
- package/dist/components/nav/nav-item-collapsed.js.map +1 -1
- package/dist/components/nav/nav-item.js +4 -2
- package/dist/components/nav/nav-item.js.map +1 -1
- package/dist/components/nav/nav-sub-collapsed.js.map +1 -1
- package/dist/components/nav/nav-sub.js.map +1 -1
- package/dist/components/nav/nav.js.map +1 -1
- package/dist/components/nav/style.d.ts +1 -1
- package/dist/components/node-render/style.d.ts +1 -1
- package/dist/components/notification/index.d.ts +2 -2
- package/dist/components/notification/notification-box.js +2 -2
- package/dist/components/notification/notification-box.js.map +1 -1
- package/dist/components/notification/notification.js.map +1 -1
- package/dist/components/notification/style.d.ts +1 -1
- package/dist/components/number/number.js.map +1 -1
- package/dist/components/number/style.d.ts +1 -1
- package/dist/components/number-input/number-input.js +2 -1
- package/dist/components/number-input/number-input.js.map +1 -1
- package/dist/components/number-range-input/number-range-input.js.map +1 -1
- package/dist/components/paginator/paginator.js.map +1 -1
- package/dist/components/palette/palette-alpha.js.map +1 -1
- package/dist/components/palette/palette-color-switch.js.map +1 -1
- package/dist/components/palette/palette-hue.js.map +1 -1
- package/dist/components/palette/palette-sv.js.map +1 -1
- package/dist/components/palette/palette.js.map +1 -1
- package/dist/components/password-input/password-input.js.map +1 -1
- package/dist/components/pop-confirm/pop-confirm.js.map +1 -1
- package/dist/components/progress/progress.js.map +1 -1
- package/dist/components/progress/style.d.ts +1 -1
- package/dist/components/progress-nodes/progress-nodes.js.map +1 -1
- package/dist/components/progress-nodes/style.d.ts +1 -1
- package/dist/components/radio/radio.js.map +1 -1
- package/dist/components/radio-group/radio-group.js.map +1 -1
- package/dist/components/rich-text-editor/rich-text-editor.js +2 -1
- package/dist/components/rich-text-editor/rich-text-editor.js.map +1 -1
- package/dist/components/rich-text-editor/style.d.ts +1 -1
- package/dist/components/rich-text-editor/toolbar.js +3 -4
- package/dist/components/rich-text-editor/toolbar.js.map +1 -1
- package/dist/components/scroll/scroll-bar.js.map +1 -1
- package/dist/components/scroll/scroll.js.map +1 -1
- package/dist/components/scroll/style.d.ts +1 -1
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/slider/slider-thumb.js.map +1 -1
- package/dist/components/slider/slider.js.map +1 -1
- package/dist/components/slider/style.d.ts +1 -1
- package/dist/components/steps/steps.js.map +1 -1
- package/dist/components/steps/style.d.ts +1 -1
- package/dist/components/switch/style.d.ts +1 -1
- package/dist/components/switch/switch.js.map +1 -1
- package/dist/components/table/index.d.ts +2 -2
- package/dist/components/table/node/col.d.ts +1 -49
- package/dist/components/table/table-body.js.map +1 -1
- package/dist/components/table/table-cell.js.map +1 -1
- package/dist/components/table/table-foot.js.map +1 -1
- package/dist/components/table/table-row.js +2 -1
- package/dist/components/table/table-row.js.map +1 -1
- package/dist/components/table/table.js.map +1 -1
- package/dist/components/table/use-check.js +2 -1
- package/dist/components/table/use-check.js.map +1 -1
- package/dist/components/table/use-col-resize.js +9 -1
- package/dist/components/table/use-col-resize.js.map +1 -1
- package/dist/components/table/use-columns.d.ts +1 -1
- package/dist/components/table/use-rows.js +2 -1
- package/dist/components/table/use-rows.js.map +1 -1
- package/dist/components/table-editor/table-editor.js.map +1 -1
- package/dist/components/tabs/tabs-horizontal.js +2 -1
- package/dist/components/tabs/tabs-horizontal.js.map +1 -1
- package/dist/components/tabs/tabs-vertical.js.map +1 -1
- package/dist/components/tabs/tabs.js.map +1 -1
- package/dist/components/tabs/use-tabs-bar.js +10 -25
- package/dist/components/tabs/use-tabs-bar.js.map +1 -1
- package/dist/components/tag/style.d.ts +1 -1
- package/dist/components/tag/tag.js.map +1 -1
- package/dist/components/text/style.d.ts +1 -1
- package/dist/components/text/text.js.map +1 -1
- package/dist/components/textarea/textarea.js.map +1 -1
- package/dist/components/theme/theme.js +3 -2
- package/dist/components/theme/theme.js.map +1 -1
- package/dist/components/tip/style.d.ts +1 -1
- package/dist/components/tip/tip.js.map +1 -1
- package/dist/components/tree/tree-node.js.map +1 -1
- package/dist/components/tree/tree.js.map +1 -1
- package/dist/components/tree-select/tree-select.js.map +1 -1
- package/dist/components/watermark/style.d.ts +1 -1
- package/dist/components/watermark/watermark.js.map +1 -1
- package/dist/index.d.ts +92 -96
- package/dist/index.js +2 -1
- package/dist/node_modules/.bun/@codemirror_autocomplete@6.20.3/node_modules/@codemirror/autocomplete/dist/index.js +2 -2
- package/dist/node_modules/.bun/@codemirror_autocomplete@6.20.3/node_modules/@codemirror/autocomplete/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@codemirror_commands@6.10.4/node_modules/@codemirror/commands/dist/index.js +3 -3
- package/dist/node_modules/.bun/@codemirror_commands@6.10.4/node_modules/@codemirror/commands/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@codemirror_lang-css@6.3.1/node_modules/@codemirror/lang-css/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@codemirror_lang-html@6.4.11/node_modules/@codemirror/lang-html/dist/index.js +5 -4
- package/dist/node_modules/.bun/@codemirror_lang-html@6.4.11/node_modules/@codemirror/lang-html/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@codemirror_lang-javascript@6.2.5/node_modules/@codemirror/lang-javascript/dist/index.js +2 -2
- package/dist/node_modules/.bun/{@codemirror_lang-markdown@6.5.1 → @codemirror_lang-markdown@6.5.2}/node_modules/@codemirror/lang-markdown/dist/index.js +4 -3
- package/dist/node_modules/.bun/@codemirror_lang-markdown@6.5.2/node_modules/@codemirror/lang-markdown/dist/index.js.map +1 -0
- package/dist/node_modules/.bun/@codemirror_lang-sql@6.10.0/node_modules/@codemirror/lang-sql/dist/index.js +2 -1
- package/dist/node_modules/.bun/@codemirror_lang-sql@6.10.0/node_modules/@codemirror/lang-sql/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@codemirror_language@6.12.4/node_modules/@codemirror/language/dist/index.js +2 -2
- package/dist/node_modules/.bun/@codemirror_language@6.12.4/node_modules/@codemirror/language/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@codemirror_lint@6.9.7/node_modules/@codemirror/lint/dist/index.js +4 -3
- package/dist/node_modules/.bun/@codemirror_lint@6.9.7/node_modules/@codemirror/lint/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@codemirror_search@6.7.1/node_modules/@codemirror/search/dist/index.js +2 -2
- package/dist/node_modules/.bun/@codemirror_search@6.7.1/node_modules/@codemirror/search/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/{@codemirror_state@6.7.0 → @codemirror_state@6.7.1}/node_modules/@codemirror/state/dist/index.js +13 -3
- package/dist/node_modules/.bun/@codemirror_state@6.7.1/node_modules/@codemirror/state/dist/index.js.map +1 -0
- package/dist/node_modules/.bun/@codemirror_theme-one-dark@6.1.3/node_modules/@codemirror/theme-one-dark/dist/index.js +1 -1
- package/dist/node_modules/.bun/@codemirror_theme-one-dark@6.1.3/node_modules/@codemirror/theme-one-dark/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/{@codemirror_view@6.43.4 → @codemirror_view@6.43.8}/node_modules/@codemirror/view/dist/index.js +86 -64
- package/dist/node_modules/.bun/@codemirror_view@6.43.8/node_modules/@codemirror/view/dist/index.js.map +1 -0
- package/dist/node_modules/.bun/@lezer_common@1.5.2/node_modules/@lezer/common/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@lezer_css@1.3.4/node_modules/@lezer/css/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@lezer_highlight@1.2.3/node_modules/@lezer/highlight/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@lezer_html@1.3.13/node_modules/@lezer/html/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@lezer_javascript@1.5.4/node_modules/@lezer/javascript/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@lezer_lr@1.4.10/node_modules/@lezer/lr/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@lezer_markdown@1.7.2/node_modules/@lezer/markdown/dist/index.js +1 -1
- package/dist/node_modules/.bun/@lezer_markdown@1.7.2/node_modules/@lezer/markdown/dist/index.js.map +1 -1
- package/dist/node_modules/.bun/@marijn_find-cluster-break@1.0.2/node_modules/@marijn/find-cluster-break/src/index.js.map +1 -1
- package/dist/node_modules/.bun/style-mod@4.1.3/node_modules/style-mod/src/style-mod.js.map +1 -1
- package/dist/types/collapse.d.ts +7 -1
- package/dist/types/contextmenu.d.ts +10 -4
- package/dist/types/index.d.ts +1 -7
- package/dist/types/layout.d.ts +16 -1
- package/package.json +34 -30
- package/src/components/batch-edit/__test__/batch-edit.test.ts +199 -0
- package/src/components/batch-edit/batch-edit-form.vue +8 -8
- package/src/components/batch-edit/batch-edit.vue +2 -1
- package/src/components/batch-edit/di.ts +2 -0
- package/src/components/batch-edit/use-edit-state.ts +19 -12
- package/src/components/button/button.vue +2 -2
- package/src/components/button/style.scss +8 -29
- package/src/components/collapse/__test__/collapse.test.ts +59 -0
- package/src/components/collapse/collapse-item.vue +32 -11
- package/src/components/contextmenu/__test__/contextmenu.test.ts +165 -0
- package/src/components/contextmenu/contextmenu-item.vue +7 -4
- package/src/components/contextmenu/contextmenu-panel.vue +7 -4
- package/src/components/contextmenu/index.ts +1 -0
- package/src/components/contextmenu/style.scss +16 -0
- package/src/components/dialog/style.scss +5 -1
- package/src/components/file-viewer/helper.ts +0 -53
- package/src/components/file-viewer/previewers/sheet-previewer.vue +91 -46
- package/src/components/layout/layout.vue +19 -8
- package/src/components/message-confirm/style.scss +19 -0
- package/src/components/notification/style.scss +16 -4
- package/src/components/radio-group/style.scss +1 -1
- package/src/components/slider/style.scss +1 -1
- package/src/components/table/use-col-resize.ts +9 -1
- package/src/components/tabs/use-tabs-bar.ts +15 -20
- package/src/types/collapse.ts +8 -1
- package/src/types/contextmenu.ts +10 -4
- package/src/types/layout.ts +16 -1
- package/dist/components/action/action-group.vue.d.ts +0 -25
- package/dist/components/action/action.vue.d.ts +0 -33
- package/dist/components/action/index.d.ts +0 -3
- package/dist/components/auto-complete/auto-complete.vue.d.ts +0 -41
- package/dist/components/auto-complete/index.d.ts +0 -2
- package/dist/components/badge/badge.vue.d.ts +0 -20
- package/dist/components/badge/index.d.ts +0 -2
- package/dist/components/batch-edit/batch-edit.vue.d.ts +0 -45
- package/dist/components/breadcrumb/breadcrumb.vue.d.ts +0 -24
- package/dist/components/breadcrumb/index.d.ts +0 -2
- package/dist/components/button/button-group.vue.d.ts +0 -19
- package/dist/components/button/button.vue.d.ts +0 -27
- package/dist/components/button/index.d.ts +0 -3
- package/dist/components/calendar/calendar.vue.d.ts +0 -17
- package/dist/components/calendar/index.d.ts +0 -2
- package/dist/components/card/card-action.vue.d.ts +0 -18
- package/dist/components/card/card-content.vue.d.ts +0 -18
- package/dist/components/card/card-cover.vue.d.ts +0 -8
- package/dist/components/card/card-header.vue.d.ts +0 -16
- package/dist/components/card/card.vue.d.ts +0 -18
- package/dist/components/card/index.d.ts +0 -6
- package/dist/components/cascade/cascade.vue.d.ts +0 -31
- package/dist/components/cascade/index.d.ts +0 -2
- package/dist/components/check-tag/check-tag.vue.d.ts +0 -22
- package/dist/components/check-tag/index.d.ts +0 -2
- package/dist/components/checkbox/checkbox-button.vue.d.ts +0 -35
- package/dist/components/checkbox/checkbox.vue.d.ts +0 -34
- package/dist/components/checkbox/index.d.ts +0 -3
- package/dist/components/checkbox-group/checkbox-group.vue.d.ts +0 -24
- package/dist/components/checkbox-group/index.d.ts +0 -2
- package/dist/components/code-editor/code-editor.vue.d.ts +0 -30
- package/dist/components/code-editor/index.d.ts +0 -2
- package/dist/components/collapse/collapse-item.vue.d.ts +0 -32
- package/dist/components/collapse/collapse.vue.d.ts +0 -27
- package/dist/components/collapse/index.d.ts +0 -3
- package/dist/components/condition-editor/condition-editor.vue.d.ts +0 -15
- package/dist/components/contextmenu/contextmenu.vue.d.ts +0 -14
- package/dist/components/date-panel/date-panel.vue.d.ts +0 -17
- package/dist/components/date-panel/index.d.ts +0 -2
- package/dist/components/date-picker/date-picker.vue.d.ts +0 -18
- package/dist/components/date-picker/index.d.ts +0 -2
- package/dist/components/date-range-picker/date-range-picker.vue.d.ts +0 -18
- package/dist/components/date-range-picker/index.d.ts +0 -2
- package/dist/components/dialog/dialog.vue.d.ts +0 -43
- package/dist/components/dialog/index.d.ts +0 -2
- package/dist/components/drawer/drawer.vue.d.ts +0 -36
- package/dist/components/drawer/index.d.ts +0 -2
- package/dist/components/dropdown/dropdown.vue.d.ts +0 -30
- package/dist/components/dropdown/index.d.ts +0 -2
- package/dist/components/dual-nav/dual-nav.vue.d.ts +0 -15
- package/dist/components/dual-nav/index.d.ts +0 -2
- package/dist/components/empty/empty.vue.d.ts +0 -11
- package/dist/components/empty/index.d.ts +0 -2
- package/dist/components/expression-editor/expression-editor.vue.d.ts +0 -16
- package/dist/components/expression-editor/index.d.ts +0 -2
- package/dist/components/file-picker/file-picker.vue.d.ts +0 -27
- package/dist/components/file-picker/index.d.ts +0 -2
- package/dist/components/file-viewer/file-viewer.vue.d.ts +0 -40
- package/dist/components/file-viewer/index.d.ts +0 -2
- package/dist/components/file-viewer/sheet-parser.js +0 -46
- package/dist/components/file-viewer/sheet-parser.js.map +0 -1
- package/dist/components/float-button/float-button.vue.d.ts +0 -12
- package/dist/components/float-button/index.d.ts +0 -2
- package/dist/components/form/form.vue.d.ts +0 -23
- package/dist/components/form/index.d.ts +0 -2
- package/dist/components/form-item/form-item.vue.d.ts +0 -21
- package/dist/components/form-item/index.d.ts +0 -2
- package/dist/components/gantt-chart/gantt-chart.vue.d.ts +0 -8
- package/dist/components/gantt-chart/index.d.ts +0 -2
- package/dist/components/grid/grid-item.vue.d.ts +0 -20
- package/dist/components/grid/grid.vue.d.ts +0 -27
- package/dist/components/grid/index.d.ts +0 -3
- package/dist/components/grid-input/grid-input.vue.d.ts +0 -19
- package/dist/components/grid-input/index.d.ts +0 -2
- package/dist/components/group-input/group-input.vue.d.ts +0 -26
- package/dist/components/group-input/index.d.ts +0 -2
- package/dist/components/group-nav/group-nav.vue.d.ts +0 -12
- package/dist/components/group-nav/index.d.ts +0 -2
- package/dist/components/icon/icon.vue.d.ts +0 -18
- package/dist/components/icon/index.d.ts +0 -2
- package/dist/components/input/index.d.ts +0 -2
- package/dist/components/input/input.vue.d.ts +0 -50
- package/dist/components/kbd/kbd.vue.d.ts +0 -16
- package/dist/components/layout/index.d.ts +0 -2
- package/dist/components/layout/layout.vue.d.ts +0 -20
- package/dist/components/list/index.d.ts +0 -3
- package/dist/components/list/list-item.vue.d.ts +0 -16
- package/dist/components/list/list.vue.d.ts +0 -21
- package/dist/components/loading/loading.vue.d.ts +0 -11
- package/dist/components/message/message.vue.d.ts +0 -16
- package/dist/components/message-confirm/message-confirm.vue.d.ts +0 -19
- package/dist/components/multi-select/index.d.ts +0 -2
- package/dist/components/multi-select/multi-select.vue.d.ts +0 -48
- package/dist/components/multi-tree-select/index.d.ts +0 -2
- package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +0 -44
- package/dist/components/nav/index.d.ts +0 -4
- package/dist/components/nav/nav-item.vue.d.ts +0 -12
- package/dist/components/nav/nav-sub.vue.d.ts +0 -13
- package/dist/components/nav/nav.vue.d.ts +0 -19
- package/dist/components/notification/notification.vue.d.ts +0 -18
- package/dist/components/number/index.d.ts +0 -2
- package/dist/components/number/number.vue.d.ts +0 -11
- package/dist/components/number-input/index.d.ts +0 -2
- package/dist/components/number-input/number-input.vue.d.ts +0 -39
- package/dist/components/number-range-input/index.d.ts +0 -2
- package/dist/components/number-range-input/number-range-input.vue.d.ts +0 -36
- package/dist/components/paginator/index.d.ts +0 -2
- package/dist/components/paginator/paginator.vue.d.ts +0 -29
- package/dist/components/palette/index.d.ts +0 -2
- package/dist/components/palette/palette.vue.d.ts +0 -20
- package/dist/components/password-input/index.d.ts +0 -2
- package/dist/components/password-input/password-input.vue.d.ts +0 -30
- package/dist/components/pop-confirm/index.d.ts +0 -2
- package/dist/components/pop-confirm/pop-confirm.vue.d.ts +0 -33
- package/dist/components/progress/index.d.ts +0 -2
- package/dist/components/progress/progress.vue.d.ts +0 -25
- package/dist/components/progress-nodes/index.d.ts +0 -2
- package/dist/components/progress-nodes/progress-nodes.vue.d.ts +0 -36
- package/dist/components/radio/index.d.ts +0 -2
- package/dist/components/radio/radio.vue.d.ts +0 -31
- package/dist/components/radio-group/index.d.ts +0 -2
- package/dist/components/radio-group/radio-group.vue.d.ts +0 -26
- package/dist/components/rich-text-editor/index.d.ts +0 -2
- package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +0 -23
- package/dist/components/scroll/index.d.ts +0 -2
- package/dist/components/scroll/scroll.vue.d.ts +0 -28
- package/dist/components/select/index.d.ts +0 -2
- package/dist/components/select/select.vue.d.ts +0 -38
- package/dist/components/slider/index.d.ts +0 -2
- package/dist/components/slider/slider.vue.d.ts +0 -21
- package/dist/components/steps/index.d.ts +0 -2
- package/dist/components/steps/steps.vue.d.ts +0 -29
- package/dist/components/switch/index.d.ts +0 -2
- package/dist/components/switch/switch.vue.d.ts +0 -24
- package/dist/components/table/node/row.d.ts +0 -49
- package/dist/components/table/table.vue.d.ts +0 -54
- package/dist/components/table-editor/index.d.ts +0 -2
- package/dist/components/table-editor/table-editor.vue.d.ts +0 -12
- package/dist/components/tabs/index.d.ts +0 -4
- package/dist/components/tabs/tabs-horizontal.vue.d.ts +0 -40
- package/dist/components/tabs/tabs-vertical.vue.d.ts +0 -39
- package/dist/components/tabs/tabs.vue.d.ts +0 -36
- package/dist/components/tag/index.d.ts +0 -2
- package/dist/components/tag/tag.vue.d.ts +0 -22
- package/dist/components/text/index.d.ts +0 -2
- package/dist/components/text/text.vue.d.ts +0 -10
- package/dist/components/textarea/index.d.ts +0 -2
- package/dist/components/textarea/textarea.vue.d.ts +0 -34
- package/dist/components/theme/index.d.ts +0 -2
- package/dist/components/theme/theme.vue.d.ts +0 -8
- package/dist/components/tip/index.d.ts +0 -2
- package/dist/components/tip/tip.vue.d.ts +0 -31
- package/dist/components/tree/di.d.ts +0 -12
- package/dist/components/tree/index.d.ts +0 -2
- package/dist/components/tree/tree.vue.d.ts +0 -40
- package/dist/components/tree-select/index.d.ts +0 -2
- package/dist/components/tree-select/tree-select.vue.d.ts +0 -48
- package/dist/components/watermark/index.d.ts +0 -2
- package/dist/components/watermark/watermark.vue.d.ts +0 -21
- package/dist/node_modules/.bun/@codemirror_lang-markdown@6.5.1/node_modules/@codemirror/lang-markdown/dist/index.js.map +0 -1
- package/dist/node_modules/.bun/@codemirror_state@6.7.0/node_modules/@codemirror/state/dist/index.js.map +0 -1
- package/dist/node_modules/.bun/@codemirror_view@6.43.4/node_modules/@codemirror/view/dist/index.js.map +0 -1
- package/src/components/file-viewer/sheet-parser.ts +0 -52
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.js","names":[],"sources":["../../../../src/components/expression-editor/core/editor.ts"],"sourcesContent":["import type { BEM } from '@veltra/utils'\n\nimport type { VariableItem } from '../../../types'\nimport { createChip, isChipElement, readChipType, readChipValue } from './chip'\nimport { normalize, parse, serialize, type Doc, type Segment } from './model'\n\nconst TEXT_SEG_ATTR = 'data-seg'\nconst TEXT_SEG_VALUE = 'text'\n\nexport interface EditorVariableInfo {\n value: string\n label: string\n type?: string\n}\n\nexport interface EditorOptions {\n container: HTMLElement\n cls: BEM<'expression-editor'>\n initialDoc: Doc\n /**\n * 在 DOM → 模型反推、字符串 → 模型反序列化时为 chip 补齐 label / type。\n * 用 getter 形式以便外层 `variables` props 变化时拿到最新映射。\n */\n getVariableMap?: () => Map<string, VariableItem>\n /** 模型每次更新(包括用户键入文本)后回调 */\n onChange?: (doc: Doc) => void\n /** 选中区域 / 光标偏移变化时回调,offset 为序列化字符串中的位置;无选中或不在编辑器内时为 null */\n onSelectionChange?: (info: { offset: number | null }) => void\n /** 用户点击某个 chip 的主体(重选) */\n onChipReselect?: (info: { chipEl: HTMLElement; segIndex: number; chipOffset: number }) => void\n /** 用户点击某个 chip 的 ×(删除) */\n onChipRemove?: (info: { chipEl: HTMLElement; segIndex: number }) => void\n}\n\nexport interface EditorAPI {\n /** 当前模型 */\n getDoc(): Doc\n /** 完全替换模型(会重渲染 DOM) */\n setDoc(doc: Doc): void\n /** 序列化为字符串(modelValue 形态) */\n getValue(): string\n /** 反序列化字符串为模型并替换(可选传入 variableMap 以补齐 label/type) */\n setValue(value: string): void\n /** 当前光标偏移(无 selection 返回 null) */\n getCaretOffset(): number | null\n /** 把光标设置到指定偏移(不会修改模型) */\n setCaretOffset(offset: number): void\n /**\n * 用一个 var chip 替换 [start, end) 区间。\n * 调用方通常在 mention 选中时用:start = `@` 起点、end = 当前光标。\n */\n replaceRangeWithVar(start: number, end: number, variable: EditorVariableInfo): void\n /** 移除指定段下标对应的 var chip(必须是 var 段)。 */\n removeVarAt(segIndex: number): void\n /** 替换指定段下标对应的 var chip 为新变量(必须是 var 段)。 */\n replaceVarAt(segIndex: number, variable: EditorVariableInfo): void\n /** 卸载所有事件监听(不会销毁 container DOM) */\n dispose(): void\n /** 强制根据当前模型重渲染 DOM(光标位置尽量保留) */\n rerender(): void\n /** 容器引用(只读) */\n readonly container: HTMLElement\n}\n\nexport function createEditor(opts: EditorOptions): EditorAPI {\n let doc: Doc = normalize(opts.initialDoc)\n let composing = false\n\n function emitChange(next: Doc) {\n doc = next\n opts.onChange?.(doc)\n }\n\n function makeTextSpan(value: string): HTMLSpanElement {\n const span = document.createElement('span')\n span.setAttribute(TEXT_SEG_ATTR, TEXT_SEG_VALUE)\n span.textContent = value\n return span\n }\n\n function makeChipSpan(seg: Extract<Segment, { kind: 'var' }>): HTMLElement {\n return createChip(seg, {\n cls: opts.cls,\n onReselect: (chipEl) => {\n const { segIndex, chipOffset } = locateChip(chipEl)\n if (segIndex < 0) return\n opts.onChipReselect?.({ chipEl, segIndex, chipOffset })\n },\n onRemove: (chipEl) => {\n const { segIndex } = locateChip(chipEl)\n if (segIndex < 0) return\n opts.onChipRemove?.({ chipEl, segIndex })\n }\n })\n }\n\n function locateChip(chipEl: HTMLElement): { segIndex: number; chipOffset: number } {\n let chipOffset = 0\n let segIdx = -1\n let i = 0\n for (const child of Array.from(opts.container.childNodes)) {\n if (child === chipEl) {\n segIdx = i\n return { segIndex: segIdx, chipOffset }\n }\n chipOffset += childSerialLength(child)\n i++\n }\n return { segIndex: -1, chipOffset: -1 }\n }\n\n function childSerialLength(node: Node): number {\n if (isChipElement(node)) return readChipValue(node).length + 2\n return (node.textContent ?? '').length\n }\n\n /** 渲染 doc 到 container:每个 var 两侧都补一个 text span(即便空),保证光标可停靠。 */\n function render(targetCaret?: number) {\n const container = opts.container\n container.innerHTML = ''\n\n // 在边界与每两个 var 之间确保有 text span 占位\n const expanded: Segment[] = []\n let lastWasVar = false\n let first = true\n for (const seg of doc) {\n if (first) {\n if (seg.kind === 'var') expanded.push({ kind: 'text', value: '' })\n first = false\n } else if (lastWasVar && seg.kind === 'var') {\n expanded.push({ kind: 'text', value: '' })\n }\n expanded.push(seg)\n lastWasVar = seg.kind === 'var'\n }\n if (lastWasVar || expanded.length === 0) expanded.push({ kind: 'text', value: '' })\n\n for (const seg of expanded) {\n if (seg.kind === 'text') container.appendChild(makeTextSpan(seg.value))\n else container.appendChild(makeChipSpan(seg))\n }\n\n if (typeof targetCaret === 'number') setCaret(targetCaret)\n }\n\n /** 从 DOM 反推模型:宽容裸 text node、空 text span。 */\n function readDocFromDOM(): Doc {\n const segs: Segment[] = []\n for (const child of Array.from(opts.container.childNodes)) {\n if (isChipElement(child)) {\n const value = readChipValue(child)\n const domType = readChipType(child)\n const fallbackLabel =\n child.querySelector(`.${opts.cls.e('chip-label')}`)?.textContent ?? value\n // 优先从 variableMap 取最新 label / type,保持与外部数据源一致\n const fromMap = opts.getVariableMap?.().get(value)\n const finalType = fromMap?.type ?? domType\n const seg: Segment = finalType\n ? { kind: 'var', value, label: fromMap?.label ?? fallbackLabel, type: finalType }\n : { kind: 'var', value, label: fromMap?.label ?? fallbackLabel }\n segs.push(seg)\n } else {\n segs.push({ kind: 'text', value: child.textContent ?? '' })\n }\n }\n return normalize(segs)\n }\n\n /**\n * 计算光标在序列化字符串中的全局偏移。\n * 规则:\n * - 在 text span / 裸 text node 中:父级 / 节点之前的 segments 长度累加 + selection 内偏移\n * - 在 chip 边界:根据 selection 在 chip 节点之前 / 之后判断\n */\n function getCaretOffset(): number | null {\n const sel = document.getSelection()\n if (!sel || sel.rangeCount === 0) return null\n const range = sel.getRangeAt(0)\n if (!opts.container.contains(range.startContainer)) return null\n\n let offset = 0\n let found = false\n for (const child of Array.from(opts.container.childNodes)) {\n if (found) break\n if (isChipElement(child)) {\n if (range.startContainer === child) {\n // selection.startOffset 表示子节点索引:0 表示 chip 起始,>=1 表示 chip 之后\n if (range.startOffset === 0) return offset\n return offset + childSerialLength(child)\n }\n if (range.startContainer === opts.container && getChildIndex(child) === range.startOffset) {\n // 容器层 selection:偏移即子节点索引\n return offset\n }\n offset += childSerialLength(child)\n } else {\n // text span 或裸 text 节点\n if (\n range.startContainer === child ||\n (child.contains(range.startContainer) && child !== opts.container)\n ) {\n // 计算 selection 在该 child textContent 中的偏移\n const localOffset = computeTextOffsetWithin(\n child,\n range.startContainer,\n range.startOffset\n )\n return offset + localOffset\n }\n if (range.startContainer === opts.container && getChildIndex(child) === range.startOffset) {\n return offset\n }\n offset += childSerialLength(child)\n }\n }\n if (\n range.startContainer === opts.container &&\n range.startOffset === opts.container.childNodes.length\n ) {\n return offset\n }\n return null\n }\n\n function getChildIndex(node: Node): number {\n let i = 0\n let cur: Node | null = node.previousSibling\n while (cur) {\n i++\n cur = cur.previousSibling\n }\n return i\n }\n\n function computeTextOffsetWithin(root: Node, target: Node, targetOffset: number): number {\n if (root === target) return targetOffset\n let total = 0\n function walk(n: Node): boolean {\n if (n === target) {\n total += targetOffset\n return true\n }\n if (n.nodeType === 3) {\n total += (n as Text).data.length\n return false\n }\n for (const c of Array.from(n.childNodes)) {\n if (walk(c)) return true\n }\n return false\n }\n walk(root)\n return total\n }\n\n /** 把光标放到 offset 处,offset 大于文档长度时落到末尾。 */\n function setCaret(offset: number): void {\n const sel = document.getSelection()\n if (!sel) return\n\n let remain = offset\n const children = Array.from(opts.container.childNodes)\n for (let i = 0; i < children.length; i++) {\n const child = children[i]!\n const len = childSerialLength(child)\n if (isChipElement(child)) {\n if (remain <= 0) {\n // 光标定到 chip 之前 → 落到容器层 child 索引\n placeAt(opts.container, i)\n return\n }\n if (remain < len) {\n // 落在 chip 内部 → 视作 chip 之后\n placeAt(opts.container, i + 1)\n return\n }\n remain -= len\n } else {\n if (remain <= len) {\n // 落在该 text span 内\n placeWithinText(child, remain)\n return\n }\n remain -= len\n }\n }\n // 落到末尾\n if (children.length === 0) {\n placeAt(opts.container, 0)\n return\n }\n const last = children[children.length - 1]!\n if (isChipElement(last)) placeAt(opts.container, children.length)\n else placeWithinText(last, (last.textContent ?? '').length)\n }\n\n function placeAt(parent: Node, index: number) {\n const sel = document.getSelection()\n if (!sel) return\n const range = document.createRange()\n range.setStart(parent, index)\n range.collapse(true)\n sel.removeAllRanges()\n sel.addRange(range)\n }\n\n function placeWithinText(span: Node, offset: number): void {\n const sel = document.getSelection()\n if (!sel) return\n const target = firstTextDescendant(span)\n const range = document.createRange()\n if (target) {\n const max = target.data.length\n range.setStart(target, Math.min(offset, max))\n } else {\n // 空 span:让光标落到 span 内(child index 0)\n range.setStart(span, 0)\n }\n range.collapse(true)\n sel.removeAllRanges()\n sel.addRange(range)\n }\n\n function firstTextDescendant(root: Node): Text | null {\n if (root.nodeType === 3) return root as Text\n for (const c of Array.from(root.childNodes)) {\n const t = firstTextDescendant(c)\n if (t) return t\n }\n return null\n }\n\n /** input 后:从 DOM 反推 doc,并触发 onChange(如有变化)。 */\n function syncFromDOM(): void {\n if (composing) return\n const next = readDocFromDOM()\n if (!docEqual(next, doc)) emitChange(next)\n }\n\n function docEqual(a: Doc, b: Doc): boolean {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n const x = a[i]!\n const y = b[i]!\n if (x.kind !== y.kind) return false\n if (x.kind === 'text' && y.kind === 'text' && x.value !== y.value) return false\n if (x.kind === 'var' && y.kind === 'var') {\n if (x.value !== y.value || x.label !== y.label || x.type !== y.type) return false\n }\n }\n return true\n }\n\n function onInput() {\n syncFromDOM()\n }\n function onCompositionStart() {\n composing = true\n }\n function onCompositionEnd() {\n composing = false\n syncFromDOM()\n }\n function onPaste(e: ClipboardEvent) {\n e.preventDefault()\n const text = e.clipboardData?.getData('text/plain') ?? ''\n if (!text) return\n insertPlainTextAtCaret(text)\n }\n function onSelectionChange() {\n if (composing) return\n if (!opts.onSelectionChange) return\n const sel = document.getSelection()\n if (!sel || sel.rangeCount === 0) {\n opts.onSelectionChange({ offset: null })\n return\n }\n const range = sel.getRangeAt(0)\n if (!opts.container.contains(range.startContainer)) {\n opts.onSelectionChange({ offset: null })\n return\n }\n opts.onSelectionChange({ offset: getCaretOffset() })\n }\n\n function insertPlainTextAtCaret(text: string) {\n const sel = document.getSelection()\n if (!sel || sel.rangeCount === 0) return\n const range = sel.getRangeAt(0)\n if (!opts.container.contains(range.startContainer)) return\n range.deleteContents()\n const node = document.createTextNode(text)\n range.insertNode(node)\n range.setStartAfter(node)\n range.collapse(true)\n sel.removeAllRanges()\n sel.addRange(range)\n syncFromDOM()\n }\n\n // 命令:替换区间为 var chip\n function replaceRangeWithVar(start: number, end: number, variable: EditorVariableInfo) {\n const a = Math.min(start, end)\n const b = Math.max(start, end)\n const left = sliceDoc(doc, 0, a)\n const right = sliceDoc(doc, b, totalLength(doc))\n const inserted: Segment = variable.type\n ? { kind: 'var', value: variable.value, label: variable.label, type: variable.type }\n : { kind: 'var', value: variable.value, label: variable.label }\n const next = normalize([...left, inserted, ...right])\n emitChange(next)\n render(a + variable.value.length + 2) // 光标定到 chip 之后\n }\n\n function removeVarAt(segIndex: number) {\n const target = doc[segIndex]\n if (!target || target.kind !== 'var') return\n const before = doc.slice(0, segIndex)\n const after = doc.slice(segIndex + 1)\n const caretOffset = sliceLength(before)\n const next = normalize([...before, ...after])\n emitChange(next)\n render(caretOffset)\n }\n\n function replaceVarAt(segIndex: number, variable: EditorVariableInfo) {\n const target = doc[segIndex]\n if (!target || target.kind !== 'var') return\n const next = doc.slice()\n const replaced: Segment = variable.type\n ? { kind: 'var', value: variable.value, label: variable.label, type: variable.type }\n : { kind: 'var', value: variable.value, label: variable.label }\n next[segIndex] = replaced\n const caretOffset = sliceLength(doc.slice(0, segIndex)) + variable.value.length + 2\n emitChange(normalize(next))\n render(caretOffset)\n }\n\n // 工具:基于序列化偏移的切片(不会切开 var)\n function sliceDoc(d: Doc, start: number, end: number): Doc {\n const out: Segment[] = []\n let pos = 0\n for (const seg of d) {\n const len = seg.kind === 'text' ? seg.value.length : seg.value.length + 2\n const segStart = pos\n const segEnd = pos + len\n if (segEnd <= start || segStart >= end) {\n pos += len\n continue\n }\n if (seg.kind === 'text') {\n const a = Math.max(0, start - segStart)\n const b = Math.min(len, end - segStart)\n const slice = seg.value.slice(a, b)\n if (slice) out.push({ kind: 'text', value: slice })\n } else {\n // var 是原子:只有当 [start, end) 完整覆盖该 var 时保留;否则抛弃\n if (start <= segStart && end >= segEnd) out.push(seg)\n }\n pos += len\n }\n return out\n }\n\n function sliceLength(d: Doc): number {\n let n = 0\n for (const s of d) n += s.kind === 'text' ? s.value.length : s.value.length + 2\n return n\n }\n\n function totalLength(d: Doc): number {\n return sliceLength(d)\n }\n\n // 绑定监听\n const container = opts.container\n container.addEventListener('input', onInput)\n container.addEventListener('compositionstart', onCompositionStart)\n container.addEventListener('compositionend', onCompositionEnd)\n container.addEventListener('paste', onPaste)\n document.addEventListener('selectionchange', onSelectionChange)\n\n // 初次渲染\n render()\n\n return {\n getDoc: () => doc,\n setDoc: (next) => {\n doc = normalize(next)\n render()\n opts.onChange?.(doc)\n },\n getValue: () => serialize(doc),\n setValue: (value) => {\n doc = parse(value, opts.getVariableMap?.())\n render()\n opts.onChange?.(doc)\n },\n getCaretOffset,\n setCaretOffset: setCaret,\n replaceRangeWithVar,\n removeVarAt,\n replaceVarAt,\n rerender: () => render(),\n dispose: () => {\n container.removeEventListener('input', onInput)\n container.removeEventListener('compositionstart', onCompositionStart)\n container.removeEventListener('compositionend', onCompositionEnd)\n container.removeEventListener('paste', onPaste)\n document.removeEventListener('selectionchange', onSelectionChange)\n },\n container\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"editor.js","names":[],"sources":["../../../../src/components/expression-editor/core/editor.ts"],"sourcesContent":["import type { BEM } from '@veltra/utils'\n\nimport type { VariableItem } from '../../../types'\nimport { createChip, isChipElement, readChipType, readChipValue } from './chip'\nimport { normalize, parse, serialize, type Doc, type Segment } from './model'\n\nconst TEXT_SEG_ATTR = 'data-seg'\nconst TEXT_SEG_VALUE = 'text'\n\nexport interface EditorVariableInfo {\n value: string\n label: string\n type?: string\n}\n\nexport interface EditorOptions {\n container: HTMLElement\n cls: BEM<'expression-editor'>\n initialDoc: Doc\n /**\n * 在 DOM → 模型反推、字符串 → 模型反序列化时为 chip 补齐 label / type。\n * 用 getter 形式以便外层 `variables` props 变化时拿到最新映射。\n */\n getVariableMap?: () => Map<string, VariableItem>\n /** 模型每次更新(包括用户键入文本)后回调 */\n onChange?: (doc: Doc) => void\n /** 选中区域 / 光标偏移变化时回调,offset 为序列化字符串中的位置;无选中或不在编辑器内时为 null */\n onSelectionChange?: (info: { offset: number | null }) => void\n /** 用户点击某个 chip 的主体(重选) */\n onChipReselect?: (info: { chipEl: HTMLElement; segIndex: number; chipOffset: number }) => void\n /** 用户点击某个 chip 的 ×(删除) */\n onChipRemove?: (info: { chipEl: HTMLElement; segIndex: number }) => void\n}\n\nexport interface EditorAPI {\n /** 当前模型 */\n getDoc(): Doc\n /** 完全替换模型(会重渲染 DOM) */\n setDoc(doc: Doc): void\n /** 序列化为字符串(modelValue 形态) */\n getValue(): string\n /** 反序列化字符串为模型并替换(可选传入 variableMap 以补齐 label/type) */\n setValue(value: string): void\n /** 当前光标偏移(无 selection 返回 null) */\n getCaretOffset(): number | null\n /** 把光标设置到指定偏移(不会修改模型) */\n setCaretOffset(offset: number): void\n /**\n * 用一个 var chip 替换 [start, end) 区间。\n * 调用方通常在 mention 选中时用:start = `@` 起点、end = 当前光标。\n */\n replaceRangeWithVar(start: number, end: number, variable: EditorVariableInfo): void\n /** 移除指定段下标对应的 var chip(必须是 var 段)。 */\n removeVarAt(segIndex: number): void\n /** 替换指定段下标对应的 var chip 为新变量(必须是 var 段)。 */\n replaceVarAt(segIndex: number, variable: EditorVariableInfo): void\n /** 卸载所有事件监听(不会销毁 container DOM) */\n dispose(): void\n /** 强制根据当前模型重渲染 DOM(光标位置尽量保留) */\n rerender(): void\n /** 容器引用(只读) */\n readonly container: HTMLElement\n}\n\nexport function createEditor(opts: EditorOptions): EditorAPI {\n let doc: Doc = normalize(opts.initialDoc)\n let composing = false\n\n function emitChange(next: Doc) {\n doc = next\n opts.onChange?.(doc)\n }\n\n function makeTextSpan(value: string): HTMLSpanElement {\n const span = document.createElement('span')\n span.setAttribute(TEXT_SEG_ATTR, TEXT_SEG_VALUE)\n span.textContent = value\n return span\n }\n\n function makeChipSpan(seg: Extract<Segment, { kind: 'var' }>): HTMLElement {\n return createChip(seg, {\n cls: opts.cls,\n onReselect: (chipEl) => {\n const { segIndex, chipOffset } = locateChip(chipEl)\n if (segIndex < 0) return\n opts.onChipReselect?.({ chipEl, segIndex, chipOffset })\n },\n onRemove: (chipEl) => {\n const { segIndex } = locateChip(chipEl)\n if (segIndex < 0) return\n opts.onChipRemove?.({ chipEl, segIndex })\n }\n })\n }\n\n function locateChip(chipEl: HTMLElement): { segIndex: number; chipOffset: number } {\n let chipOffset = 0\n let segIdx = -1\n let i = 0\n for (const child of Array.from(opts.container.childNodes)) {\n if (child === chipEl) {\n segIdx = i\n return { segIndex: segIdx, chipOffset }\n }\n chipOffset += childSerialLength(child)\n i++\n }\n return { segIndex: -1, chipOffset: -1 }\n }\n\n function childSerialLength(node: Node): number {\n if (isChipElement(node)) return readChipValue(node).length + 2\n return (node.textContent ?? '').length\n }\n\n /** 渲染 doc 到 container:每个 var 两侧都补一个 text span(即便空),保证光标可停靠。 */\n function render(targetCaret?: number) {\n const container = opts.container\n container.innerHTML = ''\n\n // 在边界与每两个 var 之间确保有 text span 占位\n const expanded: Segment[] = []\n let lastWasVar = false\n let first = true\n for (const seg of doc) {\n if (first) {\n if (seg.kind === 'var') expanded.push({ kind: 'text', value: '' })\n first = false\n } else if (lastWasVar && seg.kind === 'var') {\n expanded.push({ kind: 'text', value: '' })\n }\n expanded.push(seg)\n lastWasVar = seg.kind === 'var'\n }\n if (lastWasVar || expanded.length === 0) expanded.push({ kind: 'text', value: '' })\n\n for (const seg of expanded) {\n if (seg.kind === 'text') container.appendChild(makeTextSpan(seg.value))\n else container.appendChild(makeChipSpan(seg))\n }\n\n if (typeof targetCaret === 'number') setCaret(targetCaret)\n }\n\n /** 从 DOM 反推模型:宽容裸 text node、空 text span。 */\n function readDocFromDOM(): Doc {\n const segs: Segment[] = []\n for (const child of Array.from(opts.container.childNodes)) {\n if (isChipElement(child)) {\n const value = readChipValue(child)\n const domType = readChipType(child)\n const fallbackLabel =\n child.querySelector(`.${opts.cls.e('chip-label')}`)?.textContent ?? value\n // 优先从 variableMap 取最新 label / type,保持与外部数据源一致\n const fromMap = opts.getVariableMap?.().get(value)\n const finalType = fromMap?.type ?? domType\n const seg: Segment = finalType\n ? { kind: 'var', value, label: fromMap?.label ?? fallbackLabel, type: finalType }\n : { kind: 'var', value, label: fromMap?.label ?? fallbackLabel }\n segs.push(seg)\n } else {\n segs.push({ kind: 'text', value: child.textContent ?? '' })\n }\n }\n return normalize(segs)\n }\n\n /**\n * 计算光标在序列化字符串中的全局偏移。\n * 规则:\n * - 在 text span / 裸 text node 中:父级 / 节点之前的 segments 长度累加 + selection 内偏移\n * - 在 chip 边界:根据 selection 在 chip 节点之前 / 之后判断\n */\n function getCaretOffset(): number | null {\n const sel = document.getSelection()\n if (!sel || sel.rangeCount === 0) return null\n const range = sel.getRangeAt(0)\n if (!opts.container.contains(range.startContainer)) return null\n\n let offset = 0\n let found = false\n for (const child of Array.from(opts.container.childNodes)) {\n if (found) break\n if (isChipElement(child)) {\n if (range.startContainer === child) {\n // selection.startOffset 表示子节点索引:0 表示 chip 起始,>=1 表示 chip 之后\n if (range.startOffset === 0) return offset\n return offset + childSerialLength(child)\n }\n if (range.startContainer === opts.container && getChildIndex(child) === range.startOffset) {\n // 容器层 selection:偏移即子节点索引\n return offset\n }\n offset += childSerialLength(child)\n } else {\n // text span 或裸 text 节点\n if (\n range.startContainer === child ||\n (child.contains(range.startContainer) && child !== opts.container)\n ) {\n // 计算 selection 在该 child textContent 中的偏移\n const localOffset = computeTextOffsetWithin(\n child,\n range.startContainer,\n range.startOffset\n )\n return offset + localOffset\n }\n if (range.startContainer === opts.container && getChildIndex(child) === range.startOffset) {\n return offset\n }\n offset += childSerialLength(child)\n }\n }\n if (\n range.startContainer === opts.container &&\n range.startOffset === opts.container.childNodes.length\n ) {\n return offset\n }\n return null\n }\n\n function getChildIndex(node: Node): number {\n let i = 0\n let cur: Node | null = node.previousSibling\n while (cur) {\n i++\n cur = cur.previousSibling\n }\n return i\n }\n\n function computeTextOffsetWithin(root: Node, target: Node, targetOffset: number): number {\n if (root === target) return targetOffset\n let total = 0\n function walk(n: Node): boolean {\n if (n === target) {\n total += targetOffset\n return true\n }\n if (n.nodeType === 3) {\n total += (n as Text).data.length\n return false\n }\n for (const c of Array.from(n.childNodes)) {\n if (walk(c)) return true\n }\n return false\n }\n walk(root)\n return total\n }\n\n /** 把光标放到 offset 处,offset 大于文档长度时落到末尾。 */\n function setCaret(offset: number): void {\n const sel = document.getSelection()\n if (!sel) return\n\n let remain = offset\n const children = Array.from(opts.container.childNodes)\n for (let i = 0; i < children.length; i++) {\n const child = children[i]!\n const len = childSerialLength(child)\n if (isChipElement(child)) {\n if (remain <= 0) {\n // 光标定到 chip 之前 → 落到容器层 child 索引\n placeAt(opts.container, i)\n return\n }\n if (remain < len) {\n // 落在 chip 内部 → 视作 chip 之后\n placeAt(opts.container, i + 1)\n return\n }\n remain -= len\n } else {\n if (remain <= len) {\n // 落在该 text span 内\n placeWithinText(child, remain)\n return\n }\n remain -= len\n }\n }\n // 落到末尾\n if (children.length === 0) {\n placeAt(opts.container, 0)\n return\n }\n const last = children[children.length - 1]!\n if (isChipElement(last)) placeAt(opts.container, children.length)\n else placeWithinText(last, (last.textContent ?? '').length)\n }\n\n function placeAt(parent: Node, index: number) {\n const sel = document.getSelection()\n if (!sel) return\n const range = document.createRange()\n range.setStart(parent, index)\n range.collapse(true)\n sel.removeAllRanges()\n sel.addRange(range)\n }\n\n function placeWithinText(span: Node, offset: number): void {\n const sel = document.getSelection()\n if (!sel) return\n const target = firstTextDescendant(span)\n const range = document.createRange()\n if (target) {\n const max = target.data.length\n range.setStart(target, Math.min(offset, max))\n } else {\n // 空 span:让光标落到 span 内(child index 0)\n range.setStart(span, 0)\n }\n range.collapse(true)\n sel.removeAllRanges()\n sel.addRange(range)\n }\n\n function firstTextDescendant(root: Node): Text | null {\n if (root.nodeType === 3) return root as Text\n for (const c of Array.from(root.childNodes)) {\n const t = firstTextDescendant(c)\n if (t) return t\n }\n return null\n }\n\n /** input 后:从 DOM 反推 doc,并触发 onChange(如有变化)。 */\n function syncFromDOM(): void {\n if (composing) return\n const next = readDocFromDOM()\n if (!docEqual(next, doc)) emitChange(next)\n }\n\n function docEqual(a: Doc, b: Doc): boolean {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n const x = a[i]!\n const y = b[i]!\n if (x.kind !== y.kind) return false\n if (x.kind === 'text' && y.kind === 'text' && x.value !== y.value) return false\n if (x.kind === 'var' && y.kind === 'var') {\n if (x.value !== y.value || x.label !== y.label || x.type !== y.type) return false\n }\n }\n return true\n }\n\n function onInput() {\n syncFromDOM()\n }\n function onCompositionStart() {\n composing = true\n }\n function onCompositionEnd() {\n composing = false\n syncFromDOM()\n }\n function onPaste(e: ClipboardEvent) {\n e.preventDefault()\n const text = e.clipboardData?.getData('text/plain') ?? ''\n if (!text) return\n insertPlainTextAtCaret(text)\n }\n function onSelectionChange() {\n if (composing) return\n if (!opts.onSelectionChange) return\n const sel = document.getSelection()\n if (!sel || sel.rangeCount === 0) {\n opts.onSelectionChange({ offset: null })\n return\n }\n const range = sel.getRangeAt(0)\n if (!opts.container.contains(range.startContainer)) {\n opts.onSelectionChange({ offset: null })\n return\n }\n opts.onSelectionChange({ offset: getCaretOffset() })\n }\n\n function insertPlainTextAtCaret(text: string) {\n const sel = document.getSelection()\n if (!sel || sel.rangeCount === 0) return\n const range = sel.getRangeAt(0)\n if (!opts.container.contains(range.startContainer)) return\n range.deleteContents()\n const node = document.createTextNode(text)\n range.insertNode(node)\n range.setStartAfter(node)\n range.collapse(true)\n sel.removeAllRanges()\n sel.addRange(range)\n syncFromDOM()\n }\n\n // 命令:替换区间为 var chip\n function replaceRangeWithVar(start: number, end: number, variable: EditorVariableInfo) {\n const a = Math.min(start, end)\n const b = Math.max(start, end)\n const left = sliceDoc(doc, 0, a)\n const right = sliceDoc(doc, b, totalLength(doc))\n const inserted: Segment = variable.type\n ? { kind: 'var', value: variable.value, label: variable.label, type: variable.type }\n : { kind: 'var', value: variable.value, label: variable.label }\n const next = normalize([...left, inserted, ...right])\n emitChange(next)\n render(a + variable.value.length + 2) // 光标定到 chip 之后\n }\n\n function removeVarAt(segIndex: number) {\n const target = doc[segIndex]\n if (!target || target.kind !== 'var') return\n const before = doc.slice(0, segIndex)\n const after = doc.slice(segIndex + 1)\n const caretOffset = sliceLength(before)\n const next = normalize([...before, ...after])\n emitChange(next)\n render(caretOffset)\n }\n\n function replaceVarAt(segIndex: number, variable: EditorVariableInfo) {\n const target = doc[segIndex]\n if (!target || target.kind !== 'var') return\n const next = doc.slice()\n const replaced: Segment = variable.type\n ? { kind: 'var', value: variable.value, label: variable.label, type: variable.type }\n : { kind: 'var', value: variable.value, label: variable.label }\n next[segIndex] = replaced\n const caretOffset = sliceLength(doc.slice(0, segIndex)) + variable.value.length + 2\n emitChange(normalize(next))\n render(caretOffset)\n }\n\n // 工具:基于序列化偏移的切片(不会切开 var)\n function sliceDoc(d: Doc, start: number, end: number): Doc {\n const out: Segment[] = []\n let pos = 0\n for (const seg of d) {\n const len = seg.kind === 'text' ? seg.value.length : seg.value.length + 2\n const segStart = pos\n const segEnd = pos + len\n if (segEnd <= start || segStart >= end) {\n pos += len\n continue\n }\n if (seg.kind === 'text') {\n const a = Math.max(0, start - segStart)\n const b = Math.min(len, end - segStart)\n const slice = seg.value.slice(a, b)\n if (slice) out.push({ kind: 'text', value: slice })\n } else {\n // var 是原子:只有当 [start, end) 完整覆盖该 var 时保留;否则抛弃\n if (start <= segStart && end >= segEnd) out.push(seg)\n }\n pos += len\n }\n return out\n }\n\n function sliceLength(d: Doc): number {\n let n = 0\n for (const s of d) n += s.kind === 'text' ? s.value.length : s.value.length + 2\n return n\n }\n\n function totalLength(d: Doc): number {\n return sliceLength(d)\n }\n\n // 绑定监听\n const container = opts.container\n container.addEventListener('input', onInput)\n container.addEventListener('compositionstart', onCompositionStart)\n container.addEventListener('compositionend', onCompositionEnd)\n container.addEventListener('paste', onPaste)\n document.addEventListener('selectionchange', onSelectionChange)\n\n // 初次渲染\n render()\n\n return {\n getDoc: () => doc,\n setDoc: (next) => {\n doc = normalize(next)\n render()\n opts.onChange?.(doc)\n },\n getValue: () => serialize(doc),\n setValue: (value) => {\n doc = parse(value, opts.getVariableMap?.())\n render()\n opts.onChange?.(doc)\n },\n getCaretOffset,\n setCaretOffset: setCaret,\n replaceRangeWithVar,\n removeVarAt,\n replaceVarAt,\n rerender: () => render(),\n dispose: () => {\n container.removeEventListener('input', onInput)\n container.removeEventListener('compositionstart', onCompositionStart)\n container.removeEventListener('compositionend', onCompositionEnd)\n container.removeEventListener('paste', onPaste)\n document.removeEventListener('selectionchange', onSelectionChange)\n },\n container\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expression-editor.js","names":[],"sources":["../../../src/components/expression-editor/expression-editor.vue"],"sourcesContent":["<template>\n <div :class=\"className\">\n <div\n ref=\"container\"\n :class=\"cls.e('container')\"\n :contenteditable=\"!readonly && !disabled\"\n :data-empty=\"isEmpty || undefined\"\n :data-placeholder=\"props.placeholder\"\n @keydown=\"onKeydown\"\n @blur=\"onBlur\"\n ></div>\n\n <div v-if=\"showPlaceholder\" :class=\"cls.e('placeholder')\">\n {{ props.placeholder }}\n </div>\n\n <VariablePicker\n ref=\"pickerRef\"\n :visible=\"pickerVisible\"\n :trigger-dom=\"pickerTriggerDom\"\n :variables=\"props.variables\"\n :filter=\"pickerFilter\"\n :selectable-levels=\"props.selectableLevels ?? 'leaf'\"\n @select=\"onPickerSelect\"\n @dismiss=\"onPickerDismiss\"\n @update:visible=\"onPickerVisibleChange\"\n />\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { bem } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch\n} from 'vue'\n\nimport type { ExpressionEditorProps, VariableItem } from '../../types'\nimport VariablePicker from './components/variable-picker.vue'\nimport { createEditor, type EditorAPI } from './core/editor'\nimport { createMention, type MentionAPI } from './core/mention'\nimport { parse, type Doc } from './core/model'\nimport { createVariableMap } from './di'\n\ndefineOptions({ name: 'UExpressionEditor' })\n\nconst props = withDefaults(defineProps<ExpressionEditorProps>(), {\n placeholder: '请输入表达式,输入 @ 可插入变量',\n selectableLevels: 'leaf'\n})\n\nconst emit = defineEmits<{ (e: 'update:modelValue', value: string): void }>()\n\nconst cls = bem('expression-editor')\nconst { formProps } = injectFormContext()\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst containerRef = useTemplateRef<HTMLDivElement>('container')\nconst pickerRef = useTemplateRef<{ handleKeydown: (e: KeyboardEvent) => boolean }>('pickerRef')\n\nconst className = computed(() => [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n])\n\nconst variableMap = computed(() => createVariableMap(props.variables))\n\nconst editorRef = shallowRef<EditorAPI | null>(null)\nconst mention: MentionAPI = createMention()\n\nconst currentDoc = shallowRef<Doc>([])\nconst isEmpty = computed(() => currentDoc.value.length === 0)\nconst showPlaceholder = computed(() => isEmpty.value && !disabled.value)\n\nconst pickerMode = shallowRef<'mention' | 'reselect' | null>(null)\nconst pickerTriggerDom = shallowRef<HTMLElement | undefined>(undefined)\nconst reselectingSegIdx = shallowRef<number | null>(null)\nconst pickerFilter = shallowRef('')\n\nconst pickerVisible = computed(() => pickerMode.value !== null)\n\nfunction syncMention() {\n const editor = editorRef.value\n if (!editor) return\n if (pickerMode.value === 'reselect') return\n const caret = editor.getCaretOffset()\n const state = mention.update(currentDoc.value, caret)\n if (state) {\n pickerMode.value = 'mention'\n pickerFilter.value = state.filter\n pickerTriggerDom.value = containerRef.value ?? undefined\n } else if (pickerMode.value === 'mention') {\n closePicker()\n }\n}\n\nfunction closePicker() {\n pickerMode.value = null\n reselectingSegIdx.value = null\n pickerFilter.value = ''\n}\n\nonMounted(() => {\n if (!containerRef.value) return\n const initialDoc = parse(props.modelValue ?? '', variableMap.value)\n currentDoc.value = initialDoc\n\n const editor = createEditor({\n container: containerRef.value,\n cls,\n initialDoc,\n getVariableMap: () => variableMap.value,\n onChange: (doc) => {\n currentDoc.value = doc\n const value = serializeFromDoc(doc)\n if (value !== (props.modelValue ?? '')) emit('update:modelValue', value)\n syncMention()\n },\n onSelectionChange: () => {\n syncMention()\n },\n onChipReselect: ({ chipEl, segIndex }) => {\n if (disabled.value || readonly.value) return\n mention.commit()\n pickerMode.value = 'reselect'\n pickerFilter.value = ''\n pickerTriggerDom.value = chipEl\n reselectingSegIdx.value = segIndex\n },\n onChipRemove: ({ segIndex }) => {\n if (disabled.value || readonly.value) return\n editor.removeVarAt(segIndex)\n }\n })\n editorRef.value = editor\n})\n\nonBeforeUnmount(() => {\n editorRef.value?.dispose()\n})\n\nfunction serializeFromDoc(doc: Doc): string {\n let s = ''\n for (const seg of doc) s += seg.kind === 'text' ? seg.value : `{${seg.value}}`\n return s\n}\n\nwatch(\n () => props.modelValue,\n (v) => {\n const editor = editorRef.value\n if (!editor) return\n if (v === editor.getValue()) return\n editor.setValue(v ?? '')\n }\n)\n\nwatch(variableMap, () => {\n // variables 变化:重渲染以刷新 chip label / type\n const editor = editorRef.value\n if (!editor) return\n editor.setValue(editor.getValue())\n})\n\nfunction onKeydown(e: KeyboardEvent) {\n if (disabled.value || readonly.value) return\n // mention / reselect 激活时,优先把箭头键 / Enter / Esc 转给 picker\n if (pickerMode.value !== null) {\n const handledByPicker = pickerRef.value?.handleKeydown(e)\n if (handledByPicker) {\n e.preventDefault()\n return\n }\n }\n\n if (pickerMode.value === 'mention') {\n // 这些键导致 mention 退出(保留 @filter 文本,光标继续移动)\n if (e.key === ' ' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n mention.dismiss()\n closePicker()\n }\n }\n}\n\nfunction onBlur() {\n if (pickerMode.value === 'mention') {\n mention.dismiss()\n // 下一帧再关闭,避免和 picker 内 click 冲突\n void nextTick(() => closePicker())\n }\n}\n\nfunction onPickerSelect(item: VariableItem) {\n const editor = editorRef.value\n if (!editor) return\n\n if (pickerMode.value === 'mention') {\n const state = mention.getState()\n if (!state) return\n const anchor = state.anchorOffset\n const caret = editor.getCaretOffset() ?? anchor + state.filter.length + 1\n editor.replaceRangeWithVar(anchor, caret, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n mention.commit()\n } else if (pickerMode.value === 'reselect') {\n const idx = reselectingSegIdx.value\n if (idx !== null) {\n editor.replaceVarAt(idx, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n }\n }\n closePicker()\n}\n\nfunction onPickerDismiss() {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n}\n\nfunction onPickerVisibleChange(v: boolean) {\n if (!v && pickerMode.value !== null) {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n }\n}\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"expression-editor.js","names":[],"sources":["../../../src/components/expression-editor/expression-editor.vue"],"sourcesContent":["<template>\n <div :class=\"className\">\n <div\n ref=\"container\"\n :class=\"cls.e('container')\"\n :contenteditable=\"!readonly && !disabled\"\n :data-empty=\"isEmpty || undefined\"\n :data-placeholder=\"props.placeholder\"\n @keydown=\"onKeydown\"\n @blur=\"onBlur\"\n ></div>\n\n <div v-if=\"showPlaceholder\" :class=\"cls.e('placeholder')\">\n {{ props.placeholder }}\n </div>\n\n <VariablePicker\n ref=\"pickerRef\"\n :visible=\"pickerVisible\"\n :trigger-dom=\"pickerTriggerDom\"\n :variables=\"props.variables\"\n :filter=\"pickerFilter\"\n :selectable-levels=\"props.selectableLevels ?? 'leaf'\"\n @select=\"onPickerSelect\"\n @dismiss=\"onPickerDismiss\"\n @update:visible=\"onPickerVisibleChange\"\n />\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { bem } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch\n} from 'vue'\n\nimport type { ExpressionEditorProps, VariableItem } from '../../types'\nimport VariablePicker from './components/variable-picker.vue'\nimport { createEditor, type EditorAPI } from './core/editor'\nimport { createMention, type MentionAPI } from './core/mention'\nimport { parse, type Doc } from './core/model'\nimport { createVariableMap } from './di'\n\ndefineOptions({ name: 'UExpressionEditor' })\n\nconst props = withDefaults(defineProps<ExpressionEditorProps>(), {\n placeholder: '请输入表达式,输入 @ 可插入变量',\n selectableLevels: 'leaf'\n})\n\nconst emit = defineEmits<{ (e: 'update:modelValue', value: string): void }>()\n\nconst cls = bem('expression-editor')\nconst { formProps } = injectFormContext()\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst containerRef = useTemplateRef<HTMLDivElement>('container')\nconst pickerRef = useTemplateRef<{ handleKeydown: (e: KeyboardEvent) => boolean }>('pickerRef')\n\nconst className = computed(() => [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n])\n\nconst variableMap = computed(() => createVariableMap(props.variables))\n\nconst editorRef = shallowRef<EditorAPI | null>(null)\nconst mention: MentionAPI = createMention()\n\nconst currentDoc = shallowRef<Doc>([])\nconst isEmpty = computed(() => currentDoc.value.length === 0)\nconst showPlaceholder = computed(() => isEmpty.value && !disabled.value)\n\nconst pickerMode = shallowRef<'mention' | 'reselect' | null>(null)\nconst pickerTriggerDom = shallowRef<HTMLElement | undefined>(undefined)\nconst reselectingSegIdx = shallowRef<number | null>(null)\nconst pickerFilter = shallowRef('')\n\nconst pickerVisible = computed(() => pickerMode.value !== null)\n\nfunction syncMention() {\n const editor = editorRef.value\n if (!editor) return\n if (pickerMode.value === 'reselect') return\n const caret = editor.getCaretOffset()\n const state = mention.update(currentDoc.value, caret)\n if (state) {\n pickerMode.value = 'mention'\n pickerFilter.value = state.filter\n pickerTriggerDom.value = containerRef.value ?? undefined\n } else if (pickerMode.value === 'mention') {\n closePicker()\n }\n}\n\nfunction closePicker() {\n pickerMode.value = null\n reselectingSegIdx.value = null\n pickerFilter.value = ''\n}\n\nonMounted(() => {\n if (!containerRef.value) return\n const initialDoc = parse(props.modelValue ?? '', variableMap.value)\n currentDoc.value = initialDoc\n\n const editor = createEditor({\n container: containerRef.value,\n cls,\n initialDoc,\n getVariableMap: () => variableMap.value,\n onChange: (doc) => {\n currentDoc.value = doc\n const value = serializeFromDoc(doc)\n if (value !== (props.modelValue ?? '')) emit('update:modelValue', value)\n syncMention()\n },\n onSelectionChange: () => {\n syncMention()\n },\n onChipReselect: ({ chipEl, segIndex }) => {\n if (disabled.value || readonly.value) return\n mention.commit()\n pickerMode.value = 'reselect'\n pickerFilter.value = ''\n pickerTriggerDom.value = chipEl\n reselectingSegIdx.value = segIndex\n },\n onChipRemove: ({ segIndex }) => {\n if (disabled.value || readonly.value) return\n editor.removeVarAt(segIndex)\n }\n })\n editorRef.value = editor\n})\n\nonBeforeUnmount(() => {\n editorRef.value?.dispose()\n})\n\nfunction serializeFromDoc(doc: Doc): string {\n let s = ''\n for (const seg of doc) s += seg.kind === 'text' ? seg.value : `{${seg.value}}`\n return s\n}\n\nwatch(\n () => props.modelValue,\n (v) => {\n const editor = editorRef.value\n if (!editor) return\n if (v === editor.getValue()) return\n editor.setValue(v ?? '')\n }\n)\n\nwatch(variableMap, () => {\n // variables 变化:重渲染以刷新 chip label / type\n const editor = editorRef.value\n if (!editor) return\n editor.setValue(editor.getValue())\n})\n\nfunction onKeydown(e: KeyboardEvent) {\n if (disabled.value || readonly.value) return\n // mention / reselect 激活时,优先把箭头键 / Enter / Esc 转给 picker\n if (pickerMode.value !== null) {\n const handledByPicker = pickerRef.value?.handleKeydown(e)\n if (handledByPicker) {\n e.preventDefault()\n return\n }\n }\n\n if (pickerMode.value === 'mention') {\n // 这些键导致 mention 退出(保留 @filter 文本,光标继续移动)\n if (e.key === ' ' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n mention.dismiss()\n closePicker()\n }\n }\n}\n\nfunction onBlur() {\n if (pickerMode.value === 'mention') {\n mention.dismiss()\n // 下一帧再关闭,避免和 picker 内 click 冲突\n void nextTick(() => closePicker())\n }\n}\n\nfunction onPickerSelect(item: VariableItem) {\n const editor = editorRef.value\n if (!editor) return\n\n if (pickerMode.value === 'mention') {\n const state = mention.getState()\n if (!state) return\n const anchor = state.anchorOffset\n const caret = editor.getCaretOffset() ?? anchor + state.filter.length + 1\n editor.replaceRangeWithVar(anchor, caret, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n mention.commit()\n } else if (pickerMode.value === 'reselect') {\n const idx = reselectingSegIdx.value\n if (idx !== null) {\n editor.replaceVarAt(idx, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n }\n }\n closePicker()\n}\n\nfunction onPickerDismiss() {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n}\n\nfunction onPickerVisibleChange(v: boolean) {\n if (!v && pickerMode.value !== null) {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n }\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqDA,MAAM,QAAQ;EAKd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,mBAAmB;EACnC,MAAM,EAAE,cAAc,kBAAkB;EACxC,MAAM,EAAE,MAAM,UAAU,aAAa,qBAAqB,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC;EAElF,MAAM,eAAe,eAA+B,WAAW;EAC/D,MAAM,YAAY,eAAiE,WAAW;EAE9F,MAAM,YAAY,eAAe;GAC/B,IAAI;GACJ,IAAI,EAAE,KAAK,KAAK;GAChB,IAAI,GAAG,YAAY,SAAS,KAAK;GACjC,IAAI,GAAG,YAAY,SAAS,KAAK;EACnC,CAAC;EAED,MAAM,cAAc,eAAe,kBAAkB,MAAM,SAAS,CAAC;EAErE,MAAM,YAAY,WAA6B,IAAI;EACnD,MAAM,UAAsB,cAAc;EAE1C,MAAM,aAAa,WAAgB,CAAC,CAAC;EACrC,MAAM,UAAU,eAAe,WAAW,MAAM,WAAW,CAAC;EAC5D,MAAM,kBAAkB,eAAe,QAAQ,SAAS,CAAC,SAAS,KAAK;EAEvE,MAAM,aAAa,WAA0C,IAAI;EACjE,MAAM,mBAAmB,WAAoC,KAAA,CAAS;EACtE,MAAM,oBAAoB,WAA0B,IAAI;EACxD,MAAM,eAAe,WAAW,EAAE;EAElC,MAAM,gBAAgB,eAAe,WAAW,UAAU,IAAI;EAE9D,SAAS,cAAc;GACrB,MAAM,SAAS,UAAU;GACzB,IAAI,CAAC,QAAQ;GACb,IAAI,WAAW,UAAU,YAAY;GACrC,MAAM,QAAQ,OAAO,eAAe;GACpC,MAAM,QAAQ,QAAQ,OAAO,WAAW,OAAO,KAAK;GACpD,IAAI,OAAO;IACT,WAAW,QAAQ;IACnB,aAAa,QAAQ,MAAM;IAC3B,iBAAiB,QAAQ,aAAa,SAAS,KAAA;GACjD,OAAO,IAAI,WAAW,UAAU,WAC9B,YAAY;EAEhB;EAEA,SAAS,cAAc;GACrB,WAAW,QAAQ;GACnB,kBAAkB,QAAQ;GAC1B,aAAa,QAAQ;EACvB;EAEA,gBAAgB;GACd,IAAI,CAAC,aAAa,OAAO;GACzB,MAAM,aAAa,MAAM,MAAM,cAAc,IAAI,YAAY,KAAK;GAClE,WAAW,QAAQ;GAEnB,MAAM,SAAS,aAAa;IAC1B,WAAW,aAAa;IACxB;IACA;IACA,sBAAsB,YAAY;IAClC,WAAW,QAAQ;KACjB,WAAW,QAAQ;KACnB,MAAM,QAAQ,iBAAiB,GAAG;KAClC,IAAI,WAAW,MAAM,cAAc,KAAK,KAAK,qBAAqB,KAAK;KACvE,YAAY;IACd;IACA,yBAAyB;KACvB,YAAY;IACd;IACA,iBAAiB,EAAE,QAAQ,eAAe;KACxC,IAAI,SAAS,SAAS,SAAS,OAAO;KACtC,QAAQ,OAAO;KACf,WAAW,QAAQ;KACnB,aAAa,QAAQ;KACrB,iBAAiB,QAAQ;KACzB,kBAAkB,QAAQ;IAC5B;IACA,eAAe,EAAE,eAAe;KAC9B,IAAI,SAAS,SAAS,SAAS,OAAO;KACtC,OAAO,YAAY,QAAQ;IAC7B;GACF,CAAC;GACD,UAAU,QAAQ;EACpB,CAAC;EAED,sBAAsB;GACpB,UAAU,OAAO,QAAQ;EAC3B,CAAC;EAED,SAAS,iBAAiB,KAAkB;GAC1C,IAAI,IAAI;GACR,KAAK,MAAM,OAAO,KAAK,KAAK,IAAI,SAAS,SAAS,IAAI,QAAQ,IAAI,IAAI,MAAM;GAC5E,OAAO;EACT;EAEA,YACQ,MAAM,aACX,MAAM;GACL,MAAM,SAAS,UAAU;GACzB,IAAI,CAAC,QAAQ;GACb,IAAI,MAAM,OAAO,SAAS,GAAG;GAC7B,OAAO,SAAS,KAAK,EAAE;EACzB,CACF;EAEA,MAAM,mBAAmB;GAEvB,MAAM,SAAS,UAAU;GACzB,IAAI,CAAC,QAAQ;GACb,OAAO,SAAS,OAAO,SAAS,CAAC;EACnC,CAAC;EAED,SAAS,UAAU,GAAkB;GACnC,IAAI,SAAS,SAAS,SAAS,OAAO;GAEtC,IAAI,WAAW,UAAU,MACC;QAAA,UAAU,OAAO,cAAc,CAAC,GACnC;KACnB,EAAE,eAAe;KACjB;IACF;;GAGF,IAAI,WAAW,UAAU,WAEnB;QAAA,EAAE,QAAQ,OAAO,EAAE,QAAQ,eAAe,EAAE,QAAQ,cAAc;KACpE,QAAQ,QAAQ;KAChB,YAAY;IACd;;EAEJ;EAEA,SAAS,SAAS;GAChB,IAAI,WAAW,UAAU,WAAW;IAClC,QAAQ,QAAQ;IAEhB,eAAoB,YAAY,CAAC;GACnC;EACF;EAEA,SAAS,eAAe,MAAoB;GAC1C,MAAM,SAAS,UAAU;GACzB,IAAI,CAAC,QAAQ;GAEb,IAAI,WAAW,UAAU,WAAW;IAClC,MAAM,QAAQ,QAAQ,SAAS;IAC/B,IAAI,CAAC,OAAO;IACZ,MAAM,SAAS,MAAM;IACrB,MAAM,QAAQ,OAAO,eAAe,KAAK,SAAS,MAAM,OAAO,SAAS;IACxE,OAAO,oBAAoB,QAAQ,OAAO;KACxC,OAAO,KAAK;KACZ,OAAO,KAAK;KACZ,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;IACzC,CAAC;IACD,QAAQ,OAAO;GACjB,OAAO,IAAI,WAAW,UAAU,YAAY;IAC1C,MAAM,MAAM,kBAAkB;IAC9B,IAAI,QAAQ,MACV,OAAO,aAAa,KAAK;KACvB,OAAO,KAAK;KACZ,OAAO,KAAK;KACZ,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;IACzC,CAAC;GAEL;GACA,YAAY;EACd;EAEA,SAAS,kBAAkB;GACzB,IAAI,WAAW,UAAU,WAAW,QAAQ,QAAQ;GACpD,YAAY;EACd;EAEA,SAAS,sBAAsB,GAAY;GACzC,IAAI,CAAC,KAAK,WAAW,UAAU,MAAM;IACnC,IAAI,WAAW,UAAU,WAAW,QAAQ,QAAQ;IACpD,YAAY;GACd;EACF;;GA9OE,OAAA,UAAA,GAAA,mBA0BM,OAAA,EA1BA,OAAK,eAAE,UAAA,KAAS,EAAA,GAAA;IACpB,mBAQO,OAAA;KAPL,KAAI;KACH,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA;KACZ,iBAAe,CAAG,MAAA,QAAA,KAAQ,CAAK,MAAA,QAAA;KAC/B,cAAY,QAAA,SAAW,KAAA;KACvB,oBAAkB,MAAM;KACf;KACH;;IAGE,gBAAA,SAAA,UAAA,GAAX,mBAEM,OAAA;;KAFuB,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,aAAA,CAAA;IACpC,GAAA,gBAAA,MAAM,WAAW,GAAA,CAAA,KAAA,mBAAA,QAAA,IAAA;IAGtB,YAUE,aAAA;KATI,SAAA;KAAJ,KAAI;KACH,SAAS,cAAA;KACT,eAAa,iBAAA;KACb,WAAW,MAAM;KACjB,QAAQ,aAAA;KACR,qBAAmB,MAAM,oBAAgB;KACzC,UAAQ;KACR,WAAS;KACT,oBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-picker.js","names":[],"sources":["../../../src/components/file-picker/file-picker.vue"],"sourcesContent":["<template>\n <component\n :is=\"tag\"\n :class=\"cls.b\"\n @click.stop=\"handleClickPicker\"\n @dragover.prevent=\"handleDragover\"\n @dragleave=\"handleDragLeave\"\n @drop.prevent=\"handleDrop\"\n >\n <input\n :multiple=\"multiple\"\n :class=\"cls.e('native')\"\n type=\"file\"\n :accept=\"accept\"\n hidden\n placeholder=\"选择文件\"\n ref=\"fileRef\"\n @change=\"handleChange\"\n capture=\"environment\"\n />\n <slot :is-dragover=\"isDragover\" />\n </component>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { shallowRef, ref } from 'vue'\n\nimport type { UploaderProps, UploaderEmits } from '../../types'\nimport { matchAccept } from './helper'\n\ndefineOptions({ name: 'UFilePicker' })\n\nconst props = withDefaults(defineProps<UploaderProps>(), { tag: 'div', multiple: false })\n\nconst emit = defineEmits<UploaderEmits>()\n\nconst cls = bem('file-picker')\n\nconst fileRef = shallowRef<HTMLInputElement>()\nconst isDragover = ref(false)\n\nconst processFiles = (files: File[]) => {\n const filteredFiles = files.filter((file) => matchAccept(file, props.accept))\n emit('pick', filteredFiles)\n}\n\nconst handleChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n const files = Array.from(target.files || [])\n processFiles(files)\n target.value = ''\n}\n\nconst handleDragover = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = true\n}\n\nconst handleDragLeave = (e: DragEvent) => {\n if (props.disabled) return\n const currentTarget = e.currentTarget as HTMLElement\n const relatedTarget = e.relatedTarget as HTMLElement | null\n\n if (currentTarget.contains(relatedTarget)) return\n isDragover.value = false\n}\n\nconst handleDrop = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = false\n const files = Array.from(e.dataTransfer?.files || [])\n processFiles(files)\n}\n\nfunction handleClickPicker() {\n if (props.disabled) return\n fileRef.value?.click()\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;EAiCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAE7B,MAAM,UAAU,WAA6B;EAC7C,MAAM,aAAa,IAAI,KAAK;EAE5B,MAAM,gBAAgB,UAAkB;GACtC,MAAM,gBAAgB,MAAM,QAAQ,SAAS,YAAY,MAAM,MAAM,MAAM,CAAC;GAC5E,KAAK,QAAQ,aAAa;EAC5B;EAEA,MAAM,gBAAgB,MAAa;GACjC,MAAM,SAAS,EAAE;GACjB,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,CAAC,CAAC;GAC3C,aAAa,KAAK;GAClB,OAAO,QAAQ;EACjB;EAEA,MAAM,kBAAkB,MAAiB;GACvC,IAAI,MAAM,UAAU;GACpB,WAAW,QAAQ;EACrB;EAEA,MAAM,mBAAmB,MAAiB;GACxC,IAAI,MAAM,UAAU;GACpB,MAAM,gBAAgB,EAAE;GACxB,MAAM,gBAAgB,EAAE;GAExB,IAAI,cAAc,SAAS,aAAa,GAAG;GAC3C,WAAW,QAAQ;EACrB;EAEA,MAAM,cAAc,MAAiB;GACnC,IAAI,MAAM,UAAU;GACpB,WAAW,QAAQ;GACnB,MAAM,QAAQ,MAAM,KAAK,EAAE,cAAc,SAAS,CAAC,CAAC;GACpD,aAAa,KAAK;EACpB;EAEA,SAAS,oBAAoB;GAC3B,IAAI,MAAM,UAAU;GACpB,QAAQ,OAAO,MAAM;EACvB;;
|
|
1
|
+
{"version":3,"file":"file-picker.js","names":[],"sources":["../../../src/components/file-picker/file-picker.vue"],"sourcesContent":["<template>\n <component\n :is=\"tag\"\n :class=\"cls.b\"\n @click.stop=\"handleClickPicker\"\n @dragover.prevent=\"handleDragover\"\n @dragleave=\"handleDragLeave\"\n @drop.prevent=\"handleDrop\"\n >\n <input\n :multiple=\"multiple\"\n :class=\"cls.e('native')\"\n type=\"file\"\n :accept=\"accept\"\n hidden\n placeholder=\"选择文件\"\n ref=\"fileRef\"\n @change=\"handleChange\"\n capture=\"environment\"\n />\n <slot :is-dragover=\"isDragover\" />\n </component>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { shallowRef, ref } from 'vue'\n\nimport type { UploaderProps, UploaderEmits } from '../../types'\nimport { matchAccept } from './helper'\n\ndefineOptions({ name: 'UFilePicker' })\n\nconst props = withDefaults(defineProps<UploaderProps>(), { tag: 'div', multiple: false })\n\nconst emit = defineEmits<UploaderEmits>()\n\nconst cls = bem('file-picker')\n\nconst fileRef = shallowRef<HTMLInputElement>()\nconst isDragover = ref(false)\n\nconst processFiles = (files: File[]) => {\n const filteredFiles = files.filter((file) => matchAccept(file, props.accept))\n emit('pick', filteredFiles)\n}\n\nconst handleChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n const files = Array.from(target.files || [])\n processFiles(files)\n target.value = ''\n}\n\nconst handleDragover = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = true\n}\n\nconst handleDragLeave = (e: DragEvent) => {\n if (props.disabled) return\n const currentTarget = e.currentTarget as HTMLElement\n const relatedTarget = e.relatedTarget as HTMLElement | null\n\n if (currentTarget.contains(relatedTarget)) return\n isDragover.value = false\n}\n\nconst handleDrop = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = false\n const files = Array.from(e.dataTransfer?.files || [])\n processFiles(files)\n}\n\nfunction handleClickPicker() {\n if (props.disabled) return\n fileRef.value?.click()\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;EAiCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAE7B,MAAM,UAAU,WAA6B;EAC7C,MAAM,aAAa,IAAI,KAAK;EAE5B,MAAM,gBAAgB,UAAkB;GACtC,MAAM,gBAAgB,MAAM,QAAQ,SAAS,YAAY,MAAM,MAAM,MAAM,CAAC;GAC5E,KAAK,QAAQ,aAAa;EAC5B;EAEA,MAAM,gBAAgB,MAAa;GACjC,MAAM,SAAS,EAAE;GACjB,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,CAAC,CAAC;GAC3C,aAAa,KAAK;GAClB,OAAO,QAAQ;EACjB;EAEA,MAAM,kBAAkB,MAAiB;GACvC,IAAI,MAAM,UAAU;GACpB,WAAW,QAAQ;EACrB;EAEA,MAAM,mBAAmB,MAAiB;GACxC,IAAI,MAAM,UAAU;GACpB,MAAM,gBAAgB,EAAE;GACxB,MAAM,gBAAgB,EAAE;GAExB,IAAI,cAAc,SAAS,aAAa,GAAG;GAC3C,WAAW,QAAQ;EACrB;EAEA,MAAM,cAAc,MAAiB;GACnC,IAAI,MAAM,UAAU;GACpB,WAAW,QAAQ;GACnB,MAAM,QAAQ,MAAM,KAAK,EAAE,cAAc,SAAS,CAAC,CAAC;GACpD,aAAa,KAAK;EACpB;EAEA,SAAS,oBAAoB;GAC3B,IAAI,MAAM,UAAU;GACpB,QAAQ,OAAO,MAAM;EACvB;;GA7EE,OAAA,UAAA,GAAA,YAoBY,wBAnBL,QAAA,GAAG,GAAA;IACP,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,CAAC;IACZ,SAAK,cAAO,mBAAiB,CAAA,MAAA,CAAA;IAC7B,YAAQ,cAAU,gBAAc,CAAA,SAAA,CAAA;IAChC,aAAW;IACX,QAAI,cAAU,YAAU,CAAA,SAAA,CAAA;;IAYvB,SAAA,cAAA,CAVF,mBAUE,SAAA;KATC,UAAU,QAAA;KACV,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA,CAAA;KACb,MAAK;KACJ,QAAQ,QAAA;KACT,QAAA;KACA,aAAY;KACR,SAAA;KAAJ,KAAI;KACH,UAAQ;KACT,SAAQ;IAEV,GAAA,MAAA,IAAA,UAAA,GAAA,WAAkC,KAAA,QAAA,WAAA,EAA3B,YAAa,WAAA,MAAU,CAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-viewer.js","names":[],"sources":["../../../src/components/file-viewer/file-viewer.vue"],"sourcesContent":["<template>\n <Teleport to=\"body\" :disabled=\"!isModal\">\n <transition :name=\"isModal ? 'u-file-viewer-modal' : ''\">\n <div\n v-if=\"!isModal || openModel\"\n :class=\"[cls.b, bem.is('modal', isModal)]\"\n :tabindex=\"isModal ? -1 : undefined\"\n ref=\"rootRef\"\n @mousedown.self=\"handleBackdropMousedown\"\n >\n <div v-if=\"isModal\" :class=\"cls.e('backdrop')\" @mousedown.self=\"handleBackdropMousedown\" />\n <div :class=\"cls.e('inner')\">\n <aside v-if=\"showSidebar\" :class=\"cls.e('sidebar')\" :style=\"{ width: sidebarWidthCss }\">\n <header :class=\"cls.e('sidebar-head')\">\n <span :class=\"cls.e('sidebar-title')\">文件</span>\n <span :class=\"cls.e('sidebar-count')\">{{ normalizedFiles.length }}</span>\n </header>\n <u-scroll tag=\"ul\" :class=\"cls.e('list')\">\n <li\n v-for=\"f in normalizedFiles\"\n :key=\"f.id\"\n :class=\"[cls.e('item'), bem.is('active', f.id === activeId)]\"\n :title=\"f.name\"\n @click=\"activate(f.id)\"\n >\n <span :class=\"cls.e('item-meta')\">\n <span :class=\"cls.e('item-name')\" :title=\"f.name\">{{ f.name }}</span>\n <span :class=\"cls.e('item-size')\">{{ formatBytes(f.size) }}</span>\n </span>\n <span :class=\"cls.e('item-kind')\">{{ label(f.kind) }}</span>\n </li>\n <li v-if=\"!normalizedFiles.length\" :class=\"cls.e('list-empty')\">\n <u-empty text=\"暂无文件\" :size=\"32\" />\n </li>\n </u-scroll>\n </aside>\n\n <section :class=\"cls.e('stage')\">\n <header :class=\"cls.e('stage-head')\">\n <div :class=\"cls.e('stage-title')\">\n <span v-if=\"activeFile\" :class=\"[cls.e('badge'), cls.em('badge', activeFile.kind)]\">\n {{ label(activeFile.kind) }}\n </span>\n <span :class=\"cls.e('stage-copy')\">\n <span :class=\"cls.e('stage-name')\" :title=\"activeFile?.name\">\n {{ activeFile?.name ?? '—' }}\n </span>\n <span v-if=\"activeFile\" :class=\"cls.e('stage-sub')\">\n <span>{{ activeIndexLabel }}</span>\n <span v-if=\"activeFile.size\">{{ formatBytes(activeFile.size) }}</span>\n </span>\n </span>\n </div>\n <div :class=\"cls.e('stage-actions')\">\n <span :class=\"cls.e('action-group')\">\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"!hasPrev\"\n type=\"button\"\n aria-label=\"上一个\"\n title=\"上一个\"\n @click=\"prev\"\n >\n <u-icon :size=\"15\">\n <ArrowLeft />\n </u-icon>\n </button>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"!hasNext\"\n type=\"button\"\n aria-label=\"下一个\"\n title=\"下一个\"\n @click=\"next\"\n >\n <u-icon :size=\"15\">\n <ArrowRight />\n </u-icon>\n </button>\n </span>\n <span v-if=\"isZoomable\" :class=\"cls.e('action-group')\">\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"zoomOutDisabled\"\n type=\"button\"\n aria-label=\"缩小\"\n title=\"缩小\"\n @click=\"zoomOut\"\n >\n <u-icon :size=\"15\">\n <ZoomOut />\n </u-icon>\n </button>\n <span :class=\"cls.e('zoom-value')\">{{ zoomPercent }}</span>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"zoomInDisabled\"\n type=\"button\"\n aria-label=\"放大\"\n title=\"放大\"\n @click=\"zoomIn\"\n >\n <u-icon :size=\"15\">\n <ZoomIn />\n </u-icon>\n </button>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"isTransformReset\"\n type=\"button\"\n aria-label=\"重置视图\"\n title=\"重置视图\"\n @click=\"resetTransform\"\n >\n <u-icon :size=\"15\">\n <Refresh />\n </u-icon>\n </button>\n </span>\n <button\n v-if=\"downloadable && activeFile\"\n :class=\"[cls.e('action'), cls.em('action', 'primary'), cls.em('action', 'icon')]\"\n type=\"button\"\n aria-label=\"下载\"\n title=\"下载\"\n @click=\"download\"\n >\n <u-icon :size=\"15\">\n <Download />\n </u-icon>\n </button>\n <button\n v-if=\"isModal\"\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n type=\"button\"\n aria-label=\"关闭预览\"\n title=\"关闭\"\n @click=\"handleClose\"\n >\n <u-icon :size=\"16\">\n <Close />\n </u-icon>\n </button>\n </div>\n </header>\n <div :class=\"cls.e('body')\">\n <transition name=\"u-file-viewer-fade\" mode=\"out-in\">\n <div\n v-if=\"activeFile\"\n :key=\"activeFile.id\"\n :class=\"[\n cls.e('viewport'),\n bem.is('transformable', isTransformable),\n bem.is('pannable', canPan),\n bem.is('dragging', isDragging)\n ]\"\n @pointerdown.capture=\"handleViewportPointerDown\"\n @pointermove.capture=\"handleViewportPointerMove\"\n @pointerup.capture=\"handleViewportPointerEnd\"\n @pointercancel.capture=\"handleViewportPointerEnd\"\n @wheel=\"handleViewportWheel\"\n @dblclick=\"handleViewportDblclick\"\n >\n <component\n :is=\"PreviewerMap[activeFile.kind]\"\n ref=\"previewerRef\"\n :file=\"activeFile\"\n :max-rows=\"sheetMaxRows\"\n :class=\"isTransformable ? cls.e('previewer') : undefined\"\n :style=\"previewerStyle\"\n @error=\"handleChildError\"\n @zoom-change=\"handlePdfZoomChange\"\n />\n </div>\n <div v-else :class=\"cls.e('empty')\">\n <u-empty text=\"暂无可预览文件\" />\n </div>\n </transition>\n </div>\n </section>\n </div>\n </div>\n </transition>\n </Teleport>\n</template>\n\n<script lang=\"ts\" setup>\nimport {\n ArrowLeft,\n ArrowRight,\n Close,\n Download,\n Refresh,\n ZoomIn,\n ZoomOut\n} from '@veltra/icons/normal'\nimport { bem, withUnit } from '@veltra/utils'\nimport {\n computed,\n defineAsyncComponent,\n nextTick,\n onBeforeUnmount,\n ref,\n shallowRef,\n watch\n} from 'vue'\nimport type { CSSProperties } from 'vue'\n\nimport type {\n _FileViewerExposed,\n FileViewerEmits,\n FileViewerItem,\n FileViewerKind,\n FileViewerProps\n} from '../../types/file-viewer'\nimport { UEmpty } from '../empty'\nimport { UIcon } from '../icon'\nimport { UScroll } from '../scroll'\nimport { FILE_VIEWER_KIND_LABEL, downloadFile, formatBytes, inferKind } from './helper'\n\ndefineOptions({ name: 'UFileViewer', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FileViewerProps>(), {\n modelValue: undefined,\n sidebarWidth: '280px',\n sheetMaxRows: 50_000,\n downloadable: true,\n open: undefined,\n closeOnClickBackdrop: true,\n closeOnEsc: true\n})\n\nconst emit = defineEmits<FileViewerEmits>()\n\nconst cls = bem('file-viewer')\n\nconst MIN_SCALE = 0.5\nconst MAX_SCALE = 3\n/** 每次缩放固定增减 10% */\nconst SCALE_STEP = 0.1\n/** 使用 CSS transform 缩放的类型(PDF 由 EmbedPDF zoom 插件处理) */\nconst TRANSFORMABLE_KINDS = new Set<FileViewerKind>(['image'])\n/** 工具栏显示缩放控件的类型 */\nconst ZOOMABLE_KINDS = new Set<FileViewerKind>(['image', 'pdf'])\n\nconst activeId = defineModel<string | undefined>('modelValue', { default: undefined })\nconst openModel = defineModel<boolean | undefined>('open', { default: undefined })\n\nconst rootRef = shallowRef<HTMLDivElement>()\nconst previewerRef = shallowRef<{\n zoomIn?: () => void\n zoomOut?: () => void\n resetZoom?: () => void\n}>()\nconst scale = ref(1)\nconst pdfZoomLevel = ref(1)\nconst offsetX = ref(0)\nconst offsetY = ref(0)\nconst isDragging = ref(false)\n\nlet dragState:\n | { pointerId: number; startX: number; startY: number; originX: number; originY: number }\n | undefined\n\nconst PreviewerMap: Record<FileViewerKind, ReturnType<typeof defineAsyncComponent>> = {\n image: defineAsyncComponent(() => import('./previewers/image-previewer.vue')),\n video: defineAsyncComponent(() => import('./previewers/video-previewer.vue')),\n pdf: defineAsyncComponent(() => import('./previewers/pdf-previewer.vue')),\n sheet: defineAsyncComponent(() => import('./previewers/sheet-previewer.vue')),\n docx: defineAsyncComponent(() => import('./previewers/docx-previewer.vue')),\n text: defineAsyncComponent(() => import('./previewers/text-previewer.vue'))\n}\n\ninterface NormalizedFile extends FileViewerItem {\n id: string\n kind: FileViewerKind\n}\n\nconst normalizedFiles = computed<NormalizedFile[]>(() =>\n props.files.map((f, i) => ({ ...f, id: f.id ?? `file-${i}`, kind: inferKind(f.name, f.kind) }))\n)\n\nconst activeFile = computed<NormalizedFile | undefined>(() =>\n normalizedFiles.value.find((f) => f.id === activeId.value)\n)\n\nconst activeIndex = computed(() => normalizedFiles.value.findIndex((f) => f.id === activeId.value))\n\nconst hasPrev = computed(() => activeIndex.value > 0)\nconst hasNext = computed(\n () => activeIndex.value >= 0 && activeIndex.value < normalizedFiles.value.length - 1\n)\n\nconst showSidebar = computed(() => props.sidebarWidth !== false && props.sidebarWidth !== 0)\n\nconst sidebarWidthCss = computed(() => {\n const w = props.sidebarWidth\n if (w === false || w === 0) return undefined\n return withUnit(w ?? '280px', 'px')\n})\n\n/** 是否启用模态模式:只要父组件显式传入 open(含 v-model:open),即进入模态 */\nconst isModal = computed(() => openModel.value !== undefined)\n\nconst activeIndexLabel = computed(() =>\n activeIndex.value >= 0 ? `${activeIndex.value + 1} / ${normalizedFiles.value.length}` : ''\n)\n\nconst isTransformable = computed(\n () => !!activeFile.value && TRANSFORMABLE_KINDS.has(activeFile.value.kind)\n)\n\nconst isZoomable = computed(() => !!activeFile.value && ZOOMABLE_KINDS.has(activeFile.value.kind))\n\nconst isPdfActive = computed(() => activeFile.value?.kind === 'pdf')\n\nconst canPan = computed(() => isTransformable.value && scale.value > 1)\n\nconst displayZoomLevel = computed(() => (isPdfActive.value ? pdfZoomLevel.value : scale.value))\n\nconst zoomPercent = computed(() => `${Math.round(displayZoomLevel.value * 100)}%`)\n\nconst zoomInDisabled = computed(() => !isZoomable.value || displayZoomLevel.value >= MAX_SCALE)\n\nconst zoomOutDisabled = computed(() => !isZoomable.value || displayZoomLevel.value <= MIN_SCALE)\n\nconst isTransformReset = computed(() => {\n if (isPdfActive.value) {\n return Math.abs(pdfZoomLevel.value - 1) < 0.02\n }\n return scale.value === 1 && offsetX.value === 0 && offsetY.value === 0\n})\n\nconst previewerStyle = computed<CSSProperties | undefined>(() => {\n if (!isTransformable.value) return undefined\n return {\n transform: `translate3d(${offsetX.value}px, ${offsetY.value}px, 0) scale(${scale.value})`\n }\n})\n\nfunction label(kind: FileViewerKind): string {\n return FILE_VIEWER_KIND_LABEL[kind]\n}\n\nfunction activate(id: string) {\n if (activeId.value === id) return\n activeId.value = id\n const f = normalizedFiles.value.find((x) => x.id === id)\n if (f) emit('change', f)\n}\n\nfunction prev() {\n const i = activeIndex.value\n if (i <= 0) return\n const target = normalizedFiles.value[i - 1]\n if (target) activate(target.id)\n}\n\nfunction next() {\n const i = activeIndex.value\n if (i < 0 || i >= normalizedFiles.value.length - 1) return\n const target = normalizedFiles.value[i + 1]\n if (target) activate(target.id)\n}\n\nfunction normalizeScale(value: number): number {\n const clamped = Math.min(MAX_SCALE, Math.max(MIN_SCALE, value))\n return Math.round(clamped * 100) / 100\n}\n\nfunction setScale(value: number) {\n scale.value = normalizeScale(value)\n if (scale.value <= 1) {\n offsetX.value = 0\n offsetY.value = 0\n }\n}\n\nfunction zoomIn() {\n if (!isZoomable.value) return\n if (isPdfActive.value) {\n previewerRef.value?.zoomIn?.()\n return\n }\n setScale(scale.value + SCALE_STEP)\n}\n\nfunction zoomOut() {\n if (!isZoomable.value) return\n if (isPdfActive.value) {\n previewerRef.value?.zoomOut?.()\n return\n }\n setScale(scale.value - SCALE_STEP)\n}\n\nfunction resetTransform() {\n if (isPdfActive.value) {\n previewerRef.value?.resetZoom?.()\n pdfZoomLevel.value = 1\n return\n }\n scale.value = 1\n offsetX.value = 0\n offsetY.value = 0\n dragState = undefined\n isDragging.value = false\n}\n\nfunction handlePdfZoomChange(level: number) {\n pdfZoomLevel.value = level\n}\n\nfunction isZoomWheel(e: WheelEvent): boolean {\n return e.ctrlKey || e.metaKey\n}\n\nfunction handleViewportWheel(e: WheelEvent) {\n if (!activeFile.value || activeFile.value.kind !== 'image') return\n if (!isZoomWheel(e)) return\n if (isInteractiveTarget(e.target)) return\n e.preventDefault()\n const delta = e.deltaY > 0 ? -SCALE_STEP : SCALE_STEP\n setScale(scale.value + delta)\n}\n\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false\n return !!target.closest('button, a, input, textarea, select, video, [contenteditable=\"true\"]')\n}\n\nfunction handleViewportPointerDown(e: PointerEvent) {\n if (!canPan.value || e.button !== 0 || isInteractiveTarget(e.target)) return\n\n dragState = {\n pointerId: e.pointerId,\n startX: e.clientX,\n startY: e.clientY,\n originX: offsetX.value,\n originY: offsetY.value\n }\n isDragging.value = true\n const el = e.currentTarget as HTMLElement\n el.setPointerCapture(e.pointerId)\n e.preventDefault()\n}\n\nfunction handleViewportPointerMove(e: PointerEvent) {\n if (!dragState || dragState.pointerId !== e.pointerId) return\n offsetX.value = dragState.originX + e.clientX - dragState.startX\n offsetY.value = dragState.originY + e.clientY - dragState.startY\n}\n\nfunction handleViewportPointerEnd(e: PointerEvent) {\n if (!dragState || dragState.pointerId !== e.pointerId) return\n const el = e.currentTarget as HTMLElement\n if (el.hasPointerCapture(e.pointerId)) {\n el.releasePointerCapture(e.pointerId)\n }\n dragState = undefined\n isDragging.value = false\n}\n\nfunction handleViewportDblclick() {\n if (isPdfActive.value) return\n if (!isTransformable.value) return\n if (scale.value === 1) {\n setScale(2)\n } else {\n resetTransform()\n }\n}\n\nasync function download() {\n if (!activeFile.value) return\n try {\n await downloadFile(activeFile.value)\n } catch (err) {\n emit('error', { file: activeFile.value, error: err })\n }\n}\n\nfunction handleChildError(err: unknown) {\n if (!activeFile.value) return\n emit('error', { file: activeFile.value, error: err })\n}\n\nfunction handleClose() {\n if (!isModal.value) return\n openModel.value = false\n}\n\nfunction handleWindowKeydown(e: KeyboardEvent) {\n if (e.key !== 'Escape') return\n if (!isModal.value || !openModel.value) return\n if (props.closeOnEsc === false) return\n e.stopPropagation()\n handleClose()\n}\n\nfunction handleBackdropMousedown() {\n if (!isModal.value) return\n if (props.closeOnClickBackdrop === false) return\n handleClose()\n}\n\nwatch(\n normalizedFiles,\n (files) => {\n if (!files.length) {\n activeId.value = undefined\n return\n }\n if (!activeId.value || !files.some((f) => f.id === activeId.value)) {\n activeId.value = files[0]!.id\n }\n },\n { immediate: true }\n)\n\nwatch(\n () => activeFile.value?.id,\n async () => {\n pdfZoomLevel.value = 1\n await nextTick()\n resetTransform()\n }\n)\n\n// 模态打开时:锁定 body 滚动 + 让容器获得焦点以便接收 ESC\nlet previousBodyOverflow = ''\nlet isBodyLocked = false\n\nfunction lockBody() {\n if (isBodyLocked || typeof document === 'undefined') return\n previousBodyOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n isBodyLocked = true\n}\n\nfunction unlockBody() {\n if (!isBodyLocked || typeof document === 'undefined') return\n document.body.style.overflow = previousBodyOverflow\n isBodyLocked = false\n}\n\nwatch(\n [isModal, openModel],\n ([modal, open]) => {\n if (modal && open) {\n lockBody()\n nextTick(() => {\n rootRef.value?.focus()\n })\n if (typeof window !== 'undefined') {\n window.addEventListener('keydown', handleWindowKeydown, true)\n }\n } else {\n unlockBody()\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', handleWindowKeydown, true)\n }\n }\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n unlockBody()\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', handleWindowKeydown, true)\n }\n})\n\ndefineExpose<_FileViewerExposed>({ activeId, activate, next, prev })\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file-viewer.js","names":[],"sources":["../../../src/components/file-viewer/file-viewer.vue"],"sourcesContent":["<template>\n <Teleport to=\"body\" :disabled=\"!isModal\">\n <transition :name=\"isModal ? 'u-file-viewer-modal' : ''\">\n <div\n v-if=\"!isModal || openModel\"\n :class=\"[cls.b, bem.is('modal', isModal)]\"\n :tabindex=\"isModal ? -1 : undefined\"\n ref=\"rootRef\"\n @mousedown.self=\"handleBackdropMousedown\"\n >\n <div v-if=\"isModal\" :class=\"cls.e('backdrop')\" @mousedown.self=\"handleBackdropMousedown\" />\n <div :class=\"cls.e('inner')\">\n <aside v-if=\"showSidebar\" :class=\"cls.e('sidebar')\" :style=\"{ width: sidebarWidthCss }\">\n <header :class=\"cls.e('sidebar-head')\">\n <span :class=\"cls.e('sidebar-title')\">文件</span>\n <span :class=\"cls.e('sidebar-count')\">{{ normalizedFiles.length }}</span>\n </header>\n <u-scroll tag=\"ul\" :class=\"cls.e('list')\">\n <li\n v-for=\"f in normalizedFiles\"\n :key=\"f.id\"\n :class=\"[cls.e('item'), bem.is('active', f.id === activeId)]\"\n :title=\"f.name\"\n @click=\"activate(f.id)\"\n >\n <span :class=\"cls.e('item-meta')\">\n <span :class=\"cls.e('item-name')\" :title=\"f.name\">{{ f.name }}</span>\n <span :class=\"cls.e('item-size')\">{{ formatBytes(f.size) }}</span>\n </span>\n <span :class=\"cls.e('item-kind')\">{{ label(f.kind) }}</span>\n </li>\n <li v-if=\"!normalizedFiles.length\" :class=\"cls.e('list-empty')\">\n <u-empty text=\"暂无文件\" :size=\"32\" />\n </li>\n </u-scroll>\n </aside>\n\n <section :class=\"cls.e('stage')\">\n <header :class=\"cls.e('stage-head')\">\n <div :class=\"cls.e('stage-title')\">\n <span v-if=\"activeFile\" :class=\"[cls.e('badge'), cls.em('badge', activeFile.kind)]\">\n {{ label(activeFile.kind) }}\n </span>\n <span :class=\"cls.e('stage-copy')\">\n <span :class=\"cls.e('stage-name')\" :title=\"activeFile?.name\">\n {{ activeFile?.name ?? '—' }}\n </span>\n <span v-if=\"activeFile\" :class=\"cls.e('stage-sub')\">\n <span>{{ activeIndexLabel }}</span>\n <span v-if=\"activeFile.size\">{{ formatBytes(activeFile.size) }}</span>\n </span>\n </span>\n </div>\n <div :class=\"cls.e('stage-actions')\">\n <span :class=\"cls.e('action-group')\">\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"!hasPrev\"\n type=\"button\"\n aria-label=\"上一个\"\n title=\"上一个\"\n @click=\"prev\"\n >\n <u-icon :size=\"15\">\n <ArrowLeft />\n </u-icon>\n </button>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"!hasNext\"\n type=\"button\"\n aria-label=\"下一个\"\n title=\"下一个\"\n @click=\"next\"\n >\n <u-icon :size=\"15\">\n <ArrowRight />\n </u-icon>\n </button>\n </span>\n <span v-if=\"isZoomable\" :class=\"cls.e('action-group')\">\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"zoomOutDisabled\"\n type=\"button\"\n aria-label=\"缩小\"\n title=\"缩小\"\n @click=\"zoomOut\"\n >\n <u-icon :size=\"15\">\n <ZoomOut />\n </u-icon>\n </button>\n <span :class=\"cls.e('zoom-value')\">{{ zoomPercent }}</span>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"zoomInDisabled\"\n type=\"button\"\n aria-label=\"放大\"\n title=\"放大\"\n @click=\"zoomIn\"\n >\n <u-icon :size=\"15\">\n <ZoomIn />\n </u-icon>\n </button>\n <button\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n :disabled=\"isTransformReset\"\n type=\"button\"\n aria-label=\"重置视图\"\n title=\"重置视图\"\n @click=\"resetTransform\"\n >\n <u-icon :size=\"15\">\n <Refresh />\n </u-icon>\n </button>\n </span>\n <button\n v-if=\"downloadable && activeFile\"\n :class=\"[cls.e('action'), cls.em('action', 'primary'), cls.em('action', 'icon')]\"\n type=\"button\"\n aria-label=\"下载\"\n title=\"下载\"\n @click=\"download\"\n >\n <u-icon :size=\"15\">\n <Download />\n </u-icon>\n </button>\n <button\n v-if=\"isModal\"\n :class=\"[cls.e('action'), cls.em('action', 'icon')]\"\n type=\"button\"\n aria-label=\"关闭预览\"\n title=\"关闭\"\n @click=\"handleClose\"\n >\n <u-icon :size=\"16\">\n <Close />\n </u-icon>\n </button>\n </div>\n </header>\n <div :class=\"cls.e('body')\">\n <transition name=\"u-file-viewer-fade\" mode=\"out-in\">\n <div\n v-if=\"activeFile\"\n :key=\"activeFile.id\"\n :class=\"[\n cls.e('viewport'),\n bem.is('transformable', isTransformable),\n bem.is('pannable', canPan),\n bem.is('dragging', isDragging)\n ]\"\n @pointerdown.capture=\"handleViewportPointerDown\"\n @pointermove.capture=\"handleViewportPointerMove\"\n @pointerup.capture=\"handleViewportPointerEnd\"\n @pointercancel.capture=\"handleViewportPointerEnd\"\n @wheel=\"handleViewportWheel\"\n @dblclick=\"handleViewportDblclick\"\n >\n <component\n :is=\"PreviewerMap[activeFile.kind]\"\n ref=\"previewerRef\"\n :file=\"activeFile\"\n :max-rows=\"sheetMaxRows\"\n :class=\"isTransformable ? cls.e('previewer') : undefined\"\n :style=\"previewerStyle\"\n @error=\"handleChildError\"\n @zoom-change=\"handlePdfZoomChange\"\n />\n </div>\n <div v-else :class=\"cls.e('empty')\">\n <u-empty text=\"暂无可预览文件\" />\n </div>\n </transition>\n </div>\n </section>\n </div>\n </div>\n </transition>\n </Teleport>\n</template>\n\n<script lang=\"ts\" setup>\nimport {\n ArrowLeft,\n ArrowRight,\n Close,\n Download,\n Refresh,\n ZoomIn,\n ZoomOut\n} from '@veltra/icons/normal'\nimport { bem, withUnit } from '@veltra/utils'\nimport {\n computed,\n defineAsyncComponent,\n nextTick,\n onBeforeUnmount,\n ref,\n shallowRef,\n watch\n} from 'vue'\nimport type { CSSProperties } from 'vue'\n\nimport type {\n _FileViewerExposed,\n FileViewerEmits,\n FileViewerItem,\n FileViewerKind,\n FileViewerProps\n} from '../../types/file-viewer'\nimport { UEmpty } from '../empty'\nimport { UIcon } from '../icon'\nimport { UScroll } from '../scroll'\nimport { FILE_VIEWER_KIND_LABEL, downloadFile, formatBytes, inferKind } from './helper'\n\ndefineOptions({ name: 'UFileViewer', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FileViewerProps>(), {\n modelValue: undefined,\n sidebarWidth: '280px',\n sheetMaxRows: 50_000,\n downloadable: true,\n open: undefined,\n closeOnClickBackdrop: true,\n closeOnEsc: true\n})\n\nconst emit = defineEmits<FileViewerEmits>()\n\nconst cls = bem('file-viewer')\n\nconst MIN_SCALE = 0.5\nconst MAX_SCALE = 3\n/** 每次缩放固定增减 10% */\nconst SCALE_STEP = 0.1\n/** 使用 CSS transform 缩放的类型(PDF 由 EmbedPDF zoom 插件处理) */\nconst TRANSFORMABLE_KINDS = new Set<FileViewerKind>(['image'])\n/** 工具栏显示缩放控件的类型 */\nconst ZOOMABLE_KINDS = new Set<FileViewerKind>(['image', 'pdf'])\n\nconst activeId = defineModel<string | undefined>('modelValue', { default: undefined })\nconst openModel = defineModel<boolean | undefined>('open', { default: undefined })\n\nconst rootRef = shallowRef<HTMLDivElement>()\nconst previewerRef = shallowRef<{\n zoomIn?: () => void\n zoomOut?: () => void\n resetZoom?: () => void\n}>()\nconst scale = ref(1)\nconst pdfZoomLevel = ref(1)\nconst offsetX = ref(0)\nconst offsetY = ref(0)\nconst isDragging = ref(false)\n\nlet dragState:\n | { pointerId: number; startX: number; startY: number; originX: number; originY: number }\n | undefined\n\nconst PreviewerMap: Record<FileViewerKind, ReturnType<typeof defineAsyncComponent>> = {\n image: defineAsyncComponent(() => import('./previewers/image-previewer.vue')),\n video: defineAsyncComponent(() => import('./previewers/video-previewer.vue')),\n pdf: defineAsyncComponent(() => import('./previewers/pdf-previewer.vue')),\n sheet: defineAsyncComponent(() => import('./previewers/sheet-previewer.vue')),\n docx: defineAsyncComponent(() => import('./previewers/docx-previewer.vue')),\n text: defineAsyncComponent(() => import('./previewers/text-previewer.vue'))\n}\n\ninterface NormalizedFile extends FileViewerItem {\n id: string\n kind: FileViewerKind\n}\n\nconst normalizedFiles = computed<NormalizedFile[]>(() =>\n props.files.map((f, i) => ({ ...f, id: f.id ?? `file-${i}`, kind: inferKind(f.name, f.kind) }))\n)\n\nconst activeFile = computed<NormalizedFile | undefined>(() =>\n normalizedFiles.value.find((f) => f.id === activeId.value)\n)\n\nconst activeIndex = computed(() => normalizedFiles.value.findIndex((f) => f.id === activeId.value))\n\nconst hasPrev = computed(() => activeIndex.value > 0)\nconst hasNext = computed(\n () => activeIndex.value >= 0 && activeIndex.value < normalizedFiles.value.length - 1\n)\n\nconst showSidebar = computed(() => props.sidebarWidth !== false && props.sidebarWidth !== 0)\n\nconst sidebarWidthCss = computed(() => {\n const w = props.sidebarWidth\n if (w === false || w === 0) return undefined\n return withUnit(w ?? '280px', 'px')\n})\n\n/** 是否启用模态模式:只要父组件显式传入 open(含 v-model:open),即进入模态 */\nconst isModal = computed(() => openModel.value !== undefined)\n\nconst activeIndexLabel = computed(() =>\n activeIndex.value >= 0 ? `${activeIndex.value + 1} / ${normalizedFiles.value.length}` : ''\n)\n\nconst isTransformable = computed(\n () => !!activeFile.value && TRANSFORMABLE_KINDS.has(activeFile.value.kind)\n)\n\nconst isZoomable = computed(() => !!activeFile.value && ZOOMABLE_KINDS.has(activeFile.value.kind))\n\nconst isPdfActive = computed(() => activeFile.value?.kind === 'pdf')\n\nconst canPan = computed(() => isTransformable.value && scale.value > 1)\n\nconst displayZoomLevel = computed(() => (isPdfActive.value ? pdfZoomLevel.value : scale.value))\n\nconst zoomPercent = computed(() => `${Math.round(displayZoomLevel.value * 100)}%`)\n\nconst zoomInDisabled = computed(() => !isZoomable.value || displayZoomLevel.value >= MAX_SCALE)\n\nconst zoomOutDisabled = computed(() => !isZoomable.value || displayZoomLevel.value <= MIN_SCALE)\n\nconst isTransformReset = computed(() => {\n if (isPdfActive.value) {\n return Math.abs(pdfZoomLevel.value - 1) < 0.02\n }\n return scale.value === 1 && offsetX.value === 0 && offsetY.value === 0\n})\n\nconst previewerStyle = computed<CSSProperties | undefined>(() => {\n if (!isTransformable.value) return undefined\n return {\n transform: `translate3d(${offsetX.value}px, ${offsetY.value}px, 0) scale(${scale.value})`\n }\n})\n\nfunction label(kind: FileViewerKind): string {\n return FILE_VIEWER_KIND_LABEL[kind]\n}\n\nfunction activate(id: string) {\n if (activeId.value === id) return\n activeId.value = id\n const f = normalizedFiles.value.find((x) => x.id === id)\n if (f) emit('change', f)\n}\n\nfunction prev() {\n const i = activeIndex.value\n if (i <= 0) return\n const target = normalizedFiles.value[i - 1]\n if (target) activate(target.id)\n}\n\nfunction next() {\n const i = activeIndex.value\n if (i < 0 || i >= normalizedFiles.value.length - 1) return\n const target = normalizedFiles.value[i + 1]\n if (target) activate(target.id)\n}\n\nfunction normalizeScale(value: number): number {\n const clamped = Math.min(MAX_SCALE, Math.max(MIN_SCALE, value))\n return Math.round(clamped * 100) / 100\n}\n\nfunction setScale(value: number) {\n scale.value = normalizeScale(value)\n if (scale.value <= 1) {\n offsetX.value = 0\n offsetY.value = 0\n }\n}\n\nfunction zoomIn() {\n if (!isZoomable.value) return\n if (isPdfActive.value) {\n previewerRef.value?.zoomIn?.()\n return\n }\n setScale(scale.value + SCALE_STEP)\n}\n\nfunction zoomOut() {\n if (!isZoomable.value) return\n if (isPdfActive.value) {\n previewerRef.value?.zoomOut?.()\n return\n }\n setScale(scale.value - SCALE_STEP)\n}\n\nfunction resetTransform() {\n if (isPdfActive.value) {\n previewerRef.value?.resetZoom?.()\n pdfZoomLevel.value = 1\n return\n }\n scale.value = 1\n offsetX.value = 0\n offsetY.value = 0\n dragState = undefined\n isDragging.value = false\n}\n\nfunction handlePdfZoomChange(level: number) {\n pdfZoomLevel.value = level\n}\n\nfunction isZoomWheel(e: WheelEvent): boolean {\n return e.ctrlKey || e.metaKey\n}\n\nfunction handleViewportWheel(e: WheelEvent) {\n if (!activeFile.value || activeFile.value.kind !== 'image') return\n if (!isZoomWheel(e)) return\n if (isInteractiveTarget(e.target)) return\n e.preventDefault()\n const delta = e.deltaY > 0 ? -SCALE_STEP : SCALE_STEP\n setScale(scale.value + delta)\n}\n\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false\n return !!target.closest('button, a, input, textarea, select, video, [contenteditable=\"true\"]')\n}\n\nfunction handleViewportPointerDown(e: PointerEvent) {\n if (!canPan.value || e.button !== 0 || isInteractiveTarget(e.target)) return\n\n dragState = {\n pointerId: e.pointerId,\n startX: e.clientX,\n startY: e.clientY,\n originX: offsetX.value,\n originY: offsetY.value\n }\n isDragging.value = true\n const el = e.currentTarget as HTMLElement\n el.setPointerCapture(e.pointerId)\n e.preventDefault()\n}\n\nfunction handleViewportPointerMove(e: PointerEvent) {\n if (!dragState || dragState.pointerId !== e.pointerId) return\n offsetX.value = dragState.originX + e.clientX - dragState.startX\n offsetY.value = dragState.originY + e.clientY - dragState.startY\n}\n\nfunction handleViewportPointerEnd(e: PointerEvent) {\n if (!dragState || dragState.pointerId !== e.pointerId) return\n const el = e.currentTarget as HTMLElement\n if (el.hasPointerCapture(e.pointerId)) {\n el.releasePointerCapture(e.pointerId)\n }\n dragState = undefined\n isDragging.value = false\n}\n\nfunction handleViewportDblclick() {\n if (isPdfActive.value) return\n if (!isTransformable.value) return\n if (scale.value === 1) {\n setScale(2)\n } else {\n resetTransform()\n }\n}\n\nasync function download() {\n if (!activeFile.value) return\n try {\n await downloadFile(activeFile.value)\n } catch (err) {\n emit('error', { file: activeFile.value, error: err })\n }\n}\n\nfunction handleChildError(err: unknown) {\n if (!activeFile.value) return\n emit('error', { file: activeFile.value, error: err })\n}\n\nfunction handleClose() {\n if (!isModal.value) return\n openModel.value = false\n}\n\nfunction handleWindowKeydown(e: KeyboardEvent) {\n if (e.key !== 'Escape') return\n if (!isModal.value || !openModel.value) return\n if (props.closeOnEsc === false) return\n e.stopPropagation()\n handleClose()\n}\n\nfunction handleBackdropMousedown() {\n if (!isModal.value) return\n if (props.closeOnClickBackdrop === false) return\n handleClose()\n}\n\nwatch(\n normalizedFiles,\n (files) => {\n if (!files.length) {\n activeId.value = undefined\n return\n }\n if (!activeId.value || !files.some((f) => f.id === activeId.value)) {\n activeId.value = files[0]!.id\n }\n },\n { immediate: true }\n)\n\nwatch(\n () => activeFile.value?.id,\n async () => {\n pdfZoomLevel.value = 1\n await nextTick()\n resetTransform()\n }\n)\n\n// 模态打开时:锁定 body 滚动 + 让容器获得焦点以便接收 ESC\nlet previousBodyOverflow = ''\nlet isBodyLocked = false\n\nfunction lockBody() {\n if (isBodyLocked || typeof document === 'undefined') return\n previousBodyOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n isBodyLocked = true\n}\n\nfunction unlockBody() {\n if (!isBodyLocked || typeof document === 'undefined') return\n document.body.style.overflow = previousBodyOverflow\n isBodyLocked = false\n}\n\nwatch(\n [isModal, openModel],\n ([modal, open]) => {\n if (modal && open) {\n lockBody()\n nextTick(() => {\n rootRef.value?.focus()\n })\n if (typeof window !== 'undefined') {\n window.addEventListener('keydown', handleWindowKeydown, true)\n }\n } else {\n unlockBody()\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', handleWindowKeydown, true)\n }\n }\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n unlockBody()\n if (typeof window !== 'undefined') {\n window.removeEventListener('keydown', handleWindowKeydown, true)\n }\n})\n\ndefineExpose<_FileViewerExposed>({ activeId, activate, next, prev })\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4OA,MAAM,YAAY;AAClB,MAAM,YAAY;;AAElB,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAjBnB,MAAM,QAAQ;EAUd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAO7B,MAAM,sCAAsB,IAAI,IAAoB,CAAC,OAAO,CAAC;;EAE7D,MAAM,iCAAiB,IAAI,IAAoB,CAAC,SAAS,KAAK,CAAC;EAE/D,MAAM,WAAW,SAA+B,SAAC,YAAoC;EACrF,MAAM,YAAY,SAAgC,SAAC,MAA8B;EAEjF,MAAM,UAAU,WAA2B;EAC3C,MAAM,eAAe,WAIlB;EACH,MAAM,QAAQ,IAAI,CAAC;EACnB,MAAM,eAAe,IAAI,CAAC;EAC1B,MAAM,UAAU,IAAI,CAAC;EACrB,MAAM,UAAU,IAAI,CAAC;EACrB,MAAM,aAAa,IAAI,KAAK;EAE5B,IAAI;EAIJ,MAAM,eAAgF;GACpF,OAAO,2BAA2B,OAAO,kCAAmC;GAC5E,OAAO,2BAA2B,OAAO,kCAAmC;GAC5E,KAAK,2BAA2B,OAAO,gCAAiC;GACxE,OAAO,2BAA2B,OAAO,kCAAmC;GAC5E,MAAM,2BAA2B,OAAO,iCAAkC;GAC1E,MAAM,2BAA2B,OAAO,iCAAkC;EAC5E;EAOA,MAAM,kBAAkB,eACtB,MAAM,MAAM,KAAK,GAAG,OAAO;GAAE,GAAG;GAAG,IAAI,EAAE,MAAM,QAAQ;GAAK,MAAM,UAAU,EAAE,MAAM,EAAE,IAAI;EAAE,EAAE,CAChG;EAEA,MAAM,aAAa,eACjB,gBAAgB,MAAM,MAAM,MAAM,EAAE,OAAO,SAAS,KAAK,CAC3D;EAEA,MAAM,cAAc,eAAe,gBAAgB,MAAM,WAAW,MAAM,EAAE,OAAO,SAAS,KAAK,CAAC;EAElG,MAAM,UAAU,eAAe,YAAY,QAAQ,CAAC;EACpD,MAAM,UAAU,eACR,YAAY,SAAS,KAAK,YAAY,QAAQ,gBAAgB,MAAM,SAAS,CACrF;EAEA,MAAM,cAAc,eAAe,MAAM,iBAAiB,SAAS,MAAM,iBAAiB,CAAC;EAE3F,MAAM,kBAAkB,eAAe;GACrC,MAAM,IAAI,MAAM;GAChB,IAAI,MAAM,SAAS,MAAM,GAAG,OAAO,KAAA;GACnC,OAAO,SAAS,KAAK,SAAS,IAAI;EACpC,CAAC;;EAGD,MAAM,UAAU,eAAe,UAAU,UAAU,KAAA,CAAS;EAE5D,MAAM,mBAAmB,eACvB,YAAY,SAAS,IAAI,GAAG,YAAY,QAAQ,EAAE,KAAK,gBAAgB,MAAM,WAAW,EAC1F;EAEA,MAAM,kBAAkB,eAChB,CAAC,CAAC,WAAW,SAAS,oBAAoB,IAAI,WAAW,MAAM,IAAI,CAC3E;EAEA,MAAM,aAAa,eAAe,CAAC,CAAC,WAAW,SAAS,eAAe,IAAI,WAAW,MAAM,IAAI,CAAC;EAEjG,MAAM,cAAc,eAAe,WAAW,OAAO,SAAS,KAAK;EAEnE,MAAM,SAAS,eAAe,gBAAgB,SAAS,MAAM,QAAQ,CAAC;EAEtE,MAAM,mBAAmB,eAAgB,YAAY,QAAQ,aAAa,QAAQ,MAAM,KAAM;EAE9F,MAAM,cAAc,eAAe,GAAG,KAAK,MAAM,iBAAiB,QAAQ,GAAG,EAAE,EAAE;EAEjF,MAAM,iBAAiB,eAAe,CAAC,WAAW,SAAS,iBAAiB,SAAS,SAAS;EAE9F,MAAM,kBAAkB,eAAe,CAAC,WAAW,SAAS,iBAAiB,SAAS,SAAS;EAE/F,MAAM,mBAAmB,eAAe;GACtC,IAAI,YAAY,OACd,OAAO,KAAK,IAAI,aAAa,QAAQ,CAAC,IAAI;GAE5C,OAAO,MAAM,UAAU,KAAK,QAAQ,UAAU,KAAK,QAAQ,UAAU;EACvE,CAAC;EAED,MAAM,iBAAiB,eAA0C;GAC/D,IAAI,CAAC,gBAAgB,OAAO,OAAO,KAAA;GACnC,OAAO,EACL,WAAW,eAAe,QAAQ,MAAM,MAAM,QAAQ,MAAM,eAAe,MAAM,MAAM,GACzF;EACF,CAAC;EAED,SAAS,MAAM,MAA8B;GAC3C,OAAO,uBAAuB;EAChC;EAEA,SAAS,SAAS,IAAY;GAC5B,IAAI,SAAS,UAAU,IAAI;GAC3B,SAAS,QAAQ;GACjB,MAAM,IAAI,gBAAgB,MAAM,MAAM,MAAM,EAAE,OAAO,EAAE;GACvD,IAAI,GAAG,KAAK,UAAU,CAAC;EACzB;EAEA,SAAS,OAAO;GACd,MAAM,IAAI,YAAY;GACtB,IAAI,KAAK,GAAG;GACZ,MAAM,SAAS,gBAAgB,MAAM,IAAI;GACzC,IAAI,QAAQ,SAAS,OAAO,EAAE;EAChC;EAEA,SAAS,OAAO;GACd,MAAM,IAAI,YAAY;GACtB,IAAI,IAAI,KAAK,KAAK,gBAAgB,MAAM,SAAS,GAAG;GACpD,MAAM,SAAS,gBAAgB,MAAM,IAAI;GACzC,IAAI,QAAQ,SAAS,OAAO,EAAE;EAChC;EAEA,SAAS,eAAe,OAAuB;GAE7C,OAAO,KAAK,MADI,KAAK,IAAI,WAAW,KAAK,IAAI,WAAW,KAAK,CAC3C,IAAU,GAAG,IAAI;EACrC;EAEA,SAAS,SAAS,OAAe;GAC/B,MAAM,QAAQ,eAAe,KAAK;GAClC,IAAI,MAAM,SAAS,GAAG;IACpB,QAAQ,QAAQ;IAChB,QAAQ,QAAQ;GAClB;EACF;EAEA,SAAS,SAAS;GAChB,IAAI,CAAC,WAAW,OAAO;GACvB,IAAI,YAAY,OAAO;IACrB,aAAa,OAAO,SAAS;IAC7B;GACF;GACA,SAAS,MAAM,QAAQ,UAAU;EACnC;EAEA,SAAS,UAAU;GACjB,IAAI,CAAC,WAAW,OAAO;GACvB,IAAI,YAAY,OAAO;IACrB,aAAa,OAAO,UAAU;IAC9B;GACF;GACA,SAAS,MAAM,QAAQ,UAAU;EACnC;EAEA,SAAS,iBAAiB;GACxB,IAAI,YAAY,OAAO;IACrB,aAAa,OAAO,YAAY;IAChC,aAAa,QAAQ;IACrB;GACF;GACA,MAAM,QAAQ;GACd,QAAQ,QAAQ;GAChB,QAAQ,QAAQ;GAChB,YAAY,KAAA;GACZ,WAAW,QAAQ;EACrB;EAEA,SAAS,oBAAoB,OAAe;GAC1C,aAAa,QAAQ;EACvB;EAEA,SAAS,YAAY,GAAwB;GAC3C,OAAO,EAAE,WAAW,EAAE;EACxB;EAEA,SAAS,oBAAoB,GAAe;GAC1C,IAAI,CAAC,WAAW,SAAS,WAAW,MAAM,SAAS,SAAS;GAC5D,IAAI,CAAC,YAAY,CAAC,GAAG;GACrB,IAAI,oBAAoB,EAAE,MAAM,GAAG;GACnC,EAAE,eAAe;GACjB,MAAM,QAAQ,EAAE,SAAS,IAAI,MAAc;GAC3C,SAAS,MAAM,QAAQ,KAAK;EAC9B;EAEA,SAAS,oBAAoB,QAAqC;GAChE,IAAI,EAAE,kBAAkB,cAAc,OAAO;GAC7C,OAAO,CAAC,CAAC,OAAO,QAAQ,uEAAqE;EAC/F;EAEA,SAAS,0BAA0B,GAAiB;GAClD,IAAI,CAAC,OAAO,SAAS,EAAE,WAAW,KAAK,oBAAoB,EAAE,MAAM,GAAG;GAEtE,YAAY;IACV,WAAW,EAAE;IACb,QAAQ,EAAE;IACV,QAAQ,EAAE;IACV,SAAS,QAAQ;IACjB,SAAS,QAAQ;GACnB;GACA,WAAW,QAAQ;GAEnB,EADa,cACV,kBAAkB,EAAE,SAAS;GAChC,EAAE,eAAe;EACnB;EAEA,SAAS,0BAA0B,GAAiB;GAClD,IAAI,CAAC,aAAa,UAAU,cAAc,EAAE,WAAW;GACvD,QAAQ,QAAQ,UAAU,UAAU,EAAE,UAAU,UAAU;GAC1D,QAAQ,QAAQ,UAAU,UAAU,EAAE,UAAU,UAAU;EAC5D;EAEA,SAAS,yBAAyB,GAAiB;GACjD,IAAI,CAAC,aAAa,UAAU,cAAc,EAAE,WAAW;GACvD,MAAM,KAAK,EAAE;GACb,IAAI,GAAG,kBAAkB,EAAE,SAAS,GAClC,GAAG,sBAAsB,EAAE,SAAS;GAEtC,YAAY,KAAA;GACZ,WAAW,QAAQ;EACrB;EAEA,SAAS,yBAAyB;GAChC,IAAI,YAAY,OAAO;GACvB,IAAI,CAAC,gBAAgB,OAAO;GAC5B,IAAI,MAAM,UAAU,GAClB,SAAS,CAAC;QAEV,eAAe;EAEnB;EAEA,eAAe,WAAW;GACxB,IAAI,CAAC,WAAW,OAAO;GACvB,IAAI;IACF,MAAM,aAAa,WAAW,KAAK;GACrC,SAAS,KAAK;IACZ,KAAK,SAAS;KAAE,MAAM,WAAW;KAAO,OAAO;IAAI,CAAC;GACtD;EACF;EAEA,SAAS,iBAAiB,KAAc;GACtC,IAAI,CAAC,WAAW,OAAO;GACvB,KAAK,SAAS;IAAE,MAAM,WAAW;IAAO,OAAO;GAAI,CAAC;EACtD;EAEA,SAAS,cAAc;GACrB,IAAI,CAAC,QAAQ,OAAO;GACpB,UAAU,QAAQ;EACpB;EAEA,SAAS,oBAAoB,GAAkB;GAC7C,IAAI,EAAE,QAAQ,UAAU;GACxB,IAAI,CAAC,QAAQ,SAAS,CAAC,UAAU,OAAO;GACxC,IAAI,MAAM,eAAe,OAAO;GAChC,EAAE,gBAAgB;GAClB,YAAY;EACd;EAEA,SAAS,0BAA0B;GACjC,IAAI,CAAC,QAAQ,OAAO;GACpB,IAAI,MAAM,yBAAyB,OAAO;GAC1C,YAAY;EACd;EAEA,MACE,kBACC,UAAU;GACT,IAAI,CAAC,MAAM,QAAQ;IACjB,SAAS,QAAQ,KAAA;IACjB;GACF;GACA,IAAI,CAAC,SAAS,SAAS,CAAC,MAAM,MAAM,MAAM,EAAE,OAAO,SAAS,KAAK,GAC/D,SAAS,QAAQ,MAAM,EAAE,CAAE;EAE/B,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,YACQ,WAAW,OAAO,IACxB,YAAY;GACV,aAAa,QAAQ;GACrB,MAAM,SAAS;GACf,eAAe;EACjB,CACF;EAGA,IAAI,uBAAuB;EAC3B,IAAI,eAAe;EAEnB,SAAS,WAAW;GAClB,IAAI,gBAAgB,OAAO,aAAa,aAAa;GACrD,uBAAuB,SAAS,KAAK,MAAM;GAC3C,SAAS,KAAK,MAAM,WAAW;GAC/B,eAAe;EACjB;EAEA,SAAS,aAAa;GACpB,IAAI,CAAC,gBAAgB,OAAO,aAAa,aAAa;GACtD,SAAS,KAAK,MAAM,WAAW;GAC/B,eAAe;EACjB;EAEA,MACE,CAAC,SAAS,SAAS,IAClB,CAAC,OAAO,UAAU;GACjB,IAAI,SAAS,MAAM;IACjB,SAAS;IACT,eAAe;KACb,QAAQ,OAAO,MAAM;IACvB,CAAC;IACD,IAAI,OAAO,WAAW,aACpB,OAAO,iBAAiB,WAAW,qBAAqB,IAAI;GAEhE,OAAO;IACL,WAAW;IACX,IAAI,OAAO,WAAW,aACpB,OAAO,oBAAoB,WAAW,qBAAqB,IAAI;GAEnE;EACF,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,WAAW;GACX,IAAI,OAAO,WAAW,aACpB,OAAO,oBAAoB,WAAW,qBAAqB,IAAI;EAEnE,CAAC;EAED,SAAiC;GAAE;GAAU;GAAU;GAAM;EAAK,CAAC;;GA7jBjE,OAAA,UAAA,GAAA,YAsLW,UAAA;IAtLD,IAAG;IAAQ,UAAQ,CAAG,QAAA;GAC9B,GAAA,CAAA,YAoLa,YAAA,EApLA,MAAM,QAAA,QAAO,wBAAA,GAAA,GAAA;IAmLlB,SAAA,cAAA,CAAA,CAjLG,QAAA,SAAW,UAAA,SAAA,UAAA,GADpB,mBAkLM,OAAA;;KAhLH,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,GAAG,MAAA,GAAA,CAAG,CAAC,GAAE,SAAU,QAAA,KAAO,CAAA,CAAA;KACtC,UAAU,QAAA,QAAO,KAAQ,KAAA;KACtB,SAAA;KAAJ,KAAI;KACH,aAAS,cAAO,yBAAuB,CAAA,MAAA,CAAA;IAE7B,GAAA,CAAA,QAAA,SAAA,UAAA,GAAX,mBAA2F,OAAA;;KAAtE,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,UAAA,CAAA;KAAe,aAAS,cAAO,yBAAuB,CAAA,MAAA,CAAA;IACvF,GAAA,MAAA,EAAA,KAAA,mBAAA,QAAA,IAAA,GAAA,mBAyKM,OAAA,EAzKA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,CAAA,EAAA,GACH,CAAA,YAAA,SAAA,UAAA,GAAb,mBAuBQ,SAAA;;KAvBmB,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;KAAc,OAAK,eAAA,EAAA,OAAW,gBAAA,MAAe,CAAA;IAClF,GAAA,CAAA,mBAGS,UAAA,EAHA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,cAAA,CAAA,EAAA,GACnB,CAAA,mBAA+C,QAAA,EAAxC,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,eAAA,CAAA,EAAA,GAAmB,MAAE,CAAA,GACxC,mBAAyE,QAAA,EAAlE,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,eAAA,CAAA,EAAA,GAAsB,gBAAA,gBAAA,MAAgB,MAAM,GAAA,CAAA,CAAA,GAAA,CAEjE,GAAA,YAiBW,MAAA,WAAA,GAAA;KAjBD,KAAI;KAAM,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,MAAA,CAAA;;KAEA,SAAA,cAAA,EAAA,UAAA,IAAA,GAD9B,mBAYK,UAAA,MAAA,WAXS,gBAAA,QAAL,MAAC;MADV,OAAA,UAAA,GAAA,mBAYK,MAAA;OAVF,KAAK,EAAE;OACP,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,MAAA,GAAU,MAAA,GAAA,CAAG,CAAC,GAAE,UAAW,EAAE,OAAO,SAAA,KAAQ,CAAA,CAAA;OACzD,OAAO,EAAE;OACT,UAAK,WAAE,SAAS,EAAE,EAAE;MAErB,GAAA,CAAA,mBAGO,QAAA,EAHA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA,EAAA,GACjB,CAAA,mBAAqE,QAAA;OAA9D,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA;OAAgB,OAAO,EAAE;MAAS,GAAA,gBAAA,EAAE,IAAI,GAAA,IAAA,UAAA,GAC3D,mBAAkE,QAAA,EAA3D,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA,EAAA,GAAkB,gBAAA,MAAA,WAAA,CAAW,CAAC,EAAE,IAAI,CAAA,GAAA,CAAA,CAAA,GAAA,CAEzD,GAAA,mBAA4D,QAAA,EAArD,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA,EAAA,GAAkB,gBAAA,MAAM,EAAE,IAAI,CAAA,GAAA,CAAA,CAAA,GAAA,IAAA,UAAA;KAExC,CAAA,GAAA,GAAA,IAAA,CAAA,gBAAA,MAAgB,UAAA,UAAA,GAA3B,mBAEK,MAAA;;MAF+B,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,YAAA,CAAA;KAC9C,GAAA,CAAA,YAAkC,MAAA,WAAA,GAAA;MAAzB,MAAK;MAAQ,MAAM;;;IAKlC,GAAA,GAAA,CAAA,OAAA,CAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,QAAA,IAAA,GAAA,mBA8IU,WAAA,EA9IA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,CAAA,EAAA,GACpB,CAAA,mBA0GS,UAAA,EA1GA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,YAAA,CAAA,EAAA,GACnB,CAAA,mBAaM,OAAA,EAbA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,aAAA,CAAA,EAAA,GACJ,CAAA,WAAA,SAAA,UAAA,GAAZ,mBAEO,QAAA;;KAFkB,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,GAAW,MAAA,GAAA,CAAG,CAAC,GAAE,SAAU,WAAA,MAAW,IAAI,CAAA,CAAA;IAC3E,GAAA,gBAAA,MAAM,WAAA,MAAW,IAAI,CAAA,GAAA,CAAA,KAAA,mBAAA,QAAA,IAAA,GAE1B,mBAQO,QAAA,EARA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,YAAA,CAAA,EAAA,GACjB,CAAA,mBAEO,QAAA;KAFA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,YAAA,CAAA;KAAiB,OAAO,WAAA,OAAY;IAClD,GAAA,gBAAA,WAAA,OAAY,QAAI,GAAA,GAAA,IAAA,UAAA,GAET,WAAA,SAAA,UAAA,GAAZ,mBAGO,QAAA;;KAHkB,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA;IACnC,GAAA,CAAA,mBAAmC,QAAA,MAAA,gBAA1B,iBAAA,KAAgB,GAAA,CAAA,GACb,WAAA,MAAW,QAAA,UAAA,GAAvB,mBAAsE,QAAA,YAAA,gBAAtC,MAAA,WAAA,CAAW,CAAC,WAAA,MAAW,IAAI,CAAA,GAAA,CAAA,KAAA,mBAAA,QAAA,IAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,QAAA,IAAA,CAAA,GAAA,CAAA,CAAA,GAAA,CAIjE,GAAA,mBA0FM,OAAA,EA1FA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,eAAA,CAAA,EAAA,GAAA;KAChB,mBAyBO,QAAA,EAzBA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,cAAA,CAAA,EAAA,GACjB,CAAA,mBAWS,UAAA;MAVN,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA,GAAY,MAAA,GAAA,CAAG,CAAC,GAAE,UAAA,MAAA,CAAA,CAAA;MAC/B,UAAQ,CAAG,QAAA;MACZ,MAAK;MACL,cAAW;MACX,OAAM;MACL,SAAO;KAER,GAAA,CAAA,YAES,MAAA,WAAA,GAAA,EAFA,MAAM,GAAE,GAAA;MACF,SAAA,cAAA,CAAb,YAAa,MAAA,SAAA,CAAA,CAAA,CAAA;;KAGjB,CAAA,CAAA,GAAA,IAAA,UAAA,GAAA,mBAWS,UAAA;MAVN,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA,GAAY,MAAA,GAAA,CAAG,CAAC,GAAE,UAAA,MAAA,CAAA,CAAA;MAC/B,UAAQ,CAAG,QAAA;MACZ,MAAK;MACL,cAAW;MACX,OAAM;MACL,SAAO;KAER,GAAA,CAAA,YAES,MAAA,WAAA,GAAA,EAFA,MAAM,GAAE,GAAA;MACD,SAAA,cAAA,CAAd,YAAc,MAAA,UAAA,CAAA,CAAA,CAAA;;;KAIR,WAAA,SAAA,UAAA,GAAZ,mBAsCO,QAAA;;MAtCkB,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,cAAA,CAAA;;MACnC,mBAWS,UAAA;OAVN,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA,GAAY,MAAA,GAAA,CAAG,CAAC,GAAE,UAAA,MAAA,CAAA,CAAA;OAC/B,UAAU,gBAAA;OACX,MAAK;OACL,cAAW;OACX,OAAM;OACL,SAAO;MAER,GAAA,CAAA,YAES,MAAA,WAAA,GAAA,EAFA,MAAM,GAAE,GAAA;OACJ,SAAA,cAAA,CAAX,YAAW,MAAA,OAAA,CAAA,CAAA,CAAA;;;MAGf,mBAA2D,QAAA,EAApD,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,YAAA,CAAA,EAAA,GAAmB,gBAAA,YAAA,KAAW,GAAA,CAAA;MACjD,mBAWS,UAAA;OAVN,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA,GAAY,MAAA,GAAA,CAAG,CAAC,GAAE,UAAA,MAAA,CAAA,CAAA;OAC/B,UAAU,eAAA;OACX,MAAK;OACL,cAAW;OACX,OAAM;OACL,SAAO;MAER,GAAA,CAAA,YAES,MAAA,WAAA,GAAA,EAFA,MAAM,GAAE,GAAA;OACL,SAAA,cAAA,CAAV,YAAU,MAAA,MAAA,CAAA,CAAA,CAAA;;;MAGd,mBAWS,UAAA;OAVN,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA,GAAY,MAAA,GAAA,CAAG,CAAC,GAAE,UAAA,MAAA,CAAA,CAAA;OAC/B,UAAU,iBAAA;OACX,MAAK;OACL,cAAW;OACX,OAAM;OACL,SAAO;MAER,GAAA,CAAA,YAES,MAAA,WAAA,GAAA,EAFA,MAAM,GAAE,GAAA;OACJ,SAAA,cAAA,CAAX,YAAW,MAAA,OAAA,CAAA,CAAA,CAAA;;;;KAKT,QAAA,gBAAgB,WAAA,SAAA,UAAA,GADxB,mBAWS,UAAA;;MATN,OAAK,eAAA;OAAG,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA;OAAY,MAAA,GAAA,CAAG,CAAC,GAAE,UAAA,SAAA;OAAuB,MAAA,GAAA,CAAG,CAAC,GAAE,UAAA,MAAA;MAAA,CAAA;MAC7D,MAAK;MACL,cAAW;MACX,OAAM;MACL,SAAO;KAER,GAAA,CAAA,YAES,MAAA,WAAA,GAAA,EAFA,MAAM,GAAE,GAAA;MACH,SAAA,cAAA,CAAZ,YAAY,MAAA,QAAA,CAAA,CAAA,CAAA;;;KAIR,QAAA,SAAA,UAAA,GADR,mBAWS,UAAA;;MATN,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,EAAC,QAAA,GAAY,MAAA,GAAA,CAAG,CAAC,GAAE,UAAA,MAAA,CAAA,CAAA;MAChC,MAAK;MACL,cAAW;MACX,OAAM;MACL,SAAO;KAER,GAAA,CAAA,YAES,MAAA,WAAA,GAAA,EAFA,MAAM,GAAE,GAAA;MACN,SAAA,cAAA,CAAT,YAAS,MAAA,KAAA,CAAA,CAAA,CAAA;;;IAKjB,GAAA,CAAA,CAAA,GAAA,CAAA,GAAA,mBAiCM,OAAA,EAjCA,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,MAAA,CAAA,EAAA,GAChB,CAAA,YA+Ba,YAAA;KA/BD,MAAK;KAAqB,MAAK;;KA2BnC,SAAA,cAAA,CAzBE,WAAA,SAAA,UAAA,GADR,mBA0BM,OAAA;MAxBH,KAAK,WAAA,MAAW;MAChB,OAAK,eAAA;OAAwB,MAAA,GAAA,CAAG,CAAC,EAAC,UAAA;OAAkC,MAAA,GAAA,CAAG,CAAC,GAAE,iBAAkB,gBAAA,KAAe;OAAuB,MAAA,GAAA,CAAG,CAAC,GAAE,YAAa,OAAA,KAAM;OAAuB,MAAA,GAAA,CAAG,CAAC,GAAE,YAAa,WAAA,KAAU;;MAM1L,sBAAA;MACA,sBAAA;MACF,oBAAA;MACI,wBAAA;MACvB,SAAO;MACP,YAAU;KAEX,GAAA,EAAA,UAAA,GAAA,YASE,wBARK,aAAa,WAAA,MAAW,KAAI,GAAA;MAC7B,SAAA;MAAJ,KAAI;MACH,MAAM,WAAA;MACN,YAAU,QAAA;MACV,OAAK,eAAE,gBAAA,QAAkB,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,IAAgB,KAAA,CAAS;MACvD,OAAK,eAAE,eAAA,KAAc;MACrB,SAAO;MACP,cAAa;;;;;;KAGlB,CAAA,EAAA,GAAA,EAAA,MAAA,UAAA,GAAA,mBAEM,OAAA;;MAFO,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,CAAA;KACvB,GAAA,CAAA,YAA0B,MAAA,WAAA,GAAA,EAAjB,MAAK,UAAS,CAAA,CAAA,GAAA,CAAA,EAAA,CAAA"}
|
|
@@ -105,43 +105,6 @@ function toBlobUrl(src, mime) {
|
|
|
105
105
|
revoke: () => URL.revokeObjectURL(url)
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
|
-
/**
|
|
109
|
-
* RFC-4180 子集 CSV 解析:支持 "" 转义、\r\n 与 \n 换行、, 分隔。
|
|
110
|
-
* 为性能起见采用状态机而非 split。
|
|
111
|
-
*/
|
|
112
|
-
function parseCsv(text) {
|
|
113
|
-
const rows = [];
|
|
114
|
-
let row = [];
|
|
115
|
-
let field = "";
|
|
116
|
-
let inQuotes = false;
|
|
117
|
-
const len = text.length;
|
|
118
|
-
for (let i = 0; i < len; i++) {
|
|
119
|
-
const ch = text[i];
|
|
120
|
-
if (inQuotes) {
|
|
121
|
-
if (ch === "\"") if (text[i + 1] === "\"") {
|
|
122
|
-
field += "\"";
|
|
123
|
-
i++;
|
|
124
|
-
} else inQuotes = false;
|
|
125
|
-
else field += ch;
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
if (ch === "\"") inQuotes = true;
|
|
129
|
-
else if (ch === ",") {
|
|
130
|
-
row.push(field);
|
|
131
|
-
field = "";
|
|
132
|
-
} else if (ch === "\n") {
|
|
133
|
-
row.push(field);
|
|
134
|
-
rows.push(row);
|
|
135
|
-
row = [];
|
|
136
|
-
field = "";
|
|
137
|
-
} else if (ch === "\r") {} else field += ch;
|
|
138
|
-
}
|
|
139
|
-
if (field.length > 0 || row.length > 0) {
|
|
140
|
-
row.push(field);
|
|
141
|
-
rows.push(row);
|
|
142
|
-
}
|
|
143
|
-
return rows;
|
|
144
|
-
}
|
|
145
108
|
function formatBytes(bytes) {
|
|
146
109
|
if (bytes === void 0 || bytes === null || Number.isNaN(bytes)) return "-";
|
|
147
110
|
if (bytes < 1024) return `${bytes} B`;
|
|
@@ -180,6 +143,6 @@ async function downloadFile(file) {
|
|
|
180
143
|
if (revoke) setTimeout(revoke, 4e3);
|
|
181
144
|
}
|
|
182
145
|
//#endregion
|
|
183
|
-
export { FILE_VIEWER_KIND_LABEL, downloadFile, formatBytes, getExtension, inferKind,
|
|
146
|
+
export { FILE_VIEWER_KIND_LABEL, downloadFile, formatBytes, getExtension, inferKind, toArrayBuffer, toBlobUrl };
|
|
184
147
|
|
|
185
148
|
//# sourceMappingURL=helper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.js","names":[],"sources":["../../../src/components/file-viewer/helper.ts"],"sourcesContent":["import type { FileViewerItem, FileViewerKind } from '../../types/file-viewer'\n\nconst IMAGE_EXTS = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg', 'avif', 'ico'])\n\nconst VIDEO_EXTS = new Set(['mp4', 'webm', 'mov', 'm4v', 'ogv', 'mkv'])\n\nconst SHEET_EXTS = new Set(['xlsx', 'xlsm', 'xlsb', 'csv'])\n\nconst TEXT_EXTS = new Set([\n 'txt',\n 'log',\n 'md',\n 'markdown',\n 'json',\n 'yml',\n 'yaml',\n 'xml',\n 'js',\n 'ts',\n 'tsx',\n 'jsx',\n 'css',\n 'scss',\n 'sass',\n 'less',\n 'html',\n 'htm',\n 'ini',\n 'toml',\n 'sh',\n 'bash',\n 'zsh',\n 'env',\n 'sql'\n])\n\nexport function getExtension(name: string): string {\n const idx = name.lastIndexOf('.')\n return idx === -1 ? '' : name.slice(idx + 1).toLowerCase()\n}\n\nexport function inferKind(name: string, explicit?: FileViewerKind): FileViewerKind {\n if (explicit) return explicit\n const ext = getExtension(name)\n if (IMAGE_EXTS.has(ext)) return 'image'\n if (VIDEO_EXTS.has(ext)) return 'video'\n if (ext === 'pdf') return 'pdf'\n if (SHEET_EXTS.has(ext)) return 'sheet'\n if (ext === 'docx') return 'docx'\n if (TEXT_EXTS.has(ext)) return 'text'\n return 'text'\n}\n\nexport const FILE_VIEWER_KIND_LABEL: Record<FileViewerKind, string> = {\n image: 'IMG',\n video: 'MP4',\n pdf: 'PDF',\n sheet: 'XLS',\n docx: 'DOC',\n text: 'TXT'\n}\n\n/** 规范化数据源为 ArrayBuffer,可被 AbortController 中断(仅 URL fetch 场景生效) */\nexport async function toArrayBuffer(\n src: FileViewerItem['src'],\n signal?: AbortSignal\n): Promise<ArrayBuffer> {\n if (typeof src === 'string') {\n const res = await fetch(src, { signal })\n if (!res.ok) {\n throw new Error(`Fetch failed: ${res.status} ${res.statusText}`)\n }\n return await res.arrayBuffer()\n }\n if (src instanceof ArrayBuffer) return src\n if (src instanceof Uint8Array) {\n // 复制底层以切断共享引用,防止外部修改影响预览\n return src.slice().buffer as ArrayBuffer\n }\n // File/Blob\n return await src.arrayBuffer()\n}\n\n/** 返回用于 <img> / <video> 等标签 src 的 URL;二进制会创建 ObjectURL 并返回 revoke 钩子 */\nexport function toBlobUrl(\n src: FileViewerItem['src'],\n mime?: string\n): { url: string; revoke: () => void } {\n if (typeof src === 'string') {\n return { url: src, revoke: () => {} }\n }\n let blob: Blob\n if (src instanceof Blob) {\n blob = src\n } else if (src instanceof ArrayBuffer) {\n blob = new Blob([src], { type: mime ?? 'application/octet-stream' })\n } else {\n // Uint8Array: 复制到新的 ArrayBuffer,避免与外部共享底层\n const copy = new Uint8Array(src.byteLength)\n copy.set(src)\n blob = new Blob([copy.buffer], { type: mime ?? 'application/octet-stream' })\n }\n const url = URL.createObjectURL(blob)\n return { url, revoke: () => URL.revokeObjectURL(url) }\n}\n\
|
|
1
|
+
{"version":3,"file":"helper.js","names":[],"sources":["../../../src/components/file-viewer/helper.ts"],"sourcesContent":["import type { FileViewerItem, FileViewerKind } from '../../types/file-viewer'\n\nconst IMAGE_EXTS = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg', 'avif', 'ico'])\n\nconst VIDEO_EXTS = new Set(['mp4', 'webm', 'mov', 'm4v', 'ogv', 'mkv'])\n\nconst SHEET_EXTS = new Set(['xlsx', 'xlsm', 'xlsb', 'csv'])\n\nconst TEXT_EXTS = new Set([\n 'txt',\n 'log',\n 'md',\n 'markdown',\n 'json',\n 'yml',\n 'yaml',\n 'xml',\n 'js',\n 'ts',\n 'tsx',\n 'jsx',\n 'css',\n 'scss',\n 'sass',\n 'less',\n 'html',\n 'htm',\n 'ini',\n 'toml',\n 'sh',\n 'bash',\n 'zsh',\n 'env',\n 'sql'\n])\n\nexport function getExtension(name: string): string {\n const idx = name.lastIndexOf('.')\n return idx === -1 ? '' : name.slice(idx + 1).toLowerCase()\n}\n\nexport function inferKind(name: string, explicit?: FileViewerKind): FileViewerKind {\n if (explicit) return explicit\n const ext = getExtension(name)\n if (IMAGE_EXTS.has(ext)) return 'image'\n if (VIDEO_EXTS.has(ext)) return 'video'\n if (ext === 'pdf') return 'pdf'\n if (SHEET_EXTS.has(ext)) return 'sheet'\n if (ext === 'docx') return 'docx'\n if (TEXT_EXTS.has(ext)) return 'text'\n return 'text'\n}\n\nexport const FILE_VIEWER_KIND_LABEL: Record<FileViewerKind, string> = {\n image: 'IMG',\n video: 'MP4',\n pdf: 'PDF',\n sheet: 'XLS',\n docx: 'DOC',\n text: 'TXT'\n}\n\n/** 规范化数据源为 ArrayBuffer,可被 AbortController 中断(仅 URL fetch 场景生效) */\nexport async function toArrayBuffer(\n src: FileViewerItem['src'],\n signal?: AbortSignal\n): Promise<ArrayBuffer> {\n if (typeof src === 'string') {\n const res = await fetch(src, { signal })\n if (!res.ok) {\n throw new Error(`Fetch failed: ${res.status} ${res.statusText}`)\n }\n return await res.arrayBuffer()\n }\n if (src instanceof ArrayBuffer) return src\n if (src instanceof Uint8Array) {\n // 复制底层以切断共享引用,防止外部修改影响预览\n return src.slice().buffer as ArrayBuffer\n }\n // File/Blob\n return await src.arrayBuffer()\n}\n\n/** 返回用于 <img> / <video> 等标签 src 的 URL;二进制会创建 ObjectURL 并返回 revoke 钩子 */\nexport function toBlobUrl(\n src: FileViewerItem['src'],\n mime?: string\n): { url: string; revoke: () => void } {\n if (typeof src === 'string') {\n return { url: src, revoke: () => {} }\n }\n let blob: Blob\n if (src instanceof Blob) {\n blob = src\n } else if (src instanceof ArrayBuffer) {\n blob = new Blob([src], { type: mime ?? 'application/octet-stream' })\n } else {\n // Uint8Array: 复制到新的 ArrayBuffer,避免与外部共享底层\n const copy = new Uint8Array(src.byteLength)\n copy.set(src)\n blob = new Blob([copy.buffer], { type: mime ?? 'application/octet-stream' })\n }\n const url = URL.createObjectURL(blob)\n return { url, revoke: () => URL.revokeObjectURL(url) }\n}\n\nexport function formatBytes(bytes?: number): string {\n if (bytes === undefined || bytes === null || Number.isNaN(bytes)) return '-'\n if (bytes < 1024) return `${bytes} B`\n const units = ['KB', 'MB', 'GB', 'TB']\n let v = bytes / 1024\n let i = 0\n while (v >= 1024 && i < units.length - 1) {\n v /= 1024\n i++\n }\n return `${v.toFixed(v >= 10 ? 0 : 1)} ${units[i]}`\n}\n\n/** 触发浏览器下载 */\nexport async function downloadFile(file: FileViewerItem): Promise<void> {\n let href: string\n let revoke: (() => void) | undefined\n if (typeof file.src === 'string') {\n href = file.src\n } else {\n const url = toBlobUrl(file.src, file.mime)\n href = url.url\n revoke = url.revoke\n }\n const a = document.createElement('a')\n a.href = href\n a.download = file.name\n a.rel = 'noopener'\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n if (revoke) setTimeout(revoke, 4000)\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docx-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/docx-previewer.vue"],"sourcesContent":["<template>\n <u-scroll tag=\"div\" :class=\"cls.e('docx')\" v-bind=\"attrs\">\n <div ref=\"container\" :class=\"cls.e('docx-body')\" />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, useAttrs, useTemplateRef, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { UScroll } from '../../scroll'\n\ndefineOptions({ name: 'UFileViewerDocxPreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst container = useTemplateRef<HTMLDivElement>('container')\nconst loading = ref(true)\n\nlet controller: AbortController | undefined\n\nasync function load() {\n controller?.abort()\n controller = new AbortController()\n const signal = controller.signal\n loading.value = true\n\n try {\n const [{ toArrayBuffer }, docx] = await Promise.all([\n import('../helper'),\n import('docx-preview')\n ])\n\n const buf = await toArrayBuffer(props.file.src, signal)\n if (signal.aborted) return\n const el = container.value\n if (!el) return\n el.innerHTML = ''\n\n await docx.renderAsync(buf, el, undefined, {\n className: 'u-file-viewer__docx-doc',\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n ignoreFonts: false,\n breakPages: true,\n experimental: false,\n useBase64URL: false,\n renderChanges: false,\n renderHeaders: true,\n renderFooters: true,\n renderFootnotes: true\n })\n } catch (err) {\n if ((err as { name?: string })?.name === 'AbortError') return\n emit('error', err)\n } finally {\n loading.value = false\n }\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n controller?.abort()\n if (container.value) container.value.innerHTML = ''\n})\n</script>\n"],"mappings":";;;;;;;;;;;EAgBA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAC7B,MAAM,QAAQ,SAAS;EAEvB,MAAM,YAAY,eAA+B,WAAW;EAC5D,MAAM,UAAU,IAAI,IAAI;EAExB,IAAI;EAEJ,eAAe,OAAO;GACpB,YAAY,MAAM;GAClB,aAAa,IAAI,gBAAgB;GACjC,MAAM,SAAS,WAAW;GAC1B,QAAQ,QAAQ;GAEhB,IAAI;IACF,MAAM,CAAC,EAAE,iBAAiB,QAAQ,MAAM,QAAQ,IAAI,CAClD,OAAO,iBACP,OAAO,eACT,CAAC;IAED,MAAM,MAAM,MAAM,cAAc,MAAM,KAAK,KAAK,MAAM;IACtD,IAAI,OAAO,SAAS;IACpB,MAAM,KAAK,UAAU;IACrB,IAAI,CAAC,IAAI;IACT,GAAG,YAAY;IAEf,MAAM,KAAK,YAAY,KAAK,IAAI,KAAA,GAAW;KACzC,WAAW;KACX,WAAW;KACX,aAAa;KACb,cAAc;KACd,aAAa;KACb,YAAY;KACZ,cAAc;KACd,cAAc;KACd,eAAe;KACf,eAAe;KACf,eAAe;KACf,iBAAiB;IACnB,CAAC;GACH,SAAS,KAAK;IACZ,IAAK,KAA2B,SAAS,cAAc;IACvD,KAAK,SAAS,GAAG;GACnB,UAAU;IACR,QAAQ,QAAQ;GAClB;EACF;EAEA,YACQ,MAAM,YACN,KAAK,GACX,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,YAAY,MAAM;GAClB,IAAI,UAAU,OAAO,UAAU,MAAM,YAAY;EACnD,CAAC;;
|
|
1
|
+
{"version":3,"file":"docx-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/docx-previewer.vue"],"sourcesContent":["<template>\n <u-scroll tag=\"div\" :class=\"cls.e('docx')\" v-bind=\"attrs\">\n <div ref=\"container\" :class=\"cls.e('docx-body')\" />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n </u-scroll>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, useAttrs, useTemplateRef, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { UScroll } from '../../scroll'\n\ndefineOptions({ name: 'UFileViewerDocxPreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst container = useTemplateRef<HTMLDivElement>('container')\nconst loading = ref(true)\n\nlet controller: AbortController | undefined\n\nasync function load() {\n controller?.abort()\n controller = new AbortController()\n const signal = controller.signal\n loading.value = true\n\n try {\n const [{ toArrayBuffer }, docx] = await Promise.all([\n import('../helper'),\n import('docx-preview')\n ])\n\n const buf = await toArrayBuffer(props.file.src, signal)\n if (signal.aborted) return\n const el = container.value\n if (!el) return\n el.innerHTML = ''\n\n await docx.renderAsync(buf, el, undefined, {\n className: 'u-file-viewer__docx-doc',\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n ignoreFonts: false,\n breakPages: true,\n experimental: false,\n useBase64URL: false,\n renderChanges: false,\n renderHeaders: true,\n renderFooters: true,\n renderFootnotes: true\n })\n } catch (err) {\n if ((err as { name?: string })?.name === 'AbortError') return\n emit('error', err)\n } finally {\n loading.value = false\n }\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n controller?.abort()\n if (container.value) container.value.innerHTML = ''\n})\n</script>\n"],"mappings":";;;;;;;;;;;EAgBA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAC7B,MAAM,QAAQ,SAAS;EAEvB,MAAM,YAAY,eAA+B,WAAW;EAC5D,MAAM,UAAU,IAAI,IAAI;EAExB,IAAI;EAEJ,eAAe,OAAO;GACpB,YAAY,MAAM;GAClB,aAAa,IAAI,gBAAgB;GACjC,MAAM,SAAS,WAAW;GAC1B,QAAQ,QAAQ;GAEhB,IAAI;IACF,MAAM,CAAC,EAAE,iBAAiB,QAAQ,MAAM,QAAQ,IAAI,CAClD,OAAO,iBACP,OAAO,eACT,CAAC;IAED,MAAM,MAAM,MAAM,cAAc,MAAM,KAAK,KAAK,MAAM;IACtD,IAAI,OAAO,SAAS;IACpB,MAAM,KAAK,UAAU;IACrB,IAAI,CAAC,IAAI;IACT,GAAG,YAAY;IAEf,MAAM,KAAK,YAAY,KAAK,IAAI,KAAA,GAAW;KACzC,WAAW;KACX,WAAW;KACX,aAAa;KACb,cAAc;KACd,aAAa;KACb,YAAY;KACZ,cAAc;KACd,cAAc;KACd,eAAe;KACf,eAAe;KACf,eAAe;KACf,iBAAiB;IACnB,CAAC;GACH,SAAS,KAAK;IACZ,IAAK,KAA2B,SAAS,cAAc;IACvD,KAAK,SAAS,GAAG;GACnB,UAAU;IACR,QAAQ,QAAQ;GAClB;EACF;EAEA,YACQ,MAAM,YACN,KAAK,GACX,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,YAAY,MAAM;GAClB,IAAI,UAAU,OAAO,UAAU,MAAM,YAAY;EACnD,CAAC;;GA5EC,OAAA,UAAA,GAAA,YAGW,MAAA,WAAA,GAHX,WAGW;IAHD,KAAI;IAAO,OAAO,MAAA,GAAA,CAAG,CAAC,EAAC,MAAA;GAAkB,GAAA,MAAA,KAAA,CAAK,GAAA;IACH,SAAA,cAAA,CAAnD,mBAAmD,OAAA;KAA1C,SAAA;KAAJ,KAAI;KAAa,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,WAAA,CAAA;IACvB,GAAA,MAAA,CAAA,GAAA,QAAA,SAAA,UAAA,GAAX,mBAAwD,OAAA;;KAAnC,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;IAAa,GAAA,QAAI,CAAA,KAAA,mBAAA,QAAA,IAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/image-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('image')\" v-bind=\"attrs\">\n <img\n v-if=\"url\"\n :src=\"url\"\n :alt=\"file.name\"\n draggable=\"false\"\n @dragstart.prevent\n @load=\"loading = false\"\n @error=\"onImgError\"\n />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n <div v-if=\"failed\" :class=\"cls.e('loading')\">图片加载失败</div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, shallowRef, useAttrs, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { toBlobUrl } from '../helper'\n\ndefineOptions({ name: 'UFileViewerImagePreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst url = shallowRef<string>('')\nconst loading = ref(true)\nconst failed = ref(false)\n\nlet revoke: (() => void) | undefined\n\nfunction load() {\n loading.value = true\n failed.value = false\n revoke?.()\n const r = toBlobUrl(props.file.src, props.file.mime)\n url.value = r.url\n revoke = r.revoke\n}\n\nfunction onImgError(e: Event) {\n loading.value = false\n failed.value = true\n emit('error', e)\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n revoke?.()\n url.value = ''\n})\n</script>\n"],"mappings":";;;;;;;;;;;;EAyBA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAC7B,MAAM,QAAQ,SAAS;EAEvB,MAAM,MAAM,WAAmB,EAAE;EACjC,MAAM,UAAU,IAAI,IAAI;EACxB,MAAM,SAAS,IAAI,KAAK;EAExB,IAAI;EAEJ,SAAS,OAAO;GACd,QAAQ,QAAQ;GAChB,OAAO,QAAQ;GACf,SAAS;GACT,MAAM,IAAI,UAAU,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI;GACnD,IAAI,QAAQ,EAAE;GACd,SAAS,EAAE;EACb;EAEA,SAAS,WAAW,GAAU;GAC5B,QAAQ,QAAQ;GAChB,OAAO,QAAQ;GACf,KAAK,SAAS,CAAC;EACjB;EAEA,YACQ,MAAM,YACN,KAAK,GACX,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,SAAS;GACT,IAAI,QAAQ;EACd,CAAC;;
|
|
1
|
+
{"version":3,"file":"image-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/image-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('image')\" v-bind=\"attrs\">\n <img\n v-if=\"url\"\n :src=\"url\"\n :alt=\"file.name\"\n draggable=\"false\"\n @dragstart.prevent\n @load=\"loading = false\"\n @error=\"onImgError\"\n />\n <div v-if=\"loading\" :class=\"cls.e('loading')\">加载中…</div>\n <div v-if=\"failed\" :class=\"cls.e('loading')\">图片加载失败</div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { onBeforeUnmount, ref, shallowRef, useAttrs, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { toBlobUrl } from '../helper'\n\ndefineOptions({ name: 'UFileViewerImagePreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{ (e: 'error', err: unknown): void }>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst url = shallowRef<string>('')\nconst loading = ref(true)\nconst failed = ref(false)\n\nlet revoke: (() => void) | undefined\n\nfunction load() {\n loading.value = true\n failed.value = false\n revoke?.()\n const r = toBlobUrl(props.file.src, props.file.mime)\n url.value = r.url\n revoke = r.revoke\n}\n\nfunction onImgError(e: Event) {\n loading.value = false\n failed.value = true\n emit('error', e)\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n revoke?.()\n url.value = ''\n})\n</script>\n"],"mappings":";;;;;;;;;;;;EAyBA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAC7B,MAAM,QAAQ,SAAS;EAEvB,MAAM,MAAM,WAAmB,EAAE;EACjC,MAAM,UAAU,IAAI,IAAI;EACxB,MAAM,SAAS,IAAI,KAAK;EAExB,IAAI;EAEJ,SAAS,OAAO;GACd,QAAQ,QAAQ;GAChB,OAAO,QAAQ;GACf,SAAS;GACT,MAAM,IAAI,UAAU,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI;GACnD,IAAI,QAAQ,EAAE;GACd,SAAS,EAAE;EACb;EAEA,SAAS,WAAW,GAAU;GAC5B,QAAQ,QAAQ;GAChB,OAAO,QAAQ;GACf,KAAK,SAAS,CAAC;EACjB;EAEA,YACQ,MAAM,YACN,KAAK,GACX,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,SAAS;GACT,IAAI,QAAQ;EACd,CAAC;;GA7DC,OAAA,UAAA,GAAA,mBAYM,OAZN,WAYM,EAZA,OAAO,MAAA,GAAA,CAAG,CAAC,EAAC,OAAA,EAAA,GAAmB,MAAA,KAAA,CAAK,GAAA;IAEhC,IAAA,SAAA,UAAA,GADR,mBAQE,OAAA;;KANC,KAAK,IAAA;KACL,KAAK,QAAA,KAAK;KACX,WAAU;KACT,aAAS,OAAA,OAAA,OAAA,KAAA,oBAAV,CAAA,GAAkB,CAAA,SAAA,CAAA;KACjB,QAAI,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,QAAO;KACb,SAAO;;IAEC,QAAA,SAAA,UAAA,GAAX,mBAAwD,OAAA;;KAAnC,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;IAAa,GAAA,QAAI,CAAA,KAAA,mBAAA,QAAA,IAAA;IACvC,OAAA,SAAA,UAAA,GAAX,mBAAyD,OAAA;;KAArC,OAAK,eAAE,MAAA,GAAA,CAAG,CAAC,EAAC,SAAA,CAAA;IAAa,GAAA,UAAM,CAAA,KAAA,mBAAA,QAAA,IAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('pdf')\" v-bind=\"attrs\">\n <div v-if=\"!engine || isLoading\" :class=\"cls.e('loading')\">正在加载 PDF 引擎…</div>\n <EmbedPDF v-else-if=\"pdfUrl\" :engine=\"engine\" :plugins=\"plugins\" v-slot=\"{ activeDocumentId }\">\n <PdfZoomBridge\n v-if=\"activeDocumentId\"\n :document-id=\"activeDocumentId\"\n @zoom-change=\"onZoomChange\"\n />\n <DocumentContent\n v-if=\"activeDocumentId\"\n :document-id=\"activeDocumentId\"\n v-slot=\"{ isLoaded }\"\n >\n <Viewport v-if=\"isLoaded\" :document-id=\"activeDocumentId\" :class=\"cls.e('pdf-viewport')\">\n <PdfViewportScroll>\n <ZoomGestureWrapper :document-id=\"activeDocumentId\" :enable-wheel=\"true\">\n <Scroller :document-id=\"activeDocumentId\">\n <template #default=\"{ page }\">\n <div\n :class=\"cls.e('pdf-page')\"\n :style=\"{ width: page.width + 'px', height: page.height + 'px' }\"\n >\n <RenderLayer :document-id=\"activeDocumentId\" :page-index=\"page.pageIndex\" />\n </div>\n </template>\n </Scroller>\n </ZoomGestureWrapper>\n </PdfViewportScroll>\n </Viewport>\n </DocumentContent>\n </EmbedPDF>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { createPluginRegistration } from '@embedpdf/core'\nimport { EmbedPDF } from '@embedpdf/core/vue'\nimport { usePdfiumEngine } from '@embedpdf/engines/vue'\nimport {\n DocumentContent,\n DocumentManagerPluginPackage\n} from '@embedpdf/plugin-document-manager/vue'\nimport { RenderLayer, RenderPluginPackage } from '@embedpdf/plugin-render/vue'\nimport { ScrollPluginPackage, Scroller } from '@embedpdf/plugin-scroll/vue'\nimport { ViewportPluginPackage, Viewport } from '@embedpdf/plugin-viewport/vue'\nimport {\n ZoomGestureWrapper,\n ZoomMode,\n ZoomPluginPackage,\n type ZoomScope\n} from '@embedpdf/plugin-zoom/vue'\nimport { bem } from '@veltra/utils'\nimport { computed, onBeforeUnmount, shallowRef, useAttrs, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { toBlobUrl } from '../helper'\nimport PdfViewportScroll from './pdf-viewport-scroll.vue'\nimport PdfZoomBridge from './pdf-zoom-bridge.vue'\n\ndefineOptions({ name: 'UFileViewerPdfPreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{\n (e: 'error', err: unknown): void\n (e: 'zoom-change', level: number): void\n}>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst { engine, isLoading, error } = usePdfiumEngine()\n\nconst pdfUrl = shallowRef<string>('')\nlet revoke: (() => void) | undefined\n\n/** 当前文档的 zoom API(由 PdfZoomBridge 注入) */\nlet zoomScope: ZoomScope | null = null\n\nfunction load() {\n revoke?.()\n const r = toBlobUrl(props.file.src, props.file.mime ?? 'application/pdf')\n pdfUrl.value = r.url\n revoke = r.revoke\n}\n\nconst plugins = computed(() => {\n if (!pdfUrl.value) return []\n return [\n createPluginRegistration(DocumentManagerPluginPackage, {\n initialDocuments: [{ url: pdfUrl.value }]\n }),\n createPluginRegistration(ViewportPluginPackage, { viewportGap: 0 }),\n createPluginRegistration(ScrollPluginPackage, { defaultBufferSize: 2 }),\n createPluginRegistration(RenderPluginPackage),\n createPluginRegistration(ZoomPluginPackage, {\n defaultZoomLevel: ZoomMode.FitPage,\n minZoom: 0.5,\n maxZoom: 3,\n zoomStep: 0.1\n })\n ]\n})\n\nfunction onZoomChange(payload: { level: number; scope: ZoomScope | null }) {\n zoomScope = payload.scope\n emit('zoom-change', payload.level)\n}\n\nfunction zoomIn() {\n zoomScope?.zoomIn()\n}\n\nfunction zoomOut() {\n zoomScope?.zoomOut()\n}\n\nfunction resetZoom() {\n zoomScope?.requestZoom(ZoomMode.FitPage)\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nwatch(error, (err) => {\n if (err) emit('error', err)\n})\n\nonBeforeUnmount(() => {\n revoke?.()\n pdfUrl.value = ''\n zoomScope = null\n})\n\ndefineExpose({ zoomIn, zoomOut, resetZoom })\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EA8DA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAKb,MAAM,MAAM,IAAI,aAAa;EAC7B,MAAM,QAAQ,SAAS;EAEvB,MAAM,EAAE,QAAQ,WAAW,UAAU,gBAAgB;EAErD,MAAM,SAAS,WAAmB,EAAE;EACpC,IAAI;;EAGJ,IAAI,YAA8B;EAElC,SAAS,OAAO;GACd,SAAS;GACT,MAAM,IAAI,UAAU,MAAM,KAAK,KAAK,MAAM,KAAK,QAAQ,iBAAiB;GACxE,OAAO,QAAQ,EAAE;GACjB,SAAS,EAAE;EACb;EAEA,MAAM,UAAU,eAAe;GAC7B,IAAI,CAAC,OAAO,OAAO,OAAO,CAAC;GAC3B,OAAO;IACL,yBAAyB,8BAA8B,EACrD,kBAAkB,CAAC,EAAE,KAAK,OAAO,MAAM,CAAC,EAC1C,CAAC;IACD,yBAAyB,uBAAuB,EAAE,aAAa,EAAE,CAAC;IAClE,yBAAyB,qBAAqB,EAAE,mBAAmB,EAAE,CAAC;IACtE,yBAAyB,mBAAmB;IAC5C,yBAAyB,mBAAmB;KAC1C,kBAAkB,SAAS;KAC3B,SAAS;KACT,SAAS;KACT,UAAU;IACZ,CAAC;GACH;EACF,CAAC;EAED,SAAS,aAAa,SAAqD;GACzE,YAAY,QAAQ;GACpB,KAAK,eAAe,QAAQ,KAAK;EACnC;EAEA,SAAS,SAAS;GAChB,WAAW,OAAO;EACpB;EAEA,SAAS,UAAU;GACjB,WAAW,QAAQ;EACrB;EAEA,SAAS,YAAY;GACnB,WAAW,YAAY,SAAS,OAAO;EACzC;EAEA,YACQ,MAAM,YACN,KAAK,GACX,EAAE,WAAW,KAAK,CACpB;EAEA,MAAM,QAAQ,QAAQ;GACpB,IAAI,KAAK,KAAK,SAAS,GAAG;EAC5B,CAAC;EAED,sBAAsB;GACpB,SAAS;GACT,OAAO,QAAQ;GACf,YAAY;EACd,CAAC;EAED,SAAa;GAAE;GAAQ;GAAS;EAAU,CAAC;;
|
|
1
|
+
{"version":3,"file":"pdf-previewer.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-previewer.vue"],"sourcesContent":["<template>\n <div :class=\"cls.e('pdf')\" v-bind=\"attrs\">\n <div v-if=\"!engine || isLoading\" :class=\"cls.e('loading')\">正在加载 PDF 引擎…</div>\n <EmbedPDF v-else-if=\"pdfUrl\" :engine=\"engine\" :plugins=\"plugins\" v-slot=\"{ activeDocumentId }\">\n <PdfZoomBridge\n v-if=\"activeDocumentId\"\n :document-id=\"activeDocumentId\"\n @zoom-change=\"onZoomChange\"\n />\n <DocumentContent\n v-if=\"activeDocumentId\"\n :document-id=\"activeDocumentId\"\n v-slot=\"{ isLoaded }\"\n >\n <Viewport v-if=\"isLoaded\" :document-id=\"activeDocumentId\" :class=\"cls.e('pdf-viewport')\">\n <PdfViewportScroll>\n <ZoomGestureWrapper :document-id=\"activeDocumentId\" :enable-wheel=\"true\">\n <Scroller :document-id=\"activeDocumentId\">\n <template #default=\"{ page }\">\n <div\n :class=\"cls.e('pdf-page')\"\n :style=\"{ width: page.width + 'px', height: page.height + 'px' }\"\n >\n <RenderLayer :document-id=\"activeDocumentId\" :page-index=\"page.pageIndex\" />\n </div>\n </template>\n </Scroller>\n </ZoomGestureWrapper>\n </PdfViewportScroll>\n </Viewport>\n </DocumentContent>\n </EmbedPDF>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { createPluginRegistration } from '@embedpdf/core'\nimport { EmbedPDF } from '@embedpdf/core/vue'\nimport { usePdfiumEngine } from '@embedpdf/engines/vue'\nimport {\n DocumentContent,\n DocumentManagerPluginPackage\n} from '@embedpdf/plugin-document-manager/vue'\nimport { RenderLayer, RenderPluginPackage } from '@embedpdf/plugin-render/vue'\nimport { ScrollPluginPackage, Scroller } from '@embedpdf/plugin-scroll/vue'\nimport { ViewportPluginPackage, Viewport } from '@embedpdf/plugin-viewport/vue'\nimport {\n ZoomGestureWrapper,\n ZoomMode,\n ZoomPluginPackage,\n type ZoomScope\n} from '@embedpdf/plugin-zoom/vue'\nimport { bem } from '@veltra/utils'\nimport { computed, onBeforeUnmount, shallowRef, useAttrs, watch } from 'vue'\n\nimport type { FileViewerItem } from '../../../types/file-viewer'\nimport { toBlobUrl } from '../helper'\nimport PdfViewportScroll from './pdf-viewport-scroll.vue'\nimport PdfZoomBridge from './pdf-zoom-bridge.vue'\n\ndefineOptions({ name: 'UFileViewerPdfPreviewer', inheritAttrs: false })\n\nconst props = defineProps<{ file: FileViewerItem }>()\n\nconst emit = defineEmits<{\n (e: 'error', err: unknown): void\n (e: 'zoom-change', level: number): void\n}>()\n\nconst cls = bem('file-viewer')\nconst attrs = useAttrs()\n\nconst { engine, isLoading, error } = usePdfiumEngine()\n\nconst pdfUrl = shallowRef<string>('')\nlet revoke: (() => void) | undefined\n\n/** 当前文档的 zoom API(由 PdfZoomBridge 注入) */\nlet zoomScope: ZoomScope | null = null\n\nfunction load() {\n revoke?.()\n const r = toBlobUrl(props.file.src, props.file.mime ?? 'application/pdf')\n pdfUrl.value = r.url\n revoke = r.revoke\n}\n\nconst plugins = computed(() => {\n if (!pdfUrl.value) return []\n return [\n createPluginRegistration(DocumentManagerPluginPackage, {\n initialDocuments: [{ url: pdfUrl.value }]\n }),\n createPluginRegistration(ViewportPluginPackage, { viewportGap: 0 }),\n createPluginRegistration(ScrollPluginPackage, { defaultBufferSize: 2 }),\n createPluginRegistration(RenderPluginPackage),\n createPluginRegistration(ZoomPluginPackage, {\n defaultZoomLevel: ZoomMode.FitPage,\n minZoom: 0.5,\n maxZoom: 3,\n zoomStep: 0.1\n })\n ]\n})\n\nfunction onZoomChange(payload: { level: number; scope: ZoomScope | null }) {\n zoomScope = payload.scope\n emit('zoom-change', payload.level)\n}\n\nfunction zoomIn() {\n zoomScope?.zoomIn()\n}\n\nfunction zoomOut() {\n zoomScope?.zoomOut()\n}\n\nfunction resetZoom() {\n zoomScope?.requestZoom(ZoomMode.FitPage)\n}\n\nwatch(\n () => props.file,\n () => load(),\n { immediate: true }\n)\n\nwatch(error, (err) => {\n if (err) emit('error', err)\n})\n\nonBeforeUnmount(() => {\n revoke?.()\n pdfUrl.value = ''\n zoomScope = null\n})\n\ndefineExpose({ zoomIn, zoomOut, resetZoom })\n</script>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-viewport-scroll.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-viewport-scroll.vue"],"sourcesContent":["<template>\n <slot />\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, inject, onBeforeUnmount, type Ref, watch } from 'vue'\n\ndefineOptions({ name: 'UFileViewerPdfViewportScroll' })\n\n/** EmbedPDF Viewport 向子树注入的滚动容器 ref */\nconst VIEWPORT_ELEMENT_KEY = 'viewport-element'\n\nconst viewportRef = inject<Ref<HTMLDivElement | null>>(VIEWPORT_ELEMENT_KEY)\nconst viewportEl = computed(() => viewportRef?.value ?? null)\n\nlet panState:\n | { pointerId: number; startX: number; startY: number; scrollLeft: number; scrollTop: number }\n | undefined\n\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false\n return !!target.closest(\n 'button, a, input, textarea, select, video, [contenteditable=\"true\"], .u-scroll__bar-x, .u-scroll__bar-y'\n )\n}\n\nfunction handlePointerDown(e: PointerEvent) {\n if (e.button !== 0 || isInteractiveTarget(e.target)) return\n\n const el = viewportEl.value\n if (!el) return\n\n panState = {\n pointerId: e.pointerId,\n startX: e.clientX,\n startY: e.clientY,\n scrollLeft: el.scrollLeft,\n scrollTop: el.scrollTop\n }\n el.classList.add('is-panning')\n el.setPointerCapture(e.pointerId)\n e.preventDefault()\n}\n\nfunction handlePointerMove(e: PointerEvent) {\n if (!panState || panState.pointerId !== e.pointerId) return\n\n const el = viewportEl.value\n if (!el) return\n\n el.scrollLeft = panState.scrollLeft - (e.clientX - panState.startX)\n el.scrollTop = panState.scrollTop - (e.clientY - panState.startY)\n}\n\nfunction endPan(e: PointerEvent) {\n if (!panState || panState.pointerId !== e.pointerId) return\n\n const el = viewportEl.value\n if (el?.hasPointerCapture(e.pointerId)) {\n el.releasePointerCapture(e.pointerId)\n }\n el?.classList.remove('is-panning')\n panState = undefined\n}\n\nlet detachPan: (() => void) | undefined\n\nwatch(\n viewportEl,\n (el, _, onCleanup) => {\n detachPan?.()\n detachPan = undefined\n if (!el) return\n\n el.addEventListener('pointerdown', handlePointerDown, { capture: true })\n el.addEventListener('pointermove', handlePointerMove, { capture: true })\n el.addEventListener('pointerup', endPan, { capture: true })\n el.addEventListener('pointercancel', endPan, { capture: true })\n\n detachPan = () => {\n el.removeEventListener('pointerdown', handlePointerDown, { capture: true })\n el.removeEventListener('pointermove', handlePointerMove, { capture: true })\n el.removeEventListener('pointerup', endPan, { capture: true })\n el.removeEventListener('pointercancel', endPan, { capture: true })\n el.classList.remove('is-panning')\n panState = undefined\n }\n\n onCleanup(() => {\n detachPan?.()\n detachPan = undefined\n })\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n detachPan?.()\n detachPan = undefined\n})\n</script>\n"],"mappings":";;AAUA,MAAM,uBAAuB;;;;;;EAE7B,MAAM,cAAc,OAAmC,oBAAoB;EAC3E,MAAM,aAAa,eAAe,aAAa,SAAS,IAAI;EAE5D,IAAI;EAIJ,SAAS,oBAAoB,QAAqC;GAChE,IAAI,EAAE,kBAAkB,cAAc,OAAO;GAC7C,OAAO,CAAC,CAAC,OAAO,QACd,2GACF;EACF;EAEA,SAAS,kBAAkB,GAAiB;GAC1C,IAAI,EAAE,WAAW,KAAK,oBAAoB,EAAE,MAAM,GAAG;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,CAAC,IAAI;GAET,WAAW;IACT,WAAW,EAAE;IACb,QAAQ,EAAE;IACV,QAAQ,EAAE;IACV,YAAY,GAAG;IACf,WAAW,GAAG;GAChB;GACA,GAAG,UAAU,IAAI,YAAY;GAC7B,GAAG,kBAAkB,EAAE,SAAS;GAChC,EAAE,eAAe;EACnB;EAEA,SAAS,kBAAkB,GAAiB;GAC1C,IAAI,CAAC,YAAY,SAAS,cAAc,EAAE,WAAW;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,CAAC,IAAI;GAET,GAAG,aAAa,SAAS,cAAc,EAAE,UAAU,SAAS;GAC5D,GAAG,YAAY,SAAS,aAAa,EAAE,UAAU,SAAS;EAC5D;EAEA,SAAS,OAAO,GAAiB;GAC/B,IAAI,CAAC,YAAY,SAAS,cAAc,EAAE,WAAW;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,IAAI,kBAAkB,EAAE,SAAS,GACnC,GAAG,sBAAsB,EAAE,SAAS;GAEtC,IAAI,UAAU,OAAO,YAAY;GACjC,WAAW,KAAA;EACb;EAEA,IAAI;EAEJ,MACE,aACC,IAAI,GAAG,cAAc;GACpB,YAAY;GACZ,YAAY,KAAA;GACZ,IAAI,CAAC,IAAI;GAET,GAAG,iBAAiB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;GACvE,GAAG,iBAAiB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;GACvE,GAAG,iBAAiB,aAAa,QAAQ,EAAE,SAAS,KAAK,CAAC;GAC1D,GAAG,iBAAiB,iBAAiB,QAAQ,EAAE,SAAS,KAAK,CAAC;GAE9D,kBAAkB;IAChB,GAAG,oBAAoB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;IAC1E,GAAG,oBAAoB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;IAC1E,GAAG,oBAAoB,aAAa,QAAQ,EAAE,SAAS,KAAK,CAAC;IAC7D,GAAG,oBAAoB,iBAAiB,QAAQ,EAAE,SAAS,KAAK,CAAC;IACjE,GAAG,UAAU,OAAO,YAAY;IAChC,WAAW,KAAA;GACb;GAEA,gBAAgB;IACd,YAAY;IACZ,YAAY,KAAA;GACd,CAAC;EACH,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,YAAY;GACZ,YAAY,KAAA;EACd,CAAC;;
|
|
1
|
+
{"version":3,"file":"pdf-viewport-scroll.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-viewport-scroll.vue"],"sourcesContent":["<template>\n <slot />\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, inject, onBeforeUnmount, type Ref, watch } from 'vue'\n\ndefineOptions({ name: 'UFileViewerPdfViewportScroll' })\n\n/** EmbedPDF Viewport 向子树注入的滚动容器 ref */\nconst VIEWPORT_ELEMENT_KEY = 'viewport-element'\n\nconst viewportRef = inject<Ref<HTMLDivElement | null>>(VIEWPORT_ELEMENT_KEY)\nconst viewportEl = computed(() => viewportRef?.value ?? null)\n\nlet panState:\n | { pointerId: number; startX: number; startY: number; scrollLeft: number; scrollTop: number }\n | undefined\n\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false\n return !!target.closest(\n 'button, a, input, textarea, select, video, [contenteditable=\"true\"], .u-scroll__bar-x, .u-scroll__bar-y'\n )\n}\n\nfunction handlePointerDown(e: PointerEvent) {\n if (e.button !== 0 || isInteractiveTarget(e.target)) return\n\n const el = viewportEl.value\n if (!el) return\n\n panState = {\n pointerId: e.pointerId,\n startX: e.clientX,\n startY: e.clientY,\n scrollLeft: el.scrollLeft,\n scrollTop: el.scrollTop\n }\n el.classList.add('is-panning')\n el.setPointerCapture(e.pointerId)\n e.preventDefault()\n}\n\nfunction handlePointerMove(e: PointerEvent) {\n if (!panState || panState.pointerId !== e.pointerId) return\n\n const el = viewportEl.value\n if (!el) return\n\n el.scrollLeft = panState.scrollLeft - (e.clientX - panState.startX)\n el.scrollTop = panState.scrollTop - (e.clientY - panState.startY)\n}\n\nfunction endPan(e: PointerEvent) {\n if (!panState || panState.pointerId !== e.pointerId) return\n\n const el = viewportEl.value\n if (el?.hasPointerCapture(e.pointerId)) {\n el.releasePointerCapture(e.pointerId)\n }\n el?.classList.remove('is-panning')\n panState = undefined\n}\n\nlet detachPan: (() => void) | undefined\n\nwatch(\n viewportEl,\n (el, _, onCleanup) => {\n detachPan?.()\n detachPan = undefined\n if (!el) return\n\n el.addEventListener('pointerdown', handlePointerDown, { capture: true })\n el.addEventListener('pointermove', handlePointerMove, { capture: true })\n el.addEventListener('pointerup', endPan, { capture: true })\n el.addEventListener('pointercancel', endPan, { capture: true })\n\n detachPan = () => {\n el.removeEventListener('pointerdown', handlePointerDown, { capture: true })\n el.removeEventListener('pointermove', handlePointerMove, { capture: true })\n el.removeEventListener('pointerup', endPan, { capture: true })\n el.removeEventListener('pointercancel', endPan, { capture: true })\n el.classList.remove('is-panning')\n panState = undefined\n }\n\n onCleanup(() => {\n detachPan?.()\n detachPan = undefined\n })\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n detachPan?.()\n detachPan = undefined\n})\n</script>\n"],"mappings":";;AAUA,MAAM,uBAAuB;;;;;;EAE7B,MAAM,cAAc,OAAmC,oBAAoB;EAC3E,MAAM,aAAa,eAAe,aAAa,SAAS,IAAI;EAE5D,IAAI;EAIJ,SAAS,oBAAoB,QAAqC;GAChE,IAAI,EAAE,kBAAkB,cAAc,OAAO;GAC7C,OAAO,CAAC,CAAC,OAAO,QACd,2GACF;EACF;EAEA,SAAS,kBAAkB,GAAiB;GAC1C,IAAI,EAAE,WAAW,KAAK,oBAAoB,EAAE,MAAM,GAAG;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,CAAC,IAAI;GAET,WAAW;IACT,WAAW,EAAE;IACb,QAAQ,EAAE;IACV,QAAQ,EAAE;IACV,YAAY,GAAG;IACf,WAAW,GAAG;GAChB;GACA,GAAG,UAAU,IAAI,YAAY;GAC7B,GAAG,kBAAkB,EAAE,SAAS;GAChC,EAAE,eAAe;EACnB;EAEA,SAAS,kBAAkB,GAAiB;GAC1C,IAAI,CAAC,YAAY,SAAS,cAAc,EAAE,WAAW;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,CAAC,IAAI;GAET,GAAG,aAAa,SAAS,cAAc,EAAE,UAAU,SAAS;GAC5D,GAAG,YAAY,SAAS,aAAa,EAAE,UAAU,SAAS;EAC5D;EAEA,SAAS,OAAO,GAAiB;GAC/B,IAAI,CAAC,YAAY,SAAS,cAAc,EAAE,WAAW;GAErD,MAAM,KAAK,WAAW;GACtB,IAAI,IAAI,kBAAkB,EAAE,SAAS,GACnC,GAAG,sBAAsB,EAAE,SAAS;GAEtC,IAAI,UAAU,OAAO,YAAY;GACjC,WAAW,KAAA;EACb;EAEA,IAAI;EAEJ,MACE,aACC,IAAI,GAAG,cAAc;GACpB,YAAY;GACZ,YAAY,KAAA;GACZ,IAAI,CAAC,IAAI;GAET,GAAG,iBAAiB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;GACvE,GAAG,iBAAiB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;GACvE,GAAG,iBAAiB,aAAa,QAAQ,EAAE,SAAS,KAAK,CAAC;GAC1D,GAAG,iBAAiB,iBAAiB,QAAQ,EAAE,SAAS,KAAK,CAAC;GAE9D,kBAAkB;IAChB,GAAG,oBAAoB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;IAC1E,GAAG,oBAAoB,eAAe,mBAAmB,EAAE,SAAS,KAAK,CAAC;IAC1E,GAAG,oBAAoB,aAAa,QAAQ,EAAE,SAAS,KAAK,CAAC;IAC7D,GAAG,oBAAoB,iBAAiB,QAAQ,EAAE,SAAS,KAAK,CAAC;IACjE,GAAG,UAAU,OAAO,YAAY;IAChC,WAAW,KAAA;GACb;GAEA,gBAAgB;IACd,YAAY;IACZ,YAAY,KAAA;GACd,CAAC;EACH,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,YAAY;GACZ,YAAY,KAAA;EACd,CAAC;;GAlGC,OAAA,WAAQ,KAAA,QAAA,SAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-zoom-bridge.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-zoom-bridge.vue"],"sourcesContent":["<template>\n <span hidden aria-hidden=\"true\" />\n</template>\n\n<script lang=\"ts\" setup>\nimport { useZoom, ZoomMode, type ZoomScope } from '@embedpdf/plugin-zoom/vue'\nimport { watch } from 'vue'\n\ndefineOptions({ name: 'UFileViewerPdfZoomBridge' })\n\nconst props = defineProps<{ documentId: string }>()\n\nconst emit = defineEmits<{\n (e: 'zoom-change', payload: { level: number; scope: ZoomScope | null }): void\n}>()\n\nconst { provides: zoom, state } = useZoom(() => props.documentId)\n\nwatch(\n [zoom, () => state.value.currentZoomLevel],\n () => {\n emit('zoom-change', { level: state.value.currentZoomLevel, scope: zoom.value })\n },\n { immediate: true }\n)\n\ndefineExpose({ resetZoom: () => zoom.value?.requestZoom(ZoomMode.FitPage) })\n</script>\n"],"mappings":";;;;;;;;;;;;;EAUA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAIb,MAAM,EAAE,UAAU,MAAM,UAAU,cAAc,MAAM,UAAU;EAEhE,MACE,CAAC,YAAY,MAAM,MAAM,gBAAgB,SACnC;GACJ,KAAK,eAAe;IAAE,OAAO,MAAM,MAAM;IAAkB,OAAO,KAAK;GAAM,CAAC;EAChF,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,SAAa,EAAE,iBAAiB,KAAK,OAAO,YAAY,SAAS,OAAO,EAAE,CAAC;;
|
|
1
|
+
{"version":3,"file":"pdf-zoom-bridge.js","names":[],"sources":["../../../../src/components/file-viewer/previewers/pdf-zoom-bridge.vue"],"sourcesContent":["<template>\n <span hidden aria-hidden=\"true\" />\n</template>\n\n<script lang=\"ts\" setup>\nimport { useZoom, ZoomMode, type ZoomScope } from '@embedpdf/plugin-zoom/vue'\nimport { watch } from 'vue'\n\ndefineOptions({ name: 'UFileViewerPdfZoomBridge' })\n\nconst props = defineProps<{ documentId: string }>()\n\nconst emit = defineEmits<{\n (e: 'zoom-change', payload: { level: number; scope: ZoomScope | null }): void\n}>()\n\nconst { provides: zoom, state } = useZoom(() => props.documentId)\n\nwatch(\n [zoom, () => state.value.currentZoomLevel],\n () => {\n emit('zoom-change', { level: state.value.currentZoomLevel, scope: zoom.value })\n },\n { immediate: true }\n)\n\ndefineExpose({ resetZoom: () => zoom.value?.requestZoom(ZoomMode.FitPage) })\n</script>\n"],"mappings":";;;;;;;;;;;;;EAUA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAIb,MAAM,EAAE,UAAU,MAAM,UAAU,cAAc,MAAM,UAAU;EAEhE,MACE,CAAC,YAAY,MAAM,MAAM,gBAAgB,SACnC;GACJ,KAAK,eAAe;IAAE,OAAO,MAAM,MAAM;IAAkB,OAAO,KAAK;GAAM,CAAC;EAChF,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,SAAa,EAAE,iBAAiB,KAAK,OAAO,YAAY,SAAS,OAAO,EAAE,CAAC;;GAzBzE,OAAA,UAAA,GAAA,mBAAkC,QAAlC,UAAkC"}
|