stk-table-vue 1.0.0-beta.5 → 1.0.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.
Files changed (71) hide show
  1. package/README.md +174 -173
  2. package/lib/{Dropdown-Clc70S1z.js → Dropdown-wEI6qpCx.js} +2 -2
  3. package/lib/{StkTable-QUd4TJCF.js → StkTable-BK4VNsvG.js} +124 -20
  4. package/lib/src/StkTable/custom-cells/ChangeCell/createChangeCell.d.ts +55 -0
  5. package/lib/src/StkTable/custom-cells/ChangeCell/index.d.ts +2 -0
  6. package/lib/src/StkTable/custom-cells/NumberCell/createNumberCell.d.ts +44 -0
  7. package/lib/src/StkTable/custom-cells/NumberCell/index.d.ts +2 -0
  8. package/lib/src/StkTable/custom-cells/utils/formatNumber.d.ts +35 -0
  9. package/lib/src/StkTable/index.d.ts +7 -1
  10. package/lib/stk-table-vue.js +192 -12
  11. package/lib/style.css +41 -10
  12. package/package.json +89 -85
  13. package/src/StkTable/StkTable.vue +1849 -1849
  14. package/src/StkTable/components/DragHandle.vue +9 -9
  15. package/src/StkTable/components/SortIcon.vue +6 -6
  16. package/src/StkTable/components/TreeNodeCell.vue +19 -19
  17. package/src/StkTable/components/TriangleIcon.vue +3 -3
  18. package/src/StkTable/const.ts +50 -50
  19. package/src/StkTable/custom-cells/ChangeCell/ChangeCell.less +34 -0
  20. package/src/StkTable/custom-cells/ChangeCell/createChangeCell.ts +90 -0
  21. package/src/StkTable/custom-cells/ChangeCell/index.ts +4 -0
  22. package/src/StkTable/custom-cells/CheckboxCell/{Checkbox.less → CheckboxCell.less} +14 -14
  23. package/src/StkTable/custom-cells/CheckboxCell/{Checkbox.vue → CheckboxCell.vue} +56 -41
  24. package/src/StkTable/custom-cells/CheckboxCell/createCheckboxCell.ts +146 -146
  25. package/src/StkTable/custom-cells/CheckboxCell/index.ts +5 -5
  26. package/src/StkTable/custom-cells/EditableCell/EditableCell.less +1 -0
  27. package/src/StkTable/custom-cells/FilterCell/Dropdown/index.ts +16 -16
  28. package/src/StkTable/custom-cells/FilterCell/Dropdown/index.vue +184 -184
  29. package/src/StkTable/custom-cells/FilterCell/Filter.less +118 -118
  30. package/src/StkTable/custom-cells/FilterCell/Filter.vue +66 -66
  31. package/src/StkTable/custom-cells/FilterCell/createFilterCell.ts +120 -120
  32. package/src/StkTable/custom-cells/FilterCell/index.ts +6 -6
  33. package/src/StkTable/custom-cells/FilterCell/types.ts +43 -43
  34. package/src/StkTable/custom-cells/NumberCell/createNumberCell.ts +43 -0
  35. package/src/StkTable/custom-cells/NumberCell/index.ts +2 -0
  36. package/src/StkTable/custom-cells/utils/formatNumber.ts +137 -0
  37. package/src/StkTable/features/const.ts +1 -1
  38. package/src/StkTable/features/index.ts +1 -1
  39. package/src/StkTable/features/useAreaSelection.bak.ts +951 -951
  40. package/src/StkTable/features/useAreaSelection.ts +1224 -1079
  41. package/src/StkTable/index.ts +20 -14
  42. package/src/StkTable/registerFeature.ts +40 -40
  43. package/src/StkTable/style.less +776 -767
  44. package/src/StkTable/types/highlightDimOptions.ts +28 -28
  45. package/src/StkTable/types/index.ts +452 -452
  46. package/src/StkTable/useAutoResize.ts +87 -87
  47. package/src/StkTable/useColResize.ts +202 -202
  48. package/src/StkTable/useFixedCol.ts +142 -142
  49. package/src/StkTable/useFixedStyle.ts +75 -75
  50. package/src/StkTable/useGetFixedColPosition.ts +63 -63
  51. package/src/StkTable/useHighlight.ts +270 -270
  52. package/src/StkTable/useIndexResolver.ts +29 -29
  53. package/src/StkTable/useKeyboardArrowScroll.ts +114 -114
  54. package/src/StkTable/useMaxRowSpan.ts +50 -50
  55. package/src/StkTable/useMergeCells.ts +138 -138
  56. package/src/StkTable/useRowExpand.ts +81 -81
  57. package/src/StkTable/useScrollRowByRow.ts +96 -96
  58. package/src/StkTable/useScrollbar.ts +177 -177
  59. package/src/StkTable/useSorter.ts +259 -259
  60. package/src/StkTable/useTableColumns.ts +131 -131
  61. package/src/StkTable/useThDrag.ts +94 -94
  62. package/src/StkTable/useTrDrag.ts +100 -100
  63. package/src/StkTable/useTree.ts +152 -152
  64. package/src/StkTable/useVirtualScroll.ts +693 -693
  65. package/src/StkTable/useWheeling.ts +23 -23
  66. package/src/StkTable/utils/constRefUtils.ts +29 -29
  67. package/src/StkTable/utils/useTriggerRef.ts +33 -33
  68. package/src/VirtualTree.vue +622 -622
  69. package/src/VirtualTreeSelect.vue +367 -367
  70. package/src/vite-env.d.ts +10 -10
  71. /package/lib/src/StkTable/custom-cells/CheckboxCell/{Checkbox.vue.d.ts → CheckboxCell.vue.d.ts} +0 -0
package/README.md CHANGED
@@ -1,173 +1,174 @@
1
- <p align="center">
2
- <a href="https://ja-plus.github.io/stk-table-vue/">
3
- <img src="./docs-src/public/assets/logo.svg" width="152">
4
- </a>
5
- <h3 align='center'>Stk Table Vue</h3>
6
- <p align="center">
7
- <a href="https://www.npmjs.com/package/stk-table-vue"><img src="https://img.shields.io/npm/v/stk-table-vue"></a>
8
- <a href="https://www.npmjs.com/package/stk-table-vue"><img src="https://img.shields.io/npm/dw/stk-table-vue"></a>
9
- <a href="https://github.com/ja-plus/stk-table-vue/stargazers"><img src="https://img.shields.io/github/stars/ja-plus/stk-table-vue.svg"></a>
10
- <a href="https://raw.githubusercontent.com/ja-plus/stk-table-vue/master/LICENSE"><img src="https://img.shields.io/npm/l/stk-table-vue"></a>
11
- <a href="https://github.com/ja-plus/stk-table-vue"><img src="https://img.shields.io/npm/types/stk-table-vue"></a>
12
- </p>
13
- </p>
14
-
15
- Stk Table Vue(Sticky Table) is a high-performance virtual list component based on Vue.
16
-
17
- Smooth performance with tens of thousands of rows
18
-
19
- Used for real-time data display, with data highlighting and dynamic effects.
20
-
21
- Support Vue3 and Vue2.7
22
-
23
-
24
- ## Documentation
25
- ### [Stk Table Vue Official](https://ja-plus.github.io/stk-table-vue/)
26
-
27
-
28
- ## Repo:
29
- - [Github](https://github.com/ja-plus/stk-table-vue)
30
- - [Gitee](https://gitee.com/japlus/stk-table-vue)
31
-
32
- ## Demo
33
- [<span style="font-size: 16px;font-weight: bold;">Online Demo in stackblitz</span>](https://stackblitz.com/edit/vitejs-vite-ad91hh?file=src%2FDemo%2Findex.vue)
34
-
35
- ## Usage
36
- > npm install stk-table-vue
37
-
38
- ```html
39
- <script setup>
40
- import { StkTable } from 'stk-table-vue'
41
- import { ref, useTemplateRef } from 'vue'
42
- const stkTableRef = ref<InstanceType<typeof StkTable>>();
43
- // or Vue 3.5 useTemplateRef
44
- const stkTableRef = useTemplateRef('stkTableRef');
45
-
46
- // highlight row
47
- stkTableRef.value.setHighlightDimRow([rowKey], {
48
- method: 'css' | 'animation', // default animation
49
- className: 'custom-class-name', // for method 'css'
50
- keyframe: [{ backgroundColor: '#aaa' }, { backgroundColor: '#222' }], // same as https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Animations_API/Keyframe_Formats
51
- duration: 2000,
52
- });
53
- // highlight cell
54
- stkTableRef.value.setHighlightDimCell(rowKey, colDataIndex, {
55
- method: 'css' | 'animation',
56
- className: 'custom-class-name', // for method 'css'
57
- keyframe: [{ backgroundColor: '#aaa' }, { backgroundColor: '#222' }], // for method 'animation'
58
- duration: 2000,
59
- });
60
-
61
- const columns = [
62
- {title: 'name', dataIndex: 'name'},
63
- {title: 'age', dataIndex: 'age'},
64
- {title: 'address', dataIndex: 'address'},
65
- ];
66
-
67
- const dataSource = [
68
- {id: 1, name: 'John', age: 32, address: 'New York'},
69
- {id: 2, name: 'Jim', age: 42, address: 'London'},
70
- {id: 3, name: 'Joe', age: 52, address: 'Tokyo'},
71
- {id: 4, name: 'Jack', age: 62, address: 'Sydney'},
72
- {id: 5, name: 'Jill', age: 72, address: 'Paris'},
73
- ]
74
-
75
- </script>
76
-
77
- <template>
78
- <StkTable ref='stkTableRef' row-key="id" :data-source="dataSource" :columns="columns"></StkTable>
79
- </template>
80
-
81
- ```
82
-
83
- ### Vue2.7 Usage
84
- [Vue2.7 Usage](https://ja-plus.github.io/stk-table-vue/main/start/vue2-usage.html)
85
-
86
- ## API
87
- * [Props](https://ja-plus.github.io/stk-table-vue/main/api/table-props.html)
88
-
89
- * [Emits](https://ja-plus.github.io/stk-table-vue/main/api/emits.html)
90
-
91
- * [Slots](https://ja-plus.github.io/stk-table-vue/main/api/slots.html)
92
-
93
- * [Expose](https://ja-plus.github.io/stk-table-vue/main/api/expose.html)
94
-
95
- * [StkTableColumn: Define column type](https://ja-plus.github.io/stk-table-vue/main/api/stk-table-column.html)
96
-
97
- * [Highlight: setHighlightDimCell & setHighlightDimRow](https://ja-plus.github.io/stk-table-vue/main/api/expose.html#sethighlightdimcell)
98
-
99
-
100
- ### Example
101
- ```vue
102
- <template>
103
- <StkTable
104
- ref="stkTable"
105
- row-key="name"
106
- v-model:columns="columns"
107
- :style="{height:props.height}"
108
- theme='dark'
109
- height='200px'
110
- bordered="h"
111
- :row-height="28"
112
- :show-overflow="false"
113
- :show-header-overflow="false"
114
- :sort-remote="false"
115
- col-resizable
116
- header-drag
117
- virtual
118
- virtual-x
119
- no-data-full
120
- col-resizable
121
- auto-resize
122
- fixed-col-shadow
123
- :col-min-width="10"
124
- :headless="false"
125
- :data-source="dataSource"
126
- @current-change="onCurrentChange"
127
- @row-menu="onRowMenu"
128
- @header-row-menu="onHeaderRowMenu"
129
- @row-click="onRowClick"
130
- @row-dblclick="onRowDblclick"
131
- @sort-change="handleSortChange"
132
- @cell-click="onCellClick"
133
- @header-cell-click="onHeaderCellClick"
134
- @scroll="onTableScroll"
135
- @scroll-x="onTableScrollX"
136
- @col-order-change="onColOrderChange"
137
- />
138
- </template>
139
- <script setup>
140
- import { h, defineComponent } from 'vue';
141
- const columns = [
142
- {
143
- title: 'Name',
144
- dataIndex: 'name',
145
- fixed: 'left',
146
- width: '200px',
147
- headerClassName: 'my-th',
148
- className: 'my-td',
149
- sorter: true,
150
- customHeaderCell: function FunctionalComponent(props){
151
- return h(
152
- 'span',
153
- { style: 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap' },
154
- props.col.title + '(render) text-overflow,',
155
- );
156
- },
157
- customCell: defineComponent({
158
- setup(){
159
- //...
160
- return () => <div></div> // vue jsx
161
- }
162
- })
163
- },
164
- ]
165
- </script>
166
- ```
167
-
168
- ## Compare
169
- Compare performance with other vue table [vue-table-compare](https://github.com/ja-plus/vue-table-compare)
170
-
171
-
172
- ## Other
173
- * `$*$`
1
+ <p align="center">
2
+ <a href="https://ja-plus.github.io/stk-table-vue/">
3
+ <img src="./docs-src/public/assets/logo.svg" width="152">
4
+ </a>
5
+ <h3 align='center'>Stk Table Vue</h3>
6
+ <p align="center">
7
+ <a href="https://www.npmjs.com/package/stk-table-vue"><img src="https://img.shields.io/npm/v/stk-table-vue"></a>
8
+ <a href="https://www.npmjs.com/package/stk-table-vue"><img src="https://img.shields.io/npm/dw/stk-table-vue"></a>
9
+ <a href="https://github.com/ja-plus/stk-table-vue/stargazers"><img src="https://img.shields.io/github/stars/ja-plus/stk-table-vue.svg"></a>
10
+ <a href="https://raw.githubusercontent.com/ja-plus/stk-table-vue/master/LICENSE"><img src="https://img.shields.io/npm/l/stk-table-vue"></a>
11
+ <a href="https://github.com/ja-plus/stk-table-vue"><img src="https://img.shields.io/npm/types/stk-table-vue"></a>
12
+ </p>
13
+ </p>
14
+
15
+ Stk Table Vue(Sticky Table) is a high-performance virtual list component based on Vue.
16
+
17
+ Smooth performance with tens of thousands of rows
18
+
19
+ Used for real-time data display, with data highlighting and dynamic effects.
20
+
21
+ Support Vue3 and Vue2.7
22
+
23
+
24
+ ## Documentation
25
+ ### [Stk Table Vue Official](https://ja-plus.github.io/stk-table-vue/)
26
+ ### [Stk Table React Official](https://ja-plus.github.io/stk-table-react/)
27
+
28
+
29
+ ## Repo:
30
+ - [Github](https://github.com/ja-plus/stk-table-vue)
31
+ - [Gitee](https://gitee.com/japlus/stk-table-vue)
32
+
33
+ ## Demo
34
+ [<span style="font-size: 16px;font-weight: bold;">Online Demo in stackblitz</span>](https://stackblitz.com/edit/vitejs-vite-ad91hh?file=src%2FDemo%2Findex.vue)
35
+
36
+ ## Usage
37
+ > npm install stk-table-vue
38
+
39
+ ```html
40
+ <script setup>
41
+ import { StkTable } from 'stk-table-vue'
42
+ import { ref, useTemplateRef } from 'vue'
43
+ const stkTableRef = ref<InstanceType<typeof StkTable>>();
44
+ // or Vue 3.5 useTemplateRef
45
+ const stkTableRef = useTemplateRef('stkTableRef');
46
+
47
+ // highlight row
48
+ stkTableRef.value.setHighlightDimRow([rowKey], {
49
+ method: 'css' | 'animation', // default animation
50
+ className: 'custom-class-name', // for method 'css'
51
+ keyframe: [{ backgroundColor: '#aaa' }, { backgroundColor: '#222' }], // same as https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Animations_API/Keyframe_Formats
52
+ duration: 2000,
53
+ });
54
+ // highlight cell
55
+ stkTableRef.value.setHighlightDimCell(rowKey, colDataIndex, {
56
+ method: 'css' | 'animation',
57
+ className: 'custom-class-name', // for method 'css'
58
+ keyframe: [{ backgroundColor: '#aaa' }, { backgroundColor: '#222' }], // for method 'animation'
59
+ duration: 2000,
60
+ });
61
+
62
+ const columns = [
63
+ {title: 'name', dataIndex: 'name'},
64
+ {title: 'age', dataIndex: 'age'},
65
+ {title: 'address', dataIndex: 'address'},
66
+ ];
67
+
68
+ const dataSource = [
69
+ {id: 1, name: 'John', age: 32, address: 'New York'},
70
+ {id: 2, name: 'Jim', age: 42, address: 'London'},
71
+ {id: 3, name: 'Joe', age: 52, address: 'Tokyo'},
72
+ {id: 4, name: 'Jack', age: 62, address: 'Sydney'},
73
+ {id: 5, name: 'Jill', age: 72, address: 'Paris'},
74
+ ]
75
+
76
+ </script>
77
+
78
+ <template>
79
+ <StkTable ref='stkTableRef' row-key="id" :data-source="dataSource" :columns="columns"></StkTable>
80
+ </template>
81
+
82
+ ```
83
+
84
+ ### Vue2.7 Usage
85
+ [Vue2.7 Usage](https://ja-plus.github.io/stk-table-vue/main/start/vue2-usage.html)
86
+
87
+ ## API
88
+ * [Props](https://ja-plus.github.io/stk-table-vue/main/api/table-props.html)
89
+
90
+ * [Emits](https://ja-plus.github.io/stk-table-vue/main/api/emits.html)
91
+
92
+ * [Slots](https://ja-plus.github.io/stk-table-vue/main/api/slots.html)
93
+
94
+ * [Expose](https://ja-plus.github.io/stk-table-vue/main/api/expose.html)
95
+
96
+ * [StkTableColumn: Define column type](https://ja-plus.github.io/stk-table-vue/main/api/stk-table-column.html)
97
+
98
+ * [Highlight: setHighlightDimCell & setHighlightDimRow](https://ja-plus.github.io/stk-table-vue/main/api/expose.html#sethighlightdimcell)
99
+
100
+
101
+ ### Example
102
+ ```vue
103
+ <template>
104
+ <StkTable
105
+ ref="stkTable"
106
+ row-key="name"
107
+ v-model:columns="columns"
108
+ :style="{height:props.height}"
109
+ theme='dark'
110
+ height='200px'
111
+ bordered="h"
112
+ :row-height="28"
113
+ :show-overflow="false"
114
+ :show-header-overflow="false"
115
+ :sort-remote="false"
116
+ col-resizable
117
+ header-drag
118
+ virtual
119
+ virtual-x
120
+ no-data-full
121
+ col-resizable
122
+ auto-resize
123
+ fixed-col-shadow
124
+ :col-min-width="10"
125
+ :headless="false"
126
+ :data-source="dataSource"
127
+ @current-change="onCurrentChange"
128
+ @row-menu="onRowMenu"
129
+ @header-row-menu="onHeaderRowMenu"
130
+ @row-click="onRowClick"
131
+ @row-dblclick="onRowDblclick"
132
+ @sort-change="handleSortChange"
133
+ @cell-click="onCellClick"
134
+ @header-cell-click="onHeaderCellClick"
135
+ @scroll="onTableScroll"
136
+ @scroll-x="onTableScrollX"
137
+ @col-order-change="onColOrderChange"
138
+ />
139
+ </template>
140
+ <script setup>
141
+ import { h, defineComponent } from 'vue';
142
+ const columns = [
143
+ {
144
+ title: 'Name',
145
+ dataIndex: 'name',
146
+ fixed: 'left',
147
+ width: '200px',
148
+ headerClassName: 'my-th',
149
+ className: 'my-td',
150
+ sorter: true,
151
+ customHeaderCell: function FunctionalComponent(props){
152
+ return h(
153
+ 'span',
154
+ { style: 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap' },
155
+ props.col.title + '(render) text-overflow,',
156
+ );
157
+ },
158
+ customCell: defineComponent({
159
+ setup(){
160
+ //...
161
+ return () => <div></div> // vue jsx
162
+ }
163
+ })
164
+ },
165
+ ]
166
+ </script>
167
+ ```
168
+
169
+ ## Compare
170
+ Compare performance with other vue table [vue-table-compare](https://github.com/ja-plus/vue-table-compare)
171
+
172
+
173
+ ## Other
174
+ * `$*$`
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * name: stk-table-vue
3
- * version: v1.0.0-beta.4
3
+ * version: v1.0.0
4
4
  * description: High performance realtime virtual table for vue3 and vue2.7
5
5
  * author: japlus
6
6
  * homepage: https://ja-plus.github.io/stk-table-vue/
7
7
  * license: MIT
8
8
  */
9
- import { t as StkTable_default } from "./StkTable-QUd4TJCF.js";
9
+ import { t as StkTable_default } from "./StkTable-BK4VNsvG.js";
10
10
  import { createElementBlock, createElementVNode, createVNode, defineComponent, h, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, reactive, ref, withModifiers } from "vue";
11
11
  //#region src/StkTable/custom-cells/FilterCell/Dropdown/index.vue?vue&type=script&setup=true&lang.ts
12
12
  var DROPDOWN_DEFAULT_WIDTH = 300;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * name: stk-table-vue
3
- * version: v1.0.0-beta.4
3
+ * version: v1.0.0
4
4
  * description: High performance realtime virtual table for vue3 and vue2.7
5
5
  * author: japlus
6
6
  * homepage: https://ja-plus.github.io/stk-table-vue/
@@ -347,12 +347,12 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
347
347
  const KEY_ESCAPE = "Escape";
348
348
  const KEY_ESC = "Esc";
349
349
  const KEY_C = "c";
350
- const CELL_RANGE_SELECTED = "cell-range-selected";
351
- const CELL_RANGE_TOP = "cell-range-t";
352
- const CELL_RANGE_BOTTOM = "cell-range-b";
353
- const CELL_RANGE_LEFT = "cell-range-l";
354
- const CELL_RANGE_RIGHT = "cell-range-r";
355
- const ROW_RANGE_SELECTED = "row-range-selected";
350
+ const ATTR_CELL_SELECTED = "data-cs-s";
351
+ const ATTR_CELL_TOP = "data-cs-t";
352
+ const ATTR_CELL_BOTTOM = "data-cs-b";
353
+ const ATTR_CELL_LEFT = "data-cs-l";
354
+ const ATTR_CELL_RIGHT = "data-cs-r";
355
+ const ATTR_ROW_SELECTED = "data-rs-s";
356
356
  const selectionRanges = ref([]);
357
357
  const isSelecting = ref(false);
358
358
  /** start cell */
@@ -478,10 +478,17 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
478
478
  if (!container) return;
479
479
  const cellHighlight = highlightCellEnabled.value;
480
480
  const rowHighlight = highlightRowEnabled.value;
481
- const oldSelectedCells = container.querySelectorAll(`.${CELL_RANGE_SELECTED}`);
482
- for (let i = 0; i < oldSelectedCells.length; i++) oldSelectedCells[i].classList.remove(CELL_RANGE_SELECTED, CELL_RANGE_TOP, CELL_RANGE_BOTTOM, CELL_RANGE_LEFT, CELL_RANGE_RIGHT);
483
- const oldSelectedRows = container.querySelectorAll(`.${ROW_RANGE_SELECTED}`);
484
- for (let i = 0; i < oldSelectedRows.length; i++) oldSelectedRows[i].classList.remove(ROW_RANGE_SELECTED);
481
+ const oldSelectedCells = container.querySelectorAll(`[${ATTR_CELL_SELECTED}]`);
482
+ for (let i = 0; i < oldSelectedCells.length; i++) {
483
+ const el = oldSelectedCells[i];
484
+ el.removeAttribute(ATTR_CELL_SELECTED);
485
+ el.removeAttribute(ATTR_CELL_TOP);
486
+ el.removeAttribute(ATTR_CELL_BOTTOM);
487
+ el.removeAttribute(ATTR_CELL_LEFT);
488
+ el.removeAttribute(ATTR_CELL_RIGHT);
489
+ }
490
+ const oldSelectedRows = container.querySelectorAll(`[${ATTR_ROW_SELECTED}]`);
491
+ for (let i = 0; i < oldSelectedRows.length; i++) oldSelectedRows[i].removeAttribute(ATTR_ROW_SELECTED);
485
492
  recomputeSelectedCellKeys();
486
493
  const ranges = selectionRanges.value;
487
494
  if (!ranges.length) return;
@@ -491,7 +498,7 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
491
498
  const { minRow, maxRow } = normalizeRange(range);
492
499
  for (let r = minRow; r <= maxRow; r++) {
493
500
  const tr = tbody.querySelector(`tr[data-row-i="${r}"]`);
494
- if (tr) tr.classList.add(ROW_RANGE_SELECTED);
501
+ if (tr) tr.setAttribute(ATTR_ROW_SELECTED, "");
495
502
  }
496
503
  }
497
504
  if (cellHighlight) {
@@ -521,12 +528,14 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
521
528
  if (!row || !cols[colIndex]) continue;
522
529
  const ck = cellKeyGen(row, cols[colIndex]);
523
530
  if (!selectedCellKeys.has(ck)) continue;
524
- td.classList.add(CELL_RANGE_SELECTED);
531
+ td.setAttribute(ATTR_CELL_SELECTED, "");
525
532
  if (rowIndex >= lrMinRow && rowIndex <= lrMaxRow && colIndex >= lrMinCol && colIndex <= lrMaxCol) {
526
- if (rowIndex === lrMinRow) td.classList.add(CELL_RANGE_TOP);
527
- if (rowIndex === lrMaxRow) td.classList.add(CELL_RANGE_BOTTOM);
528
- if (colIndex === lrMinCol) td.classList.add(CELL_RANGE_LEFT);
529
- if (colIndex === lrMaxCol) td.classList.add(CELL_RANGE_RIGHT);
533
+ const effEndRow = rowIndex + (parseInt(td.getAttribute("rowspan") || "1", 10) || 1) - 1;
534
+ const effEndCol = colIndex + (parseInt(td.getAttribute("colspan") || "1", 10) || 1) - 1;
535
+ if (rowIndex === lrMinRow) td.setAttribute(ATTR_CELL_TOP, "");
536
+ if (effEndRow === lrMaxRow) td.setAttribute(ATTR_CELL_BOTTOM, "");
537
+ if (colIndex === lrMinCol) td.setAttribute(ATTR_CELL_LEFT, "");
538
+ if (effEndCol === lrMaxCol) td.setAttribute(ATTR_CELL_RIGHT, "");
530
539
  }
531
540
  }
532
541
  }
@@ -642,6 +651,92 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
642
651
  if (!colKey) return -1;
643
652
  return colKeyToIndexMap.value.get(colKey) ?? -1;
644
653
  }
654
+ /** 获取指定单元格的合并信息 [rowspan, colspan],无合并返回 [1, 1] */
655
+ function getMergeSpan(rowIndex, colIndex) {
656
+ const data = dataSourceCopy.value;
657
+ const cols = tableHeaderLast.value;
658
+ const row = data[rowIndex];
659
+ const col = cols[colIndex];
660
+ if (!row || !col || !col.mergeCells) return [1, 1];
661
+ const { rowspan = 1, colspan = 1 } = col.mergeCells({
662
+ row,
663
+ col,
664
+ rowIndex,
665
+ colIndex
666
+ }) || {};
667
+ return [rowspan || 1, colspan || 1];
668
+ }
669
+ /**
670
+ * 扩展选区范围,使其完整覆盖边界上部分选中的合并单元格
671
+ * en: Expand selection range to fully cover merged cells that are partially selected at boundaries
672
+ */
673
+ function expandRangeToCoverMergedCells(range) {
674
+ const { minRow, maxRow, minCol, maxCol } = normalizeRange(range);
675
+ const data = dataSourceCopy.value;
676
+ const cols = tableHeaderLast.value;
677
+ const rowCount = data.length;
678
+ const colCount = cols.length;
679
+ const mergeColIndices = [];
680
+ for (let c = 0; c < colCount; c++) {
681
+ var _cols$c;
682
+ if ((_cols$c = cols[c]) === null || _cols$c === void 0 ? void 0 : _cols$c.mergeCells) mergeColIndices.push(c);
683
+ }
684
+ if (!mergeColIndices.length) return range;
685
+ let [eMinRow, eMaxRow, eMinCol, eMaxCol] = [
686
+ minRow,
687
+ maxRow,
688
+ minCol,
689
+ maxCol
690
+ ];
691
+ let changed = true;
692
+ let guard = 0;
693
+ while (changed && guard++ < 100) {
694
+ changed = false;
695
+ for (const c of mergeColIndices) {
696
+ if (c < eMinCol || c > eMaxCol) continue;
697
+ const [rs] = getMergeSpan(eMaxRow, c);
698
+ if (rs > 1 && eMaxRow + rs - 1 < rowCount && eMaxRow + rs - 1 > eMaxRow) {
699
+ eMaxRow = eMaxRow + rs - 1;
700
+ changed = true;
701
+ }
702
+ }
703
+ for (let r = eMinRow; r <= eMaxRow; r++) {
704
+ const [, cs] = getMergeSpan(r, eMaxCol);
705
+ if (cs > 1 && eMaxCol + cs - 1 < colCount && eMaxCol + cs - 1 > eMaxCol) {
706
+ eMaxCol = eMaxCol + cs - 1;
707
+ changed = true;
708
+ }
709
+ }
710
+ for (const c of mergeColIndices) {
711
+ if (c < eMinCol || c > eMaxCol) continue;
712
+ for (let r = eMinRow - 1; r >= 0 && r > eMinRow - 500; r--) {
713
+ const [rs] = getMergeSpan(r, c);
714
+ if (rs <= 1) continue;
715
+ if (r + rs - 1 >= eMinRow) {
716
+ if (r < eMinRow) {
717
+ eMinRow = r;
718
+ changed = true;
719
+ }
720
+ } else break;
721
+ }
722
+ }
723
+ for (let r = eMinRow; r <= eMaxRow; r++) for (let c = eMinCol - 1; c >= 0 && c > eMinCol - 500; c--) {
724
+ const [, cs] = getMergeSpan(r, c);
725
+ if (cs <= 1) continue;
726
+ if (c + cs - 1 >= eMinCol) {
727
+ if (c < eMinCol) {
728
+ eMinCol = c;
729
+ changed = true;
730
+ }
731
+ } else break;
732
+ }
733
+ }
734
+ if (eMinRow === minRow && eMaxRow === maxRow && eMinCol === minCol && eMaxCol === maxCol) return range;
735
+ const { begin, end } = range.index;
736
+ const newBeginRow = begin.row < end.row || begin.row === end.row ? eMinRow : eMaxRow;
737
+ const newEndRow = begin.row < end.row || begin.row === end.row ? eMaxRow : eMinRow;
738
+ return makeRange(newBeginRow, begin.col <= end.col ? eMinCol : eMaxCol, newEndRow, begin.col <= end.col ? eMaxCol : eMinCol);
739
+ }
645
740
  /** 获取列的左边距和宽度
646
741
  * @param colIndex 列的绝对索引
647
742
  * @returns [left, width]
@@ -720,10 +815,10 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
720
815
  const colIndex = getColIndexByKey(getClosestColKey(e.target));
721
816
  if (rowIndex < 0 || colIndex < 0) return;
722
817
  const ctrlKey = e.ctrlKey || e.metaKey;
723
- const range = makeRange(rowIndex, colIndex, rowIndex, colIndex);
818
+ const range = expandRangeToCoverMergedCells(makeRange(rowIndex, colIndex, rowIndex, colIndex));
724
819
  if (e.shiftKey && anchorCell && shiftEnabled.value) {
725
820
  const ranges = selectionRanges.value.slice();
726
- const shiftRange = makeRange(anchorCell.rowIndex, anchorCell.colIndex, rowIndex, colIndex);
821
+ const shiftRange = expandRangeToCoverMergedCells(makeRange(anchorCell.rowIndex, anchorCell.colIndex, rowIndex, colIndex));
727
822
  if (ranges.length) ranges[ranges.length - 1] = shiftRange;
728
823
  else ranges.push(shiftRange);
729
824
  selectionRanges.value = ranges;
@@ -762,7 +857,7 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
762
857
  /** 更新最后一个选区的终点(拖拽过程中) */
763
858
  function updateSelectionEnd(endRowIndex, endColIndex) {
764
859
  if (!anchorCell) return;
765
- const newRange = makeRange(anchorCell.rowIndex, anchorCell.colIndex, endRowIndex, endColIndex);
860
+ const newRange = expandRangeToCoverMergedCells(makeRange(anchorCell.rowIndex, anchorCell.colIndex, endRowIndex, endColIndex));
766
861
  const ranges = [...selectionRanges.value];
767
862
  if (ranges.length > 0) ranges[ranges.length - 1] = newRange;
768
863
  else ranges.push(newRange);
@@ -825,6 +920,15 @@ function useAreaSelection(props, emits, tableContainerRef, dataSourceCopy, table
825
920
  stopAutoScroll();
826
921
  document.removeEventListener("mousemove", onDocumentMouseMove);
827
922
  document.removeEventListener("mouseup", onDocumentMouseUp);
923
+ const ranges = selectionRanges.value;
924
+ if (ranges.length) {
925
+ const expanded = expandRangeToCoverMergedCells(ranges[ranges.length - 1]);
926
+ if (expanded !== ranges[ranges.length - 1]) {
927
+ const newRanges = [...ranges];
928
+ newRanges[newRanges.length - 1] = expanded;
929
+ selectionRanges.value = newRanges;
930
+ }
931
+ }
828
932
  emitSelectionChange();
829
933
  }
830
934
  function emitSelectionChange() {
@@ -0,0 +1,55 @@
1
+ import { FormatNumberOptions } from '../utils/formatNumber';
2
+
3
+ /** createChangeCell 配置选项 */
4
+ export interface CreateChangeCellOptions extends FormatNumberOptions {
5
+ /** 涨跌颜色是否反转:false=A股(涨红跌绿,默认),true=国际(涨绿跌红) */
6
+ colorReverse?: boolean;
7
+ /** 是否显示涨跌箭头 ▲/▼,默认 false */
8
+ arrow?: boolean;
9
+ /** 自定义上涨颜色(覆盖默认配色,传入后不受 colorReverse 影响) */
10
+ riseColor?: string;
11
+ /** 自定义下跌颜色 */
12
+ fallColor?: string;
13
+ /** 自定义平盘颜色 */
14
+ flatColor?: string;
15
+ }
16
+ /**
17
+ * 涨跌单元格工厂函数
18
+ *
19
+ * 在 {@link formatNumber} 的基础上叠加涨跌染色与箭头。染色按 `cellValue` 正负判断,
20
+ * 颜色方向可通过 `colorReverse` 切换(A股 / 国际),也可用 `riseColor` 等自定义。
21
+ * 数字对齐请在列配置上设置 `align: 'right'`。
22
+ *
23
+ * @param options 格式化 + 染色/箭头选项
24
+ * @returns `ChangeCell` 组件构造函数,使用时需调用一次:`customCell: ChangeCell()`
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * const { ChangeCell } = createChangeCell({ decimals: 2, showSign: true, arrow: true });
29
+ * const ChangeCellComp = ChangeCell();
30
+ * const columns = [
31
+ * { title: '涨跌额', dataIndex: 'change', align: 'right', customCell: ChangeCellComp },
32
+ * ];
33
+ * ```
34
+ */
35
+ export declare function createChangeCell(options?: CreateChangeCellOptions): {
36
+ ChangeCell: () => import('vue').Raw<import('vue').DefineComponent<{
37
+ row: any;
38
+ col: import('../..').StkTableColumn<any>;
39
+ cellValue: any;
40
+ rowIndex: number;
41
+ colIndex: number;
42
+ expanded?: import('../..').StkTableColumn<any> | undefined;
43
+ treeExpanded?: boolean | undefined;
44
+ }, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
45
+ [key: string]: any;
46
+ }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
47
+ row: any;
48
+ col: import('../..').StkTableColumn<any>;
49
+ cellValue: any;
50
+ rowIndex: number;
51
+ colIndex: number;
52
+ expanded?: import('../..').StkTableColumn<any> | undefined;
53
+ treeExpanded?: boolean | undefined;
54
+ }> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>>;
55
+ };
@@ -0,0 +1,2 @@
1
+ export { createChangeCell } from './createChangeCell';
2
+ export type { CreateChangeCellOptions } from './createChangeCell';