stk-table-vue 0.6.9 → 0.6.10

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.
@@ -1,29 +1,29 @@
1
- import { DEFAULT_COL_WIDTH, STK_ID_PREFIX } from '../const';
2
- import { PrivateStkTableColumn, StkTableColumn } from '../types';
3
-
4
- /**
5
- * 获取列宽
6
- *
7
- * 关于列宽的操作往往在横向滚动中使用。既然已经有横向滚动了,则列宽会被压缩至minWidth,所以优先取minWidth
8
- */
9
- export function getColWidth(col: StkTableColumn<any> | null): number {
10
- const val = col?.minWidth ?? col?.width ?? DEFAULT_COL_WIDTH;
11
- if (typeof val === 'number') {
12
- return Math.floor(val);
13
- }
14
- return parseInt(val);
15
- }
16
-
17
- /** 获取计算后的宽度 */
18
- export function getCalculatedColWidth(col: PrivateStkTableColumn<any> | null) {
19
- return col?.__WIDTH__ ?? +DEFAULT_COL_WIDTH;
20
- }
21
-
22
- /** 创建组件唯一标识 */
23
- export function createStkTableId() {
24
- let id = window.__STK_TB_ID_COUNT__;
25
- if (!id) id = 0;
26
- id += 1;
27
- window.__STK_TB_ID_COUNT__ = id;
28
- return STK_ID_PREFIX + id.toString(36);
29
- }
1
+ import { DEFAULT_COL_WIDTH, STK_ID_PREFIX } from '../const';
2
+ import { PrivateStkTableColumn, StkTableColumn } from '../types';
3
+
4
+ /**
5
+ * 获取列宽
6
+ *
7
+ * 关于列宽的操作往往在横向滚动中使用。既然已经有横向滚动了,则列宽会被压缩至minWidth,所以优先取minWidth
8
+ */
9
+ export function getColWidth(col: StkTableColumn<any> | null): number {
10
+ const val = col?.minWidth ?? col?.width ?? DEFAULT_COL_WIDTH;
11
+ if (typeof val === 'number') {
12
+ return Math.floor(val);
13
+ }
14
+ return parseInt(val);
15
+ }
16
+
17
+ /** 获取计算后的宽度 */
18
+ export function getCalculatedColWidth(col: PrivateStkTableColumn<any> | null) {
19
+ return (col && col.__WIDTH__) ?? +DEFAULT_COL_WIDTH;
20
+ }
21
+
22
+ /** 创建组件唯一标识 */
23
+ export function createStkTableId() {
24
+ let id = window.__STK_TB_ID_COUNT__;
25
+ if (!id) id = 0;
26
+ id += 1;
27
+ window.__STK_TB_ID_COUNT__ = id;
28
+ return STK_ID_PREFIX + id.toString(36);
29
+ }
@@ -1,212 +1,212 @@
1
- import { Order, SortConfig, SortOption, SortState, StkTableColumn } from '../types';
2
-
3
- /** 是否空值 */
4
- export function isEmptyValue(val: any, isNumber?: boolean) {
5
- let isEmpty = val === null || val === void 0;
6
- if (isNumber) {
7
- isEmpty = isEmpty || typeof val === 'boolean' || Number.isNaN(+val);
8
- }
9
- return isEmpty;
10
- }
11
-
12
- /**
13
- * 对有序数组插入新数据
14
- *
15
- * 注意:不会改变原数组,返回新数组
16
- * @param sortState
17
- * @param sortState.dataIndex 排序的字段
18
- * @param sortState.order 排序顺序
19
- * @param sortState.sortType 排序方式
20
- * @param newItem 要插入的数据
21
- * @param targetArray 表格数据
22
- * @return targetArray 的浅拷贝
23
- */
24
- export function insertToOrderedArray<T extends object>(sortState: SortState<T>, newItem: T, targetArray: T[], sortConfig: SortConfig<T> = {}) {
25
- const { dataIndex, order } = sortState;
26
- sortConfig = { emptyToBottom: false, ...sortConfig };
27
- let { sortType } = sortState;
28
- if (!sortType) sortType = typeof newItem[dataIndex] as 'number' | 'string';
29
- const data = [...targetArray];
30
-
31
- if (!order || !data.length) {
32
- // 没有排序的情况,插入在最上方
33
- data.unshift(newItem);
34
- return data;
35
- }
36
-
37
- if (sortConfig.emptyToBottom && isEmptyValue(newItem)) {
38
- // 空值排在最下方
39
- data.push(newItem);
40
- }
41
-
42
- const isNumber = sortType === 'number';
43
-
44
- // 二分插入
45
- const targetVal: any = newItem[dataIndex];
46
- const sIndex = binarySearch(data, midIndex => {
47
- const midVal: any = data[midIndex][dataIndex];
48
- const compareRes = strCompare(midVal, targetVal, isNumber, sortConfig.stringLocaleCompare);
49
- return order === 'asc' ? compareRes : -compareRes;
50
- });
51
- data.splice(sIndex, 0, newItem);
52
- return data;
53
- }
54
-
55
- /**
56
- * 二分查找
57
- * @param searchArray 查找数组
58
- * @param compareCallback 比较函数,返回 -1|0|1
59
- */
60
- export function binarySearch(searchArray: any[], compareCallback: (midIndex: number) => number) {
61
- let sIndex = 0;
62
- let eIndex = searchArray.length - 1;
63
- while (sIndex <= eIndex) {
64
- const midIndex = Math.floor((sIndex + eIndex) / 2);
65
- const compareRes = compareCallback(midIndex);
66
- if (compareRes === 0) {
67
- //midVal == targetVal
68
- sIndex = midIndex;
69
- break;
70
- } else if (compareRes < 0) {
71
- // midVal < targetVal
72
- sIndex = midIndex + 1;
73
- } else {
74
- //midVal > targetVal
75
- eIndex = midIndex - 1;
76
- }
77
- }
78
- return sIndex;
79
- }
80
- /**
81
- * 字符串比较
82
- * @param a
83
- * @param b
84
- * @param type 类型
85
- * @param isNumber 是否是数字类型
86
- * @param localeCompare 是否 使用Array.prototyshpe.localeCompare
87
- * @return {number} <0: a < b, 0: a = b, >0: a > b
88
- */
89
- export function strCompare(a: string, b: string, isNumber: boolean, localeCompare = false): number {
90
- let _a: number | string = a;
91
- let _b: number | string = b;
92
- if (isNumber) {
93
- // 是数字就转数字
94
- _a = +a;
95
- _b = +b;
96
- } else if (localeCompare) {
97
- // 字符串才可以localeCompare
98
- return String(a).localeCompare(b);
99
- }
100
- if (_a > _b) return 1;
101
- else if (_a === _b) return 0;
102
- else return -1;
103
- }
104
-
105
- /**
106
- * 分离出空数据和非空数据成两个数组。NaN视为空数据。
107
- * @param sortOption
108
- * @param targetDataSource
109
- * @param isNumber 是否数字
110
- * @return [值数组,空数组]
111
- */
112
- function separatedData<T extends Record<string, any>>(sortOption: SortOption<T>, targetDataSource: T[], isNumber?: boolean) {
113
- const emptyArr: T[] = [];
114
- const valueArr: T[] = [];
115
-
116
- for (let i = 0; i < targetDataSource.length; i++) {
117
- const row = targetDataSource[i];
118
- const sortField = sortOption.sortField || sortOption.dataIndex;
119
- const isEmpty = isEmptyValue(row?.[sortField], isNumber); // deal row is null
120
- if (isEmpty) {
121
- emptyArr.push(row);
122
- } else {
123
- valueArr.push(row);
124
- }
125
- }
126
- return [valueArr, emptyArr] as const;
127
- }
128
-
129
- /**
130
- * 表格排序抽离
131
- * 可以在组件外部自己实现表格排序,组件配置remote,使表格不排序。
132
- * 使用者在@sort-change事件中自行更改table props 'dataSource'完成排序。
133
- * TODO: key 唯一值,排序字段相同时,根据唯一值排序。
134
- *
135
- * sortConfig.defaultSort 会在order为null时生效
136
- * @param sortOption 列配置
137
- * @param order 排序方式
138
- * @param dataSource 排序的数组
139
- */
140
- export function tableSort<T extends Record<string, any>>(
141
- sortOption: SortOption<T>,
142
- order: Order,
143
- dataSource: T[],
144
- sortConfig: SortConfig<T> = {},
145
- ): T[] {
146
- if (!dataSource?.length || !sortOption) return dataSource || [];
147
-
148
- sortConfig = { emptyToBottom: false, ...sortConfig };
149
- let targetDataSource = [...dataSource];
150
- let sortField = sortOption.sortField || sortOption.dataIndex;
151
-
152
- if (!order && sortConfig.defaultSort) {
153
- // 默认排序
154
- order = sortConfig.defaultSort.order;
155
- sortField = sortConfig.defaultSort.dataIndex;
156
- }
157
-
158
- if (typeof sortOption.sorter === 'function') {
159
- const customSorterData = sortOption.sorter(targetDataSource, { order, column: sortOption });
160
- if (customSorterData) targetDataSource = customSorterData;
161
- } else if (order) {
162
- let { sortType } = sortOption;
163
- if (!sortType) sortType = typeof dataSource[0][sortField] as 'number' | 'string';
164
-
165
- const isNumber = sortType === 'number';
166
- const [valueArr, emptyArr] = separatedData(sortOption, targetDataSource, isNumber);
167
-
168
- if (order === 'asc') {
169
- valueArr.sort((a, b) => strCompare(a[sortField], b[sortField], isNumber, sortConfig.stringLocaleCompare));
170
- } else {
171
- valueArr.sort((a, b) => strCompare(b[sortField], a[sortField], isNumber, sortConfig.stringLocaleCompare));
172
- }
173
-
174
- if (order === 'desc' || sortConfig.emptyToBottom) {
175
- targetDataSource = [...valueArr, ...emptyArr];
176
- } else {
177
- targetDataSource = [...emptyArr, ...valueArr];
178
- }
179
- }
180
- return targetDataSource;
181
- }
182
-
183
- /** 多级表头深度 从0开始为一级*/
184
- export function howDeepTheHeader(arr: StkTableColumn<any>[], level = 0) {
185
- const levels = [level];
186
- arr.forEach(item => {
187
- if (item.children?.length) {
188
- levels.push(howDeepTheHeader(item.children, level + 1));
189
- }
190
- });
191
- return Math.max(...levels);
192
- }
193
-
194
- /** number width +px */
195
- export function transformWidthToStr(width?: string | number) {
196
- if (width === void 0) return;
197
- const numberWidth = Number(width);
198
- return width + (!Number.isNaN(numberWidth) ? 'px' : '');
199
- }
200
-
201
- export function getBrowsersVersion(browserName: string) {
202
- try {
203
- const reg = new RegExp(`${browserName}/\\d+`, 'i');
204
- const userAgent = navigator.userAgent.match(reg);
205
- if (userAgent) {
206
- return +userAgent[0].split('/')[1];
207
- }
208
- } catch (e) {
209
- console.error('Cannot get version', e);
210
- }
211
- return 100;
212
- }
1
+ import { Order, SortConfig, SortOption, SortState, StkTableColumn } from '../types';
2
+
3
+ /** 是否空值 */
4
+ export function isEmptyValue(val: any, isNumber?: boolean) {
5
+ let isEmpty = val === null || val === void 0;
6
+ if (isNumber) {
7
+ isEmpty = isEmpty || typeof val === 'boolean' || Number.isNaN(+val);
8
+ }
9
+ return isEmpty;
10
+ }
11
+
12
+ /**
13
+ * 对有序数组插入新数据
14
+ *
15
+ * 注意:不会改变原数组,返回新数组
16
+ * @param sortState
17
+ * @param sortState.dataIndex 排序的字段
18
+ * @param sortState.order 排序顺序
19
+ * @param sortState.sortType 排序方式
20
+ * @param newItem 要插入的数据
21
+ * @param targetArray 表格数据
22
+ * @return targetArray 的浅拷贝
23
+ */
24
+ export function insertToOrderedArray<T extends object>(sortState: SortState<T>, newItem: T, targetArray: T[], sortConfig: SortConfig<T> = {}) {
25
+ const { dataIndex, order } = sortState;
26
+ sortConfig = { emptyToBottom: false, ...sortConfig };
27
+ let { sortType } = sortState;
28
+ if (!sortType) sortType = typeof newItem[dataIndex] as 'number' | 'string';
29
+ const data = targetArray.slice();
30
+
31
+ if (!order || !data.length) {
32
+ // 没有排序的情况,插入在最上方
33
+ data.unshift(newItem);
34
+ return data;
35
+ }
36
+
37
+ if (sortConfig.emptyToBottom && isEmptyValue(newItem)) {
38
+ // 空值排在最下方
39
+ data.push(newItem);
40
+ }
41
+
42
+ const isNumber = sortType === 'number';
43
+
44
+ // 二分插入
45
+ const targetVal: any = newItem[dataIndex];
46
+ const sIndex = binarySearch(data, midIndex => {
47
+ const midVal: any = data[midIndex][dataIndex];
48
+ const compareRes = strCompare(midVal, targetVal, isNumber, sortConfig.stringLocaleCompare);
49
+ return order === 'asc' ? compareRes : -compareRes;
50
+ });
51
+ data.splice(sIndex, 0, newItem);
52
+ return data;
53
+ }
54
+
55
+ /**
56
+ * 二分查找
57
+ * @param searchArray 查找数组
58
+ * @param compareCallback 比较函数,返回 -1|0|1
59
+ */
60
+ export function binarySearch(searchArray: any[], compareCallback: (midIndex: number) => number) {
61
+ let sIndex = 0;
62
+ let eIndex = searchArray.length - 1;
63
+ while (sIndex <= eIndex) {
64
+ const midIndex = Math.floor((sIndex + eIndex) / 2);
65
+ const compareRes = compareCallback(midIndex);
66
+ if (compareRes === 0) {
67
+ //midVal == targetVal
68
+ sIndex = midIndex;
69
+ break;
70
+ } else if (compareRes < 0) {
71
+ // midVal < targetVal
72
+ sIndex = midIndex + 1;
73
+ } else {
74
+ //midVal > targetVal
75
+ eIndex = midIndex - 1;
76
+ }
77
+ }
78
+ return sIndex;
79
+ }
80
+ /**
81
+ * 字符串比较
82
+ * @param a
83
+ * @param b
84
+ * @param type 类型
85
+ * @param isNumber 是否是数字类型
86
+ * @param localeCompare 是否 使用Array.prototyshpe.localeCompare
87
+ * @return {number} <0: a < b, 0: a = b, >0: a > b
88
+ */
89
+ export function strCompare(a: string, b: string, isNumber: boolean, localeCompare = false): number {
90
+ let _a: number | string = a;
91
+ let _b: number | string = b;
92
+ if (isNumber) {
93
+ // 是数字就转数字
94
+ _a = +a;
95
+ _b = +b;
96
+ } else if (localeCompare) {
97
+ // 字符串才可以localeCompare
98
+ return String(a).localeCompare(b);
99
+ }
100
+ if (_a > _b) return 1;
101
+ else if (_a === _b) return 0;
102
+ else return -1;
103
+ }
104
+
105
+ /**
106
+ * 分离出空数据和非空数据成两个数组。NaN视为空数据。
107
+ * @param sortOption
108
+ * @param targetDataSource
109
+ * @param isNumber 是否数字
110
+ * @return [值数组,空数组]
111
+ */
112
+ function separatedData<T extends Record<string, any>>(sortOption: SortOption<T>, targetDataSource: T[], isNumber?: boolean) {
113
+ const emptyArr: T[] = [];
114
+ const valueArr: T[] = [];
115
+
116
+ for (let i = 0; i < targetDataSource.length; i++) {
117
+ const row = targetDataSource[i];
118
+ const sortField = sortOption.sortField || sortOption.dataIndex;
119
+ const isEmpty = isEmptyValue(row?.[sortField], isNumber); // deal row is null
120
+ if (isEmpty) {
121
+ emptyArr.push(row);
122
+ } else {
123
+ valueArr.push(row);
124
+ }
125
+ }
126
+ return [valueArr, emptyArr] as const;
127
+ }
128
+
129
+ /**
130
+ * 表格排序抽离
131
+ * 可以在组件外部自己实现表格排序,组件配置remote,使表格不排序。
132
+ * 使用者在@sort-change事件中自行更改table props 'dataSource'完成排序。
133
+ * TODO: key 唯一值,排序字段相同时,根据唯一值排序。
134
+ *
135
+ * sortConfig.defaultSort 会在order为null时生效
136
+ * @param sortOption 列配置
137
+ * @param order 排序方式
138
+ * @param dataSource 排序的数组
139
+ */
140
+ export function tableSort<T extends Record<string, any>>(
141
+ sortOption: SortOption<T>,
142
+ order: Order,
143
+ dataSource: T[],
144
+ sortConfig: SortConfig<T> = {},
145
+ ): T[] {
146
+ if (!dataSource?.length || !sortOption) return dataSource || [];
147
+
148
+ sortConfig = { emptyToBottom: false, ...sortConfig };
149
+ let targetDataSource = dataSource.slice();
150
+ let sortField = sortOption.sortField || sortOption.dataIndex;
151
+
152
+ if (!order && sortConfig.defaultSort) {
153
+ // 默认排序
154
+ order = sortConfig.defaultSort.order;
155
+ sortField = sortConfig.defaultSort.dataIndex;
156
+ }
157
+
158
+ if (typeof sortOption.sorter === 'function') {
159
+ const customSorterData = sortOption.sorter(targetDataSource, { order, column: sortOption });
160
+ if (customSorterData) targetDataSource = customSorterData;
161
+ } else if (order) {
162
+ let { sortType } = sortOption;
163
+ if (!sortType) sortType = typeof dataSource[0][sortField] as 'number' | 'string';
164
+
165
+ const isNumber = sortType === 'number';
166
+ const [valueArr, emptyArr] = separatedData(sortOption, targetDataSource, isNumber);
167
+
168
+ if (order === 'asc') {
169
+ valueArr.sort((a, b) => strCompare(a[sortField], b[sortField], isNumber, sortConfig.stringLocaleCompare));
170
+ } else {
171
+ valueArr.sort((a, b) => strCompare(b[sortField], a[sortField], isNumber, sortConfig.stringLocaleCompare));
172
+ }
173
+
174
+ if (order === 'desc' || sortConfig.emptyToBottom) {
175
+ targetDataSource = valueArr.concat(emptyArr);
176
+ } else {
177
+ targetDataSource = emptyArr.concat(valueArr);
178
+ }
179
+ }
180
+ return targetDataSource;
181
+ }
182
+
183
+ /** 多级表头深度 从0开始为一级*/
184
+ export function howDeepTheHeader(arr: StkTableColumn<any>[], level = 0) {
185
+ const levels = [level];
186
+ arr.forEach(item => {
187
+ if (item.children?.length) {
188
+ levels.push(howDeepTheHeader(item.children, level + 1));
189
+ }
190
+ });
191
+ return Math.max(...levels);
192
+ }
193
+
194
+ /** number width +px */
195
+ export function transformWidthToStr(width?: string | number) {
196
+ if (width === void 0) return;
197
+ const numberWidth = Number(width);
198
+ return width + (!Number.isNaN(numberWidth) ? 'px' : '');
199
+ }
200
+
201
+ export function getBrowsersVersion(browserName: string) {
202
+ try {
203
+ const reg = new RegExp(`${browserName}/\\d+`, 'i');
204
+ const userAgent = navigator.userAgent.match(reg);
205
+ if (userAgent) {
206
+ return +userAgent[0].split('/')[1];
207
+ }
208
+ } catch (e) {
209
+ console.error('Cannot get version', e);
210
+ }
211
+ return 100;
212
+ }
@@ -1,33 +1,33 @@
1
- import { Ref, shallowRef } from 'vue';
2
-
3
- type UseTriggerRef<T> = {
4
- getRef: () => Ref<T>;
5
- getValue: () => T;
6
- setValue: (v: T) => void;
7
- triggerRef: () => void;
8
- };
9
- /**
10
- * 创建一个可触发更新的引用对象。
11
- * @template T 引用对象的类型。
12
- * @param initialValue 初始值。
13
- * @returns 包含获取引用、获取值、设置值和触发更新的函数的对象。
14
- */
15
- export function useTriggerRef<T>(initialValue: T): UseTriggerRef<T> {
16
- let value = initialValue;
17
- const ref = shallowRef(value);
18
-
19
- function getValue() {
20
- return value;
21
- }
22
- function setValue(v: T) {
23
- value = v;
24
- }
25
- function getRef() {
26
- return ref;
27
- }
28
- function triggerRef() {
29
- ref.value = value;
30
- }
31
-
32
- return { getRef, getValue, setValue, triggerRef };
33
- }
1
+ import { Ref, shallowRef } from 'vue';
2
+
3
+ type UseTriggerRef<T> = {
4
+ getRef: () => Ref<T>;
5
+ getValue: () => T;
6
+ setValue: (v: T) => void;
7
+ triggerRef: () => void;
8
+ };
9
+ /**
10
+ * 创建一个可触发更新的引用对象。
11
+ * @template T 引用对象的类型。
12
+ * @param initialValue 初始值。
13
+ * @returns 包含获取引用、获取值、设置值和触发更新的函数的对象。
14
+ */
15
+ export function useTriggerRef<T>(initialValue: T): UseTriggerRef<T> {
16
+ let value = initialValue;
17
+ const ref = shallowRef(value);
18
+
19
+ function getValue() {
20
+ return value;
21
+ }
22
+ function setValue(v: T) {
23
+ value = v;
24
+ }
25
+ function getRef() {
26
+ return ref;
27
+ }
28
+ function triggerRef() {
29
+ ref.value = value;
30
+ }
31
+
32
+ return { getRef, getValue, setValue, triggerRef };
33
+ }