@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.
Files changed (130) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +9 -115
  3. package/declarations/components/yeti-table/body.d.ts +32 -0
  4. package/declarations/components/yeti-table/body.d.ts.map +1 -0
  5. package/declarations/components/yeti-table/header.d.ts +33 -0
  6. package/declarations/components/yeti-table/header.d.ts.map +1 -0
  7. package/declarations/components/yeti-table/pagination.d.ts +40 -0
  8. package/declarations/components/yeti-table/pagination.d.ts.map +1 -0
  9. package/declarations/components/yeti-table/table.d.ts +21 -0
  10. package/declarations/components/yeti-table/table.d.ts.map +1 -0
  11. package/declarations/components/yeti-table/tbody/row/cell.d.ts +44 -0
  12. package/declarations/components/yeti-table/tbody/row/cell.d.ts.map +1 -0
  13. package/declarations/components/yeti-table/tbody/row.d.ts +37 -0
  14. package/declarations/components/yeti-table/tbody/row.d.ts.map +1 -0
  15. package/declarations/components/yeti-table/tbody.d.ts +29 -0
  16. package/declarations/components/yeti-table/tbody.d.ts.map +1 -0
  17. package/declarations/components/yeti-table/tfoot/row/cell.d.ts +40 -0
  18. package/declarations/components/yeti-table/tfoot/row/cell.d.ts.map +1 -0
  19. package/declarations/components/yeti-table/tfoot/row.d.ts +37 -0
  20. package/declarations/components/yeti-table/tfoot/row.d.ts.map +1 -0
  21. package/declarations/components/yeti-table/tfoot.d.ts +27 -0
  22. package/declarations/components/yeti-table/tfoot.d.ts.map +1 -0
  23. package/declarations/components/yeti-table/thead/row/cell.d.ts +54 -0
  24. package/declarations/components/yeti-table/thead/row/cell.d.ts.map +1 -0
  25. package/declarations/components/yeti-table/thead/row/column.d.ts +69 -0
  26. package/declarations/components/yeti-table/thead/row/column.d.ts.map +1 -0
  27. package/declarations/components/yeti-table/thead/row.d.ts +55 -0
  28. package/declarations/components/yeti-table/thead/row.d.ts.map +1 -0
  29. package/declarations/components/yeti-table/thead.d.ts +34 -0
  30. package/declarations/components/yeti-table/thead.d.ts.map +1 -0
  31. package/declarations/components/yeti-table.d.ts +107 -0
  32. package/declarations/components/yeti-table.d.ts.map +1 -0
  33. package/declarations/index.d.ts +1 -0
  34. package/declarations/index.d.ts.map +1 -0
  35. package/declarations/template-registry.d.ts +1 -0
  36. package/declarations/template-registry.d.ts.map +1 -0
  37. package/declarations/themes/default-theme.d.ts +3 -27
  38. package/declarations/themes/default-theme.d.ts.map +1 -1
  39. package/declarations/types.d.ts +82 -0
  40. package/declarations/types.d.ts.map +1 -0
  41. package/declarations/utils/create-regex.d.ts +1 -1
  42. package/declarations/utils/create-regex.d.ts.map +1 -1
  43. package/declarations/utils/filtering-utils.d.ts +2 -4
  44. package/declarations/utils/filtering-utils.d.ts.map +1 -1
  45. package/declarations/utils/sorting-utils.d.ts +6 -15
  46. package/declarations/utils/sorting-utils.d.ts.map +1 -1
  47. package/dist/components/yeti-table/body.js +19 -14
  48. package/dist/components/yeti-table/body.js.map +1 -1
  49. package/dist/components/yeti-table/header.js +10 -10
  50. package/dist/components/yeti-table/header.js.map +1 -1
  51. package/dist/components/yeti-table/pagination.js +14 -44
  52. package/dist/components/yeti-table/pagination.js.map +1 -1
  53. package/dist/components/yeti-table/table.js +1 -23
  54. package/dist/components/yeti-table/table.js.map +1 -1
  55. package/dist/components/yeti-table/tbody/row/cell.js +12 -12
  56. package/dist/components/yeti-table/tbody/row/cell.js.map +1 -1
  57. package/dist/components/yeti-table/tbody/row.js +15 -21
  58. package/dist/components/yeti-table/tbody/row.js.map +1 -1
  59. package/dist/components/yeti-table/tbody.js +1 -0
  60. package/dist/components/yeti-table/tbody.js.map +1 -1
  61. package/dist/components/yeti-table/tfoot/row/cell.js +9 -9
  62. package/dist/components/yeti-table/tfoot/row/cell.js.map +1 -1
  63. package/dist/components/yeti-table/tfoot/row.js +11 -11
  64. package/dist/components/yeti-table/tfoot/row.js.map +1 -1
  65. package/dist/components/yeti-table/tfoot.js +1 -0
  66. package/dist/components/yeti-table/tfoot.js.map +1 -1
  67. package/dist/components/yeti-table/thead/row/cell.js +11 -8
  68. package/dist/components/yeti-table/thead/row/cell.js.map +1 -1
  69. package/dist/components/yeti-table/thead/row/column.js +27 -128
  70. package/dist/components/yeti-table/thead/row/column.js.map +1 -1
  71. package/dist/components/yeti-table/thead/row.js +15 -15
  72. package/dist/components/yeti-table/thead/row.js.map +1 -1
  73. package/dist/components/yeti-table/thead.js +3 -22
  74. package/dist/components/yeti-table/thead.js.map +1 -1
  75. package/dist/components/yeti-table.js +99 -303
  76. package/dist/components/yeti-table.js.map +1 -1
  77. package/dist/index.js +2 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/template-registry.js +2 -0
  80. package/dist/template-registry.js.map +1 -0
  81. package/dist/themes/default-theme.js +3 -2
  82. package/dist/themes/default-theme.js.map +1 -1
  83. package/dist/types.js +2 -0
  84. package/dist/types.js.map +1 -0
  85. package/dist/utils/create-regex.js +6 -6
  86. package/dist/utils/create-regex.js.map +1 -1
  87. package/dist/utils/filtering-utils.js +20 -8
  88. package/dist/utils/filtering-utils.js.map +1 -1
  89. package/dist/utils/sorting-utils.js +13 -18
  90. package/dist/utils/sorting-utils.js.map +1 -1
  91. package/package.json +37 -16
  92. package/src/components/yeti-table/{body.gjs → body.gts} +49 -45
  93. package/src/components/yeti-table/header.gts +67 -0
  94. package/src/components/yeti-table/pagination.gts +118 -0
  95. package/src/components/yeti-table/table.gts +27 -0
  96. package/src/components/yeti-table/tbody/row/{cell.gjs → cell.gts} +38 -19
  97. package/src/components/yeti-table/tbody/row.gts +76 -0
  98. package/src/components/yeti-table/tbody.gts +53 -0
  99. package/src/components/yeti-table/tfoot/row/cell.gts +64 -0
  100. package/src/components/yeti-table/tfoot/row.gts +59 -0
  101. package/src/components/yeti-table/tfoot.gts +41 -0
  102. package/src/components/yeti-table/thead/row/{cell.gjs → cell.gts} +36 -13
  103. package/src/components/yeti-table/thead/row/column.gts +177 -0
  104. package/src/components/yeti-table/thead/row.gts +105 -0
  105. package/src/components/yeti-table/thead.gts +65 -0
  106. package/src/components/yeti-table.gts +629 -0
  107. package/src/template-registry.ts +10 -0
  108. package/src/themes/{default-theme.js → default-theme.ts} +5 -1
  109. package/src/types.ts +94 -0
  110. package/src/utils/{create-regex.js → create-regex.ts} +10 -10
  111. package/src/utils/filtering-utils.ts +91 -0
  112. package/src/utils/{sorting-utils.js → sorting-utils.ts} +35 -26
  113. package/dist/_app_/themes/default-theme.js +0 -1
  114. package/dist/_app_/utils/create-regex.js +0 -1
  115. package/dist/_app_/utils/filtering-utils.js +0 -1
  116. package/dist/_app_/utils/sorting-utils.js +0 -1
  117. package/src/components/yeti-table/header.gjs +0 -54
  118. package/src/components/yeti-table/pagination.gjs +0 -155
  119. package/src/components/yeti-table/table.gjs +0 -34
  120. package/src/components/yeti-table/tbody/row.gjs +0 -89
  121. package/src/components/yeti-table/tbody.gjs +0 -55
  122. package/src/components/yeti-table/tfoot/row/cell.gjs +0 -45
  123. package/src/components/yeti-table/tfoot/row.gjs +0 -44
  124. package/src/components/yeti-table/tfoot.gjs +0 -33
  125. package/src/components/yeti-table/thead/row/column.gjs +0 -260
  126. package/src/components/yeti-table/thead/row.gjs +0 -71
  127. package/src/components/yeti-table/thead.gjs +0 -45
  128. package/src/components/yeti-table.gjs +0 -780
  129. package/src/utils/filtering-utils.js +0 -75
  130. /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
- search = regex ? search : escapeRegex(search);
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
- let words = search.match(/"[^"]+"|[^ ]+/g) || [''];
52
- let a = words.map((word) => {
51
+ const words = normalized.match(/"[^"]+"|[^ ]+/g) || [''];
52
+ const a = words.map((word) => {
53
53
  if (word.charAt(0) === '"') {
54
- let m = word.match(/^"(.*)"$/);
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
- search = `^(?=.*?${a.join(')(?=.*?')}).*$`;
61
+ normalized = `^(?=.*?${a.join(')(?=.*?')}).*$`;
62
62
  }
63
63
 
64
- return new RegExp(search, caseInsensitive ? 'i' : '');
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
- function merge(left, right, comparator) {
5
- let mergedArray = [];
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
- let comparison = comparator(left[leftIndex], right[rightIndex]);
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(array, comparator = compare) {
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
- let middleIndex = Math.floor(array.length / 2);
51
- let leftArray = mergeSort(array.slice(0, middleIndex), comparator);
52
- let rightArray = mergeSort(array.slice(middleIndex), comparator);
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(itemA, itemB, sorts, compare) {
58
- let compareValue;
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 (let { prop, direction } of sorts) {
61
- let valueA = get(itemA, prop);
62
- let valueB = get(itemB, prop);
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' ? compare(valueA, valueB) : -compare(valueA, valueB);
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
- let aIsEmpty = isEmpty(itemA);
85
- let bIsEmpty = isEmpty(itemB);
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
- }