stk-table-vue 0.6.16 → 0.7.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.
Files changed (39) hide show
  1. package/README.md +211 -213
  2. package/lib/src/StkTable/StkTable.vue.d.ts +43 -24
  3. package/lib/src/StkTable/components/TriangleIcon.vue.d.ts +2 -0
  4. package/lib/src/StkTable/const.d.ts +0 -1
  5. package/lib/src/StkTable/types/highlightDimOptions.d.ts +1 -5
  6. package/lib/src/StkTable/types/index.d.ts +26 -6
  7. package/lib/src/StkTable/useHighlight.d.ts +1 -1
  8. package/lib/src/StkTable/useRowExpand.d.ts +17 -0
  9. package/lib/src/StkTable/useTree.d.ts +20 -0
  10. package/lib/stk-table-vue.js +321 -170
  11. package/lib/style.css +29 -20
  12. package/package.json +75 -75
  13. package/src/StkTable/StkTable.vue +1557 -1550
  14. package/src/StkTable/components/DragHandle.vue +9 -9
  15. package/src/StkTable/components/SortIcon.vue +6 -6
  16. package/src/StkTable/components/TriangleIcon.vue +3 -0
  17. package/src/StkTable/const.ts +37 -37
  18. package/src/StkTable/index.ts +4 -4
  19. package/src/StkTable/style.less +567 -553
  20. package/src/StkTable/types/highlightDimOptions.ts +26 -26
  21. package/src/StkTable/types/index.ts +260 -239
  22. package/src/StkTable/useAutoResize.ts +91 -91
  23. package/src/StkTable/useColResize.ts +216 -216
  24. package/src/StkTable/useFixedCol.ts +148 -148
  25. package/src/StkTable/useFixedStyle.ts +75 -75
  26. package/src/StkTable/useGetFixedColPosition.ts +65 -65
  27. package/src/StkTable/useHighlight.ts +320 -318
  28. package/src/StkTable/useKeyboardArrowScroll.ts +112 -112
  29. package/src/StkTable/useRowExpand.ts +78 -0
  30. package/src/StkTable/useThDrag.ts +102 -102
  31. package/src/StkTable/useTrDrag.ts +118 -118
  32. package/src/StkTable/useTree.ts +158 -0
  33. package/src/StkTable/useVirtualScroll.ts +462 -462
  34. package/src/StkTable/utils/constRefUtils.ts +29 -29
  35. package/src/StkTable/utils/index.ts +213 -212
  36. package/src/StkTable/utils/useTriggerRef.ts +33 -33
  37. package/src/VirtualTree.vue +622 -622
  38. package/src/VirtualTreeSelect.vue +367 -367
  39. package/src/vite-env.d.ts +10 -10
@@ -1,112 +1,112 @@
1
- import { ComputedRef, Ref, ShallowRef, onBeforeUnmount, onMounted, watch } from 'vue';
2
- import { StkTableColumn } from './types';
3
- import { VirtualScrollStore, VirtualScrollXStore } from './useVirtualScroll';
4
-
5
- /** 翻页按键 */
6
- enum ScrollCodes {
7
- ArrowUp = 'ArrowUp',
8
- ArrowRight = 'ArrowRight',
9
- ArrowDown = 'ArrowDown',
10
- ArrowLeft = 'ArrowLeft',
11
- PageUp = 'PageUp',
12
- PageDown = 'PageDown',
13
- Home = 'Home',
14
- End = 'End',
15
- }
16
- /** 所有翻页按键数组 */
17
- const ScrollCodesValues = Object.values(ScrollCodes);
18
-
19
- type Options<DT extends Record<string, any>> = {
20
- props: any;
21
- scrollTo: (y: number | null, x: number | null) => void;
22
- virtualScroll: Ref<VirtualScrollStore>;
23
- virtualScrollX: Ref<VirtualScrollXStore>;
24
- tableHeaders: ShallowRef<StkTableColumn<DT>[][]>;
25
- virtual_on: ComputedRef<boolean>;
26
- };
27
- /**
28
- * 按下键盘箭头滚动。只有悬浮在表体上才能生效键盘。
29
- *
30
- * 在低版本浏览器中,虚拟滚动时,使用键盘滚动,等选中的行消失在视口外时,滚动会失效。
31
- */
32
- export function useKeyboardArrowScroll<DT extends Record<string, any>>(
33
- targetElement: Ref<HTMLElement | undefined>,
34
- { props, scrollTo, virtualScroll, virtualScrollX, tableHeaders, virtual_on }: Options<DT>,
35
- ) {
36
- /** 检测鼠标是否悬浮在表格体上 */
37
- let isMouseOver = false;
38
- watch(virtual_on, val => {
39
- if (!val) {
40
- removeListeners();
41
- } else {
42
- addEventListeners();
43
- }
44
- });
45
-
46
- onMounted(addEventListeners);
47
-
48
- onBeforeUnmount(removeListeners);
49
-
50
- function addEventListeners() {
51
- window.addEventListener('keydown', handleKeydown);
52
- targetElement.value?.addEventListener('mouseenter', handleMouseEnter);
53
- targetElement.value?.addEventListener('mouseleave', handleMouseLeave);
54
- targetElement.value?.addEventListener('mousedown', handleMouseDown);
55
- }
56
-
57
- function removeListeners() {
58
- window.removeEventListener('keydown', handleKeydown);
59
- targetElement.value?.removeEventListener('mouseenter', handleMouseEnter);
60
- targetElement.value?.removeEventListener('mouseleave', handleMouseLeave);
61
- targetElement.value?.removeEventListener('mousedown', handleMouseDown);
62
- }
63
-
64
- /** 键盘按下事件 */
65
- function handleKeydown(e: KeyboardEvent) {
66
- if (!virtual_on.value) return; // 非虚拟滚动使用浏览器默认滚动
67
- if (!ScrollCodesValues.includes(e.code as any)) return;
68
- if (!isMouseOver) return; // 不悬浮还是要触发键盘事件的
69
- e.preventDefault(); // 不触发键盘默认的箭头事件
70
-
71
- const { scrollTop, rowHeight, containerHeight, scrollHeight } = virtualScroll.value;
72
- const { scrollLeft } = virtualScrollX.value;
73
- const { headless, headerRowHeight } = props;
74
-
75
- // 这里不用virtualScroll 中的pageSize,因为我需要上一页的最后一条放在下一页的第一条
76
- const headerHeight = headless ? 0 : tableHeaders.value.length * (headerRowHeight || rowHeight);
77
- /** 表体的page */
78
- const bodyPageSize = Math.floor((containerHeight - headerHeight) / rowHeight);
79
-
80
- if (e.code === ScrollCodes.ArrowUp) {
81
- scrollTo(scrollTop - rowHeight, null);
82
- } else if (e.code === ScrollCodes.ArrowRight) {
83
- scrollTo(null, scrollLeft + 50);
84
- } else if (e.code === ScrollCodes.ArrowDown) {
85
- scrollTo(scrollTop + rowHeight, null);
86
- } else if (e.code === ScrollCodes.ArrowLeft) {
87
- scrollTo(null, scrollLeft - 50);
88
- } else if (e.code === ScrollCodes.PageUp) {
89
- scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
90
- } else if (e.code === ScrollCodes.PageDown) {
91
- scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
92
- } else if (e.code === ScrollCodes.Home) {
93
- scrollTo(0, null);
94
- } else if (e.code === ScrollCodes.End) {
95
- scrollTo(scrollHeight, null);
96
- }
97
- }
98
-
99
- function handleMouseEnter() {
100
- isMouseOver = true;
101
- }
102
- function handleMouseLeave() {
103
- isMouseOver = false;
104
- }
105
- /**
106
- * 兜底。
107
- * 是否存在不触发mouseEnter的时候?
108
- */
109
- function handleMouseDown() {
110
- if (!isMouseOver) isMouseOver = true;
111
- }
112
- }
1
+ import { ComputedRef, Ref, ShallowRef, onBeforeUnmount, onMounted, watch } from 'vue';
2
+ import { StkTableColumn } from './types';
3
+ import { VirtualScrollStore, VirtualScrollXStore } from './useVirtualScroll';
4
+
5
+ /** 翻页按键 */
6
+ enum ScrollCodes {
7
+ ArrowUp = 'ArrowUp',
8
+ ArrowRight = 'ArrowRight',
9
+ ArrowDown = 'ArrowDown',
10
+ ArrowLeft = 'ArrowLeft',
11
+ PageUp = 'PageUp',
12
+ PageDown = 'PageDown',
13
+ Home = 'Home',
14
+ End = 'End',
15
+ }
16
+ /** 所有翻页按键数组 */
17
+ const ScrollCodesValues = Object.values(ScrollCodes);
18
+
19
+ type Options<DT extends Record<string, any>> = {
20
+ props: any;
21
+ scrollTo: (y: number | null, x: number | null) => void;
22
+ virtualScroll: Ref<VirtualScrollStore>;
23
+ virtualScrollX: Ref<VirtualScrollXStore>;
24
+ tableHeaders: ShallowRef<StkTableColumn<DT>[][]>;
25
+ virtual_on: ComputedRef<boolean>;
26
+ };
27
+ /**
28
+ * 按下键盘箭头滚动。只有悬浮在表体上才能生效键盘。
29
+ *
30
+ * 在低版本浏览器中,虚拟滚动时,使用键盘滚动,等选中的行消失在视口外时,滚动会失效。
31
+ */
32
+ export function useKeyboardArrowScroll<DT extends Record<string, any>>(
33
+ targetElement: Ref<HTMLElement | undefined>,
34
+ { props, scrollTo, virtualScroll, virtualScrollX, tableHeaders, virtual_on }: Options<DT>,
35
+ ) {
36
+ /** 检测鼠标是否悬浮在表格体上 */
37
+ let isMouseOver = false;
38
+ watch(virtual_on, val => {
39
+ if (!val) {
40
+ removeListeners();
41
+ } else {
42
+ addEventListeners();
43
+ }
44
+ });
45
+
46
+ onMounted(addEventListeners);
47
+
48
+ onBeforeUnmount(removeListeners);
49
+
50
+ function addEventListeners() {
51
+ window.addEventListener('keydown', handleKeydown);
52
+ targetElement.value?.addEventListener('mouseenter', handleMouseEnter);
53
+ targetElement.value?.addEventListener('mouseleave', handleMouseLeave);
54
+ targetElement.value?.addEventListener('mousedown', handleMouseDown);
55
+ }
56
+
57
+ function removeListeners() {
58
+ window.removeEventListener('keydown', handleKeydown);
59
+ targetElement.value?.removeEventListener('mouseenter', handleMouseEnter);
60
+ targetElement.value?.removeEventListener('mouseleave', handleMouseLeave);
61
+ targetElement.value?.removeEventListener('mousedown', handleMouseDown);
62
+ }
63
+
64
+ /** 键盘按下事件 */
65
+ function handleKeydown(e: KeyboardEvent) {
66
+ if (!virtual_on.value) return; // 非虚拟滚动使用浏览器默认滚动
67
+ if (!ScrollCodesValues.includes(e.code as any)) return;
68
+ if (!isMouseOver) return; // 不悬浮还是要触发键盘事件的
69
+ e.preventDefault(); // 不触发键盘默认的箭头事件
70
+
71
+ const { scrollTop, rowHeight, containerHeight, scrollHeight } = virtualScroll.value;
72
+ const { scrollLeft } = virtualScrollX.value;
73
+ const { headless, headerRowHeight } = props;
74
+
75
+ // 这里不用virtualScroll 中的pageSize,因为我需要上一页的最后一条放在下一页的第一条
76
+ const headerHeight = headless ? 0 : tableHeaders.value.length * (headerRowHeight || rowHeight);
77
+ /** 表体的page */
78
+ const bodyPageSize = Math.floor((containerHeight - headerHeight) / rowHeight);
79
+
80
+ if (e.code === ScrollCodes.ArrowUp) {
81
+ scrollTo(scrollTop - rowHeight, null);
82
+ } else if (e.code === ScrollCodes.ArrowRight) {
83
+ scrollTo(null, scrollLeft + 50);
84
+ } else if (e.code === ScrollCodes.ArrowDown) {
85
+ scrollTo(scrollTop + rowHeight, null);
86
+ } else if (e.code === ScrollCodes.ArrowLeft) {
87
+ scrollTo(null, scrollLeft - 50);
88
+ } else if (e.code === ScrollCodes.PageUp) {
89
+ scrollTo(scrollTop - rowHeight * bodyPageSize + headerHeight, null);
90
+ } else if (e.code === ScrollCodes.PageDown) {
91
+ scrollTo(scrollTop + rowHeight * bodyPageSize - headerHeight, null);
92
+ } else if (e.code === ScrollCodes.Home) {
93
+ scrollTo(0, null);
94
+ } else if (e.code === ScrollCodes.End) {
95
+ scrollTo(scrollHeight, null);
96
+ }
97
+ }
98
+
99
+ function handleMouseEnter() {
100
+ isMouseOver = true;
101
+ }
102
+ function handleMouseLeave() {
103
+ isMouseOver = false;
104
+ }
105
+ /**
106
+ * 兜底。
107
+ * 是否存在不触发mouseEnter的时候?
108
+ */
109
+ function handleMouseDown() {
110
+ if (!isMouseOver) isMouseOver = true;
111
+ }
112
+ }
@@ -0,0 +1,78 @@
1
+ import { ShallowRef } from 'vue';
2
+ import { ExpandedRow, PrivateRowDT, StkTableColumn, UniqKey } from './types';
3
+ import { EXPANDED_ROW_KEY_PREFIX } from './const';
4
+ type DT = PrivateRowDT;
5
+ type Option<DT extends Record<string, any>> = {
6
+ rowKeyGen: (row: any) => UniqKey;
7
+ dataSourceCopy: ShallowRef<DT[]>;
8
+ emits: any;
9
+ };
10
+
11
+ export function useRowExpand({ dataSourceCopy, rowKeyGen, emits }: Option<DT>) {
12
+ /** click expended icon to toggle expand row */
13
+ function toggleExpandRow(row: DT, col: StkTableColumn<DT>) {
14
+ const isExpand = row?.__EXPANDED__ === col ? !row?.__EXPANDED__ : true;
15
+ setRowExpand(row, isExpand, { col });
16
+ }
17
+
18
+ /**
19
+ *
20
+ * @param rowKeyOrRow rowKey or row
21
+ * @param expand expand or collapse
22
+ * @param data { col?: StkTableColumn<DT> }
23
+ * @param data.silent if set true, not emit `toggle-row-expand`, default:false
24
+ */
25
+ function setRowExpand(rowKeyOrRow: string | undefined | DT, expand?: boolean, data?: { col?: StkTableColumn<DT>; silent?: boolean }) {
26
+ let rowKey: UniqKey;
27
+ if (typeof rowKeyOrRow === 'string') {
28
+ rowKey = rowKeyOrRow;
29
+ } else {
30
+ rowKey = rowKeyGen(rowKeyOrRow);
31
+ }
32
+ const tempData = dataSourceCopy.value.slice();
33
+ const index = tempData.findIndex(it => rowKeyGen(it) === rowKey);
34
+ if (index === -1) {
35
+ console.warn('expandRow failed.rowKey:', rowKey);
36
+ return;
37
+ }
38
+
39
+ // delete other expanded row below the target row
40
+ for (let i = index + 1; i < tempData.length; i++) {
41
+ const item: PrivateRowDT = tempData[i];
42
+ const rowKey = item.__ROW_KEY__;
43
+ if (rowKey?.startsWith(EXPANDED_ROW_KEY_PREFIX)) {
44
+ tempData.splice(i, 1);
45
+ i--;
46
+ } else {
47
+ break;
48
+ }
49
+ }
50
+
51
+ const row = tempData[index];
52
+ const col = data?.col || null;
53
+
54
+ if (expand) {
55
+ // insert new expanded row
56
+ const newExpandRow: ExpandedRow = {
57
+ __ROW_KEY__: EXPANDED_ROW_KEY_PREFIX + rowKey,
58
+ __EXPANDED_ROW__: row,
59
+ __EXPANDED_COL__: col,
60
+ };
61
+ tempData.splice(index + 1, 0, newExpandRow);
62
+ }
63
+
64
+ if (row) {
65
+ row.__EXPANDED__ = expand ? col : null;
66
+ }
67
+
68
+ dataSourceCopy.value = tempData;
69
+ if (!data?.silent) {
70
+ emits('toggle-row-expand', { expanded: Boolean(expand), row, col });
71
+ }
72
+ }
73
+
74
+ return {
75
+ toggleExpandRow,
76
+ setRowExpand,
77
+ };
78
+ }
@@ -1,102 +1,102 @@
1
- import { computed, ComputedRef } from 'vue';
2
- import { StkTableColumn, UniqKey } from './types';
3
- import { isEmptyValue } from './utils';
4
-
5
- type Params<T extends Record<string, any>> = {
6
- props: any;
7
- emits: any;
8
- colKeyGen: ComputedRef<(col: StkTableColumn<T>) => UniqKey>;
9
- };
10
- /**
11
- * 列顺序拖动
12
- * @returns
13
- */
14
- export function useThDrag<DT extends Record<string, any>>({ props, emits, colKeyGen }: Params<DT>) {
15
- const findParentTH = (e: DragEvent) => (e.target as HTMLElement).closest('th');
16
-
17
- const dragConfig = computed(() => {
18
- const headerDrag = props.headerDrag;
19
- const draggable = headerDrag !== false; // true or object
20
- return {
21
- draggable,
22
- mode: 'insert',
23
- disabled: () => false,
24
- ...headerDrag,
25
- };
26
- });
27
-
28
- /** 开始拖动记录th位置 */
29
- function onThDragStart(e: DragEvent) {
30
- const th = findParentTH(e);
31
- if (!th) return;
32
- const dragStartKey = th.dataset.colKey || '';
33
- const dt = e.dataTransfer;
34
- if (dt) {
35
- dt.effectAllowed = 'move';
36
- dt.setData('text/plain', dragStartKey);
37
- }
38
-
39
- emits('th-drag-start', dragStartKey);
40
- }
41
-
42
- function onThDragOver(e: DragEvent) {
43
- const th = findParentTH(e);
44
- if (!th) return;
45
-
46
- const isHeaderDraggable = th.getAttribute('draggable') === 'true';
47
- if (!isHeaderDraggable) return;
48
-
49
- const dt = e.dataTransfer;
50
- if (dt) {
51
- dt.dropEffect = 'move';
52
- }
53
- e.preventDefault();
54
- }
55
-
56
- /** th拖动释放时 */
57
- function onThDrop(e: DragEvent) {
58
- const th = findParentTH(e);
59
- if (!th) return;
60
- const dragStartKey = e.dataTransfer?.getData('text');
61
- if (dragStartKey !== th.dataset.colKey) {
62
- handleColOrderChange(dragStartKey, th.dataset.colKey);
63
- }
64
- emits('th-drop', th.dataset.colKey);
65
- }
66
-
67
- /** 列拖动交换顺序 */
68
- function handleColOrderChange(dragStartKey: string | undefined, dragEndKey: string | undefined) {
69
- if (isEmptyValue(dragStartKey) || isEmptyValue(dragEndKey)) return;
70
-
71
- if (dragConfig.value.mode !== 'none') {
72
- const columns: StkTableColumn<any>[] = props.columns.slice();
73
-
74
- const dragStartIndex = columns.findIndex(col => colKeyGen.value(col) === dragStartKey);
75
- const dragEndIndex = columns.findIndex(col => colKeyGen.value(col) === dragEndKey);
76
-
77
- if (dragStartIndex === -1 || dragEndIndex === -1) return;
78
-
79
- const dragStartCol = columns[dragStartIndex];
80
- // if mode is none, do nothing
81
- if (dragConfig.value.mode === 'swap') {
82
- columns[dragStartIndex] = columns[dragEndIndex];
83
- columns[dragEndIndex] = dragStartCol;
84
- } else {
85
- // default is insert
86
- columns.splice(dragStartIndex, 1);
87
- columns.splice(dragEndIndex, 0, dragStartCol);
88
- }
89
- emits('update:columns', columns);
90
- }
91
-
92
- emits('col-order-change', dragStartKey, dragEndKey);
93
- }
94
-
95
- return {
96
- onThDragStart,
97
- onThDragOver,
98
- onThDrop,
99
- /** 是否可拖拽 */
100
- isHeaderDraggable: (col: StkTableColumn<DT>) => dragConfig.value.draggable && !dragConfig.value.disabled(col),
101
- };
102
- }
1
+ import { computed, ComputedRef } from 'vue';
2
+ import { StkTableColumn, UniqKey } from './types';
3
+ import { isEmptyValue } from './utils';
4
+
5
+ type Params<T extends Record<string, any>> = {
6
+ props: any;
7
+ emits: any;
8
+ colKeyGen: ComputedRef<(col: StkTableColumn<T>) => UniqKey>;
9
+ };
10
+ /**
11
+ * 列顺序拖动
12
+ * @returns
13
+ */
14
+ export function useThDrag<DT extends Record<string, any>>({ props, emits, colKeyGen }: Params<DT>) {
15
+ const findParentTH = (e: DragEvent) => (e.target as HTMLElement).closest('th');
16
+
17
+ const dragConfig = computed(() => {
18
+ const headerDrag = props.headerDrag;
19
+ const draggable = headerDrag !== false; // true or object
20
+ return {
21
+ draggable,
22
+ mode: 'insert',
23
+ disabled: () => false,
24
+ ...headerDrag,
25
+ };
26
+ });
27
+
28
+ /** 开始拖动记录th位置 */
29
+ function onThDragStart(e: DragEvent) {
30
+ const th = findParentTH(e);
31
+ if (!th) return;
32
+ const dragStartKey = th.dataset.colKey || '';
33
+ const dt = e.dataTransfer;
34
+ if (dt) {
35
+ dt.effectAllowed = 'move';
36
+ dt.setData('text/plain', dragStartKey);
37
+ }
38
+
39
+ emits('th-drag-start', dragStartKey);
40
+ }
41
+
42
+ function onThDragOver(e: DragEvent) {
43
+ const th = findParentTH(e);
44
+ if (!th) return;
45
+
46
+ const isHeaderDraggable = th.getAttribute('draggable') === 'true';
47
+ if (!isHeaderDraggable) return;
48
+
49
+ const dt = e.dataTransfer;
50
+ if (dt) {
51
+ dt.dropEffect = 'move';
52
+ }
53
+ e.preventDefault();
54
+ }
55
+
56
+ /** th拖动释放时 */
57
+ function onThDrop(e: DragEvent) {
58
+ const th = findParentTH(e);
59
+ if (!th) return;
60
+ const dragStartKey = e.dataTransfer?.getData('text');
61
+ if (dragStartKey !== th.dataset.colKey) {
62
+ handleColOrderChange(dragStartKey, th.dataset.colKey);
63
+ }
64
+ emits('th-drop', th.dataset.colKey);
65
+ }
66
+
67
+ /** 列拖动交换顺序 */
68
+ function handleColOrderChange(dragStartKey: string | undefined, dragEndKey: string | undefined) {
69
+ if (isEmptyValue(dragStartKey) || isEmptyValue(dragEndKey)) return;
70
+
71
+ if (dragConfig.value.mode !== 'none') {
72
+ const columns: StkTableColumn<any>[] = props.columns.slice();
73
+
74
+ const dragStartIndex = columns.findIndex(col => colKeyGen.value(col) === dragStartKey);
75
+ const dragEndIndex = columns.findIndex(col => colKeyGen.value(col) === dragEndKey);
76
+
77
+ if (dragStartIndex === -1 || dragEndIndex === -1) return;
78
+
79
+ const dragStartCol = columns[dragStartIndex];
80
+ // if mode is none, do nothing
81
+ if (dragConfig.value.mode === 'swap') {
82
+ columns[dragStartIndex] = columns[dragEndIndex];
83
+ columns[dragEndIndex] = dragStartCol;
84
+ } else {
85
+ // default is insert
86
+ columns.splice(dragStartIndex, 1);
87
+ columns.splice(dragEndIndex, 0, dragStartCol);
88
+ }
89
+ emits('update:columns', columns);
90
+ }
91
+
92
+ emits('col-order-change', dragStartKey, dragEndKey);
93
+ }
94
+
95
+ return {
96
+ onThDragStart,
97
+ onThDragOver,
98
+ onThDrop,
99
+ /** 是否可拖拽 */
100
+ isHeaderDraggable: (col: StkTableColumn<DT>) => dragConfig.value.draggable && !dragConfig.value.disabled(col),
101
+ };
102
+ }