@danielgindi/dgtable.js 2.0.6 → 2.0.8
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 +547 -282
- package/dist/SelectionHelper.d.ts +24 -0
- package/dist/SelectionHelper.d.ts.map +1 -0
- package/dist/by_column_filter.d.ts +14 -0
- package/dist/by_column_filter.d.ts.map +1 -0
- package/dist/cell_preview.d.ts +28 -0
- package/dist/cell_preview.d.ts.map +1 -0
- package/dist/column_collection.d.ts +41 -0
- package/dist/column_collection.d.ts.map +1 -0
- package/dist/column_resize.d.ts +25 -0
- package/dist/column_resize.d.ts.map +1 -0
- package/dist/constants.d.ts +19 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/header_events.d.ts +63 -0
- package/dist/header_events.d.ts.map +1 -0
- package/dist/helpers.d.ts +50 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/index.d.ts +166 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/internal.d.ts +56 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/lib.cjs.js +6906 -3933
- package/dist/lib.cjs.js.map +1 -1
- package/dist/lib.cjs.min.js +2 -2
- package/dist/lib.cjs.min.js.map +1 -1
- package/dist/lib.es6.js +6908 -3935
- package/dist/lib.es6.js.map +1 -1
- package/dist/lib.es6.min.js +2 -2
- package/dist/lib.es6.min.js.map +1 -1
- package/dist/lib.umd.js +9251 -4353
- package/dist/lib.umd.js.map +1 -1
- package/dist/lib.umd.min.js +2 -2
- package/dist/lib.umd.min.js.map +1 -1
- package/dist/private_types.d.ts +145 -0
- package/dist/private_types.d.ts.map +1 -0
- package/dist/rendering.d.ts +57 -0
- package/dist/rendering.d.ts.map +1 -0
- package/dist/row_collection.d.ts +38 -0
- package/dist/row_collection.d.ts.map +1 -0
- package/dist/types.d.ts +221 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/util.d.ts +9 -0
- package/dist/util.d.ts.map +1 -0
- package/eslint.config.mjs +1 -0
- package/package.json +17 -12
- package/src/SelectionHelper.ts +90 -0
- package/src/by_column_filter.ts +36 -0
- package/src/cell_preview.ts +325 -0
- package/src/column_collection.ts +131 -0
- package/src/column_resize.ts +363 -0
- package/src/constants.ts +22 -0
- package/src/header_events.ts +369 -0
- package/src/helpers.ts +291 -0
- package/src/index.ts +1628 -0
- package/src/internal.ts +263 -0
- package/src/private_types.ts +156 -0
- package/src/rendering.ts +771 -0
- package/src/row_collection.ts +197 -0
- package/src/types.ts +265 -0
- package/src/util.ts +27 -0
- package/tsconfig.json +38 -0
- package/src/SelectionHelper.js +0 -65
- package/src/by_column_filter.js +0 -25
- package/src/column_collection.js +0 -153
- package/src/index.js +0 -3999
- package/src/row_collection.js +0 -183
- package/src/util.js +0 -17
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type { RowData, ComparatorFunction, OnComparatorRequired, CustomSortingProvider } from './types';
|
|
2
|
+
|
|
3
|
+
// Private types
|
|
4
|
+
import {
|
|
5
|
+
OriginalRowIndex,
|
|
6
|
+
SortColumn,
|
|
7
|
+
} from './private_types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Options for RowCollection initialization
|
|
11
|
+
*/
|
|
12
|
+
interface RowCollectionOptions {
|
|
13
|
+
sortColumn?: SortColumn[];
|
|
14
|
+
onComparatorRequired?: OnComparatorRequired | null;
|
|
15
|
+
customSortingProvider?: CustomSortingProvider | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A collection of rows that extends Array functionality with sorting and filtering
|
|
20
|
+
*/
|
|
21
|
+
class RowCollection extends Array<RowData> {
|
|
22
|
+
sortColumn: SortColumn[];
|
|
23
|
+
onComparatorRequired: OnComparatorRequired | null = null;
|
|
24
|
+
customSortingProvider: CustomSortingProvider | null = null;
|
|
25
|
+
|
|
26
|
+
constructor(options?: RowCollectionOptions) {
|
|
27
|
+
super();
|
|
28
|
+
options = options || {};
|
|
29
|
+
this.sortColumn = options.sortColumn ?? [];
|
|
30
|
+
this.onComparatorRequired = options.onComparatorRequired ?? null;
|
|
31
|
+
this.customSortingProvider = options.customSortingProvider ?? null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Add a row or array of rows to this collection
|
|
36
|
+
*/
|
|
37
|
+
add(rows: RowData | RowData[], at?: number): void {
|
|
38
|
+
const isArray = Array.isArray(rows);
|
|
39
|
+
if (isArray) {
|
|
40
|
+
const rowArray = rows as RowData[];
|
|
41
|
+
if (typeof at === 'number') {
|
|
42
|
+
for (let i = 0, len = rowArray.length; i < len; i++) {
|
|
43
|
+
this.splice(at++, 0, rowArray[i]);
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
for (let i = 0, len = rowArray.length; i < len; i++) {
|
|
47
|
+
this.push(rowArray[i]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
const row = rows as RowData;
|
|
52
|
+
if (typeof at === 'number') {
|
|
53
|
+
this.splice(at, 0, row);
|
|
54
|
+
} else {
|
|
55
|
+
this.push(row);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Reset the collection with optional new rows
|
|
62
|
+
*/
|
|
63
|
+
reset(rows?: RowData | RowData[]): void {
|
|
64
|
+
this.length = 0;
|
|
65
|
+
if (rows) {
|
|
66
|
+
this.add(rows);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Create a filtered collection based on a filter function
|
|
72
|
+
*/
|
|
73
|
+
filteredCollection(
|
|
74
|
+
filterFunc: (row: RowData, args: unknown) => boolean,
|
|
75
|
+
args: unknown
|
|
76
|
+
): RowCollection | null {
|
|
77
|
+
if (filterFunc && args) {
|
|
78
|
+
const rows = new RowCollection({
|
|
79
|
+
sortColumn: this.sortColumn,
|
|
80
|
+
onComparatorRequired: this.onComparatorRequired,
|
|
81
|
+
customSortingProvider: this.customSortingProvider,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
for (let i = 0, len = this.length; i < len; i++) {
|
|
85
|
+
const row = this[i];
|
|
86
|
+
if (filterFunc(row, args)) {
|
|
87
|
+
(row as any)[OriginalRowIndex] = i;
|
|
88
|
+
rows.push(row);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return rows;
|
|
92
|
+
} else {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Sort the collection based on the current sort columns
|
|
99
|
+
* @returns the comparator function used, if any
|
|
100
|
+
*/
|
|
101
|
+
sort(compareFn?: (a: RowData, b: RowData) => number): this {
|
|
102
|
+
let comparator: ComparatorFunction | undefined;
|
|
103
|
+
|
|
104
|
+
// If a compare function is passed directly (from Array.sort), use native
|
|
105
|
+
if (typeof compareFn === 'function') {
|
|
106
|
+
return super.sort(compareFn);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (this.sortColumn.length) {
|
|
110
|
+
const comparators: ComparatorFunction[] = [];
|
|
111
|
+
|
|
112
|
+
for (let i = 0; i < this.sortColumn.length; i++) {
|
|
113
|
+
const defaultComparator = getDefaultComparator(this.sortColumn[i], this.sortColumn[i].descending);
|
|
114
|
+
let comp: ComparatorFunction | null = null;
|
|
115
|
+
if (this.onComparatorRequired) {
|
|
116
|
+
comp = this.onComparatorRequired(
|
|
117
|
+
this.sortColumn[i].column,
|
|
118
|
+
this.sortColumn[i].descending,
|
|
119
|
+
defaultComparator
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
if (!comp) {
|
|
123
|
+
comp = defaultComparator;
|
|
124
|
+
}
|
|
125
|
+
comparators.push(comp.bind(this));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (comparators.length === 1) {
|
|
129
|
+
comparator = comparators[0];
|
|
130
|
+
} else {
|
|
131
|
+
const len = comparators.length;
|
|
132
|
+
comparator = (leftRow: RowData, rightRow: RowData): number => {
|
|
133
|
+
let value = 0;
|
|
134
|
+
for (let i = 0; i < len; i++) {
|
|
135
|
+
value = comparators[i](leftRow, rightRow);
|
|
136
|
+
if (value !== 0) {
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return value;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const sorter = (data: RowData[]): RowData[] => {
|
|
145
|
+
data.sort(comparator);
|
|
146
|
+
return data;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
if (this.customSortingProvider) {
|
|
150
|
+
const results = this.customSortingProvider(this as unknown as RowData[], sorter);
|
|
151
|
+
if (results !== (this as unknown as RowData[])) {
|
|
152
|
+
this.splice(0, this.length, ...results);
|
|
153
|
+
}
|
|
154
|
+
} else {
|
|
155
|
+
sorter(this as unknown as RowData[]);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get a default comparator for a sort column
|
|
165
|
+
*/
|
|
166
|
+
function getDefaultComparator(column: SortColumn, descending: boolean): ComparatorFunction {
|
|
167
|
+
let comparePath = column.comparePath;
|
|
168
|
+
if (typeof comparePath === 'string') {
|
|
169
|
+
comparePath = (comparePath as unknown as string).split('.');
|
|
170
|
+
}
|
|
171
|
+
const pathLength = comparePath.length;
|
|
172
|
+
const hasPath = pathLength > 1;
|
|
173
|
+
|
|
174
|
+
const lessVal = descending ? 1 : -1;
|
|
175
|
+
const moreVal = descending ? -1 : 1;
|
|
176
|
+
|
|
177
|
+
return function (leftRow: RowData, rightRow: RowData): number {
|
|
178
|
+
let leftVal: unknown = leftRow[comparePath[0]];
|
|
179
|
+
let rightVal: unknown = rightRow[comparePath[0]];
|
|
180
|
+
|
|
181
|
+
if (hasPath) {
|
|
182
|
+
for (let i = 1; i < pathLength; i++) {
|
|
183
|
+
leftVal = leftVal && (leftVal as Record<string, unknown>)[comparePath[i]];
|
|
184
|
+
rightVal = rightVal && (rightVal as Record<string, unknown>)[comparePath[i]];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (leftVal === rightVal) return 0;
|
|
189
|
+
if (leftVal == null) return lessVal;
|
|
190
|
+
if (rightVal == null) return moreVal;
|
|
191
|
+
if (leftVal < rightVal) return lessVal;
|
|
192
|
+
return moreVal;
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export default RowCollection;
|
|
197
|
+
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import type { WidthType } from './constants';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Column sort specification
|
|
5
|
+
*/
|
|
6
|
+
export interface ColumnSortOptions {
|
|
7
|
+
column: string;
|
|
8
|
+
descending?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Serialized column sort for external use
|
|
13
|
+
*/
|
|
14
|
+
export interface SerializedColumnSort {
|
|
15
|
+
column: string;
|
|
16
|
+
descending: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Serialized column configuration
|
|
21
|
+
*/
|
|
22
|
+
export interface SerializedColumn {
|
|
23
|
+
order?: number | null;
|
|
24
|
+
width?: string | number | null;
|
|
25
|
+
visible?: boolean | null;
|
|
26
|
+
label?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Column definition options
|
|
31
|
+
*/
|
|
32
|
+
export interface ColumnOptions {
|
|
33
|
+
name: string;
|
|
34
|
+
label?: string | null;
|
|
35
|
+
width?: number | string | null;
|
|
36
|
+
dataPath?: string | string[] | null;
|
|
37
|
+
comparePath?: string | string[] | null;
|
|
38
|
+
resizable?: boolean | null;
|
|
39
|
+
movable?: boolean | null;
|
|
40
|
+
sortable?: boolean | null;
|
|
41
|
+
visible?: boolean | null;
|
|
42
|
+
cellClasses?: string | null;
|
|
43
|
+
ignoreMin?: boolean | null;
|
|
44
|
+
sticky?: 'start' | 'end' | false | null;
|
|
45
|
+
order?: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Row data type - can be any object with string keys
|
|
50
|
+
*/
|
|
51
|
+
export type RowData = Record<string, unknown>
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Cell formatter function
|
|
55
|
+
*/
|
|
56
|
+
export type CellFormatter = ((value: unknown, columnName: string, rowData: RowData) => string) & {
|
|
57
|
+
[key: symbol]: boolean;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Header cell formatter function
|
|
62
|
+
*/
|
|
63
|
+
export type HeaderCellFormatter = (label: string, columnName: string) => string;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Filter function
|
|
67
|
+
*/
|
|
68
|
+
export type FilterFunction = (row: RowData, args: unknown) => boolean;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Comparator function
|
|
72
|
+
*/
|
|
73
|
+
export type ComparatorFunction = (a: RowData, b: RowData) => number;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Comparator callback
|
|
77
|
+
*/
|
|
78
|
+
export type OnComparatorRequired = (
|
|
79
|
+
columnName: string,
|
|
80
|
+
descending: boolean,
|
|
81
|
+
defaultComparator: ComparatorFunction
|
|
82
|
+
) => ComparatorFunction;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Custom sorting provider
|
|
86
|
+
*/
|
|
87
|
+
export type CustomSortingProvider = (
|
|
88
|
+
data: RowData[],
|
|
89
|
+
sort: (data: RowData[]) => RowData[]
|
|
90
|
+
) => RowData[];
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* DGTable initialization options
|
|
94
|
+
*/
|
|
95
|
+
export interface DGTableOptions {
|
|
96
|
+
el?: Element | null;
|
|
97
|
+
className?: string | null;
|
|
98
|
+
columns?: ColumnOptions[];
|
|
99
|
+
height?: number;
|
|
100
|
+
width?: WidthType;
|
|
101
|
+
virtualTable?: boolean | null;
|
|
102
|
+
estimatedRowHeight?: number | null;
|
|
103
|
+
resizableColumns?: boolean | null;
|
|
104
|
+
movableColumns?: boolean | null;
|
|
105
|
+
sortableColumns?: number | null;
|
|
106
|
+
adjustColumnWidthForSortArrow?: boolean | null;
|
|
107
|
+
relativeWidthGrowsToFillWidth?: boolean | null;
|
|
108
|
+
relativeWidthShrinksToFillWidth?: boolean | null;
|
|
109
|
+
convertColumnWidthsToRelative?: boolean | null;
|
|
110
|
+
autoFillTableWidth?: boolean | null;
|
|
111
|
+
allowCancelSort?: boolean | null;
|
|
112
|
+
cellClasses?: string | null;
|
|
113
|
+
sortColumn?: string | string[] | ColumnSortOptions | ColumnSortOptions[];
|
|
114
|
+
cellFormatter?: CellFormatter | null;
|
|
115
|
+
headerCellFormatter?: HeaderCellFormatter | null;
|
|
116
|
+
rowsBufferSize?: number | null;
|
|
117
|
+
minColumnWidth?: number | null;
|
|
118
|
+
resizeAreaWidth?: number | null;
|
|
119
|
+
onComparatorRequired?: OnComparatorRequired | null;
|
|
120
|
+
comparatorCallback?: OnComparatorRequired | null; // deprecated
|
|
121
|
+
customSortingProvider?: CustomSortingProvider | null;
|
|
122
|
+
resizerClassName?: string | null;
|
|
123
|
+
tableClassName?: string | null;
|
|
124
|
+
allowCellPreview?: boolean | null;
|
|
125
|
+
allowHeaderCellPreview?: boolean | null;
|
|
126
|
+
cellPreviewClassName?: string | null;
|
|
127
|
+
cellPreviewAutoBackground?: boolean | null;
|
|
128
|
+
filter?: FilterFunction | null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ============================================================================
|
|
132
|
+
// Event Types
|
|
133
|
+
// ============================================================================
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Event data for 'rowcreate' event
|
|
137
|
+
*/
|
|
138
|
+
export interface RowCreateEvent {
|
|
139
|
+
filteredRowIndex: number;
|
|
140
|
+
rowIndex: number;
|
|
141
|
+
rowEl: HTMLElement;
|
|
142
|
+
rowData: RowData;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Event data for 'rowclick' event
|
|
147
|
+
*/
|
|
148
|
+
export interface RowClickEvent {
|
|
149
|
+
event: MouseEvent;
|
|
150
|
+
filteredRowIndex: number;
|
|
151
|
+
rowIndex: number;
|
|
152
|
+
rowEl: HTMLElement;
|
|
153
|
+
rowData: RowData;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Event data for 'cellpreview' event
|
|
158
|
+
*/
|
|
159
|
+
export interface CellPreviewEvent {
|
|
160
|
+
el: Element | null;
|
|
161
|
+
name: string;
|
|
162
|
+
rowIndex: number | null;
|
|
163
|
+
rowData: RowData | null;
|
|
164
|
+
cell: HTMLElement;
|
|
165
|
+
cellEl: HTMLElement;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Event data for 'cellpreviewdestroy' event
|
|
170
|
+
*/
|
|
171
|
+
export interface CellPreviewDestroyEvent {
|
|
172
|
+
el: ChildNode | null;
|
|
173
|
+
name: string;
|
|
174
|
+
rowIndex: number | null;
|
|
175
|
+
rowData: RowData | null;
|
|
176
|
+
cell: HTMLElement | null;
|
|
177
|
+
cellEl: ChildNode | null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Event data for 'headercontextmenu' event
|
|
182
|
+
*/
|
|
183
|
+
export interface HeaderContextMenuEvent {
|
|
184
|
+
columnName: string;
|
|
185
|
+
pageX: number;
|
|
186
|
+
pageY: number;
|
|
187
|
+
bounds: {
|
|
188
|
+
left: number;
|
|
189
|
+
top: number;
|
|
190
|
+
width: number;
|
|
191
|
+
height: number;
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Event data for 'movecolumn' event
|
|
197
|
+
*/
|
|
198
|
+
export interface MoveColumnEvent {
|
|
199
|
+
name: string;
|
|
200
|
+
src: number;
|
|
201
|
+
dest: number;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Event data for 'columnwidth' event
|
|
206
|
+
*/
|
|
207
|
+
export interface ColumnWidthEvent {
|
|
208
|
+
name: string;
|
|
209
|
+
width: number;
|
|
210
|
+
oldWidth: number;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Event data for 'addrows' event
|
|
215
|
+
*/
|
|
216
|
+
export interface AddRowsEvent {
|
|
217
|
+
count: number;
|
|
218
|
+
clear: boolean;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Event data for 'sort' event
|
|
223
|
+
*/
|
|
224
|
+
export interface SortEvent {
|
|
225
|
+
sorts: SerializedColumnSort[];
|
|
226
|
+
resort?: boolean;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Map of all DGTable events to their data types.
|
|
231
|
+
* Used for type-safe event handlers with autocompletion.
|
|
232
|
+
*/
|
|
233
|
+
export interface DGTableEventMap {
|
|
234
|
+
// Rendering events
|
|
235
|
+
'render': undefined;
|
|
236
|
+
'renderskeleton': undefined;
|
|
237
|
+
|
|
238
|
+
// Row events
|
|
239
|
+
'rowcreate': RowCreateEvent;
|
|
240
|
+
'rowclick': RowClickEvent;
|
|
241
|
+
'rowdestroy': HTMLElement;
|
|
242
|
+
|
|
243
|
+
// Cell preview events
|
|
244
|
+
'cellpreview': CellPreviewEvent;
|
|
245
|
+
'cellpreviewdestroy': CellPreviewDestroyEvent;
|
|
246
|
+
|
|
247
|
+
// Header events
|
|
248
|
+
'headerrowcreate': HTMLElement;
|
|
249
|
+
'headercontextmenu': HeaderContextMenuEvent;
|
|
250
|
+
|
|
251
|
+
// Column events
|
|
252
|
+
'addcolumn': string;
|
|
253
|
+
'removecolumn': string;
|
|
254
|
+
'movecolumn': MoveColumnEvent;
|
|
255
|
+
'showcolumn': string;
|
|
256
|
+
'hidecolumn': string;
|
|
257
|
+
'columnwidth': ColumnWidthEvent;
|
|
258
|
+
|
|
259
|
+
// Data events
|
|
260
|
+
'addrows': AddRowsEvent;
|
|
261
|
+
'sort': SortEvent;
|
|
262
|
+
'filter': unknown;
|
|
263
|
+
'filterclear': Record<string, never>;
|
|
264
|
+
}
|
|
265
|
+
|
package/src/util.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find an element in an array using a predicate function
|
|
3
|
+
*/
|
|
4
|
+
export function find<T>(
|
|
5
|
+
array: T[],
|
|
6
|
+
predicate: (item: T, index: number, array: T[]) => boolean
|
|
7
|
+
): T | undefined {
|
|
8
|
+
for (let i = 0, len = array.length; i >= 0 && i < len; i += 1) {
|
|
9
|
+
if (predicate(array[i], i, array))
|
|
10
|
+
return array[i];
|
|
11
|
+
}
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Encode text for safe HTML display
|
|
17
|
+
*/
|
|
18
|
+
export function htmlEncode(text: string): string {
|
|
19
|
+
return text
|
|
20
|
+
.replace(/&/g, '&')
|
|
21
|
+
.replace(/</g, '<')
|
|
22
|
+
.replace(/>/g, '>')
|
|
23
|
+
.replace(/'/g, ''')
|
|
24
|
+
.replace(/"/g, '"')
|
|
25
|
+
.replace(/\n/g, '<br />');
|
|
26
|
+
}
|
|
27
|
+
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noImplicitAny": true,
|
|
9
|
+
"strictNullChecks": false,
|
|
10
|
+
"strictFunctionTypes": true,
|
|
11
|
+
"strictBindCallApply": true,
|
|
12
|
+
"strictPropertyInitialization": false,
|
|
13
|
+
"noImplicitThis": true,
|
|
14
|
+
"useUnknownInCatchVariables": false,
|
|
15
|
+
"alwaysStrict": true,
|
|
16
|
+
"noUnusedLocals": false,
|
|
17
|
+
"noUnusedParameters": false,
|
|
18
|
+
"noImplicitReturns": false,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"noUncheckedIndexedAccess": false,
|
|
21
|
+
"esModuleInterop": true,
|
|
22
|
+
"allowSyntheticDefaultImports": true,
|
|
23
|
+
"forceConsistentCasingInFileNames": true,
|
|
24
|
+
"skipLibCheck": true,
|
|
25
|
+
"declaration": true,
|
|
26
|
+
"declarationMap": true,
|
|
27
|
+
"sourceMap": true,
|
|
28
|
+
"outDir": "./dist",
|
|
29
|
+
"rootDir": "./src",
|
|
30
|
+
"baseUrl": ".",
|
|
31
|
+
"paths": {
|
|
32
|
+
"@/*": ["src/*"]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"include": ["src/**/*"],
|
|
36
|
+
"exclude": ["node_modules", "dist"]
|
|
37
|
+
}
|
|
38
|
+
|
package/src/SelectionHelper.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/* eslint-env browser */
|
|
2
|
-
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
// saveSelection/restoreSelection courtesy of Tim Down, with my improvements
|
|
6
|
-
// https://stackoverflow.com/questions/13949059/persisting-the-changes-of-range-objects-after-selection-in-html/13950376#13950376
|
|
7
|
-
|
|
8
|
-
function isChildOf(child, parent) {
|
|
9
|
-
while ((child = child.parentNode) && child !== parent);
|
|
10
|
-
return !!child;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
class SelectionHelper {
|
|
14
|
-
|
|
15
|
-
static saveSelection(el) {
|
|
16
|
-
let range = window.getSelection().getRangeAt(0);
|
|
17
|
-
|
|
18
|
-
if (el !== range.commonAncestorContainer && !isChildOf(range.commonAncestorContainer, el))
|
|
19
|
-
return null;
|
|
20
|
-
|
|
21
|
-
let preSelectionRange = range.cloneRange();
|
|
22
|
-
preSelectionRange.selectNodeContents(el);
|
|
23
|
-
preSelectionRange.setEnd(range.startContainer, range.startOffset);
|
|
24
|
-
let start = preSelectionRange.toString().length;
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
start: start,
|
|
28
|
-
end: start + range.toString().length,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
static restoreSelection(el, savedSel) {
|
|
33
|
-
let charIndex = 0;
|
|
34
|
-
let nodeStack = [el], node, foundStart = false, stop = false;
|
|
35
|
-
let range = document.createRange();
|
|
36
|
-
range.setStart(el, 0);
|
|
37
|
-
range.collapse(true);
|
|
38
|
-
|
|
39
|
-
while (!stop && (node = nodeStack.pop())) {
|
|
40
|
-
if (node.nodeType === 3) {
|
|
41
|
-
let nextCharIndex = charIndex + node.length;
|
|
42
|
-
if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
|
|
43
|
-
range.setStart(node, savedSel.start - charIndex);
|
|
44
|
-
foundStart = true;
|
|
45
|
-
}
|
|
46
|
-
if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
|
|
47
|
-
range.setEnd(node, savedSel.end - charIndex);
|
|
48
|
-
stop = true;
|
|
49
|
-
}
|
|
50
|
-
charIndex = nextCharIndex;
|
|
51
|
-
} else {
|
|
52
|
-
let i = node.childNodes.length;
|
|
53
|
-
while (i--) {
|
|
54
|
-
nodeStack.push(node.childNodes[i]);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
let sel = window.getSelection();
|
|
60
|
-
sel.removeAllRanges();
|
|
61
|
-
sel.addRange(range);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export default SelectionHelper;
|
package/src/by_column_filter.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
function ByColumnFilter (row, args) {
|
|
4
|
-
|
|
5
|
-
let column = args.column;
|
|
6
|
-
let keyword = args.keyword == null ? '' : args.keyword.toString();
|
|
7
|
-
|
|
8
|
-
if (!keyword || !column) return true;
|
|
9
|
-
|
|
10
|
-
let actualVal = row[column];
|
|
11
|
-
if (actualVal == null) {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
actualVal = actualVal.toString();
|
|
16
|
-
|
|
17
|
-
if (!args.caseSensitive) {
|
|
18
|
-
actualVal = actualVal.toLowerCase();
|
|
19
|
-
keyword = keyword.toLowerCase();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return actualVal.indexOf(keyword) !== -1;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export default ByColumnFilter;
|