@veltra/desktop 1.1.12 → 1.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/components/batch-edit/batch-edit.js +1 -1
  2. package/dist/components/batch-edit/batch-edit.js.map +1 -1
  3. package/dist/components/batch-edit/style2.css +7 -1
  4. package/dist/components/cascade/cascade.vue.d.ts +1 -1
  5. package/dist/components/file-viewer/file-viewer.js +62 -19
  6. package/dist/components/file-viewer/file-viewer.js.map +1 -1
  7. package/dist/components/file-viewer/previewers/image-previewer.js +3 -2
  8. package/dist/components/file-viewer/previewers/image-previewer.js.map +1 -1
  9. package/dist/components/file-viewer/previewers/pdf-previewer.js +60 -17
  10. package/dist/components/file-viewer/previewers/pdf-previewer.js.map +1 -1
  11. package/dist/components/file-viewer/previewers/pdf-viewport-scroll.js +83 -0
  12. package/dist/components/file-viewer/previewers/pdf-viewport-scroll.js.map +1 -0
  13. package/dist/components/file-viewer/previewers/pdf-zoom-bridge.js +32 -0
  14. package/dist/components/file-viewer/previewers/pdf-zoom-bridge.js.map +1 -0
  15. package/dist/components/file-viewer/style2.css +14 -1
  16. package/dist/components/multi-select/multi-select.vue.d.ts +1 -1
  17. package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +1 -1
  18. package/dist/components/scroll/scroll.js +94 -30
  19. package/dist/components/scroll/scroll.js.map +1 -1
  20. package/dist/components/scroll/style2.css +22 -0
  21. package/dist/components/tabs/tabs-horizontal.vue.d.ts +2 -2
  22. package/dist/components/tabs/tabs-vertical.vue.d.ts +2 -2
  23. package/dist/components/tabs/tabs.vue.d.ts +2 -2
  24. package/dist/components/tree/tree.vue.d.ts +1 -1
  25. package/dist/components/tree-select/tree-select.vue.d.ts +1 -1
  26. package/dist/types/scroll.d.ts +6 -1
  27. package/package.json +12 -11
  28. package/src/components/batch-edit/batch-edit.vue +1 -1
  29. package/src/components/batch-edit/style.scss +9 -1
  30. package/src/components/file-viewer/file-viewer.vue +73 -16
  31. package/src/components/file-viewer/previewers/image-previewer.vue +1 -0
  32. package/src/components/file-viewer/previewers/pdf-previewer.vue +67 -14
  33. package/src/components/file-viewer/previewers/pdf-viewport-scroll.vue +112 -0
  34. package/src/components/file-viewer/previewers/pdf-zoom-bridge.vue +33 -0
  35. package/src/components/file-viewer/style.scss +16 -1
  36. package/src/components/scroll/scroll.vue +124 -75
  37. package/src/components/scroll/style.scss +22 -0
  38. package/src/types/scroll.ts +7 -1
@@ -1,23 +1,35 @@
1
1
  <template>
2
2
  <div :class="className" :style="style" ref="scrollRef">
3
- <div
4
- ref="containerRef"
5
- :class="[cls.e('container'), containerClass]"
6
- @scroll.passive="handleScroll"
7
- :style="containerStyle"
8
- >
9
- <component
10
- ref="contentRef"
11
- :style="contentStyle"
12
- :class="[cls.e('content'), contentClass]"
13
- :is="tag"
3
+ <template v-if="!isExternal">
4
+ <div
5
+ ref="containerRef"
6
+ :class="[cls.e('container'), containerClass]"
7
+ @scroll.passive="handleScroll"
8
+ :style="containerStyle"
14
9
  >
15
- <slot />
16
- </component>
17
- </div>
18
-
19
- <u-scroll-bar type="y" :class="cls.e('bar-y')" @drag="handleDragY" ref="barY" />
20
- <u-scroll-bar type="x" :class="cls.e('bar-x')" @drag="handleDragX" ref="barX" />
10
+ <component
11
+ ref="contentRef"
12
+ :style="contentStyle"
13
+ :class="[cls.e('content'), contentClass]"
14
+ :is="tag"
15
+ >
16
+ <slot />
17
+ </component>
18
+ </div>
19
+
20
+ <u-scroll-bar type="y" :class="cls.e('bar-y')" @drag="handleDragY" ref="barY" />
21
+ <u-scroll-bar type="x" :class="cls.e('bar-x')" @drag="handleDragX" ref="barX" />
22
+ </template>
23
+
24
+ <template v-else>
25
+ <slot />
26
+ <Teleport v-if="externalTarget" :to="externalTarget">
27
+ <div ref="overlayRef" :class="cls.e('overlay')">
28
+ <u-scroll-bar type="y" :class="cls.e('bar-y')" @drag="handleDragY" ref="barY" />
29
+ <u-scroll-bar type="x" :class="cls.e('bar-x')" @drag="handleDragX" ref="barX" />
30
+ </div>
31
+ </Teleport>
32
+ </template>
21
33
  </div>
22
34
  </template>
23
35
 
@@ -25,7 +37,15 @@
25
37
  import { debounce } from '@cat-kit/core'
26
38
  import { useResizeObserver } from '@veltra/compositions'
27
39
  import { bem, withUnit } from '@veltra/utils'
28
- import { type CSSProperties, computed, provide, shallowRef } from 'vue'
40
+ import {
41
+ type CSSProperties,
42
+ computed,
43
+ onBeforeUnmount,
44
+ provide,
45
+ shallowRef,
46
+ toValue,
47
+ watch
48
+ } from 'vue'
29
49
 
30
50
  import type { ScrollPosition, _ScrollExposed, ScrollProps, ScrollEmits } from '../../types'
31
51
  import { ScrollDIKey } from './di'
@@ -49,24 +69,26 @@ defineSlots<{
49
69
  }>()
50
70
 
51
71
  const cls = bem('scroll')
72
+
73
+ const isExternal = computed(() => props.target !== undefined)
74
+
75
+ const externalTarget = computed(() => (isExternal.value ? toValue(props.target) : null))
76
+
52
77
  const className = computed(() => {
53
- return [cls.b, bem.is('always', props.always)]
78
+ return [cls.b, bem.is('always', props.always), bem.is('external', isExternal.value)]
54
79
  })
55
80
 
56
- // 样式-------------------------------------------------------------
57
81
  const style = computed<CSSProperties>(() => {
82
+ if (isExternal.value) return {}
58
83
  return {
59
84
  height: withUnit(props.height, 'px')
60
85
  }
61
86
  })
62
87
 
63
- // 模板引用------------------------------------------------
64
- /** 内容引用 */
65
88
  const contentRef = shallowRef<HTMLElement>()
66
- /** 滚动根元素引用 */
67
89
  const scrollRef = shallowRef<HTMLElement>()
68
- /** 容器引用 */
69
90
  const containerRef = shallowRef<HTMLElement>()
91
+ const overlayRef = shallowRef<HTMLElement>()
70
92
  const barX = shallowRef<InstanceType<typeof UScrollBar>>()
71
93
  const barY = shallowRef<InstanceType<typeof UScrollBar>>()
72
94
  const minSize = 20
@@ -76,40 +98,28 @@ const trackSize = {
76
98
  height: 0
77
99
  }
78
100
 
79
- useResizeObserver({
80
- targets: [contentRef, scrollRef],
81
- onResize: (entries) => {
82
- if (entries.length && scrollRef.value) {
83
- const { clientHeight, clientWidth } = scrollRef.value
84
-
85
- trackSize.width = clientWidth
86
- trackSize.height = clientHeight
101
+ function getScrollContainer(): HTMLElement | undefined {
102
+ if (isExternal.value) {
103
+ return externalTarget.value ?? undefined
104
+ }
105
+ return containerRef.value
106
+ }
87
107
 
88
- barX.value?.setTrackSize(trackSize.width)
89
- barY.value?.setTrackSize(trackSize.height)
90
- updateBar()
108
+ function syncTrackSize() {
109
+ const container = getScrollContainer()
110
+ if (!container) return
91
111
 
92
- emit(
93
- 'resize',
94
- entries.map((entry) => entry.target as HTMLElement)
95
- )
96
- }
97
- }
98
- })
112
+ trackSize.width = container.clientWidth
113
+ trackSize.height = container.clientHeight
114
+ barX.value?.setTrackSize(trackSize.width)
115
+ barY.value?.setTrackSize(trackSize.height)
116
+ }
99
117
 
100
- // 更新滚动条
101
118
  const updateBar = () => {
102
- if (!containerRef.value) return
103
-
104
- const {
105
- scrollHeight,
106
- clientHeight,
107
- scrollTop,
119
+ const container = getScrollContainer()
120
+ if (!container) return
108
121
 
109
- scrollWidth,
110
- clientWidth,
111
- scrollLeft
112
- } = containerRef.value
122
+ const { scrollHeight, clientHeight, scrollTop, scrollWidth, clientWidth, scrollLeft } = container
113
123
 
114
124
  emit('scroll', {
115
125
  x: scrollLeft,
@@ -122,9 +132,7 @@ const updateBar = () => {
122
132
 
123
133
  if (scrollHeight !== clientHeight) {
124
134
  const barYHeight = Math.max((clientHeight / scrollHeight) * trackSize.height, minSize)
125
-
126
135
  const barYTop = (scrollTop / (scrollHeight - clientHeight)) * (trackSize.height - barYHeight)
127
-
128
136
  barY.value?.update(barYHeight, barYTop)
129
137
  } else {
130
138
  barY.value?.update(0, 0)
@@ -132,21 +140,18 @@ const updateBar = () => {
132
140
 
133
141
  if (scrollWidth !== clientWidth) {
134
142
  const barXWidth = Math.max((clientWidth / scrollWidth) * trackSize.width, minSize)
135
-
136
143
  const barXLeft = (scrollLeft / (scrollWidth - clientWidth)) * (trackSize.width - barXWidth)
137
-
138
144
  barX.value?.update(barXWidth, barXLeft)
139
145
  } else {
140
146
  barX.value?.update(0, 0)
141
147
  }
142
148
  }
143
149
 
144
- // 滚动条拖拽
145
150
  const handleDragX = debounce(
146
151
  (offset: number, size: number) => {
147
- const container = containerRef.value!
152
+ const container = getScrollContainer()
153
+ if (!container) return
148
154
  const { clientWidth, scrollWidth } = container
149
-
150
155
  container.scrollLeft = (offset / (trackSize.width - size)) * (scrollWidth - clientWidth)
151
156
  },
152
157
  props.dragDebounce ?? 0,
@@ -155,7 +160,8 @@ const handleDragX = debounce(
155
160
 
156
161
  const handleDragY = debounce(
157
162
  (offset: number, size: number) => {
158
- const container = containerRef.value!
163
+ const container = getScrollContainer()
164
+ if (!container) return
159
165
  const { clientHeight, scrollHeight } = container
160
166
  container.scrollTop = (offset / (trackSize.height - size)) * (scrollHeight - clientHeight)
161
167
  },
@@ -163,28 +169,61 @@ const handleDragY = debounce(
163
169
  false
164
170
  )
165
171
 
166
- // 滚动事件
167
- const handleScroll = (e) => {
172
+ const handleScroll = () => {
168
173
  updateBar()
169
174
  }
170
175
 
171
- // 滚动至------------------------------------------------
176
+ useResizeObserver({
177
+ targets: [contentRef, scrollRef, () => externalTarget.value ?? null],
178
+ onResize: (entries) => {
179
+ syncTrackSize()
180
+ updateBar()
181
+ if (entries.length) {
182
+ emit(
183
+ 'resize',
184
+ entries.map((entry) => entry.target as HTMLElement)
185
+ )
186
+ }
187
+ }
188
+ })
189
+
190
+ let detachExternalScroll: (() => void) | undefined
191
+
192
+ watch(
193
+ externalTarget,
194
+ (el, _, onCleanup) => {
195
+ detachExternalScroll?.()
196
+ detachExternalScroll = undefined
197
+ if (!el || !isExternal.value) return
198
+
199
+ const onScroll = () => updateBar()
200
+ el.addEventListener('scroll', onScroll, { passive: true })
201
+ detachExternalScroll = () => el.removeEventListener('scroll', onScroll)
202
+ syncTrackSize()
203
+ updateBar()
204
+
205
+ onCleanup(() => {
206
+ detachExternalScroll?.()
207
+ detachExternalScroll = undefined
208
+ })
209
+ },
210
+ { immediate: true }
211
+ )
212
+
213
+ onBeforeUnmount(() => {
214
+ detachExternalScroll?.()
215
+ })
216
+
172
217
  const scrollToLeft = (left: number) => {
173
- const container = containerRef.value
218
+ const container = getScrollContainer()
174
219
  if (!container) return
175
-
176
- container.scrollTo({
177
- left
178
- })
220
+ container.scrollTo({ left })
179
221
  }
180
222
 
181
223
  const scrollToTop = (top: number) => {
182
- const container = containerRef.value
224
+ const container = getScrollContainer()
183
225
  if (!container) return
184
-
185
- container.scrollTo({
186
- top
187
- })
226
+ container.scrollTo({ top })
188
227
  }
189
228
 
190
229
  const scrollTo = (position: ScrollPosition) => {
@@ -196,10 +235,20 @@ provide(ScrollDIKey, {
196
235
  cls
197
236
  })
198
237
 
238
+ const activeContainerRef = shallowRef<HTMLElement>()
239
+
240
+ watch(
241
+ [isExternal, externalTarget, containerRef],
242
+ () => {
243
+ activeContainerRef.value = getScrollContainer()
244
+ },
245
+ { immediate: true }
246
+ )
247
+
199
248
  const exposed: _ScrollExposed = {
200
249
  el: scrollRef,
201
250
  contentRef,
202
- containerRef,
251
+ containerRef: activeContainerRef,
203
252
  scrollTo,
204
253
  update: updateBar
205
254
  }
@@ -12,6 +12,28 @@ $root-name: scroll;
12
12
  overflow: hidden;
13
13
  scroll-behavior: auto;
14
14
 
15
+ @include m.is(external) {
16
+ display: contents;
17
+ }
18
+
19
+ @include m.e(overlay) {
20
+ position: absolute;
21
+ inset: 0;
22
+ overflow: hidden;
23
+ pointer-events: none;
24
+ z-index: 2;
25
+
26
+ @include m.bem($root-name, (bar-x, bar-y)) {
27
+ pointer-events: auto;
28
+ }
29
+
30
+ &:hover > {
31
+ @include m.bem($root-name, (bar-x, bar-y)) {
32
+ opacity: 1;
33
+ }
34
+ }
35
+ }
36
+
15
37
  // 滚动容器
16
38
  @include m.e(container) {
17
39
  overflow: auto;
@@ -1,5 +1,5 @@
1
1
  import type { DeconstructValue } from '@veltra/utils'
2
- import type { CSSProperties, ShallowRef } from 'vue'
2
+ import type { CSSProperties, MaybeRefOrGetter, ShallowRef } from 'vue'
3
3
 
4
4
  export type ScrollPosition = {
5
5
  /** 横向位置 */
@@ -53,6 +53,12 @@ export interface ScrollProps {
53
53
 
54
54
  /** 拖拽防抖时间 */
55
55
  dragDebounce?: number
56
+
57
+ /**
58
+ * 外部滚动容器(如 EmbedPDF Viewport)。
59
+ * 提供时仅渲染自定义滚动条并同步该元素的滚动,不创建内部滚动容器。
60
+ */
61
+ target?: MaybeRefOrGetter<HTMLElement | null | undefined>
56
62
  }
57
63
 
58
64
  export interface ScrollEmits {