stk-table-vue 0.2.8 → 0.2.9

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 CHANGED
@@ -12,7 +12,10 @@ repo:
12
12
  * [x] props.dataSource 为 shallowRef 时,高亮行不生效。(bug:2024.02.21)(resolved:0.2.3)
13
13
 
14
14
  ## Feature TODO:
15
- * [x] 高亮行,单元格。
15
+ * [x] 高亮行,单元格。使用css keyframe实现。
16
+ - [x] 虚拟滚动默认通过js计算行高亮背景色,可通过 `useCss` 设置为css keyframe实现 。
17
+ - [x] 支持配置高亮参数(持续时间,颜色,频率(虚拟滚动))。(`v0.2.9`)
18
+ - [x] `setHighlightDimRow`/`setHighlightCellRow`支持自定义高亮css类名。(`v0.2.9`)
16
19
  * [x] 虚拟滚动。
17
20
  - [x] 纵向。
18
21
  - [x] 横向(必须设置列宽)。
@@ -29,19 +32,19 @@ repo:
29
32
  - [x] 基本表头点击排序。
30
33
  - [x] 支持配置 `null` | `undefined` 永远排最后。
31
34
  - [] 支持配置 string 使用 `String.prototype.localCompare` 排序。
32
- * 多级表头。
35
+ * [x] 多级表头。
33
36
  - [x] 支持最多`2级`表头。
34
37
  - [x] 支持更多级表头。
35
38
  - [] 横向虚拟滚动。
36
39
  * [x] 支持table-layout: fixed 配置。
37
- * 鼠标悬浮在表格上,键盘滚动虚拟表格。
40
+ * [x] 鼠标悬浮在表格上,键盘滚动虚拟表格。
38
41
  - [x] 键盘 `ArrowUp`/`ArrowDown`/`ArrowLeft`/`ArrowRight` 按键支持。
39
42
  - [x] 键盘 `PageUp`/ `PageDown` 按键支持。
40
43
  * [] 非虚拟滚动时,大数据分批加载。
41
44
  * [x] vue2.7支持(引入源码使用)。
42
- - [x] `props.optimizeVue2Scroll` 优化vue2虚拟滚动流畅度。
43
- * [x] `props.emptyCellText` 支持传入函数。
44
- * [] 支持配置高亮参数。
45
+ - [x] `props.optimizeVue2Scroll` 优化vue2虚拟滚动流畅度。(`v0.2.0`)
46
+ * [x] `props.emptyCellText` 支持传入函数。(`v0.2.6`)
47
+
45
48
 
46
49
 
47
50
  ## Usage
@@ -53,8 +56,8 @@ import { StkTable } from 'stk-table-vue'
53
56
  import { ref } from 'vue'
54
57
  const stkTable = ref<InstanceType<typeof StkTable>>();
55
58
  // highlight
56
- stkTable.value.setHighlightDimRow([rowId]);// highlight row
57
- stkTable.value.setHighlightDimCell(rowId, colId) // highlight cell
59
+ stkTable.value.setHighlightDimRow([rowId],{useCss:false,className:'custom-class-name'});// highlight row
60
+ stkTable.value.setHighlightDimCell(rowId, colId,{className:'custom-class-name'}) // highlight cell
58
61
  </script>
59
62
 
60
63
  <template>
@@ -199,6 +202,18 @@ export type StkProps = {
199
202
  },
200
203
  /** 隐藏头部title。可传入dataIndex数组 */
201
204
  hideHeaderTitle?: boolean | string[];
205
+ /** 高亮配置 */
206
+ highlightConfig?: {
207
+ /** 高亮持续时间(s) */
208
+ duration?: number;
209
+ /** 高亮背景色 */
210
+ color?: {
211
+ light?: { from: string; to: string };
212
+ dark?: { from: string; to: string };
213
+ };
214
+ /** 高亮帧率(虚拟滚动生效) */
215
+ fps?: number;
216
+ };
202
217
  };
203
218
  ```
204
219
  #### Emits
@@ -1,4 +1,4 @@
1
- import { Order, SortConfig, SortOption, SortState, StkTableColumn, UniqKeyProp } from './types/index';
1
+ import { HighlightConfig, Order, SortConfig, SortOption, SortState, StkTableColumn, UniqKeyProp } from './types/index';
2
2
  /** Generic stands for DataType */
3
3
  type DT = any;
4
4
  /**
@@ -120,6 +120,8 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
120
120
  sortConfig?: SortConfig<any> | undefined;
121
121
  /** 隐藏头部title。可传入dataIndex数组 */
122
122
  hideHeaderTitle?: boolean | string[] | undefined;
123
+ /** 高亮配置 */
124
+ highlightConfig?: HighlightConfig | undefined;
123
125
  }>, {
124
126
  width: string;
125
127
  fixedMode: boolean;
@@ -156,6 +158,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
156
158
  stringLocaleCompare: boolean;
157
159
  };
158
160
  hideHeaderTitle: boolean;
161
+ highlightConfig: () => {};
159
162
  }>, {
160
163
  /** 初始化横向纵向虚拟滚动 */
161
164
  initVirtualScroll: (height?: number | undefined) => void;
@@ -166,10 +169,13 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
166
169
  /** 设置当前选中行 */
167
170
  setCurrentRow: typeof setCurrentRow;
168
171
  /** 设置高亮渐暗单元格 */
169
- setHighlightDimCell: (rowKeyValue: string, dataIndex: string) => void;
172
+ setHighlightDimCell: (rowKeyValue: string, dataIndex: string, option?: {
173
+ className?: string | undefined;
174
+ }) => void;
170
175
  /** 设置高亮渐暗行 */
171
176
  setHighlightDimRow: (rowKeyValues: import("./types/index").UniqKey[], option?: {
172
177
  useCss?: boolean | undefined;
178
+ className?: string | undefined;
173
179
  }) => void;
174
180
  /** 表格排序列dataIndex */
175
181
  sortCol: import("vue").Ref<string | null | undefined>;
@@ -285,6 +291,8 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
285
291
  sortConfig?: SortConfig<any> | undefined;
286
292
  /** 隐藏头部title。可传入dataIndex数组 */
287
293
  hideHeaderTitle?: boolean | string[] | undefined;
294
+ /** 高亮配置 */
295
+ highlightConfig?: HighlightConfig | undefined;
288
296
  }>, {
289
297
  width: string;
290
298
  fixedMode: boolean;
@@ -321,6 +329,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
321
329
  stringLocaleCompare: boolean;
322
330
  };
323
331
  hideHeaderTitle: boolean;
332
+ highlightConfig: () => {};
324
333
  }>>> & {
325
334
  onScroll?: ((ev: Event, data: {
326
335
  startIndex: number;
@@ -375,6 +384,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
375
384
  optimizeVue2Scroll: boolean;
376
385
  sortConfig: SortConfig<any>;
377
386
  hideHeaderTitle: boolean | string[];
387
+ highlightConfig: HighlightConfig;
378
388
  }, {}>, {
379
389
  tableHeader?(_: {
380
390
  col: StkTableColumn<any>;
@@ -1,9 +1,9 @@
1
- export declare const Default_Col_Width = "100";
2
- export declare const Default_Table_Height = 100;
3
- export declare const Default_Table_Width = 200;
4
- export declare const Default_Row_Height = 28;
1
+ export declare const DEFAULT_COL_WIDTH = "100";
2
+ export declare const DEFAULT_TABLE_HEIGHT = 100;
3
+ export declare const DEFAULT_TABLE_WIDTH = 200;
4
+ export declare const DEFAULT_ROW_HEIGHT = 28;
5
5
  /** 高亮背景色 */
6
- export declare const Highlight_Color: {
6
+ export declare const HIGHLIGHT_COLOR: {
7
7
  light: {
8
8
  from: string;
9
9
  to: string;
@@ -14,8 +14,12 @@ export declare const Highlight_Color: {
14
14
  };
15
15
  };
16
16
  /** 高亮持续时间 */
17
- export declare const Highlight_Duration = 2000;
17
+ export declare const HIGHLIGHT_DURATION = 2000;
18
18
  /** 高亮变更频率 */
19
- export declare const Highlight_Color_Change_Freq = 100;
19
+ export declare const HIGHLIGHT_FREQ = 100;
20
+ /** 高亮行class */
21
+ export declare const HIGHLIGHT_ROW_CLASS = "highlight-row";
22
+ /** 高连单元格class */
23
+ export declare const HIGHLIGHT_CELL_CLASS = "highlight-cell";
20
24
  /** 是否兼容低版本模式 */
21
- export declare const Is_Legacy_Mode: boolean;
25
+ export declare const IS_LEGACY_MODE: boolean;
@@ -99,4 +99,22 @@ export declare const enum TagType {
99
99
  TH = 0,
100
100
  TD = 1
101
101
  }
102
+ /** 高亮配置 */
103
+ export type HighlightConfig = {
104
+ /** 高亮持续时间(s) */
105
+ duration?: number;
106
+ /** 高亮背景色 */
107
+ color?: {
108
+ light?: {
109
+ from: string;
110
+ to: string;
111
+ };
112
+ dark?: {
113
+ from: string;
114
+ to: string;
115
+ };
116
+ };
117
+ /** 高亮帧率(虚拟滚动生效) */
118
+ fps?: number;
119
+ };
102
120
  export {};
@@ -1,11 +1,7 @@
1
1
  import { Ref } from 'vue';
2
2
  import { UniqKey } from './types';
3
3
  type Params = {
4
- props: {
5
- theme: 'light' | 'dark';
6
- virtual: boolean;
7
- dataSource: any[];
8
- };
4
+ props: any;
9
5
  tableContainer: Ref<HTMLElement | undefined>;
10
6
  };
11
7
  /** 高亮行保存的东西 */
@@ -20,9 +16,13 @@ type HighlightRowStore = {
20
16
  */
21
17
  export declare function useHighlight({ props, tableContainer }: Params): {
22
18
  highlightRowStore: Ref<Record<UniqKey, HighlightRowStore>>;
19
+ highlightFrom: import("vue").ComputedRef<string>;
23
20
  setHighlightDimRow: (rowKeyValues: UniqKey[], option?: {
24
21
  useCss?: boolean;
22
+ className?: string;
23
+ }) => void;
24
+ setHighlightDimCell: (rowKeyValue: string, dataIndex: string, option?: {
25
+ className?: string;
25
26
  }) => void;
26
- setHighlightDimCell: (rowKeyValue: string, dataIndex: string) => void;
27
27
  };
28
28
  export {};
@@ -1,15 +1,17 @@
1
1
  import { onMounted, onBeforeUnmount, watch, ref, shallowRef, computed, defineComponent, toRaw, openBlock, createElementBlock, normalizeClass, unref, normalizeStyle, withDirectives, createElementVNode, vShow, Fragment, renderList, createCommentVNode, createBlock, resolveDynamicComponent, renderSlot, toDisplayString, createTextVNode } from "vue";
2
2
  import { interpolateRgb } from "d3-interpolate";
3
- const Default_Col_Width = "100";
4
- const Default_Table_Height = 100;
5
- const Default_Table_Width = 200;
6
- const Default_Row_Height = 28;
7
- const Highlight_Color = {
3
+ const DEFAULT_COL_WIDTH = "100";
4
+ const DEFAULT_TABLE_HEIGHT = 100;
5
+ const DEFAULT_TABLE_WIDTH = 200;
6
+ const DEFAULT_ROW_HEIGHT = 28;
7
+ const HIGHLIGHT_COLOR = {
8
8
  light: { from: "#71a2fd", to: "#fff" },
9
9
  dark: { from: "#1e4c99", to: "#181c21" }
10
10
  };
11
- const Highlight_Duration = 2e3;
12
- const Highlight_Color_Change_Freq = 100;
11
+ const HIGHLIGHT_DURATION = 2e3;
12
+ const HIGHLIGHT_FREQ = 100;
13
+ const HIGHLIGHT_ROW_CLASS = "highlight-row";
14
+ const HIGHLIGHT_CELL_CLASS = "highlight-cell";
13
15
  let _chromeVersion = 0;
14
16
  try {
15
17
  const userAgent = navigator.userAgent.match(/chrome\/\d+/i);
@@ -19,7 +21,7 @@ try {
19
21
  } catch (e) {
20
22
  console.error("Cannot get Chrome version", e);
21
23
  }
22
- const Is_Legacy_Mode = _chromeVersion < 56;
24
+ const IS_LEGACY_MODE = _chromeVersion < 56;
23
25
  var TagType = /* @__PURE__ */ ((TagType2) => {
24
26
  TagType2[TagType2["TH"] = 0] = "TH";
25
27
  TagType2[TagType2["TD"] = 1] = "TD";
@@ -197,7 +199,7 @@ function howDeepTheHeader(arr, level = 1) {
197
199
  return Math.max(...levels);
198
200
  }
199
201
  function getColWidth(col) {
200
- const val = (col == null ? void 0 : col.width) ?? Default_Col_Width;
202
+ const val = (col == null ? void 0 : col.width) ?? DEFAULT_COL_WIDTH;
201
203
  if (typeof val === "number") {
202
204
  return Math.floor(val);
203
205
  }
@@ -442,13 +444,13 @@ function useFixedStyle({
442
444
  const isFixedLeft = fixed === "left";
443
445
  const style = {};
444
446
  const { colKeyStore, refStore } = fixedColumnsPositionStore.value;
445
- if (Is_Legacy_Mode) {
447
+ if (IS_LEGACY_MODE) {
446
448
  style.position = "relative";
447
449
  } else {
448
450
  style.position = "sticky";
449
451
  }
450
452
  if (tagType === TagType.TH) {
451
- if (Is_Legacy_Mode) {
453
+ if (IS_LEGACY_MODE) {
452
454
  style.top = virtualScroll.value.scrollTop + depth * props.rowHeight + "px";
453
455
  } else {
454
456
  style.top = depth * props.rowHeight + "px";
@@ -458,7 +460,7 @@ function useFixedStyle({
458
460
  style.zIndex = isFixedLeft ? "3" : "2";
459
461
  }
460
462
  if (fixed === "left" || fixed === "right") {
461
- if (Is_Legacy_Mode) {
463
+ if (IS_LEGACY_MODE) {
462
464
  if (isFixedLeft) {
463
465
  if (virtualX_on.value)
464
466
  style.left = virtualScrollX.value.scrollLeft - virtualScrollX.value.offsetLeft + "px";
@@ -482,12 +484,18 @@ function useFixedStyle({
482
484
  getFixedStyle
483
485
  };
484
486
  }
485
- const HIGHLIGHT_ROW_CLASS = "highlight-row";
486
- const HIGHLIGHT_CELL_CLASS = "highlight-cell";
487
487
  function useHighlight({ props, tableContainer }) {
488
+ var _a, _b;
489
+ const config = props.highlightConfig;
488
490
  const highlightRowStore = ref({});
489
- const highlightFrom = computed(() => Highlight_Color[props.theme].from);
490
- const highlightTo = computed(() => Highlight_Color[props.theme].to);
491
+ const duration = config.duration ? config.duration * 1e3 : HIGHLIGHT_DURATION;
492
+ const frequency = config.fps ? 1e3 / config.fps : HIGHLIGHT_FREQ;
493
+ const highlightColor = {
494
+ light: Object.assign(HIGHLIGHT_COLOR.light, (_a = config.color) == null ? void 0 : _a.light),
495
+ dark: Object.assign(HIGHLIGHT_COLOR.dark, (_b = config.color) == null ? void 0 : _b.dark)
496
+ };
497
+ const highlightFrom = computed(() => highlightColor[props.theme].from);
498
+ const highlightTo = computed(() => highlightColor[props.theme].to);
491
499
  const highlightInter = computed(() => interpolateRgb(highlightFrom.value, highlightTo.value));
492
500
  const highlightDimRowKeys = /* @__PURE__ */ new Set();
493
501
  const highlightDimRowsTimeout = /* @__PURE__ */ new Map();
@@ -502,7 +510,7 @@ function useHighlight({ props, tableContainer }) {
502
510
  const nowTs = Date.now();
503
511
  highlightDimRowKeys.forEach((rowKeyValue) => {
504
512
  const highlightItem = highlightRowStore.value[rowKeyValue];
505
- const progress = (nowTs - highlightItem.bgc_progress_ms) / Highlight_Duration;
513
+ const progress = (nowTs - highlightItem.bgc_progress_ms) / duration;
506
514
  if (0 < progress && progress < 1) {
507
515
  highlightItem.bgc = highlightInter.value(progress);
508
516
  } else {
@@ -516,34 +524,36 @@ function useHighlight({ props, tableContainer }) {
516
524
  } else {
517
525
  calcHighlightDimLoop = false;
518
526
  }
519
- }, Highlight_Color_Change_Freq);
527
+ }, frequency);
520
528
  };
521
529
  recursion();
522
530
  }
523
- function setHighlightDimCell(rowKeyValue, dataIndex) {
524
- var _a;
525
- const cellEl = (_a = tableContainer.value) == null ? void 0 : _a.querySelector(`[data-row-key="${rowKeyValue}"]>[data-index="${dataIndex}"]`);
531
+ function setHighlightDimCell(rowKeyValue, dataIndex, option = {}) {
532
+ var _a2;
533
+ const cellEl = (_a2 = tableContainer.value) == null ? void 0 : _a2.querySelector(`[data-row-key="${rowKeyValue}"]>[data-index="${dataIndex}"]`);
534
+ const opt = { className: HIGHLIGHT_CELL_CLASS, ...option };
526
535
  if (!cellEl)
527
536
  return;
528
- if (cellEl.classList.contains(HIGHLIGHT_CELL_CLASS)) {
529
- cellEl.classList.remove(HIGHLIGHT_CELL_CLASS);
537
+ if (cellEl.classList.contains(opt.className)) {
538
+ cellEl.classList.remove(opt.className);
530
539
  void cellEl.offsetHeight;
531
540
  }
532
- cellEl.classList.add(HIGHLIGHT_CELL_CLASS);
541
+ cellEl.classList.add(opt.className);
533
542
  window.clearTimeout(highlightDimCellsTimeout.get(rowKeyValue));
534
543
  highlightDimCellsTimeout.set(
535
544
  rowKeyValue,
536
545
  window.setTimeout(() => {
537
- cellEl.classList.remove(HIGHLIGHT_CELL_CLASS);
546
+ cellEl.classList.remove(opt.className);
538
547
  highlightDimCellsTimeout.delete(rowKeyValue);
539
- }, Highlight_Duration)
548
+ }, duration)
540
549
  );
541
550
  }
542
551
  function setHighlightDimRow(rowKeyValues, option = {}) {
543
- var _a, _b;
552
+ var _a2, _b2;
544
553
  if (!Array.isArray(rowKeyValues))
545
554
  rowKeyValues = [rowKeyValues];
546
- if (props.virtual && !option.useCss) {
555
+ const { className, useCss } = { className: HIGHLIGHT_ROW_CLASS, useCss: false, ...option };
556
+ if (props.virtual && !useCss) {
547
557
  const nowTs = Date.now();
548
558
  for (let i = 0; i < rowKeyValues.length; i++) {
549
559
  const rowKeyValue = rowKeyValues[i];
@@ -560,11 +570,11 @@ function useHighlight({ props, tableContainer }) {
560
570
  const rowElTemp = [];
561
571
  for (let i = 0; i < rowKeyValues.length; i++) {
562
572
  const rowKeyValue = rowKeyValues[i];
563
- const rowEl = (_a = tableContainer.value) == null ? void 0 : _a.querySelector(`[data-row-key="${rowKeyValue}"]`);
573
+ const rowEl = (_a2 = tableContainer.value) == null ? void 0 : _a2.querySelector(`[data-row-key="${rowKeyValue}"]`);
564
574
  if (!rowEl)
565
575
  continue;
566
- if (rowEl.classList.contains(HIGHLIGHT_ROW_CLASS)) {
567
- rowEl.classList.remove(HIGHLIGHT_ROW_CLASS);
576
+ if (rowEl.classList.contains(className)) {
577
+ rowEl.classList.remove(className);
568
578
  needRepaint = true;
569
579
  }
570
580
  rowElTemp.push(rowEl);
@@ -572,19 +582,20 @@ function useHighlight({ props, tableContainer }) {
572
582
  highlightDimRowsTimeout.set(
573
583
  rowKeyValue,
574
584
  window.setTimeout(() => {
575
- rowEl.classList.remove(HIGHLIGHT_ROW_CLASS);
585
+ rowEl.classList.remove(className);
576
586
  highlightDimRowsTimeout.delete(rowKeyValue);
577
- }, Highlight_Duration)
587
+ }, duration)
578
588
  );
579
589
  }
580
590
  if (needRepaint) {
581
- void ((_b = tableContainer.value) == null ? void 0 : _b.offsetWidth);
591
+ void ((_b2 = tableContainer.value) == null ? void 0 : _b2.offsetWidth);
582
592
  }
583
- rowElTemp.forEach((el) => el.classList.add(HIGHLIGHT_ROW_CLASS));
593
+ rowElTemp.forEach((el) => el.classList.add(className));
584
594
  }
585
595
  }
586
596
  return {
587
597
  highlightRowStore,
598
+ highlightFrom,
588
599
  setHighlightDimRow,
589
600
  setHighlightDimCell
590
601
  };
@@ -776,7 +787,7 @@ function useVirtualScroll({
776
787
  if (typeof height === "number") {
777
788
  containerHeight = height;
778
789
  } else {
779
- containerHeight = offsetHeight || Default_Table_Height;
790
+ containerHeight = offsetHeight || DEFAULT_TABLE_HEIGHT;
780
791
  }
781
792
  const { headless, headerRowHeight } = props;
782
793
  let pageSize = Math.ceil(containerHeight / rowHeight);
@@ -791,7 +802,7 @@ function useVirtualScroll({
791
802
  if (!props.virtualX)
792
803
  return;
793
804
  const { offsetWidth, scrollLeft } = tableContainer.value || {};
794
- virtualScrollX.value.containerWidth = offsetWidth || Default_Table_Width;
805
+ virtualScrollX.value.containerWidth = offsetWidth || DEFAULT_TABLE_WIDTH;
795
806
  updateVirtualScrollX(scrollLeft);
796
807
  }
797
808
  function initVirtualScroll(height) {
@@ -851,12 +862,15 @@ function useVirtualScroll({
851
862
  let startIndex = 0;
852
863
  let offsetLeft = 0;
853
864
  let colWidthSum = 0;
865
+ let leftColWidthSum = 0;
854
866
  for (let colIndex = 0; colIndex < headerLength; colIndex++) {
855
867
  startIndex++;
856
868
  const col = tableHeaderLast.value[colIndex];
857
- if (col.fixed === "left")
858
- continue;
859
869
  const colWidth = getColWidth(col);
870
+ if (col.fixed === "left") {
871
+ leftColWidthSum += colWidth;
872
+ continue;
873
+ }
860
874
  colWidthSum += colWidth;
861
875
  if (colWidthSum >= sLeft) {
862
876
  offsetLeft = colWidthSum - colWidth;
@@ -865,11 +879,12 @@ function useVirtualScroll({
865
879
  }
866
880
  }
867
881
  colWidthSum = 0;
882
+ const containerWidth = virtualScrollX.value.containerWidth - leftColWidthSum;
868
883
  let endIndex = headerLength;
869
884
  for (let colIndex = startIndex + 1; colIndex < headerLength; colIndex++) {
870
885
  const col = tableHeaderLast.value[colIndex];
871
886
  colWidthSum += getColWidth(col);
872
- if (colWidthSum >= virtualScrollX.value.containerWidth) {
887
+ if (colWidthSum >= containerWidth) {
873
888
  endIndex = colIndex + 1;
874
889
  break;
875
890
  }
@@ -958,7 +973,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
958
973
  fixedMode: { type: Boolean, default: false },
959
974
  headless: { type: Boolean, default: false },
960
975
  theme: { default: "light" },
961
- rowHeight: { default: Default_Row_Height },
976
+ rowHeight: { default: DEFAULT_ROW_HEIGHT },
962
977
  headerRowHeight: { default: null },
963
978
  virtual: { type: Boolean, default: false },
964
979
  virtualX: { type: Boolean, default: false },
@@ -985,7 +1000,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
985
1000
  emptyToBottom: false,
986
1001
  stringLocaleCompare: true
987
1002
  }) },
988
- hideHeaderTitle: { type: [Boolean, Array], default: false }
1003
+ hideHeaderTitle: { type: [Boolean, Array], default: false },
1004
+ highlightConfig: { default: () => ({}) }
989
1005
  },
990
1006
  emits: ["sort-change", "row-click", "current-change", "row-dblclick", "header-row-menu", "row-menu", "cell-click", "header-cell-click", "scroll", "scroll-x", "col-order-change", "th-drag-start", "th-drop", "update:columns"],
991
1007
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -1042,7 +1058,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1042
1058
  virtualX_on,
1043
1059
  virtualX_offsetRight
1044
1060
  });
1045
- const { highlightRowStore, setHighlightDimCell, setHighlightDimRow } = useHighlight({ props, tableContainer });
1061
+ const { highlightRowStore, highlightFrom, setHighlightDimCell, setHighlightDimRow } = useHighlight({ props, tableContainer });
1046
1062
  if (props.autoResize) {
1047
1063
  useAutoResize({ tableContainer, initVirtualScroll, props, debounceMs: 200 });
1048
1064
  }
@@ -1389,12 +1405,16 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1389
1405
  "border-body-v": props.bordered === "body-v",
1390
1406
  stripe: props.stripe
1391
1407
  }]),
1392
- style: normalizeStyle(
1408
+ style: normalizeStyle([
1393
1409
  _ctx.virtual && {
1394
1410
  "--row-height": unref(virtualScroll).rowHeight + "px",
1395
1411
  "--header-row-height": (props.headerRowHeight || props.rowHeight) + "px"
1412
+ },
1413
+ {
1414
+ "--highlight-color": props.highlightConfig.color && unref(highlightFrom),
1415
+ "--highlight-duration": props.highlightConfig.duration && props.highlightConfig.duration + "s"
1396
1416
  }
1397
- ),
1417
+ ]),
1398
1418
  onScroll: onTableScroll,
1399
1419
  onWheel: onTableWheel
1400
1420
  }, [
package/lib/style.css CHANGED
@@ -20,6 +20,7 @@
20
20
  --bg-border-bottom:linear-gradient(0deg, var(--border-color) var(--border-width), transparent var(--border-width));
21
21
  --bg-border-left:linear-gradient(90deg, var(--border-color) var(--border-width), transparent var(--border-width));
22
22
  --highlight-color:#71a2fd;
23
+ --highlight-duration:2s;
23
24
  --stripe-bgc:#fafafc;
24
25
  --sort-arrow-color:#757699;
25
26
  --sort-arrow-hover-color:#8f90b5;
@@ -148,7 +149,7 @@
148
149
  background-color:inherit;
149
150
  }
150
151
  .stk-table .stk-table-main td.highlight-cell{
151
- animation:stk-table-dim 2s linear;
152
+ animation:stk-table-dim var(--highlight-duration) linear;
152
153
  }
153
154
  .stk-table .stk-table-main td.text-overflow .table-cell-wrapper{
154
155
  white-space:nowrap;
@@ -247,7 +248,7 @@
247
248
  height:var(--row-height);
248
249
  }
249
250
  .stk-table .stk-table-main tbody tr.highlight-row{
250
- animation:stk-table-dim 2s linear;
251
+ animation:stk-table-dim var(--highlight-duration) linear;
251
252
  }
252
253
  .stk-table .stk-table-main tbody tr.hover,
253
254
  .stk-table .stk-table-main tbody tr:hover{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stk-table-vue",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Simple realtime virtual table for vue3&vue2.7",
5
5
  "main": "./lib/stk-table-vue.js",
6
6
  "types": "./lib/src/StkTable/index.d.ts",
@@ -15,12 +15,16 @@
15
15
  'border-body-v': props.bordered === 'body-v',
16
16
  stripe: props.stripe,
17
17
  }"
18
- :style="
18
+ :style="[
19
19
  virtual && {
20
20
  '--row-height': virtualScroll.rowHeight + 'px',
21
21
  '--header-row-height': (props.headerRowHeight || props.rowHeight) + 'px',
22
- }
23
- "
22
+ },
23
+ {
24
+ '--highlight-color': props.highlightConfig.color && highlightFrom,
25
+ '--highlight-duration': props.highlightConfig.duration && props.highlightConfig.duration + 's',
26
+ },
27
+ ]"
24
28
  @scroll="onTableScroll"
25
29
  @wheel="onTableWheel"
26
30
  >
@@ -190,8 +194,8 @@
190
194
  * [] highlight-row 颜色不能恢复到active的颜色
191
195
  */
192
196
  import { CSSProperties, computed, onMounted, ref, shallowRef, toRaw, watch } from 'vue';
193
- import { Default_Row_Height } from './const';
194
- import { Order, SortConfig, SortOption, SortState, StkTableColumn, TagType, UniqKeyProp } from './types/index';
197
+ import { DEFAULT_ROW_HEIGHT } from './const';
198
+ import { HighlightConfig, Order, SortConfig, SortOption, SortState, StkTableColumn, TagType, UniqKeyProp } from './types/index';
195
199
  import { useAutoResize } from './useAutoResize';
196
200
  import { useColResize } from './useColResize';
197
201
  import { useFixedCol } from './useFixedCol';
@@ -289,6 +293,8 @@ const props = withDefaults(
289
293
  sortConfig?: SortConfig<DT>;
290
294
  /** 隐藏头部title。可传入dataIndex数组 */
291
295
  hideHeaderTitle?: boolean | string[];
296
+ /** 高亮配置 */
297
+ highlightConfig?: HighlightConfig;
292
298
  }>(),
293
299
  {
294
300
  width: '',
@@ -298,7 +304,7 @@ const props = withDefaults(
298
304
  maxWidth: '',
299
305
  headless: false,
300
306
  theme: 'light',
301
- rowHeight: Default_Row_Height,
307
+ rowHeight: DEFAULT_ROW_HEIGHT,
302
308
  headerRowHeight: null,
303
309
  virtual: false,
304
310
  virtualX: false,
@@ -326,6 +332,7 @@ const props = withDefaults(
326
332
  stringLocaleCompare: true,
327
333
  }),
328
334
  hideHeaderTitle: false,
335
+ highlightConfig: () => ({}),
329
336
  },
330
337
  );
331
338
 
@@ -497,7 +504,7 @@ const { getFixedStyle } = useFixedStyle<DT>({
497
504
  /**
498
505
  * 高亮行,高亮单元格
499
506
  */
500
- const { highlightRowStore, setHighlightDimCell, setHighlightDimRow } = useHighlight({ props, tableContainer });
507
+ const { highlightRowStore, highlightFrom, setHighlightDimCell, setHighlightDimRow } = useHighlight({ props, tableContainer });
501
508
 
502
509
  if (props.autoResize) {
503
510
  useAutoResize({ tableContainer, initVirtualScroll, props, debounceMs: 200 });
@@ -1,18 +1,23 @@
1
- export const Default_Col_Width = '100';
1
+ export const DEFAULT_COL_WIDTH = '100';
2
2
 
3
- export const Default_Table_Height = 100;
4
- export const Default_Table_Width = 200;
5
- export const Default_Row_Height = 28;
3
+ export const DEFAULT_TABLE_HEIGHT = 100;
4
+ export const DEFAULT_TABLE_WIDTH = 200;
5
+ export const DEFAULT_ROW_HEIGHT = 28;
6
6
 
7
7
  /** 高亮背景色 */
8
- export const Highlight_Color = {
8
+ export const HIGHLIGHT_COLOR = {
9
9
  light: { from: '#71a2fd', to: '#fff' },
10
10
  dark: { from: '#1e4c99', to: '#181c21' },
11
11
  };
12
12
  /** 高亮持续时间 */
13
- export const Highlight_Duration = 2000;
13
+ export const HIGHLIGHT_DURATION = 2000;
14
14
  /** 高亮变更频率 */
15
- export const Highlight_Color_Change_Freq = 100;
15
+ export const HIGHLIGHT_FREQ = 100;
16
+
17
+ /** 高亮行class */
18
+ export const HIGHLIGHT_ROW_CLASS = 'highlight-row';
19
+ /** 高连单元格class */
20
+ export const HIGHLIGHT_CELL_CLASS = 'highlight-cell';
16
21
 
17
22
  let _chromeVersion = 0;
18
23
  try {
@@ -24,4 +29,4 @@ try {
24
29
  console.error('Cannot get Chrome version', e);
25
30
  }
26
31
  /** 是否兼容低版本模式 */
27
- export const Is_Legacy_Mode = _chromeVersion < 56;
32
+ export const IS_LEGACY_MODE = _chromeVersion < 56;
@@ -23,6 +23,7 @@
23
23
  --bg-border-bottom: linear-gradient(0deg, var(--border-color) var(--border-width), transparent var(--border-width));
24
24
  --bg-border-left: linear-gradient(90deg, var(--border-color) var(--border-width), transparent var(--border-width));
25
25
  --highlight-color: #71a2fd;
26
+ --highlight-duration: 2s;
26
27
  /* 斑马纹颜色*/
27
28
  --stripe-bgc: #fafafc;
28
29
 
@@ -211,7 +212,7 @@
211
212
  }
212
213
 
213
214
  &.highlight-cell {
214
- animation: stk-table-dim 2s linear;
215
+ animation: stk-table-dim var(--highlight-duration) linear;
215
216
  }
216
217
 
217
218
  &.text-overflow {
@@ -351,7 +352,7 @@
351
352
 
352
353
  /* td inherit tr bgc*/
353
354
  &.highlight-row {
354
- animation: stk-table-dim 2s linear;
355
+ animation: stk-table-dim var(--highlight-duration) linear;
355
356
  }
356
357
 
357
358
  /* &.highlight-row-transition {
@@ -99,3 +99,16 @@ export const enum TagType {
99
99
  TH,
100
100
  TD,
101
101
  }
102
+
103
+ /** 高亮配置 */
104
+ export type HighlightConfig = {
105
+ /** 高亮持续时间(s) */
106
+ duration?: number;
107
+ /** 高亮背景色 */
108
+ color?: {
109
+ light?: { from: string; to: string };
110
+ dark?: { from: string; to: string };
111
+ };
112
+ /** 高亮帧率(虚拟滚动生效) */
113
+ fps?: number;
114
+ };
@@ -1,5 +1,5 @@
1
1
  import { CSSProperties, Ref, computed } from 'vue';
2
- import { Is_Legacy_Mode } from './const';
2
+ import { IS_LEGACY_MODE } from './const';
3
3
  import { StkTableColumn, TagType } from './types';
4
4
  import { VirtualScrollStore, VirtualScrollXStore } from './useVirtualScroll';
5
5
  import { getColWidth } from './utils';
@@ -77,14 +77,14 @@ export function useFixedStyle<DT extends Record<string, any>>({
77
77
  const style: CSSProperties = {};
78
78
  const { colKeyStore, refStore } = fixedColumnsPositionStore.value;
79
79
 
80
- if (Is_Legacy_Mode) {
80
+ if (IS_LEGACY_MODE) {
81
81
  style.position = 'relative';
82
82
  } else {
83
83
  style.position = 'sticky';
84
84
  }
85
85
  if (tagType === TagType.TH) {
86
86
  // TH
87
- if (Is_Legacy_Mode) {
87
+ if (IS_LEGACY_MODE) {
88
88
  style.top = virtualScroll.value.scrollTop + depth * props.rowHeight + 'px';
89
89
  } else {
90
90
  style.top = depth * props.rowHeight + 'px';
@@ -96,7 +96,7 @@ export function useFixedStyle<DT extends Record<string, any>>({
96
96
  }
97
97
 
98
98
  if (fixed === 'left' || fixed === 'right') {
99
- if (Is_Legacy_Mode) {
99
+ if (IS_LEGACY_MODE) {
100
100
  if (isFixedLeft) {
101
101
  if (virtualX_on.value) style.left = virtualScrollX.value.scrollLeft - virtualScrollX.value.offsetLeft + 'px';
102
102
  else style.left = virtualScrollX.value.scrollLeft + 'px';
@@ -1,10 +1,10 @@
1
1
  import { interpolateRgb } from 'd3-interpolate';
2
2
  import { Ref, computed, ref } from 'vue';
3
- import { Highlight_Color, Highlight_Color_Change_Freq, Highlight_Duration } from './const';
4
- import { UniqKey } from './types';
3
+ import { HIGHLIGHT_CELL_CLASS, HIGHLIGHT_COLOR, HIGHLIGHT_DURATION, HIGHLIGHT_FREQ, HIGHLIGHT_ROW_CLASS } from './const';
4
+ import { HighlightConfig, UniqKey } from './types';
5
5
 
6
6
  type Params = {
7
- props: { theme: 'light' | 'dark'; virtual: boolean; dataSource: any[] };
7
+ props: any;
8
8
  tableContainer: Ref<HTMLElement | undefined>;
9
9
  };
10
10
 
@@ -15,23 +15,28 @@ type HighlightRowStore = {
15
15
  bgc_progress: number;
16
16
  };
17
17
 
18
- /** 高亮行class */
19
- const HIGHLIGHT_ROW_CLASS = 'highlight-row';
20
- /** 高连单元格class */
21
- const HIGHLIGHT_CELL_CLASS = 'highlight-cell';
22
-
23
18
  /**
24
19
  * 高亮单元格,行
25
20
  * row中新增_bgc_progress_ms 属性控制高亮状态,_bgc控制颜色
26
21
  */
27
22
  export function useHighlight({ props, tableContainer }: Params) {
23
+ const config: HighlightConfig = props.highlightConfig;
28
24
  /**
29
25
  * 高亮行记录 key-rowKey, value-obj
30
26
  */
31
27
  const highlightRowStore = ref<Record<UniqKey, HighlightRowStore>>({});
32
-
33
- const highlightFrom = computed(() => Highlight_Color[props.theme].from);
34
- const highlightTo = computed(() => Highlight_Color[props.theme].to);
28
+ /** 持续时间 */
29
+ const duration = config.duration ? config.duration * 1000 : HIGHLIGHT_DURATION;
30
+ /** 频率 */
31
+ const frequency = config.fps ? 1000 / config.fps : HIGHLIGHT_FREQ;
32
+ const highlightColor = {
33
+ light: Object.assign(HIGHLIGHT_COLOR.light, config.color?.light),
34
+ dark: Object.assign(HIGHLIGHT_COLOR.dark, config.color?.dark),
35
+ };
36
+ /** 高亮开始 */
37
+ const highlightFrom = computed(() => highlightColor[props.theme as 'light' | 'dark'].from);
38
+ /** 高亮结束 */
39
+ const highlightTo = computed(() => highlightColor[props.theme as 'light' | 'dark'].to);
35
40
  const highlightInter = computed(() => interpolateRgb(highlightFrom.value, highlightTo.value));
36
41
 
37
42
  /** 存放高亮行的key*/
@@ -67,7 +72,7 @@ export function useHighlight({ props, tableContainer }: Params) {
67
72
  // }
68
73
  const highlightItem = highlightRowStore.value[rowKeyValue];
69
74
  /** 经过的时间 ÷ 高亮持续时间 计算出 颜色过渡进度 (0-1) */
70
- const progress = (nowTs - highlightItem.bgc_progress_ms) / Highlight_Duration;
75
+ const progress = (nowTs - highlightItem.bgc_progress_ms) / duration;
71
76
  if (0 < progress && progress < 1) {
72
77
  highlightItem.bgc = highlightInter.value(progress);
73
78
  } else {
@@ -86,39 +91,46 @@ export function useHighlight({ props, tableContainer }: Params) {
86
91
  // 没有则停止循环
87
92
  calcHighlightDimLoop = false;
88
93
  }
89
- }, Highlight_Color_Change_Freq);
94
+ }, frequency);
90
95
  };
91
96
  recursion();
92
97
  }
93
98
 
94
- /** 高亮一个单元格 */
95
- function setHighlightDimCell(rowKeyValue: string, dataIndex: string) {
99
+ /**
100
+ * 高亮一个单元格
101
+ * @param rowKeyValue 一行的key
102
+ * @param dataIndex 列key
103
+ * @param option.className 高亮类名
104
+ */
105
+ function setHighlightDimCell(rowKeyValue: string, dataIndex: string, option: { className?: string } = {}) {
96
106
  // TODO: 支持动态计算高亮颜色。不易实现。需记录每一个单元格的颜色情况。
97
107
  const cellEl = tableContainer.value?.querySelector<HTMLElement>(`[data-row-key="${rowKeyValue}"]>[data-index="${dataIndex}"]`);
108
+ const opt = { className: HIGHLIGHT_CELL_CLASS, ...option };
98
109
  if (!cellEl) return;
99
- if (cellEl.classList.contains(HIGHLIGHT_CELL_CLASS)) {
100
- cellEl.classList.remove(HIGHLIGHT_CELL_CLASS);
110
+ if (cellEl.classList.contains(opt.className)) {
111
+ cellEl.classList.remove(opt.className);
101
112
  void cellEl.offsetHeight; // 通知浏览器重绘
102
113
  }
103
- cellEl.classList.add(HIGHLIGHT_CELL_CLASS);
114
+ cellEl.classList.add(opt.className);
104
115
  window.clearTimeout(highlightDimCellsTimeout.get(rowKeyValue));
105
116
  highlightDimCellsTimeout.set(
106
117
  rowKeyValue,
107
118
  window.setTimeout(() => {
108
- cellEl.classList.remove(HIGHLIGHT_CELL_CLASS);
119
+ cellEl.classList.remove(opt.className);
109
120
  highlightDimCellsTimeout.delete(rowKeyValue);
110
- }, Highlight_Duration),
121
+ }, duration),
111
122
  );
112
123
  }
113
124
 
114
125
  /**
115
126
  * 高亮一行
116
- * @param rowKeyValues
127
+ * @param rowKeyValues 行唯一键的数组
117
128
  * @param option.useCss 虚拟滚动时,高亮由js控制。如果仍想使用css 关键帧控制,则配置此项
118
129
  */
119
- function setHighlightDimRow(rowKeyValues: UniqKey[], option: { useCss?: boolean } = {}) {
130
+ function setHighlightDimRow(rowKeyValues: UniqKey[], option: { useCss?: boolean; className?: string } = {}) {
120
131
  if (!Array.isArray(rowKeyValues)) rowKeyValues = [rowKeyValues];
121
- if (props.virtual && !option.useCss) {
132
+ const { className, useCss } = { className: HIGHLIGHT_ROW_CLASS, useCss: false, ...option };
133
+ if (props.virtual && !useCss) {
122
134
  // --------虚拟滚动用js计算颜色渐变的高亮方案
123
135
  const nowTs = Date.now(); // 重置渐变进度
124
136
  for (let i = 0; i < rowKeyValues.length; i++) {
@@ -141,8 +153,8 @@ export function useHighlight({ props, tableContainer }: Params) {
141
153
  const rowKeyValue = rowKeyValues[i];
142
154
  const rowEl = tableContainer.value?.querySelector<HTMLTableRowElement>(`[data-row-key="${rowKeyValue}"]`);
143
155
  if (!rowEl) continue;
144
- if (rowEl.classList.contains(HIGHLIGHT_ROW_CLASS)) {
145
- rowEl.classList.remove(HIGHLIGHT_ROW_CLASS);
156
+ if (rowEl.classList.contains(className)) {
157
+ rowEl.classList.remove(className);
146
158
  needRepaint = true;
147
159
  }
148
160
  rowElTemp.push(rowEl);
@@ -151,20 +163,21 @@ export function useHighlight({ props, tableContainer }: Params) {
151
163
  highlightDimRowsTimeout.set(
152
164
  rowKeyValue,
153
165
  window.setTimeout(() => {
154
- rowEl.classList.remove(HIGHLIGHT_ROW_CLASS);
166
+ rowEl.classList.remove(className);
155
167
  highlightDimRowsTimeout.delete(rowKeyValue); // 回收内存
156
- }, Highlight_Duration),
168
+ }, duration),
157
169
  );
158
170
  }
159
171
  if (needRepaint) {
160
172
  void tableContainer.value?.offsetWidth; //强制浏览器重绘
161
173
  }
162
- rowElTemp.forEach(el => el.classList.add(HIGHLIGHT_ROW_CLASS)); // 统一添加动画
174
+ rowElTemp.forEach(el => el.classList.add(className)); // 统一添加动画
163
175
  }
164
176
  }
165
177
 
166
178
  return {
167
179
  highlightRowStore,
180
+ highlightFrom,
168
181
  setHighlightDimRow,
169
182
  setHighlightDimCell,
170
183
  };
@@ -1,5 +1,5 @@
1
1
  import { Ref, ShallowRef, computed, ref } from 'vue';
2
- import { Default_Table_Height, Default_Table_Width } from './const';
2
+ import { DEFAULT_TABLE_HEIGHT, DEFAULT_TABLE_WIDTH } from './const';
3
3
  import { StkTableColumn } from './types';
4
4
  import { getColWidth } from './utils';
5
5
 
@@ -145,7 +145,7 @@ export function useVirtualScroll<DT extends Record<string, any>>({
145
145
  if (typeof height === 'number') {
146
146
  containerHeight = height;
147
147
  } else {
148
- containerHeight = offsetHeight || Default_Table_Height;
148
+ containerHeight = offsetHeight || DEFAULT_TABLE_HEIGHT;
149
149
  }
150
150
  const { headless, headerRowHeight } = props;
151
151
  let pageSize = Math.ceil(containerHeight / rowHeight);
@@ -162,7 +162,7 @@ export function useVirtualScroll<DT extends Record<string, any>>({
162
162
  if (!props.virtualX) return;
163
163
  const { offsetWidth, scrollLeft } = tableContainer.value || {};
164
164
  // scrollTo(null, 0);
165
- virtualScrollX.value.containerWidth = offsetWidth || Default_Table_Width;
165
+ virtualScrollX.value.containerWidth = offsetWidth || DEFAULT_TABLE_WIDTH;
166
166
  updateVirtualScrollX(scrollLeft);
167
167
  }
168
168
  /**
@@ -239,12 +239,16 @@ export function useVirtualScroll<DT extends Record<string, any>>({
239
239
  let offsetLeft = 0;
240
240
 
241
241
  let colWidthSum = 0;
242
+ let leftColWidthSum = 0;
242
243
  for (let colIndex = 0; colIndex < headerLength; colIndex++) {
243
244
  startIndex++;
244
245
  const col = tableHeaderLast.value[colIndex];
245
- // fixed left 不进入计算列宽
246
- if (col.fixed === 'left') continue;
247
246
  const colWidth = getColWidth(col);
247
+ // fixed left 不进入计算列宽
248
+ if (col.fixed === 'left') {
249
+ leftColWidthSum += colWidth;
250
+ continue;
251
+ }
248
252
  colWidthSum += colWidth;
249
253
  // 列宽(非固定列)加到超过scrollLeft的时候,表示startIndex从上一个开始下标
250
254
  if (colWidthSum >= sLeft) {
@@ -255,13 +259,14 @@ export function useVirtualScroll<DT extends Record<string, any>>({
255
259
  }
256
260
  // -----
257
261
  colWidthSum = 0;
262
+ const containerWidth = virtualScrollX.value.containerWidth - leftColWidthSum;
258
263
  let endIndex = headerLength;
259
264
  for (let colIndex = startIndex + 1; colIndex < headerLength; colIndex++) {
260
265
  const col = tableHeaderLast.value[colIndex];
261
266
  colWidthSum += getColWidth(col);
262
267
  // 列宽大于容器宽度则停止
263
- if (colWidthSum >= virtualScrollX.value.containerWidth) {
264
- endIndex = colIndex + 1; // TODO:预渲染的列数
268
+ if (colWidthSum >= containerWidth) {
269
+ endIndex = colIndex + 1; // 由于slice[start,end),要加1
265
270
  break;
266
271
  }
267
272
  }
@@ -1,4 +1,4 @@
1
- import { Default_Col_Width } from './const';
1
+ import { DEFAULT_COL_WIDTH } from './const';
2
2
  import { Order, SortConfig, SortOption, SortState, StkTableColumn } from './types';
3
3
 
4
4
  /** 是否空值 */
@@ -184,7 +184,7 @@ export function howDeepTheHeader(arr: StkTableColumn<any>[], level = 1) {
184
184
 
185
185
  /** 获取列宽 */
186
186
  export function getColWidth(col: StkTableColumn<any> | null): number {
187
- const val = col?.width ?? Default_Col_Width;
187
+ const val = col?.width ?? DEFAULT_COL_WIDTH;
188
188
  if (typeof val === 'number') {
189
189
  return Math.floor(val);
190
190
  }