stk-table-vue 0.8.13 → 0.9.0-beta.1
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/README.md +172 -180
- package/lib/src/StkTable/StkTable.vue.d.ts +22 -2
- package/lib/src/StkTable/useScrollbar.d.ts +57 -0
- package/lib/src/StkTable/utils/index.d.ts +10 -0
- package/lib/stk-table-vue.js +563 -294
- package/lib/style.css +49 -2
- package/package.json +74 -72
- package/src/StkTable/StkTable.vue +1730 -1653
- package/src/StkTable/components/DragHandle.vue +9 -9
- package/src/StkTable/components/SortIcon.vue +6 -6
- package/src/StkTable/components/TriangleIcon.vue +3 -3
- package/src/StkTable/const.ts +50 -50
- package/src/StkTable/index.ts +4 -4
- package/src/StkTable/style.less +627 -580
- package/src/StkTable/types/highlightDimOptions.ts +26 -26
- package/src/StkTable/types/index.ts +297 -297
- package/src/StkTable/useAutoResize.ts +91 -91
- package/src/StkTable/useColResize.ts +216 -216
- package/src/StkTable/useFixedCol.ts +150 -148
- package/src/StkTable/useFixedStyle.ts +75 -75
- package/src/StkTable/useGetFixedColPosition.ts +65 -65
- package/src/StkTable/useHighlight.ts +257 -257
- package/src/StkTable/useKeyboardArrowScroll.ts +112 -112
- package/src/StkTable/useMaxRowSpan.ts +55 -55
- package/src/StkTable/useMergeCells.ts +120 -123
- package/src/StkTable/useRowExpand.ts +88 -88
- package/src/StkTable/useScrollRowByRow.ts +114 -79
- package/src/StkTable/useScrollbar.ts +187 -0
- package/src/StkTable/useThDrag.ts +102 -102
- package/src/StkTable/useTrDrag.ts +113 -118
- package/src/StkTable/useTree.ts +161 -161
- package/src/StkTable/useVirtualScroll.ts +494 -494
- package/src/StkTable/utils/constRefUtils.ts +29 -29
- package/src/StkTable/utils/index.ts +287 -242
- package/src/StkTable/utils/useTriggerRef.ts +33 -33
- package/src/VirtualTree.vue +622 -622
- package/src/VirtualTreeSelect.vue +367 -367
- package/src/vite-env.d.ts +10 -10
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
import { ShallowRef } from 'vue';
|
|
2
|
-
import { EXPANDED_ROW_KEY_PREFIX } from './const';
|
|
3
|
-
import { PrivateRowDT, RowKeyGen, StkTableColumn, UniqKey } from './types';
|
|
4
|
-
type DT = PrivateRowDT;
|
|
5
|
-
type Option<DT extends Record<string, any>> = {
|
|
6
|
-
rowKeyGen: RowKeyGen;
|
|
7
|
-
dataSourceCopy: ShallowRef<DT[]>;
|
|
8
|
-
emits: any;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export function useRowExpand({ dataSourceCopy, rowKeyGen, emits }: Option<DT>) {
|
|
12
|
-
const expandedKey = '__EXP__';
|
|
13
|
-
|
|
14
|
-
function isExpanded(row: DT, col?: StkTableColumn<DT>) {
|
|
15
|
-
return row?.[expandedKey] === col ? !row?.[expandedKey] : true;
|
|
16
|
-
}
|
|
17
|
-
/** click expended icon to toggle expand row */
|
|
18
|
-
function toggleExpandRow(row: DT, col: StkTableColumn<DT>) {
|
|
19
|
-
const isExpand = isExpanded(row, col);
|
|
20
|
-
setRowExpand(row, isExpand, { col });
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
* @param rowKeyOrRow rowKey or row
|
|
26
|
-
* @param expand expand or collapse, if set null, toggle expand
|
|
27
|
-
* @param data { col?: StkTableColumn<DT> }
|
|
28
|
-
* @param data.silent if set true, not emit `toggle-row-expand`, default:false
|
|
29
|
-
*/
|
|
30
|
-
function setRowExpand(rowKeyOrRow: string | undefined | DT, expand?: boolean | null, data?: { col?: StkTableColumn<DT>; silent?: boolean }) {
|
|
31
|
-
let rowKey: UniqKey;
|
|
32
|
-
if (typeof rowKeyOrRow === 'string') {
|
|
33
|
-
rowKey = rowKeyOrRow;
|
|
34
|
-
} else {
|
|
35
|
-
rowKey = rowKeyGen(rowKeyOrRow);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const tempData = dataSourceCopy.value.slice();
|
|
39
|
-
const index = tempData.findIndex(it => rowKeyGen(it) === rowKey);
|
|
40
|
-
if (index === -1) {
|
|
41
|
-
console.warn('expandRow failed.rowKey:', rowKey);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// delete other expanded row below the target row
|
|
46
|
-
for (let i = index + 1; i < tempData.length; i++) {
|
|
47
|
-
const item: PrivateRowDT = tempData[i];
|
|
48
|
-
const rowKey = item.__ROW_K__;
|
|
49
|
-
if (rowKey?.startsWith(EXPANDED_ROW_KEY_PREFIX)) {
|
|
50
|
-
tempData.splice(i, 1);
|
|
51
|
-
i--;
|
|
52
|
-
} else {
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const row = tempData[index];
|
|
58
|
-
const col = data?.col;
|
|
59
|
-
|
|
60
|
-
if (expand == null) {
|
|
61
|
-
expand = isExpanded(row, col);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (expand) {
|
|
65
|
-
// insert new expanded row
|
|
66
|
-
const newExpandRow: PrivateRowDT = {
|
|
67
|
-
__ROW_K__: EXPANDED_ROW_KEY_PREFIX + rowKey,
|
|
68
|
-
__EXP_R__: row,
|
|
69
|
-
__EXP_C__: col,
|
|
70
|
-
};
|
|
71
|
-
tempData.splice(index + 1, 0, newExpandRow);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (row) {
|
|
75
|
-
row[expandedKey] = expand ? col : void 0;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
dataSourceCopy.value = tempData;
|
|
79
|
-
if (!data?.silent) {
|
|
80
|
-
emits('toggle-row-expand', { expanded: Boolean(expand), row, col });
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
toggleExpandRow,
|
|
86
|
-
setRowExpand,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
1
|
+
import { ShallowRef } from 'vue';
|
|
2
|
+
import { EXPANDED_ROW_KEY_PREFIX } from './const';
|
|
3
|
+
import { PrivateRowDT, RowKeyGen, StkTableColumn, UniqKey } from './types';
|
|
4
|
+
type DT = PrivateRowDT;
|
|
5
|
+
type Option<DT extends Record<string, any>> = {
|
|
6
|
+
rowKeyGen: RowKeyGen;
|
|
7
|
+
dataSourceCopy: ShallowRef<DT[]>;
|
|
8
|
+
emits: any;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export function useRowExpand({ dataSourceCopy, rowKeyGen, emits }: Option<DT>) {
|
|
12
|
+
const expandedKey = '__EXP__';
|
|
13
|
+
|
|
14
|
+
function isExpanded(row: DT, col?: StkTableColumn<DT>) {
|
|
15
|
+
return row?.[expandedKey] === col ? !row?.[expandedKey] : true;
|
|
16
|
+
}
|
|
17
|
+
/** click expended icon to toggle expand row */
|
|
18
|
+
function toggleExpandRow(row: DT, col: StkTableColumn<DT>) {
|
|
19
|
+
const isExpand = isExpanded(row, col);
|
|
20
|
+
setRowExpand(row, isExpand, { col });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param rowKeyOrRow rowKey or row
|
|
26
|
+
* @param expand expand or collapse, if set null, toggle expand
|
|
27
|
+
* @param data { col?: StkTableColumn<DT> }
|
|
28
|
+
* @param data.silent if set true, not emit `toggle-row-expand`, default:false
|
|
29
|
+
*/
|
|
30
|
+
function setRowExpand(rowKeyOrRow: string | undefined | DT, expand?: boolean | null, data?: { col?: StkTableColumn<DT>; silent?: boolean }) {
|
|
31
|
+
let rowKey: UniqKey;
|
|
32
|
+
if (typeof rowKeyOrRow === 'string') {
|
|
33
|
+
rowKey = rowKeyOrRow;
|
|
34
|
+
} else {
|
|
35
|
+
rowKey = rowKeyGen(rowKeyOrRow);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const tempData = dataSourceCopy.value.slice();
|
|
39
|
+
const index = tempData.findIndex(it => rowKeyGen(it) === rowKey);
|
|
40
|
+
if (index === -1) {
|
|
41
|
+
console.warn('expandRow failed.rowKey:', rowKey);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// delete other expanded row below the target row
|
|
46
|
+
for (let i = index + 1; i < tempData.length; i++) {
|
|
47
|
+
const item: PrivateRowDT = tempData[i];
|
|
48
|
+
const rowKey = item.__ROW_K__;
|
|
49
|
+
if (rowKey?.startsWith(EXPANDED_ROW_KEY_PREFIX)) {
|
|
50
|
+
tempData.splice(i, 1);
|
|
51
|
+
i--;
|
|
52
|
+
} else {
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const row = tempData[index];
|
|
58
|
+
const col = data?.col;
|
|
59
|
+
|
|
60
|
+
if (expand == null) {
|
|
61
|
+
expand = isExpanded(row, col);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (expand) {
|
|
65
|
+
// insert new expanded row
|
|
66
|
+
const newExpandRow: PrivateRowDT = {
|
|
67
|
+
__ROW_K__: EXPANDED_ROW_KEY_PREFIX + rowKey,
|
|
68
|
+
__EXP_R__: row,
|
|
69
|
+
__EXP_C__: col,
|
|
70
|
+
};
|
|
71
|
+
tempData.splice(index + 1, 0, newExpandRow);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (row) {
|
|
75
|
+
row[expandedKey] = expand ? col : void 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
dataSourceCopy.value = tempData;
|
|
79
|
+
if (!data?.silent) {
|
|
80
|
+
emits('toggle-row-expand', { expanded: Boolean(expand), row, col });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
toggleExpandRow,
|
|
86
|
+
setRowExpand,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -1,79 +1,114 @@
|
|
|
1
|
-
import { computed,
|
|
2
|
-
|
|
3
|
-
type Params = {
|
|
4
|
-
props: any;
|
|
5
|
-
tableContainerRef: Ref<HTMLElement | undefined>;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export function useScrollRowByRow({ props, tableContainerRef }: Params) {
|
|
9
|
-
let isMouseDown = false;
|
|
10
|
-
let isAddListeners = false;
|
|
11
|
-
/** record the last scroll bar position */
|
|
12
|
-
let lastScrollTop = 0;
|
|
13
|
-
|
|
14
|
-
/** record is the scroll bar is dragging */
|
|
15
|
-
const isDragScroll =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (!
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
1
|
+
import { computed, customRef, onMounted, onUnmounted, Ref, watch } from 'vue';
|
|
2
|
+
|
|
3
|
+
type Params = {
|
|
4
|
+
props: any;
|
|
5
|
+
tableContainerRef: Ref<HTMLElement | undefined>;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function useScrollRowByRow({ props, tableContainerRef }: Params) {
|
|
9
|
+
// let isMouseDown = false;
|
|
10
|
+
let isAddListeners = false;
|
|
11
|
+
/** record the last scroll bar position */
|
|
12
|
+
// let lastScrollTop = 0;
|
|
13
|
+
|
|
14
|
+
/** record is the scroll bar is dragging.debounce true to false */
|
|
15
|
+
const isDragScroll = customRef((track, trigger) => {
|
|
16
|
+
let value = false;
|
|
17
|
+
let debounceTimer = 0;
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
get() {
|
|
21
|
+
track();
|
|
22
|
+
return value;
|
|
23
|
+
},
|
|
24
|
+
set(newValue) {
|
|
25
|
+
// Add debounce when change from true to false
|
|
26
|
+
if (value && !newValue) {
|
|
27
|
+
if (debounceTimer) {
|
|
28
|
+
window.clearTimeout(debounceTimer);
|
|
29
|
+
}
|
|
30
|
+
debounceTimer = window.setTimeout(() => {
|
|
31
|
+
value = newValue;
|
|
32
|
+
trigger();
|
|
33
|
+
debounceTimer = 0;
|
|
34
|
+
}, 300);
|
|
35
|
+
} else {
|
|
36
|
+
if (debounceTimer) {
|
|
37
|
+
window.clearTimeout(debounceTimer);
|
|
38
|
+
debounceTimer = 0;
|
|
39
|
+
}
|
|
40
|
+
value = newValue;
|
|
41
|
+
trigger();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const onlyDragScroll = computed(() => props.scrollRowByRow === 'scrollbar');
|
|
47
|
+
|
|
48
|
+
/** is ScrollRowByRow active */
|
|
49
|
+
const isSRBRActive = computed(() => {
|
|
50
|
+
if (onlyDragScroll.value) {
|
|
51
|
+
return isDragScroll.value;
|
|
52
|
+
}
|
|
53
|
+
return props.scrollRowByRow;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
watch(onlyDragScroll, v => {
|
|
57
|
+
if (v) {
|
|
58
|
+
addEventListener();
|
|
59
|
+
} else {
|
|
60
|
+
removeEventListener();
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
onMounted(() => {
|
|
65
|
+
addEventListener();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
onUnmounted(() => {
|
|
69
|
+
removeEventListener();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
function addEventListener() {
|
|
73
|
+
if (isAddListeners || !onlyDragScroll.value) return;
|
|
74
|
+
const container = tableContainerRef.value;
|
|
75
|
+
if (!container) return;
|
|
76
|
+
container.addEventListener('mousedown', handleMouseDown);
|
|
77
|
+
container.addEventListener('mouseup', handleMouseUp);
|
|
78
|
+
// container.addEventListener('scroll', handleScroll);
|
|
79
|
+
isAddListeners = true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function removeEventListener() {
|
|
83
|
+
const container = tableContainerRef.value;
|
|
84
|
+
if (!container) return;
|
|
85
|
+
container.removeEventListener('mousedown', handleMouseDown);
|
|
86
|
+
container.removeEventListener('mouseup', handleMouseUp);
|
|
87
|
+
// container.removeEventListener('scroll', handleScroll);
|
|
88
|
+
isAddListeners = false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function handleMouseDown(e: Event) {
|
|
92
|
+
// console.log('mousedown target:', e.target)
|
|
93
|
+
const el = e.target as HTMLElement;
|
|
94
|
+
if(el.classList.contains('stk-table')){
|
|
95
|
+
isDragScroll.value = true;
|
|
96
|
+
}
|
|
97
|
+
// isMouseDown = true;
|
|
98
|
+
// lastScrollTop = (e.target as HTMLElement).scrollTop;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function handleMouseUp() {
|
|
102
|
+
// isMouseDown = false;
|
|
103
|
+
isDragScroll.value = false;
|
|
104
|
+
// lastScrollTop = 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// function handleScroll(e: Event) {
|
|
108
|
+
// const scrollTop = (e.target as HTMLElement).scrollTop;
|
|
109
|
+
// // if scrollTop === lastScrollTop means horizontal scroll
|
|
110
|
+
// if (!isMouseDown || scrollTop === lastScrollTop) return;
|
|
111
|
+
// isDragScroll.value = true;
|
|
112
|
+
// }
|
|
113
|
+
return { isSRBRActive, isDragScroll };
|
|
114
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { ref, onMounted, onUnmounted, nextTick, Ref } from 'vue';
|
|
2
|
+
import { throttle } from './utils/index';
|
|
3
|
+
|
|
4
|
+
export type ScrollbarOptions = {
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
/** scroll-y width */
|
|
7
|
+
width?: number;
|
|
8
|
+
/** scroll-x height */
|
|
9
|
+
height?: number;
|
|
10
|
+
/** min scroll-y width */
|
|
11
|
+
minWidth?: number;
|
|
12
|
+
/** min scroll-x height */
|
|
13
|
+
minHeight?: number;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 自定义滚动条hooks
|
|
18
|
+
* @param containerRef 滚动容器的ref
|
|
19
|
+
* @param options 滚动条配置选项
|
|
20
|
+
* @returns 滚动条相关状态和方法
|
|
21
|
+
*/
|
|
22
|
+
export function useScrollbar(containerRef: Ref<HTMLDivElement | undefined>, options: boolean | ScrollbarOptions = false) {
|
|
23
|
+
const defaultOptions: Required<ScrollbarOptions> = {
|
|
24
|
+
enabled: true,
|
|
25
|
+
minHeight: 20,
|
|
26
|
+
minWidth: 20,
|
|
27
|
+
width: 8,
|
|
28
|
+
height: 8,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const mergedOptions = {
|
|
32
|
+
...defaultOptions,
|
|
33
|
+
...(typeof options === 'boolean' ? { enabled: options } : options),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const showScrollbar = ref({ x: false, y: false });
|
|
37
|
+
|
|
38
|
+
const scrollbar = ref({ h: 0, w: 0, top: 0, left: 0 });
|
|
39
|
+
|
|
40
|
+
let isDraggingVertical = false;
|
|
41
|
+
let isDraggingHorizontal = false;
|
|
42
|
+
let dragStartY = 0;
|
|
43
|
+
let dragStartX = 0;
|
|
44
|
+
let dragStartTop = 0;
|
|
45
|
+
let dragStartLeft = 0;
|
|
46
|
+
|
|
47
|
+
let resizeObserver: ResizeObserver | null = null;
|
|
48
|
+
|
|
49
|
+
const throttledUpdateScrollbar = throttle(() => {
|
|
50
|
+
updateCustomScrollbar();
|
|
51
|
+
}, 200);
|
|
52
|
+
|
|
53
|
+
onMounted(() => {
|
|
54
|
+
if (mergedOptions.enabled && containerRef.value) {
|
|
55
|
+
resizeObserver = new ResizeObserver(throttledUpdateScrollbar);
|
|
56
|
+
resizeObserver.observe(containerRef.value);
|
|
57
|
+
}
|
|
58
|
+
// if (tableMainRef.value) {
|
|
59
|
+
// resizeObserver.observe(tableMainRef.value);
|
|
60
|
+
// }
|
|
61
|
+
initScrollbar();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
onUnmounted(() => {
|
|
65
|
+
if (resizeObserver) {
|
|
66
|
+
resizeObserver.disconnect();
|
|
67
|
+
resizeObserver = null;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
function updateCustomScrollbar() {
|
|
72
|
+
if (!mergedOptions.enabled || !containerRef.value) return;
|
|
73
|
+
|
|
74
|
+
const container = containerRef.value;
|
|
75
|
+
const { scrollHeight, clientHeight, scrollWidth, clientWidth, scrollTop, scrollLeft } = container;
|
|
76
|
+
|
|
77
|
+
const needVertical = scrollHeight > clientHeight;
|
|
78
|
+
const needHorizontal = scrollWidth > clientWidth;
|
|
79
|
+
showScrollbar.value = { x: needHorizontal, y: needVertical };
|
|
80
|
+
|
|
81
|
+
if (needVertical) {
|
|
82
|
+
const ratio = clientHeight / scrollHeight;
|
|
83
|
+
scrollbar.value.h = Math.max(mergedOptions.minHeight, ratio * clientHeight);
|
|
84
|
+
scrollbar.value.top = (scrollTop / (scrollHeight - clientHeight)) * (clientHeight - scrollbar.value.h);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (needHorizontal) {
|
|
88
|
+
const ratio = clientWidth / scrollWidth;
|
|
89
|
+
scrollbar.value.w = Math.max(mergedOptions.minWidth, ratio * clientWidth);
|
|
90
|
+
scrollbar.value.left = (scrollLeft / (scrollWidth - clientWidth)) * (clientWidth - scrollbar.value.w);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function onVerticalScrollbarMouseDown(e: MouseEvent | TouchEvent) {
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
isDraggingVertical = true;
|
|
97
|
+
|
|
98
|
+
const container = containerRef.value;
|
|
99
|
+
if (!container) return;
|
|
100
|
+
|
|
101
|
+
dragStartTop = container.scrollTop;
|
|
102
|
+
dragStartY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY;
|
|
103
|
+
|
|
104
|
+
document.addEventListener('mousemove', onVerticalDrag);
|
|
105
|
+
document.addEventListener('mouseup', onDragEnd);
|
|
106
|
+
document.addEventListener('touchmove', onVerticalDrag, { passive: false });
|
|
107
|
+
document.addEventListener('touchend', onDragEnd);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function onHorizontalScrollbarMouseDown(e: MouseEvent | TouchEvent) {
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
isDraggingHorizontal = true;
|
|
113
|
+
|
|
114
|
+
const container = containerRef.value;
|
|
115
|
+
if (!container) return;
|
|
116
|
+
|
|
117
|
+
dragStartLeft = container.scrollLeft;
|
|
118
|
+
|
|
119
|
+
dragStartX = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;
|
|
120
|
+
|
|
121
|
+
document.addEventListener('mousemove', onHorizontalDrag);
|
|
122
|
+
document.addEventListener('mouseup', onDragEnd);
|
|
123
|
+
document.addEventListener('touchmove', onHorizontalDrag, { passive: false });
|
|
124
|
+
document.addEventListener('touchend', onDragEnd);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function onVerticalDrag(e: MouseEvent | TouchEvent) {
|
|
128
|
+
if (!isDraggingVertical || !containerRef.value) return;
|
|
129
|
+
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
|
|
132
|
+
const clientY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY;
|
|
133
|
+
|
|
134
|
+
const deltaY = clientY - dragStartY;
|
|
135
|
+
const container = containerRef.value;
|
|
136
|
+
const { scrollHeight, clientHeight } = container;
|
|
137
|
+
|
|
138
|
+
const scrollRange = scrollHeight - clientHeight;
|
|
139
|
+
const trackRange = clientHeight - scrollbar.value.h;
|
|
140
|
+
const scrollDelta = (deltaY / trackRange) * scrollRange;
|
|
141
|
+
container.scrollTop = dragStartTop + scrollDelta;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function onHorizontalDrag(e: MouseEvent | TouchEvent) {
|
|
145
|
+
if (!isDraggingHorizontal || !containerRef.value) return;
|
|
146
|
+
|
|
147
|
+
e.preventDefault();
|
|
148
|
+
|
|
149
|
+
const clientX = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;
|
|
150
|
+
|
|
151
|
+
const deltaX = clientX - dragStartX;
|
|
152
|
+
const container = containerRef.value;
|
|
153
|
+
const { scrollWidth, clientWidth } = container;
|
|
154
|
+
|
|
155
|
+
const scrollRange = scrollWidth - clientWidth;
|
|
156
|
+
const trackRange = clientWidth - scrollbar.value.w;
|
|
157
|
+
const scrollDelta = (deltaX / trackRange) * scrollRange;
|
|
158
|
+
container.scrollLeft = dragStartLeft + scrollDelta;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function onDragEnd() {
|
|
162
|
+
isDraggingVertical = false;
|
|
163
|
+
isDraggingHorizontal = false;
|
|
164
|
+
|
|
165
|
+
document.removeEventListener('mousemove', onVerticalDrag);
|
|
166
|
+
document.removeEventListener('mousemove', onHorizontalDrag);
|
|
167
|
+
document.removeEventListener('mouseup', onDragEnd);
|
|
168
|
+
document.removeEventListener('touchmove', onVerticalDrag);
|
|
169
|
+
document.removeEventListener('touchmove', onHorizontalDrag);
|
|
170
|
+
document.removeEventListener('touchend', onDragEnd);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function initScrollbar() {
|
|
174
|
+
nextTick(() => {
|
|
175
|
+
updateCustomScrollbar();
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
scrollbarOptions: mergedOptions,
|
|
181
|
+
scrollbar,
|
|
182
|
+
showScrollbar,
|
|
183
|
+
onVerticalScrollbarMouseDown,
|
|
184
|
+
onHorizontalScrollbarMouseDown,
|
|
185
|
+
updateCustomScrollbar,
|
|
186
|
+
};
|
|
187
|
+
}
|