@triptyk/ember-yeti-table 3.0.0 → 3.0.1
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 +1 -1
- package/README.md +9 -115
- package/declarations/components/yeti-table/body.d.ts +32 -0
- package/declarations/components/yeti-table/body.d.ts.map +1 -0
- package/declarations/components/yeti-table/header.d.ts +33 -0
- package/declarations/components/yeti-table/header.d.ts.map +1 -0
- package/declarations/components/yeti-table/pagination.d.ts +40 -0
- package/declarations/components/yeti-table/pagination.d.ts.map +1 -0
- package/declarations/components/yeti-table/table.d.ts +21 -0
- package/declarations/components/yeti-table/table.d.ts.map +1 -0
- package/declarations/components/yeti-table/tbody/row/cell.d.ts +44 -0
- package/declarations/components/yeti-table/tbody/row/cell.d.ts.map +1 -0
- package/declarations/components/yeti-table/tbody/row.d.ts +37 -0
- package/declarations/components/yeti-table/tbody/row.d.ts.map +1 -0
- package/declarations/components/yeti-table/tbody.d.ts +29 -0
- package/declarations/components/yeti-table/tbody.d.ts.map +1 -0
- package/declarations/components/yeti-table/tfoot/row/cell.d.ts +40 -0
- package/declarations/components/yeti-table/tfoot/row/cell.d.ts.map +1 -0
- package/declarations/components/yeti-table/tfoot/row.d.ts +37 -0
- package/declarations/components/yeti-table/tfoot/row.d.ts.map +1 -0
- package/declarations/components/yeti-table/tfoot.d.ts +27 -0
- package/declarations/components/yeti-table/tfoot.d.ts.map +1 -0
- package/declarations/components/yeti-table/thead/row/cell.d.ts +54 -0
- package/declarations/components/yeti-table/thead/row/cell.d.ts.map +1 -0
- package/declarations/components/yeti-table/thead/row/column.d.ts +69 -0
- package/declarations/components/yeti-table/thead/row/column.d.ts.map +1 -0
- package/declarations/components/yeti-table/thead/row.d.ts +55 -0
- package/declarations/components/yeti-table/thead/row.d.ts.map +1 -0
- package/declarations/components/yeti-table/thead.d.ts +34 -0
- package/declarations/components/yeti-table/thead.d.ts.map +1 -0
- package/declarations/components/yeti-table.d.ts +107 -0
- package/declarations/components/yeti-table.d.ts.map +1 -0
- package/declarations/index.d.ts +1 -0
- package/declarations/index.d.ts.map +1 -0
- package/declarations/template-registry.d.ts +1 -0
- package/declarations/template-registry.d.ts.map +1 -0
- package/declarations/themes/default-theme.d.ts +3 -27
- package/declarations/themes/default-theme.d.ts.map +1 -1
- package/declarations/types.d.ts +82 -0
- package/declarations/types.d.ts.map +1 -0
- package/declarations/utils/create-regex.d.ts +1 -1
- package/declarations/utils/create-regex.d.ts.map +1 -1
- package/declarations/utils/filtering-utils.d.ts +2 -4
- package/declarations/utils/filtering-utils.d.ts.map +1 -1
- package/declarations/utils/sorting-utils.d.ts +6 -15
- package/declarations/utils/sorting-utils.d.ts.map +1 -1
- package/dist/components/yeti-table/body.js +19 -14
- package/dist/components/yeti-table/body.js.map +1 -1
- package/dist/components/yeti-table/header.js +10 -10
- package/dist/components/yeti-table/header.js.map +1 -1
- package/dist/components/yeti-table/pagination.js +14 -44
- package/dist/components/yeti-table/pagination.js.map +1 -1
- package/dist/components/yeti-table/table.js +1 -23
- package/dist/components/yeti-table/table.js.map +1 -1
- package/dist/components/yeti-table/tbody/row/cell.js +12 -12
- package/dist/components/yeti-table/tbody/row/cell.js.map +1 -1
- package/dist/components/yeti-table/tbody/row.js +15 -21
- package/dist/components/yeti-table/tbody/row.js.map +1 -1
- package/dist/components/yeti-table/tbody.js +1 -0
- package/dist/components/yeti-table/tbody.js.map +1 -1
- package/dist/components/yeti-table/tfoot/row/cell.js +9 -9
- package/dist/components/yeti-table/tfoot/row/cell.js.map +1 -1
- package/dist/components/yeti-table/tfoot/row.js +11 -11
- package/dist/components/yeti-table/tfoot/row.js.map +1 -1
- package/dist/components/yeti-table/tfoot.js +1 -0
- package/dist/components/yeti-table/tfoot.js.map +1 -1
- package/dist/components/yeti-table/thead/row/cell.js +11 -8
- package/dist/components/yeti-table/thead/row/cell.js.map +1 -1
- package/dist/components/yeti-table/thead/row/column.js +27 -128
- package/dist/components/yeti-table/thead/row/column.js.map +1 -1
- package/dist/components/yeti-table/thead/row.js +15 -15
- package/dist/components/yeti-table/thead/row.js.map +1 -1
- package/dist/components/yeti-table/thead.js +3 -22
- package/dist/components/yeti-table/thead.js.map +1 -1
- package/dist/components/yeti-table.js +99 -303
- package/dist/components/yeti-table.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/template-registry.js +2 -0
- package/dist/template-registry.js.map +1 -0
- package/dist/themes/default-theme.js +3 -2
- package/dist/themes/default-theme.js.map +1 -1
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/create-regex.js +6 -6
- package/dist/utils/create-regex.js.map +1 -1
- package/dist/utils/filtering-utils.js +20 -8
- package/dist/utils/filtering-utils.js.map +1 -1
- package/dist/utils/sorting-utils.js +13 -18
- package/dist/utils/sorting-utils.js.map +1 -1
- package/package.json +37 -16
- package/src/components/yeti-table/{body.gjs → body.gts} +49 -45
- package/src/components/yeti-table/header.gts +67 -0
- package/src/components/yeti-table/pagination.gts +118 -0
- package/src/components/yeti-table/table.gts +27 -0
- package/src/components/yeti-table/tbody/row/{cell.gjs → cell.gts} +38 -19
- package/src/components/yeti-table/tbody/row.gts +76 -0
- package/src/components/yeti-table/tbody.gts +53 -0
- package/src/components/yeti-table/tfoot/row/cell.gts +64 -0
- package/src/components/yeti-table/tfoot/row.gts +59 -0
- package/src/components/yeti-table/tfoot.gts +41 -0
- package/src/components/yeti-table/thead/row/{cell.gjs → cell.gts} +36 -13
- package/src/components/yeti-table/thead/row/column.gts +177 -0
- package/src/components/yeti-table/thead/row.gts +105 -0
- package/src/components/yeti-table/thead.gts +65 -0
- package/src/components/yeti-table.gts +629 -0
- package/src/template-registry.ts +10 -0
- package/src/themes/{default-theme.js → default-theme.ts} +5 -1
- package/src/types.ts +94 -0
- package/src/utils/{create-regex.js → create-regex.ts} +10 -10
- package/src/utils/filtering-utils.ts +91 -0
- package/src/utils/{sorting-utils.js → sorting-utils.ts} +35 -26
- package/dist/_app_/themes/default-theme.js +0 -1
- package/dist/_app_/utils/create-regex.js +0 -1
- package/dist/_app_/utils/filtering-utils.js +0 -1
- package/dist/_app_/utils/sorting-utils.js +0 -1
- package/src/components/yeti-table/header.gjs +0 -54
- package/src/components/yeti-table/pagination.gjs +0 -155
- package/src/components/yeti-table/table.gjs +0 -34
- package/src/components/yeti-table/tbody/row.gjs +0 -89
- package/src/components/yeti-table/tbody.gjs +0 -55
- package/src/components/yeti-table/tfoot/row/cell.gjs +0 -45
- package/src/components/yeti-table/tfoot/row.gjs +0 -44
- package/src/components/yeti-table/tfoot.gjs +0 -33
- package/src/components/yeti-table/thead/row/column.gjs +0 -260
- package/src/components/yeti-table/thead/row.gjs +0 -71
- package/src/components/yeti-table/thead.gjs +0 -45
- package/src/components/yeti-table.gjs +0 -780
- package/src/utils/filtering-utils.js +0 -75
- /package/src/{.gitkeep → index.ts} +0 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export type SortDirection = 'asc' | 'desc';
|
|
2
|
+
|
|
3
|
+
export interface Sort {
|
|
4
|
+
prop: string;
|
|
5
|
+
direction: SortDirection;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type FilterFunction = (value: unknown, filterUsing?: unknown) => boolean;
|
|
9
|
+
|
|
10
|
+
export type RowFilterFunction = (row: Row, filterUsing?: unknown) => boolean;
|
|
11
|
+
|
|
12
|
+
export type Row = Record<string, unknown>;
|
|
13
|
+
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
export type RowClickHandler = (...args: any[]) => void;
|
|
16
|
+
|
|
17
|
+
export interface ColumnDefinition {
|
|
18
|
+
prop?: string;
|
|
19
|
+
filter?: string;
|
|
20
|
+
filterFunction?: FilterFunction;
|
|
21
|
+
filterUsing?: unknown;
|
|
22
|
+
filterable?: boolean;
|
|
23
|
+
sortable?: boolean;
|
|
24
|
+
visible?: boolean;
|
|
25
|
+
sort?: SortDirection | null;
|
|
26
|
+
columnClass?: string;
|
|
27
|
+
name?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ThemeSorting {
|
|
31
|
+
columnSortable: string;
|
|
32
|
+
columnSorted: string;
|
|
33
|
+
columnSortedAsc: string;
|
|
34
|
+
columnSortedDesc: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface ThemePagination {
|
|
38
|
+
controls: string;
|
|
39
|
+
info: string;
|
|
40
|
+
pageSize: string;
|
|
41
|
+
next: string;
|
|
42
|
+
previous: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface Theme {
|
|
46
|
+
table: string;
|
|
47
|
+
row: string;
|
|
48
|
+
thead: string;
|
|
49
|
+
theadRow: string;
|
|
50
|
+
theadCell: string;
|
|
51
|
+
tbody: string;
|
|
52
|
+
tbodyRow: string;
|
|
53
|
+
tbodyCell: string;
|
|
54
|
+
tfoot: string;
|
|
55
|
+
tfootRow: string;
|
|
56
|
+
tfootCell: string;
|
|
57
|
+
sorting: ThemeSorting;
|
|
58
|
+
pagination: ThemePagination;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface PaginationData {
|
|
62
|
+
pageSize: number;
|
|
63
|
+
pageNumber: number;
|
|
64
|
+
pageStart: number;
|
|
65
|
+
pageEnd: number;
|
|
66
|
+
isFirstPage: boolean;
|
|
67
|
+
isLastPage?: boolean;
|
|
68
|
+
totalRows?: number;
|
|
69
|
+
totalPages?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface PaginationActions {
|
|
73
|
+
previousPage: () => void;
|
|
74
|
+
nextPage: () => void;
|
|
75
|
+
goToPage: (page: number) => void;
|
|
76
|
+
changePageSize: (size: number | string) => void;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface LoadDataParams {
|
|
80
|
+
paginationData?: PaginationData;
|
|
81
|
+
sortData: Array<{
|
|
82
|
+
prop: string | undefined;
|
|
83
|
+
direction: SortDirection | null | undefined;
|
|
84
|
+
}>;
|
|
85
|
+
filterData: {
|
|
86
|
+
filter: string;
|
|
87
|
+
filterUsing: unknown;
|
|
88
|
+
columnFilters: Array<{
|
|
89
|
+
prop: string | undefined;
|
|
90
|
+
filter: string | undefined;
|
|
91
|
+
filterUsing: unknown;
|
|
92
|
+
}>;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -24,21 +24,21 @@ const ESCAPE_REGEX = new RegExp(
|
|
|
24
24
|
'g',
|
|
25
25
|
);
|
|
26
26
|
|
|
27
|
-
function escapeRegex(val) {
|
|
27
|
+
function escapeRegex(val: string): string {
|
|
28
28
|
return val.replace(ESCAPE_REGEX, '\\$1');
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export default function createRegex(
|
|
32
|
-
search,
|
|
32
|
+
search: string | null | undefined,
|
|
33
33
|
regex = false,
|
|
34
34
|
smart = true,
|
|
35
35
|
caseInsensitive = true,
|
|
36
|
-
) {
|
|
36
|
+
): RegExp | undefined {
|
|
37
37
|
if (isBlank(search)) {
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
let normalized = regex ? (search as string) : escapeRegex(search as string);
|
|
42
42
|
|
|
43
43
|
if (smart) {
|
|
44
44
|
/* For smart filtering we want to allow the search to work regardless of
|
|
@@ -48,18 +48,18 @@ export default function createRegex(
|
|
|
48
48
|
*
|
|
49
49
|
* ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
|
|
50
50
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const words = normalized.match(/"[^"]+"|[^ ]+/g) || [''];
|
|
52
|
+
const a = words.map((word) => {
|
|
53
53
|
if (word.charAt(0) === '"') {
|
|
54
|
-
|
|
55
|
-
word = m ? m[1] : word;
|
|
54
|
+
const m = word.match(/^"(.*)"$/);
|
|
55
|
+
word = m ? (m[1] as string) : word;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
return word.replace('"', '');
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
normalized = `^(?=.*?${a.join(')(?=.*?')}).*$`;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
return new RegExp(
|
|
64
|
+
return new RegExp(normalized, caseInsensitive ? 'i' : '');
|
|
65
65
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { isEmpty } from '@ember/utils';
|
|
2
|
+
import { get } from '@ember/object';
|
|
3
|
+
|
|
4
|
+
import createRegex from './create-regex.ts';
|
|
5
|
+
import type { ColumnDefinition, Row, RowFilterFunction } from '../types.ts';
|
|
6
|
+
|
|
7
|
+
function safeString(value: unknown): string {
|
|
8
|
+
if (value == null) return '';
|
|
9
|
+
if (typeof value === 'string') return value;
|
|
10
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
11
|
+
return String(value);
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
return JSON.stringify(value);
|
|
15
|
+
} catch {
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function createColumnFilters(
|
|
21
|
+
columns: ColumnDefinition[],
|
|
22
|
+
): Array<(row: Row) => boolean> {
|
|
23
|
+
const searcheableColumns = columns.filter((c) => {
|
|
24
|
+
return !isEmpty(c.filter) || !isEmpty(c.filterFunction);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return searcheableColumns.map((c) => {
|
|
28
|
+
const regex = createRegex(c.filter);
|
|
29
|
+
|
|
30
|
+
return (row: Row) => {
|
|
31
|
+
const value = c.prop ? get(row, c.prop) : undefined;
|
|
32
|
+
let passesRegex = true;
|
|
33
|
+
|
|
34
|
+
if (!isEmpty(c.filter)) {
|
|
35
|
+
passesRegex = regex ? regex.test(safeString(value)) : true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let passesCustom = true;
|
|
39
|
+
|
|
40
|
+
if (!isEmpty(c.filterFunction)) {
|
|
41
|
+
passesCustom = c.filterFunction!(value, c.filterUsing);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return passesRegex && passesCustom;
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default function filterData(
|
|
50
|
+
data: Row[],
|
|
51
|
+
columns: ColumnDefinition[],
|
|
52
|
+
globalFilter?: string,
|
|
53
|
+
filterFunction?: RowFilterFunction,
|
|
54
|
+
filterUsing?: unknown,
|
|
55
|
+
): Row[] {
|
|
56
|
+
if (isEmpty(data)) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (isEmpty(columns)) {
|
|
61
|
+
// bail out if there are no columns to filter
|
|
62
|
+
return data;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const globalRegex = createRegex(globalFilter, false, true, true);
|
|
66
|
+
|
|
67
|
+
const columnFilters = createColumnFilters(columns);
|
|
68
|
+
|
|
69
|
+
return data.filter((row) => {
|
|
70
|
+
let passesGeneral = true;
|
|
71
|
+
|
|
72
|
+
if (!isEmpty(globalRegex)) {
|
|
73
|
+
passesGeneral = columns.some((c) => {
|
|
74
|
+
return c.prop ? globalRegex!.test(safeString(get(row, c.prop))) : false;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let passesColumn = true;
|
|
79
|
+
|
|
80
|
+
if (!isEmpty(columnFilters)) {
|
|
81
|
+
passesColumn = columnFilters.every((fn) => fn(row));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const passesCustom = true;
|
|
85
|
+
if (!isEmpty(filterFunction)) {
|
|
86
|
+
passesColumn = filterFunction!(row, filterUsing);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return passesGeneral && passesColumn && passesCustom;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { get } from '@ember/object';
|
|
2
2
|
import { compare, isNone } from '@ember/utils';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import type { Sort } from '../types.ts';
|
|
5
|
+
|
|
6
|
+
export type Comparator<T = unknown> = (a: T, b: T) => number;
|
|
7
|
+
|
|
8
|
+
function merge<T>(left: T[], right: T[], comparator: Comparator<T>): T[] {
|
|
9
|
+
const mergedArray: T[] = [];
|
|
6
10
|
let leftIndex = 0;
|
|
7
11
|
let rightIndex = 0;
|
|
8
12
|
|
|
9
13
|
while (leftIndex < left.length && rightIndex < right.length) {
|
|
10
|
-
|
|
14
|
+
const comparison = comparator(left[leftIndex]!, right[rightIndex]!);
|
|
11
15
|
|
|
12
16
|
if (comparison <= 0) {
|
|
13
|
-
mergedArray.push(left[leftIndex]);
|
|
17
|
+
mergedArray.push(left[leftIndex]!);
|
|
14
18
|
leftIndex++;
|
|
15
19
|
} else {
|
|
16
|
-
mergedArray.push(right[rightIndex]);
|
|
20
|
+
mergedArray.push(right[rightIndex]!);
|
|
17
21
|
rightIndex++;
|
|
18
22
|
}
|
|
19
23
|
}
|
|
@@ -36,33 +40,38 @@ function merge(left, right, comparator) {
|
|
|
36
40
|
* a general comparator. The built in sort function and Ember's sort functions
|
|
37
41
|
* are not stable, and `_.sortBy` doesn't take a general comparator. Ideally
|
|
38
42
|
* 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
43
|
*/
|
|
45
|
-
export function mergeSort(
|
|
44
|
+
export function mergeSort<T>(
|
|
45
|
+
array: T[],
|
|
46
|
+
comparator: Comparator<T> = compare,
|
|
47
|
+
): T[] {
|
|
46
48
|
if (array.length <= 1) {
|
|
47
49
|
return array;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
const middleIndex = Math.floor(array.length / 2);
|
|
53
|
+
const leftArray = mergeSort(array.slice(0, middleIndex), comparator);
|
|
54
|
+
const rightArray = mergeSort(array.slice(middleIndex), comparator);
|
|
53
55
|
|
|
54
56
|
return merge(leftArray, rightArray, comparator);
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
export function sortMultiple(
|
|
58
|
-
|
|
59
|
+
export function sortMultiple<T>(
|
|
60
|
+
itemA: T,
|
|
61
|
+
itemB: T,
|
|
62
|
+
sorts: Sort[],
|
|
63
|
+
compareFn: Comparator,
|
|
64
|
+
): number {
|
|
65
|
+
let compareValue = 0;
|
|
59
66
|
|
|
60
|
-
for (
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
for (const { prop, direction } of sorts) {
|
|
68
|
+
const valueA = get(itemA as object, prop);
|
|
69
|
+
const valueB = get(itemB as object, prop);
|
|
63
70
|
|
|
64
71
|
compareValue =
|
|
65
|
-
direction === 'asc'
|
|
72
|
+
direction === 'asc'
|
|
73
|
+
? compareFn(valueA, valueB)
|
|
74
|
+
: -compareFn(valueA, valueB);
|
|
66
75
|
|
|
67
76
|
if (compareValue !== 0) {
|
|
68
77
|
break;
|
|
@@ -72,17 +81,17 @@ export function sortMultiple(itemA, itemB, sorts, compare) {
|
|
|
72
81
|
return compareValue;
|
|
73
82
|
}
|
|
74
83
|
|
|
75
|
-
function isExactlyNaN(value) {
|
|
84
|
+
function isExactlyNaN(value: unknown): boolean {
|
|
76
85
|
return typeof value === 'number' && isNaN(value);
|
|
77
86
|
}
|
|
78
87
|
|
|
79
|
-
function isEmpty(value) {
|
|
88
|
+
function isEmpty(value: unknown): boolean {
|
|
80
89
|
return isNone(value) || isExactlyNaN(value);
|
|
81
90
|
}
|
|
82
91
|
|
|
83
|
-
function orderEmptyValues(itemA, itemB) {
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
function orderEmptyValues(itemA: unknown, itemB: unknown): number {
|
|
93
|
+
const aIsEmpty = isEmpty(itemA);
|
|
94
|
+
const bIsEmpty = isEmpty(itemB);
|
|
86
95
|
|
|
87
96
|
if (aIsEmpty && !bIsEmpty) {
|
|
88
97
|
return -1;
|
|
@@ -97,7 +106,7 @@ function orderEmptyValues(itemA, itemB) {
|
|
|
97
106
|
}
|
|
98
107
|
}
|
|
99
108
|
|
|
100
|
-
export function compareValues(itemA, itemB) {
|
|
109
|
+
export function compareValues(itemA: unknown, itemB: unknown): number {
|
|
101
110
|
if (isEmpty(itemA) || isEmpty(itemB)) {
|
|
102
111
|
return orderEmptyValues(itemA, itemB);
|
|
103
112
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "@triptyk/ember-yeti-table/themes/default-theme";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "@triptyk/ember-yeti-table/utils/create-regex";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "@triptyk/ember-yeti-table/utils/filtering-utils";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "@triptyk/ember-yeti-table/utils/sorting-utils";
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { action } from '@ember/object';
|
|
2
|
-
|
|
3
|
-
import Component from '@glimmer/component';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
Renders a `<thead>` element and yields the column component.
|
|
7
|
-
```hbs
|
|
8
|
-
<table.header as |header|>
|
|
9
|
-
<header.column @prop="firstName">
|
|
10
|
-
First name
|
|
11
|
-
</header.column>
|
|
12
|
-
<header.column @prop="lastName">
|
|
13
|
-
Last name
|
|
14
|
-
</header.column>
|
|
15
|
-
<header.column @prop="points">
|
|
16
|
-
Points
|
|
17
|
-
</header.column>
|
|
18
|
-
</table.header>
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
@class Header
|
|
22
|
-
@yield {object} header
|
|
23
|
-
@yield {Component} header.column the column component
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
import THead from './thead/row/column.gjs';
|
|
27
|
-
import { hash } from '@ember/helper';
|
|
28
|
-
|
|
29
|
-
export default class Header extends Component {
|
|
30
|
-
<template>
|
|
31
|
-
<thead class={{@theme.thead}} ...attributes>
|
|
32
|
-
<tr class="{{@trClass}} {{@theme.theadRow}} {{@theme.row}}">
|
|
33
|
-
{{yield
|
|
34
|
-
(hash
|
|
35
|
-
column=(component
|
|
36
|
-
THead
|
|
37
|
-
sortable=@sortable
|
|
38
|
-
sortSequence=@sortSequence
|
|
39
|
-
onClick=this.onColumnClickHeader
|
|
40
|
-
parent=@parent
|
|
41
|
-
theme=@theme
|
|
42
|
-
)
|
|
43
|
-
)
|
|
44
|
-
}}
|
|
45
|
-
</tr>
|
|
46
|
-
</thead>
|
|
47
|
-
</template>
|
|
48
|
-
@action
|
|
49
|
-
onColumnClickHeader(column, e) {
|
|
50
|
-
if (this.args.onColumnClick && column.sortable) {
|
|
51
|
-
this.args.onColumnClick(column, e);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { action } from '@ember/object';
|
|
2
|
-
import { helper } from '@ember/component/helper';
|
|
3
|
-
import Component from '@glimmer/component';
|
|
4
|
-
import { localCopy } from 'tracked-toolbox';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
Simple pagination controls component that is included to help you get started quickly.
|
|
8
|
-
Yeti Table yields a lot of pagination data, so you shouldn't have a problem
|
|
9
|
-
creating your own pagination controls.
|
|
10
|
-
|
|
11
|
-
At any rate, this component tries to be as flexible as possible. Some arguments
|
|
12
|
-
are provided to customize how this component behaves.
|
|
13
|
-
|
|
14
|
-
If you want to render these controls on the table footer, you probably want
|
|
15
|
-
a footer row that always spans all rows. To do that you can use a `colspan` equal
|
|
16
|
-
to the yielded `visibleColumns.length` number. Example:
|
|
17
|
-
|
|
18
|
-
```hbs
|
|
19
|
-
<YetiTable @data={{this.data}} @pagination={{true}} as |table|>
|
|
20
|
-
...
|
|
21
|
-
<table.tfoot as |foot|>
|
|
22
|
-
<foot.row as |row|>
|
|
23
|
-
<row.cell colspan={{table.visibleColumns.length}}>
|
|
24
|
-
<table.pagination/>
|
|
25
|
-
</row.cell>
|
|
26
|
-
</foot.row>
|
|
27
|
-
</table.tfoot>
|
|
28
|
-
</YetiTable>
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
@class Pagination
|
|
32
|
-
*/
|
|
33
|
-
import { on } from '@ember/modifier';
|
|
34
|
-
import { guidFor } from '@ember/object/internals';
|
|
35
|
-
|
|
36
|
-
export default class Pagination extends Component {
|
|
37
|
-
guid = guidFor(this);
|
|
38
|
-
|
|
39
|
-
<template>
|
|
40
|
-
<div class={{@theme.pagination.controls}} ...attributes>
|
|
41
|
-
{{#if this.showInfo}}
|
|
42
|
-
<div class={{@theme.pagination.info}}>
|
|
43
|
-
Showing
|
|
44
|
-
{{@paginationData.pageStart}}
|
|
45
|
-
to
|
|
46
|
-
{{@paginationData.pageEnd}}
|
|
47
|
-
of
|
|
48
|
-
{{@paginationData.totalRows}}
|
|
49
|
-
entries
|
|
50
|
-
</div>
|
|
51
|
-
{{/if}}
|
|
52
|
-
|
|
53
|
-
{{#if this.showPageSizeSelector}}
|
|
54
|
-
<div class={{@theme.pagination.pageSize}}>
|
|
55
|
-
<label for="page-size-select-{{this.guid}}">Rows per page:</label>
|
|
56
|
-
<select
|
|
57
|
-
id="page-size-select-{{this.guid}}"
|
|
58
|
-
disabled={{@disabled}}
|
|
59
|
-
{{on "change" this.changePageSize}}
|
|
60
|
-
>
|
|
61
|
-
{{#each this.pageSizes as |pageSize|}}
|
|
62
|
-
<option
|
|
63
|
-
value={{pageSize}}
|
|
64
|
-
selected={{this.isPaginationNumberSelected pageSize}}
|
|
65
|
-
>{{pageSize}}</option>
|
|
66
|
-
{{/each}}
|
|
67
|
-
</select>
|
|
68
|
-
</div>
|
|
69
|
-
{{/if}}
|
|
70
|
-
|
|
71
|
-
{{#if this.showButtons}}
|
|
72
|
-
<button
|
|
73
|
-
type="button"
|
|
74
|
-
class={{@theme.pagination.previous}}
|
|
75
|
-
disabled={{this.shouldDisablePrevious}}
|
|
76
|
-
{{on "click" @paginationActions.previousPage}}
|
|
77
|
-
>
|
|
78
|
-
Previous
|
|
79
|
-
</button>
|
|
80
|
-
|
|
81
|
-
<button
|
|
82
|
-
type="button"
|
|
83
|
-
class={{@theme.pagination.next}}
|
|
84
|
-
disabled={{this.shouldDisableNext}}
|
|
85
|
-
{{on "click" @paginationActions.nextPage}}
|
|
86
|
-
>
|
|
87
|
-
Next
|
|
88
|
-
</button>
|
|
89
|
-
{{/if}}
|
|
90
|
-
</div>
|
|
91
|
-
</template>
|
|
92
|
-
// theme;
|
|
93
|
-
|
|
94
|
-
// paginationData;
|
|
95
|
-
|
|
96
|
-
// paginationActions;
|
|
97
|
-
|
|
98
|
-
// disabled;
|
|
99
|
-
|
|
100
|
-
// helper function used, needed while working with ember <= 4.4. Works without helper function in ember > 4.4
|
|
101
|
-
isPaginationNumberSelected = helper(([number]) => {
|
|
102
|
-
return number === this.args.paginationData.pageSize;
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
get shouldDisablePrevious() {
|
|
106
|
-
return this.args.paginationData.isFirstPage || this.args.disabled;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
get shouldDisableNext() {
|
|
110
|
-
return this.args.paginationData.isLastPage || this.args.disabled;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Array of page sizes to populate the page size `<select>`.
|
|
115
|
-
* Particularly useful with an array helper, e.g `@pageSizes={{array 10 12 23 50 100}}`
|
|
116
|
-
* Defaults to `[10, 15, 20, 25]`.
|
|
117
|
-
*
|
|
118
|
-
* @argument pageSizes
|
|
119
|
-
* @type {Number}
|
|
120
|
-
*/
|
|
121
|
-
@localCopy('args.pageSizes', [10, 15, 20, 25])
|
|
122
|
-
pageSizes;
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Used to show/hide some textual information about the current page. Defaults to `true`.
|
|
126
|
-
*
|
|
127
|
-
* @argument showInfo
|
|
128
|
-
* @type {Boolean}
|
|
129
|
-
*/
|
|
130
|
-
@localCopy('args.showInfo', true)
|
|
131
|
-
showInfo;
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Used to show/hide the page size selector. Defaults to `true`.
|
|
135
|
-
*
|
|
136
|
-
* @argument showPageSizeSelector
|
|
137
|
-
* @type {Boolean}
|
|
138
|
-
*/
|
|
139
|
-
@localCopy('args.showPageSizeSelector', true)
|
|
140
|
-
showPageSizeSelector;
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Used to show/hide the previous and next page buttons. Defaults to `true`.
|
|
144
|
-
*
|
|
145
|
-
* @argument showButtons
|
|
146
|
-
* @type {Boolean}
|
|
147
|
-
*/
|
|
148
|
-
@localCopy('args.showButtons', true)
|
|
149
|
-
showButtons;
|
|
150
|
-
|
|
151
|
-
@action
|
|
152
|
-
changePageSize(ev) {
|
|
153
|
-
this.args.paginationActions.changePageSize(ev.target.value);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
A simple component that just renders the `<table>` element with the correct
|
|
3
|
-
theme classes.
|
|
4
|
-
|
|
5
|
-
This component should only be needed when using `@renderTableElement={{false}}` to render
|
|
6
|
-
the table element yourself. Please refer to the `@renderTableElement` documentation for
|
|
7
|
-
more information.
|
|
8
|
-
|
|
9
|
-
Example:
|
|
10
|
-
|
|
11
|
-
```hbs
|
|
12
|
-
<YetiTable @data={{this.data}} @pagination={{true}} @renderTableElement={{false}} as |t|>
|
|
13
|
-
|
|
14
|
-
<t.table> {{!-- we render the given table component ourselves --}}
|
|
15
|
-
<t.header as |header|>
|
|
16
|
-
...
|
|
17
|
-
</t.header>
|
|
18
|
-
|
|
19
|
-
<t.body/>
|
|
20
|
-
</t.table>
|
|
21
|
-
|
|
22
|
-
<t.pagination/> {{!-- pagination controls outside the <table> element --}}
|
|
23
|
-
|
|
24
|
-
</YetiTable>
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
@class Table
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
<template>
|
|
31
|
-
<table class={{@theme.table}} ...attributes>
|
|
32
|
-
{{yield}}
|
|
33
|
-
</table>
|
|
34
|
-
</template>
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { action } from '@ember/object';
|
|
2
|
-
|
|
3
|
-
import Component from '@glimmer/component';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
Renders a `<tr>` element and yields the cell component.
|
|
7
|
-
```hbs
|
|
8
|
-
<body.row as |row|>
|
|
9
|
-
<row.cell>
|
|
10
|
-
{{person.firstName}} #{{index}}
|
|
11
|
-
</row.cell>
|
|
12
|
-
<row.cell>
|
|
13
|
-
{{person.lastName}}
|
|
14
|
-
</row.cell>
|
|
15
|
-
<row.cell>
|
|
16
|
-
{{person.points}}
|
|
17
|
-
</row.cell>
|
|
18
|
-
</body.row>
|
|
19
|
-
```
|
|
20
|
-
Remember you can customize each `<tr>` class or `@onClick` handler based on the row data
|
|
21
|
-
because you have access to it from the body component.
|
|
22
|
-
|
|
23
|
-
```hbs
|
|
24
|
-
<table.body as |body person|>
|
|
25
|
-
<body.row class={{if person.isInvalid "error"}} as |row|>
|
|
26
|
-
<row.cell>
|
|
27
|
-
{{person.firstName}}
|
|
28
|
-
</row.cell>
|
|
29
|
-
<row.cell>
|
|
30
|
-
{{person.lastName}}
|
|
31
|
-
</row.cell>
|
|
32
|
-
<row.cell>
|
|
33
|
-
{{person.points}}
|
|
34
|
-
</row.cell>
|
|
35
|
-
</body.row>
|
|
36
|
-
</table.body>
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
@class TBodyRow
|
|
40
|
-
@yield {object} row
|
|
41
|
-
@yield {Component} row.cell - the cell component
|
|
42
|
-
*/
|
|
43
|
-
// template imports
|
|
44
|
-
import { hash } from '@ember/helper';
|
|
45
|
-
import { on } from '@ember/modifier';
|
|
46
|
-
import Cell from './row/cell.gjs';
|
|
47
|
-
|
|
48
|
-
export default class TBodyRow extends Component {
|
|
49
|
-
<template>
|
|
50
|
-
{{! template-lint-disable no-invalid-interactive }}
|
|
51
|
-
<tr
|
|
52
|
-
class="{{@theme.tbodyRow}} {{@theme.row}}"
|
|
53
|
-
{{on "click" this.handleClick}}
|
|
54
|
-
role={{if @onClick "button"}}
|
|
55
|
-
...attributes
|
|
56
|
-
>
|
|
57
|
-
{{yield
|
|
58
|
-
(hash cell=(component Cell theme=@theme parent=this columns=@columns))
|
|
59
|
-
}}
|
|
60
|
-
</tr>
|
|
61
|
-
</template>
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Adds a click action to the row.
|
|
65
|
-
*
|
|
66
|
-
* @argument onClick
|
|
67
|
-
* @type Function
|
|
68
|
-
*/
|
|
69
|
-
|
|
70
|
-
cells = [];
|
|
71
|
-
|
|
72
|
-
registerCell(cell) {
|
|
73
|
-
let index = this.cells.length;
|
|
74
|
-
this.cells.push(cell);
|
|
75
|
-
return index;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
unregisterCell(cell) {
|
|
79
|
-
let cells = this.cells;
|
|
80
|
-
let index = cells.indexOf(cell);
|
|
81
|
-
|
|
82
|
-
cells.splice(index, 1);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
@action
|
|
86
|
-
handleClick() {
|
|
87
|
-
this.args.onClick?.(...arguments);
|
|
88
|
-
}
|
|
89
|
-
}
|