@triptyk/ember-yeti-table 3.0.0
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/LICENSE.md +9 -0
- package/README.md +132 -0
- package/addon-main.cjs +4 -0
- package/declarations/themes/default-theme.d.ts +28 -0
- package/declarations/themes/default-theme.d.ts.map +1 -0
- package/declarations/utils/create-regex.d.ts +2 -0
- package/declarations/utils/create-regex.d.ts.map +1 -0
- package/declarations/utils/filtering-utils.d.ts +5 -0
- package/declarations/utils/filtering-utils.d.ts.map +1 -0
- package/declarations/utils/sorting-utils.d.ts +24 -0
- package/declarations/utils/sorting-utils.d.ts.map +1 -0
- package/dist/_app_/components/yeti-table/body.js +1 -0
- package/dist/_app_/components/yeti-table/header.js +1 -0
- package/dist/_app_/components/yeti-table/pagination.js +1 -0
- package/dist/_app_/components/yeti-table/table.js +1 -0
- package/dist/_app_/components/yeti-table/tbody/row/cell.js +1 -0
- package/dist/_app_/components/yeti-table/tbody/row.js +1 -0
- package/dist/_app_/components/yeti-table/tbody.js +1 -0
- package/dist/_app_/components/yeti-table/tfoot/row/cell.js +1 -0
- package/dist/_app_/components/yeti-table/tfoot/row.js +1 -0
- package/dist/_app_/components/yeti-table/tfoot.js +1 -0
- package/dist/_app_/components/yeti-table/thead/row/cell.js +1 -0
- package/dist/_app_/components/yeti-table/thead/row/column.js +1 -0
- package/dist/_app_/components/yeti-table/thead/row.js +1 -0
- package/dist/_app_/components/yeti-table/thead.js +1 -0
- package/dist/_app_/components/yeti-table.js +1 -0
- package/dist/_app_/themes/default-theme.js +1 -0
- package/dist/_app_/utils/create-regex.js +1 -0
- package/dist/_app_/utils/filtering-utils.js +1 -0
- package/dist/_app_/utils/sorting-utils.js +1 -0
- package/dist/components/yeti-table/body.js +37 -0
- package/dist/components/yeti-table/body.js.map +1 -0
- package/dist/components/yeti-table/header.js +30 -0
- package/dist/components/yeti-table/header.js.map +1 -0
- package/dist/components/yeti-table/pagination.js +86 -0
- package/dist/components/yeti-table/pagination.js.map +1 -0
- package/dist/components/yeti-table/table.js +38 -0
- package/dist/components/yeti-table/table.js.map +1 -0
- package/dist/components/yeti-table/tbody/row/cell.js +35 -0
- package/dist/components/yeti-table/tbody/row/cell.js.map +1 -0
- package/dist/components/yeti-table/tbody/row.js +47 -0
- package/dist/components/yeti-table/tbody/row.js.map +1 -0
- package/dist/components/yeti-table/tbody.js +20 -0
- package/dist/components/yeti-table/tbody.js.map +1 -0
- package/dist/components/yeti-table/tfoot/row/cell.js +31 -0
- package/dist/components/yeti-table/tfoot/row/cell.js.map +1 -0
- package/dist/components/yeti-table/tfoot/row.js +31 -0
- package/dist/components/yeti-table/tfoot/row.js.map +1 -0
- package/dist/components/yeti-table/tfoot.js +20 -0
- package/dist/components/yeti-table/tfoot.js.map +1 -0
- package/dist/components/yeti-table/thead/row/cell.js +24 -0
- package/dist/components/yeti-table/thead/row/cell.js.map +1 -0
- package/dist/components/yeti-table/thead/row/column.js +202 -0
- package/dist/components/yeti-table/thead/row/column.js.map +1 -0
- package/dist/components/yeti-table/thead/row.js +41 -0
- package/dist/components/yeti-table/thead/row.js.map +1 -0
- package/dist/components/yeti-table/thead.js +35 -0
- package/dist/components/yeti-table/thead.js.map +1 -0
- package/dist/components/yeti-table.js +618 -0
- package/dist/components/yeti-table.js.map +1 -0
- package/dist/themes/default-theme.js +51 -0
- package/dist/themes/default-theme.js.map +1 -0
- package/dist/utils/create-regex.js +34 -0
- package/dist/utils/create-regex.js.map +1 -0
- package/dist/utils/filtering-utils.js +55 -0
- package/dist/utils/filtering-utils.js.map +1 -0
- package/dist/utils/sorting-utils.js +93 -0
- package/dist/utils/sorting-utils.js.map +1 -0
- package/package.json +124 -0
- package/src/.gitkeep +0 -0
- package/src/components/yeti-table/body.gjs +94 -0
- package/src/components/yeti-table/header.gjs +54 -0
- package/src/components/yeti-table/pagination.gjs +155 -0
- package/src/components/yeti-table/table.gjs +34 -0
- package/src/components/yeti-table/tbody/row/cell.gjs +51 -0
- package/src/components/yeti-table/tbody/row.gjs +89 -0
- package/src/components/yeti-table/tbody.gjs +55 -0
- package/src/components/yeti-table/tfoot/row/cell.gjs +45 -0
- package/src/components/yeti-table/tfoot/row.gjs +44 -0
- package/src/components/yeti-table/tfoot.gjs +33 -0
- package/src/components/yeti-table/thead/row/cell.gjs +52 -0
- package/src/components/yeti-table/thead/row/column.gjs +260 -0
- package/src/components/yeti-table/thead/row.gjs +71 -0
- package/src/components/yeti-table/thead.gjs +45 -0
- package/src/components/yeti-table.gjs +780 -0
- package/src/themes/default-theme.js +53 -0
- package/src/utils/create-regex.js +65 -0
- package/src/utils/filtering-utils.js +75 -0
- package/src/utils/sorting-utils.js +108 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// BEGIN-SNIPPET default-theme.js
|
|
2
|
+
export default {
|
|
3
|
+
// applied to the <table> element
|
|
4
|
+
table: 'yeti-table',
|
|
5
|
+
// applied to any <tr>, wether it is from the header, body or footer
|
|
6
|
+
row: '',
|
|
7
|
+
|
|
8
|
+
// applied to the <thead> element
|
|
9
|
+
thead: '',
|
|
10
|
+
// applied to <tr> rows inside the <thead> element
|
|
11
|
+
theadRow: '',
|
|
12
|
+
// applied to <th> cells inside the <thead> element
|
|
13
|
+
theadCell: '',
|
|
14
|
+
|
|
15
|
+
// applied to the <tbody> element
|
|
16
|
+
tbody: '',
|
|
17
|
+
// applied to <tr> rows inside the <tbody> element
|
|
18
|
+
tbodyRow: '',
|
|
19
|
+
// applied to <td> cells inside the <thead> element
|
|
20
|
+
tbodyCell: '',
|
|
21
|
+
|
|
22
|
+
// applied to the <tfoot> element
|
|
23
|
+
tfoot: '',
|
|
24
|
+
// applied to <tr> rows inside the <tfoot> element
|
|
25
|
+
tfootRow: '',
|
|
26
|
+
// applied to <td> cells inside the <tfoot> element
|
|
27
|
+
tfootCell: '',
|
|
28
|
+
|
|
29
|
+
sorting: {
|
|
30
|
+
// applied to <th> header cells when column is sortable
|
|
31
|
+
columnSortable: 'yeti-table-sortable',
|
|
32
|
+
// applied to <th> header cells when column is currently sorted
|
|
33
|
+
columnSorted: 'yeti-table-sorted',
|
|
34
|
+
// applied to <th> header cells when column is currently sorted ascending
|
|
35
|
+
columnSortedAsc: 'yeti-table-sorted-asc',
|
|
36
|
+
// applied to <th> header cells when column is currently sorted descending
|
|
37
|
+
columnSortedDesc: 'yeti-table-sorted-desc',
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
pagination: {
|
|
41
|
+
// applied to the pagination controls container
|
|
42
|
+
controls: 'yeti-table-pagination-controls',
|
|
43
|
+
// applied to the pagination information element
|
|
44
|
+
info: 'yeti-table-pagination-controls-page-info',
|
|
45
|
+
// applied to the pageSize select element
|
|
46
|
+
pageSize: 'yeti-table-pagination-controls-page-size',
|
|
47
|
+
// applied to the next button
|
|
48
|
+
next: 'yeti-table-pagination-controls-next',
|
|
49
|
+
// applied to the previous button
|
|
50
|
+
previous: 'yeti-table-pagination-controls-previous',
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
// END-SNIPPET
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { isBlank } from '@ember/utils';
|
|
2
|
+
|
|
3
|
+
const ESCAPE_REGEX = new RegExp(
|
|
4
|
+
'(\\' +
|
|
5
|
+
[
|
|
6
|
+
'/',
|
|
7
|
+
'.',
|
|
8
|
+
'*',
|
|
9
|
+
'+',
|
|
10
|
+
'?',
|
|
11
|
+
'|',
|
|
12
|
+
'(',
|
|
13
|
+
')',
|
|
14
|
+
'[',
|
|
15
|
+
']',
|
|
16
|
+
'{',
|
|
17
|
+
'}',
|
|
18
|
+
'\\',
|
|
19
|
+
'$',
|
|
20
|
+
'^',
|
|
21
|
+
'-',
|
|
22
|
+
].join('|\\') +
|
|
23
|
+
')',
|
|
24
|
+
'g',
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
function escapeRegex(val) {
|
|
28
|
+
return val.replace(ESCAPE_REGEX, '\\$1');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default function createRegex(
|
|
32
|
+
search,
|
|
33
|
+
regex = false,
|
|
34
|
+
smart = true,
|
|
35
|
+
caseInsensitive = true,
|
|
36
|
+
) {
|
|
37
|
+
if (isBlank(search)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
search = regex ? search : escapeRegex(search);
|
|
42
|
+
|
|
43
|
+
if (smart) {
|
|
44
|
+
/* For smart filtering we want to allow the search to work regardless of
|
|
45
|
+
* word order. We also want double quoted text to be preserved, so word
|
|
46
|
+
* order is important - a la google. So this is what we want to
|
|
47
|
+
* generate:
|
|
48
|
+
*
|
|
49
|
+
* ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
|
|
50
|
+
*/
|
|
51
|
+
let words = search.match(/"[^"]+"|[^ ]+/g) || [''];
|
|
52
|
+
let a = words.map((word) => {
|
|
53
|
+
if (word.charAt(0) === '"') {
|
|
54
|
+
let m = word.match(/^"(.*)"$/);
|
|
55
|
+
word = m ? m[1] : word;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return word.replace('"', '');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
search = `^(?=.*?${a.join(')(?=.*?')}).*$`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return new RegExp(search, caseInsensitive ? 'i' : '');
|
|
65
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { isEmpty } from '@ember/utils';
|
|
2
|
+
import { get } from '@ember/object';
|
|
3
|
+
|
|
4
|
+
import createRegex from './create-regex.js';
|
|
5
|
+
|
|
6
|
+
function createColumnFilters(columns) {
|
|
7
|
+
let searcheableColumns = columns.filter((c) => {
|
|
8
|
+
return !isEmpty(c.filter) || !isEmpty(c.filterFunction);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
return searcheableColumns.map((c) => {
|
|
12
|
+
let regex = createRegex(c.filter);
|
|
13
|
+
|
|
14
|
+
return (row) => {
|
|
15
|
+
let value = get(row, c.prop);
|
|
16
|
+
let passesRegex = true;
|
|
17
|
+
|
|
18
|
+
if (!isEmpty(c.filter)) {
|
|
19
|
+
passesRegex = regex.test(value);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let passesCustom = true;
|
|
23
|
+
|
|
24
|
+
if (!isEmpty(c.filterFunction)) {
|
|
25
|
+
passesCustom = c.filterFunction(value, c.filterUsing);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return passesRegex && passesCustom;
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default function filterData(
|
|
34
|
+
data,
|
|
35
|
+
columns,
|
|
36
|
+
globalFilter,
|
|
37
|
+
filterFunction,
|
|
38
|
+
filterUsing,
|
|
39
|
+
) {
|
|
40
|
+
if (isEmpty(data)) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (isEmpty(columns)) {
|
|
45
|
+
// bail out if there are no columns to filter
|
|
46
|
+
return data;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let globalRegex = createRegex(globalFilter, false, true, true);
|
|
50
|
+
|
|
51
|
+
let columnFilters = createColumnFilters(columns);
|
|
52
|
+
|
|
53
|
+
return data.filter((row) => {
|
|
54
|
+
let passesGeneral = true;
|
|
55
|
+
|
|
56
|
+
if (!isEmpty(globalRegex)) {
|
|
57
|
+
passesGeneral = columns.some((c) => {
|
|
58
|
+
return globalRegex.test(get(row, c.prop));
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let passesColumn = true;
|
|
63
|
+
|
|
64
|
+
if (!isEmpty(columnFilters)) {
|
|
65
|
+
passesColumn = columnFilters.every((fn) => fn(row));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let passesCustom = true;
|
|
69
|
+
if (!isEmpty(filterFunction)) {
|
|
70
|
+
passesColumn = filterFunction(row, filterUsing);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return passesGeneral && passesColumn && passesCustom;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { get } from '@ember/object';
|
|
2
|
+
import { compare, isNone } from '@ember/utils';
|
|
3
|
+
|
|
4
|
+
function merge(left, right, comparator) {
|
|
5
|
+
let mergedArray = [];
|
|
6
|
+
let leftIndex = 0;
|
|
7
|
+
let rightIndex = 0;
|
|
8
|
+
|
|
9
|
+
while (leftIndex < left.length && rightIndex < right.length) {
|
|
10
|
+
let comparison = comparator(left[leftIndex], right[rightIndex]);
|
|
11
|
+
|
|
12
|
+
if (comparison <= 0) {
|
|
13
|
+
mergedArray.push(left[leftIndex]);
|
|
14
|
+
leftIndex++;
|
|
15
|
+
} else {
|
|
16
|
+
mergedArray.push(right[rightIndex]);
|
|
17
|
+
rightIndex++;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (leftIndex < left.length) {
|
|
22
|
+
mergedArray.splice(mergedArray.length, 0, ...left.slice(leftIndex));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (rightIndex < right.length) {
|
|
26
|
+
mergedArray.splice(mergedArray.length, 0, ...right.slice(rightIndex));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return mergedArray;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* An implementation of the standard merge sort algorithm.
|
|
34
|
+
*
|
|
35
|
+
* This is necessary because we need a stable sorting algorithm that accepts
|
|
36
|
+
* a general comparator. The built in sort function and Ember's sort functions
|
|
37
|
+
* are not stable, and `_.sortBy` doesn't take a general comparator. Ideally
|
|
38
|
+
* lodash would add a `_.sort` function whose API would mimic this function's.
|
|
39
|
+
*
|
|
40
|
+
* @function
|
|
41
|
+
* @param {Array} array The array to be sorted
|
|
42
|
+
* @param {Comparator} comparator The comparator function to compare elements with.
|
|
43
|
+
* @return {Array} A sorted array
|
|
44
|
+
*/
|
|
45
|
+
export function mergeSort(array, comparator = compare) {
|
|
46
|
+
if (array.length <= 1) {
|
|
47
|
+
return array;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let middleIndex = Math.floor(array.length / 2);
|
|
51
|
+
let leftArray = mergeSort(array.slice(0, middleIndex), comparator);
|
|
52
|
+
let rightArray = mergeSort(array.slice(middleIndex), comparator);
|
|
53
|
+
|
|
54
|
+
return merge(leftArray, rightArray, comparator);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function sortMultiple(itemA, itemB, sorts, compare) {
|
|
58
|
+
let compareValue;
|
|
59
|
+
|
|
60
|
+
for (let { prop, direction } of sorts) {
|
|
61
|
+
let valueA = get(itemA, prop);
|
|
62
|
+
let valueB = get(itemB, prop);
|
|
63
|
+
|
|
64
|
+
compareValue =
|
|
65
|
+
direction === 'asc' ? compare(valueA, valueB) : -compare(valueA, valueB);
|
|
66
|
+
|
|
67
|
+
if (compareValue !== 0) {
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return compareValue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function isExactlyNaN(value) {
|
|
76
|
+
return typeof value === 'number' && isNaN(value);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function isEmpty(value) {
|
|
80
|
+
return isNone(value) || isExactlyNaN(value);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function orderEmptyValues(itemA, itemB) {
|
|
84
|
+
let aIsEmpty = isEmpty(itemA);
|
|
85
|
+
let bIsEmpty = isEmpty(itemB);
|
|
86
|
+
|
|
87
|
+
if (aIsEmpty && !bIsEmpty) {
|
|
88
|
+
return -1;
|
|
89
|
+
} else if (bIsEmpty && !aIsEmpty) {
|
|
90
|
+
return 1;
|
|
91
|
+
} else if (isNone(itemA) && isExactlyNaN(itemB)) {
|
|
92
|
+
return -1;
|
|
93
|
+
} else if (isExactlyNaN(itemA) && isNone(itemB)) {
|
|
94
|
+
return 1;
|
|
95
|
+
} else {
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function compareValues(itemA, itemB) {
|
|
101
|
+
if (isEmpty(itemA) || isEmpty(itemB)) {
|
|
102
|
+
return orderEmptyValues(itemA, itemB);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return compare(itemA, itemB);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export default compareValues;
|