stk-table-vue 0.3.1 → 0.3.3

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.
@@ -14,6 +14,7 @@
14
14
  --border-color: #e8e8f4;
15
15
  --border-width: 1px;
16
16
  --td-bgc: #fff;
17
+ --td-hover-color: #71a2fd;
17
18
  --th-bgc: #fafafc;
18
19
  --th-color: #272841;
19
20
  --tr-active-bgc: rgb(230, 247, 255);
@@ -48,11 +49,13 @@
48
49
  border-left: 1px solid var(--border-color);
49
50
  /* 下面border用于表格内容不满高度时,绘制表格边界线 */
50
51
  background-image: var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
52
+
51
53
  /**深色模式 */
52
54
  &.dark {
53
55
  --th-bgc: #202029;
54
56
  --th-color: #C0C0D1;
55
57
  --td-bgc: #1b1b24;
58
+ --td-hover-color: #70a6ff;
56
59
  --border-color: #292933;
57
60
  --tr-active-bgc: #283f63;
58
61
  --tr-hover-bgc: #1a2b46;
@@ -113,28 +116,8 @@
113
116
  background-image: var(--bg-border-right), var(--bg-border-bottom);
114
117
  }
115
118
 
116
- thead {
117
- tr {
118
- &:first-child th {
119
- background-image: var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
120
- }
121
-
122
- }
123
- }
124
-
125
-
126
- &.virtual-x {
127
- .virtual-x-left {
128
- background: none;
129
- pointer-events: none;
130
- }
131
-
132
- .virtual-x-right {
133
- padding: 0;
134
- background: none;
135
- pointer-events: none;
136
- }
137
-
119
+ thead tr:first-child th {
120
+ background-image: var(--bg-border-top), var(--bg-border-right), var(--bg-border-bottom);
138
121
  }
139
122
  }
140
123
 
@@ -144,240 +127,269 @@
144
127
  }
145
128
  }
146
129
 
130
+ /* 斑马纹*/
147
131
  &.stripe {
148
132
 
149
- /* 斑马纹*/
150
- tbody {
151
- tr:nth-child(odd) {
152
- background-color: var(--stripe-bgc);
153
- }
133
+ tbody tr:nth-child(odd) {
134
+ background-color: var(--stripe-bgc);
154
135
  }
155
136
  }
156
137
 
157
- /** 列宽调整指示器 */
158
- .column-resize-indicator {
159
- width: 0;
160
- height: 100%;
161
- border-left: 2px solid var(--col-resize-indicator-color);
162
- position: absolute;
163
- z-index: 10;
164
- display: none;
165
- pointer-events: none;
138
+ /* 单元格悬浮 */
139
+ &.cell-hover tbody td:hover {
140
+ box-shadow: inset 0 0 0 2px var(--td-hover-color);
166
141
  }
167
142
 
168
- .stk-table-main {
169
- border-spacing: 0;
170
- border-collapse: separate;
171
- width: fit-content;
172
- /* 不加会导致width 超过100%时为100%,行hover高亮会断开*/
173
- min-width: 100%;
143
+ /* td 溢出*/
144
+ &.text-overflow {
145
+ .table-cell-wrapper {
146
+ white-space: nowrap;
147
+ overflow: hidden;
148
+ text-overflow: ellipsis;
149
+ }
150
+ }
174
151
 
175
- &.fixed-mode {
176
- table-layout: fixed;
177
- min-width: min-content;
152
+ /* th 溢出*/
153
+ &.header-text-overflow {
154
+ .table-header-cell-wrapper {
155
+ white-space: nowrap;
156
+ overflow: hidden;
178
157
  }
179
158
 
180
- th,
181
- td {
182
- z-index: 1;
183
- font-size: 14px;
184
- box-sizing: border-box;
185
- padding: 0 var(--cell-padding-x);
159
+ .table-header-title {
160
+ text-overflow: ellipsis;
161
+ overflow: hidden;
186
162
  }
163
+ }
187
164
 
188
- th {
189
- color: var(--th-color);
190
- background-color: var(--th-bgc);
165
+ /**虚拟滚动模式 */
166
+ &.virtual {
191
167
 
192
- &.sortable {
193
- cursor: pointer;
194
- }
168
+ /* 为不影响布局,表头行高要定死*/
169
+ .table-header-cell-wrapper {
170
+ overflow: hidden;
171
+ max-height: var(--header-row-height);
172
+ }
195
173
 
196
- &.text-overflow {
197
- .table-header-cell-wrapper {
198
- white-space: nowrap;
199
- overflow: hidden;
200
- }
174
+ tbody td {
175
+ height: var(--row-height);
176
+ line-height: 1;
201
177
 
202
- .table-header-title {
203
- text-overflow: ellipsis;
204
- overflow: hidden;
205
- }
178
+ .table-cell-wrapper {
179
+ max-height: var(--row-height);
180
+ overflow: hidden;
206
181
  }
207
182
  }
208
183
 
209
- td {
210
- &.fixed-cell {
211
- background-color: inherit;
212
- /* 防止横向滚动后透明*/
213
- }
184
+ .padding-top-tr td {
185
+ height: 0;
186
+ }
187
+ }
214
188
 
215
- &.highlight-cell {
216
- animation: stk-table-dim var(--highlight-duration);
217
- animation-timing-function: var(--highlight-timing-function); /* 必须分开些,否则var(step(x))不兼容旧浏览器*/
218
- }
189
+ th,
190
+ td {
191
+ z-index: 1;
192
+ font-size: 14px;
193
+ box-sizing: border-box;
194
+ padding: 0 var(--cell-padding-x);
195
+ }
219
196
 
220
- &.text-overflow {
221
- .table-cell-wrapper {
222
- white-space: nowrap;
223
- overflow: hidden;
224
- text-overflow: ellipsis;
225
- }
226
- }
227
-
228
- &.seq-column{
229
- text-align: center;
230
- }
197
+ th {
198
+ color: var(--th-color);
199
+ background-color: inherit;
200
+
201
+ &.sortable {
202
+ cursor: pointer;
231
203
  }
232
204
 
233
- /*固定列阴影-左*/
234
- .fixed-cell--left {
235
- --shadow-rotate: 90deg;
205
+ &:not(.sorter-desc):not(.sorter-asc):hover .table-header-sorter {
206
+ .arrow-up {
207
+ fill: var(--sort-arrow-hover-color);
208
+ }
236
209
 
237
- &.fixed-cell--shadow::after {
238
- right: -10px;
210
+ .arrow-down {
211
+ fill: var(--sort-arrow-hover-color);
239
212
  }
240
213
  }
241
214
 
242
- /*固定列阴影-右*/
243
- .fixed-cell--right {
244
- --shadow-rotate: -90deg;
215
+ &.sorter-desc .table-header-sorter {
216
+ display: initial;
245
217
 
246
- &.fixed-cell--shadow::after {
247
- left: -10px;
218
+ .arrow-up {
219
+ fill: var(--sort-arrow-active-sub-color);
248
220
  }
249
- }
250
221
 
251
- /*固定列阴影*/
252
- .fixed-cell--shadow::after {
253
- content: '';
254
- width: 10px;
255
- height: 100%;
256
- top: 0px;
257
- position: absolute;
258
- pointer-events: none;
259
- background-image: linear-gradient(var(--shadow-rotate), var(--fixed-col-shadow-color-from), var(--fixed-col-shadow-color-to)),
222
+ .arrow-down {
223
+ fill: var(--sort-arrow-active-color);
224
+ }
260
225
  }
261
226
 
262
- thead {
263
- tr {
264
- height: var(--header-row-height);
227
+ &.sorter-asc .table-header-sorter {
228
+ display: initial;
229
+
230
+ .arrow-up {
231
+ fill: var(--sort-arrow-active-color);
232
+ }
265
233
 
266
- &:first-child th {
267
- position: sticky;
268
- top: 0;
269
- }
234
+ .arrow-down {
235
+ fill: var(--sort-arrow-active-sub-color);
270
236
  }
271
237
  }
272
238
 
273
- th {
239
+ }
274
240
 
275
- &:not(.sorter-desc):not(.sorter-asc):hover .table-header-sorter {
276
- .arrow-up {
277
- fill: var(--sort-arrow-hover-color);
278
- }
241
+ thead {
242
+ tr {
243
+ background-color: var(--th-bgc);
244
+ height: var(--header-row-height);
279
245
 
280
- .arrow-down {
281
- fill: var(--sort-arrow-hover-color);
282
- }
246
+ &:first-child th {
247
+ position: sticky;
248
+ top: 0;
283
249
  }
250
+ }
251
+ }
284
252
 
285
- &.sorter-desc .table-header-sorter {
286
- display: initial;
253
+ /* stk-table-main 这层为了增加选择器优先级,防止被斑马纹颜色覆盖*/
254
+ .stk-table-main tbody tr {
255
+ background-color: var(--td-bgc);
256
+ height: var(--row-height);
257
+ /** 一行分层,有利于高亮行重绘
258
+ transform: translateZ(0);*/
287
259
 
288
- .arrow-up {
289
- fill: var(--sort-arrow-active-sub-color);
290
- }
260
+ &:hover {
261
+ background-color: var(--tr-hover-bgc);
262
+ }
291
263
 
292
- .arrow-down {
293
- fill: var(--sort-arrow-active-color);
294
- }
295
- }
264
+ &.active {
265
+ background-color: var(--tr-active-bgc);
266
+ }
267
+ }
296
268
 
297
- &.sorter-asc .table-header-sorter {
298
- display: initial;
269
+ .virtual-x-left,
270
+ .virtual-x-right {
271
+ padding: 0;
272
+ background: none;
273
+ pointer-events: none;
274
+ }
299
275
 
300
- .arrow-up {
301
- fill: var(--sort-arrow-active-color);
302
- }
303
276
 
304
- .arrow-down {
305
- fill: var(--sort-arrow-active-sub-color);
306
- }
307
- }
277
+ /** 列宽调整指示器 */
278
+ .column-resize-indicator {
279
+ width: 0;
280
+ height: 100%;
281
+ border-left: 2px solid var(--col-resize-indicator-color);
282
+ position: absolute;
283
+ z-index: 10;
284
+ display: none;
285
+ pointer-events: none;
286
+ }
308
287
 
288
+ .stk-table-main {
289
+ border-spacing: 0;
290
+ border-collapse: separate;
291
+ width: fit-content;
292
+ /* 不加会导致width 超过100%时为100%,行hover高亮会断开*/
293
+ min-width: 100%;
309
294
 
295
+ &.fixed-mode {
296
+ table-layout: fixed;
297
+ min-width: min-content;
310
298
  }
299
+ }
311
300
 
312
- .table-header-cell-wrapper {
313
- max-width: 100%;
314
- /*最大宽度不超过列宽*/
315
- display: inline-flex;
316
- align-items: center;
317
- }
301
+ .fixed-cell {
302
+ background-color: inherit;
303
+ /* 防止横向滚动后透明*/
304
+ }
318
305
 
319
- .table-header-title {
320
- overflow: hidden;
321
- align-self: flex-start;
306
+ .highlight-cell {
307
+ animation: stk-table-dim var(--highlight-duration);
308
+ animation-timing-function: var(--highlight-timing-function);
309
+ /* 必须分开些,否则var(step(x))不兼容旧浏览器*/
310
+ }
311
+
312
+ .seq-column {
313
+ text-align: center;
314
+ }
315
+
316
+ /*固定列阴影-左*/
317
+ .fixed-cell--left {
318
+ --shadow-rotate: 90deg;
319
+
320
+ &.fixed-cell--shadow::after {
321
+ right: -10px;
322
322
  }
323
+ }
323
324
 
324
- .table-header-sorter {
325
- flex-shrink: 0;
326
- margin-left: 4px;
327
- width: 16px;
328
- height: 16px;
329
- display: none;
325
+ /*固定列阴影-右*/
326
+ .fixed-cell--right {
327
+ --shadow-rotate: -90deg;
330
328
 
331
- .arrow-up,
332
- .arrow-down {
333
- fill: var(--sort-arrow-color);
334
- }
329
+ &.fixed-cell--shadow::after {
330
+ left: -10px;
335
331
  }
332
+ }
333
+
334
+ /*固定列阴影*/
335
+ .fixed-cell--shadow::after {
336
+ content: '';
337
+ width: 10px;
338
+ height: 100%;
339
+ top: 0px;
340
+ position: absolute;
341
+ pointer-events: none;
342
+ background-image: linear-gradient(var(--shadow-rotate), var(--fixed-col-shadow-color-from), var(--fixed-col-shadow-color-to)),
343
+ }
344
+
345
+ .table-header-cell-wrapper {
346
+ max-width: 100%;
347
+ /*最大宽度不超过列宽*/
348
+ display: inline-flex;
349
+ align-items: center;
350
+ }
336
351
 
337
- .table-header-resizer {
338
- position: absolute;
339
- top: 0;
340
- bottom: 0;
341
- cursor: col-resize;
342
- width: var(--resize-handle-width);
352
+ .table-header-title {
353
+ overflow: hidden;
354
+ align-self: flex-start;
355
+ }
343
356
 
344
- &.left {
345
- left: 0;
346
- }
357
+ .table-header-sorter {
358
+ flex-shrink: 0;
359
+ margin-left: 4px;
360
+ width: 16px;
361
+ height: 16px;
362
+ display: none;
347
363
 
348
- &.right {
349
- right: 0;
350
- }
364
+ .arrow-up,
365
+ .arrow-down {
366
+ fill: var(--sort-arrow-color);
351
367
  }
368
+ }
352
369
 
353
- tbody {
370
+ .table-header-resizer {
371
+ position: absolute;
372
+ top: 0;
373
+ bottom: 0;
374
+ cursor: col-resize;
375
+ width: var(--resize-handle-width);
354
376
 
355
- tr {
356
- background-color: var(--td-bgc);
357
- height: var(--row-height);
358
- /** 一行分层,有利于高亮行重绘*/
359
- transform: translateZ(0);
360
-
361
- /* td inherit tr bgc*/
362
- &.highlight-row {
363
- animation: stk-table-dim var(--highlight-duration);
364
- animation-timing-function: var(--highlight-timing-function); /* 必须分开些,否则var(step(x))不兼容旧浏览器*/
365
- }
366
-
367
-
368
- &.hover,
369
- &:hover {
370
- background-color: var(--tr-hover-bgc);
371
- }
372
-
373
- &.active {
374
- background-color: var(--tr-active-bgc);
375
- }
376
- }
377
+ &.left {
378
+ left: 0;
379
+ }
377
380
 
381
+ &.right {
382
+ right: 0;
378
383
  }
379
384
  }
380
385
 
386
+ /* td inherit tr bgc*/
387
+ .highlight-row {
388
+ animation: stk-table-dim var(--highlight-duration);
389
+ /* 必须分开写,否则var(step(x))不兼容旧浏览器*/
390
+ animation-timing-function: var(--highlight-timing-function);
391
+ }
392
+
381
393
  .stk-table-no-data {
382
394
  background-color: var(--table-bgc);
383
395
  line-height: var(--row-height);
@@ -397,40 +409,4 @@
397
409
  }
398
410
  }
399
411
 
400
- /**虚拟滚动模式 */
401
- &.virtual {
402
-
403
- /* 为不影响布局,表头行高要定死*/
404
- .table-header-cell-wrapper {
405
- overflow: hidden;
406
- max-height: var(--header-row-height);
407
- }
408
-
409
- tbody {
410
- position: relative;
411
-
412
- tr {
413
-
414
- td {
415
- height: var(--row-height);
416
- line-height: 1;
417
-
418
- .table-cell-wrapper {
419
- max-height: var(--row-height);
420
- overflow: hidden;
421
- }
422
- }
423
- }
424
- }
425
-
426
- .padding-top-tr td {
427
- height: 0;
428
- }
429
- }
430
-
431
- &.virtual-x {
432
- .virtual-x-left {
433
- padding: 0;
434
- }
435
- }
436
412
  }
@@ -1,5 +1,5 @@
1
- import { Ref, ShallowRef, onBeforeUnmount, onMounted, ref } from 'vue';
2
- import { StkTableColumn } from './types';
1
+ import { ComputedRef, Ref, ShallowRef, onBeforeUnmount, onMounted, ref } from 'vue';
2
+ import { StkTableColumn, UniqKey } from './types';
3
3
  import { getCalculatedColWidth } from './utils';
4
4
 
5
5
  type ColResizeState<DT extends Record<string, any>> = {
@@ -21,7 +21,7 @@ type Params<DT extends Record<string, any>> = {
21
21
  tableContainerRef: Ref<HTMLElement | undefined>;
22
22
  tableHeaderLast: ShallowRef<StkTableColumn<DT>[]>;
23
23
  colResizeIndicatorRef: Ref<HTMLElement | undefined>;
24
- colKeyGen: (p: any) => string;
24
+ colKeyGen: ComputedRef<(p: any) => UniqKey>;
25
25
  };
26
26
 
27
27
  /** 列宽拖动 */
@@ -78,7 +78,7 @@ export function useColResize<DT extends Record<string, any>>({
78
78
  const { scrollLeft, scrollTop } = tableContainerRef.value;
79
79
  const { left } = tableContainerRef.value.getBoundingClientRect();
80
80
  /** 列下标 */
81
- let colIndex = tableHeaderLast.value.findIndex(it => colKeyGen(it) === colKeyGen(col));
81
+ let colIndex = tableHeaderLast.value.findIndex(it => colKeyGen.value(it) === colKeyGen.value(col));
82
82
  if (isPrev) {
83
83
  // 上一列
84
84
  colIndex -= 1;
@@ -139,7 +139,7 @@ export function useColResize<DT extends Record<string, any>>({
139
139
  let width = getCalculatedColWidth(lastCol) + moveX;
140
140
  if (width < props.colMinWidth) width = props.colMinWidth;
141
141
 
142
- const curCol = tableHeaderLast.value.find(it => colKeyGen(it) === colKeyGen(lastCol));
142
+ const curCol = tableHeaderLast.value.find(it => colKeyGen.value(it) === colKeyGen.value(lastCol));
143
143
  if (!curCol) return;
144
144
  curCol.width = width + 'px';
145
145
 
@@ -1,9 +1,9 @@
1
- import { computed, ref, Ref, ShallowRef, shallowRef } from 'vue';
2
- import { StkTableColumn } from './types';
1
+ import { computed, ComputedRef, ref, Ref, ShallowRef, shallowRef } from 'vue';
2
+ import { StkTableColumn, UniqKey } from './types';
3
3
 
4
4
  type Params<T extends Record<string, any>> = {
5
5
  props: any;
6
- colKeyGen: (col: StkTableColumn<T>) => string;
6
+ colKeyGen: ComputedRef<(col: StkTableColumn<T>) => UniqKey>;
7
7
  tableHeaders: ShallowRef<StkTableColumn<T>[][]>;
8
8
  tableHeaderLast: ShallowRef<StkTableColumn<T>[]>;
9
9
  tableContainerRef: Ref<HTMLDivElement | undefined>;
@@ -42,7 +42,7 @@ export function useFixedCol<DT extends Record<string, any>>({ props, colKeyGen,
42
42
  ['fixed-cell--' + col.fixed]: col.fixed,
43
43
  'fixed-cell--shadow': showShadow,
44
44
  };
45
- colMap.set(colKeyGen(col), classObj);
45
+ colMap.set(colKeyGen.value(col), classObj);
46
46
  });
47
47
  });
48
48
  return colMap;
@@ -75,37 +75,58 @@ export function useFixedStyle<DT extends Record<string, any>>({
75
75
  const { fixed } = col;
76
76
  if (tagType === TagType.TD && !fixed) return null;
77
77
 
78
- const isFixedLeft = fixed === 'left';
79
78
  const style: CSSProperties = {};
80
79
  const { colKeyStore, refStore } = fixedColumnsPositionStore.value;
81
80
 
81
+ /** 是否是relative模式完成固定列 */
82
+ let isRelativeMode = true;
83
+ if (props.cellFixedMode === 'sticky') {
84
+ isRelativeMode = false;
85
+ }
86
+
82
87
  if (IS_LEGACY_MODE) {
88
+ // 低版本浏览器只能为固定列设置position: sticky
89
+ isRelativeMode = true;
90
+ }
91
+
92
+ const { scrollLeft, scrollWidth, offsetLeft, containerWidth } = virtualScrollX.value;
93
+ const scrollRight = scrollWidth - containerWidth - scrollLeft;
94
+
95
+ if (virtualScrollX.value.scrollLeft === 0 && fixed === 'left' && tagType === TagType.TD) {
96
+ // 滚动条在最左侧时,左侧固定列不需要,防止分层
97
+ style.position = void 0;
98
+ } else if (scrollRight === 0 && fixed === 'right' && tagType === TagType.TD) {
99
+ // 滚动条在最右侧时,右侧固定列不需要,防止分层
100
+ style.position = void 0;
101
+ } else if (isRelativeMode) {
83
102
  style.position = 'relative';
84
103
  } else {
85
104
  style.position = 'sticky';
86
105
  }
87
106
 
107
+ const isFixedLeft = fixed === 'left';
88
108
  if (tagType === TagType.TH) {
89
109
  // TH
90
- if (IS_LEGACY_MODE) {
91
- style.top = virtualScroll.value.scrollTop + depth * props.rowHeight + 'px';
110
+ if (isRelativeMode) {
111
+ style.top = virtualScroll.value.scrollTop + 'px';
92
112
  } else {
93
113
  style.top = depth * props.rowHeight + 'px';
94
114
  }
95
115
  style.zIndex = isFixedLeft ? '3' : '2'; // 保证固定列高于其他单元格
96
116
  } else {
97
117
  // TD
98
- style.zIndex = isFixedLeft ? '2' : '1';
118
+ if (isFixedLeft) {
119
+ style.zIndex = '2';
120
+ }
99
121
  }
100
122
 
101
123
  if (fixed === 'left' || fixed === 'right') {
102
- if (IS_LEGACY_MODE) {
124
+ if (isRelativeMode) {
103
125
  if (isFixedLeft) {
104
- if (virtualX_on.value) style.left = virtualScrollX.value.scrollLeft - virtualScrollX.value.offsetLeft + 'px';
105
- else style.left = virtualScrollX.value.scrollLeft + 'px';
126
+ style.left = scrollLeft - (virtualX_on.value ? offsetLeft : 0) + 'px';
106
127
  } else {
107
- // TODO:计算右侧距离
108
- style.right = `${virtualX_offsetRight.value}px`;
128
+ // fixed right
129
+ style.right = Math.max(scrollRight - (virtualX_on.value ? virtualX_offsetRight.value : 0), 0) + 'px';
109
130
  }
110
131
  } else {
111
132
  const lr = (col.dataIndex ? colKeyStore[col.dataIndex] : refStore.get(col)) + 'px';