@akinon/akitable 0.5.0 → 1.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 (51) hide show
  1. package/dist/cjs/akitable.d.ts +11 -0
  2. package/dist/cjs/akitable.d.ts.map +1 -1
  3. package/dist/cjs/akitable.js +33 -11
  4. package/dist/cjs/components/actions.js +3 -3
  5. package/dist/cjs/components/controls.js +2 -2
  6. package/dist/cjs/components/datatable.css +67 -20
  7. package/dist/cjs/components/datatable.d.ts.map +1 -1
  8. package/dist/cjs/components/datatable.js +55 -18
  9. package/dist/cjs/components/footer.d.ts.map +1 -1
  10. package/dist/cjs/components/footer.js +2 -2
  11. package/dist/cjs/components/header.css +33 -1
  12. package/dist/cjs/components/header.d.ts.map +1 -1
  13. package/dist/cjs/components/header.js +19 -11
  14. package/dist/cjs/components/pagination.css +1 -1
  15. package/dist/cjs/components/pagination.d.ts.map +1 -1
  16. package/dist/cjs/components/pagination.js +19 -4
  17. package/dist/cjs/i18n/translations/en.d.ts +1 -0
  18. package/dist/cjs/i18n/translations/en.d.ts.map +1 -1
  19. package/dist/cjs/i18n/translations/en.js +2 -1
  20. package/dist/cjs/i18n/translations/tr.d.ts +2 -1
  21. package/dist/cjs/i18n/translations/tr.d.ts.map +1 -1
  22. package/dist/cjs/i18n/translations/tr.js +3 -2
  23. package/dist/cjs/types.d.ts +100 -1
  24. package/dist/cjs/types.d.ts.map +1 -1
  25. package/dist/cjs/types.js +5 -0
  26. package/dist/esm/akitable.d.ts +11 -0
  27. package/dist/esm/akitable.d.ts.map +1 -1
  28. package/dist/esm/akitable.js +33 -11
  29. package/dist/esm/components/actions.js +3 -3
  30. package/dist/esm/components/controls.js +2 -2
  31. package/dist/esm/components/datatable.css +67 -20
  32. package/dist/esm/components/datatable.d.ts.map +1 -1
  33. package/dist/esm/components/datatable.js +55 -18
  34. package/dist/esm/components/footer.d.ts.map +1 -1
  35. package/dist/esm/components/footer.js +2 -2
  36. package/dist/esm/components/header.css +33 -1
  37. package/dist/esm/components/header.d.ts.map +1 -1
  38. package/dist/esm/components/header.js +19 -11
  39. package/dist/esm/components/pagination.css +1 -1
  40. package/dist/esm/components/pagination.d.ts.map +1 -1
  41. package/dist/esm/components/pagination.js +19 -4
  42. package/dist/esm/i18n/translations/en.d.ts +1 -0
  43. package/dist/esm/i18n/translations/en.d.ts.map +1 -1
  44. package/dist/esm/i18n/translations/en.js +2 -1
  45. package/dist/esm/i18n/translations/tr.d.ts +2 -1
  46. package/dist/esm/i18n/translations/tr.d.ts.map +1 -1
  47. package/dist/esm/i18n/translations/tr.js +3 -2
  48. package/dist/esm/types.d.ts +100 -1
  49. package/dist/esm/types.d.ts.map +1 -1
  50. package/dist/esm/types.js +4 -1
  51. package/package.json +22 -21
@@ -1,55 +1,154 @@
1
1
  import { TableColumnType } from 'antd';
2
2
  import { ReactNode } from 'react';
3
3
  type RowClickEvent = (record: AkitableData, event?: React.MouseEvent<HTMLElement>, rowIndex?: number) => void;
4
- type RowEditCallback = (modifiedRecord: AkitableData, payload: AkitableData) => void;
4
+ type RowEditCallback = (modifiedRecord: AkitableData, payload: AkitableData) => void | Promise<void>;
5
5
  export type PaginationChangeEvent = (page: number, size: number) => void;
6
6
  export interface AkitableProps {
7
+ /**
8
+ * Actions available for the table rows.
9
+ */
7
10
  actions?: AkitableAction[];
11
+ /**
12
+ * Columns definition for the table.
13
+ */
8
14
  columns: AkitableColumn[];
15
+ /**
16
+ * Data source for the table.
17
+ */
9
18
  data: AkitableData[] | AkitablePaginatedData;
19
+ /**
20
+ * Header configuration for the table.
21
+ */
10
22
  header?: AkitableHeaderProps;
23
+ /**
24
+ * Footer configuration for the table.
25
+ */
11
26
  footer?: AkitableFooterProps;
27
+ /**
28
+ * Loading state for the table.
29
+ */
12
30
  isLoading?: boolean;
31
+ /**
32
+ * Pagination configuration for the table.
33
+ */
13
34
  pagination?: AkitablePaginationProps;
35
+ /**
36
+ * Unique key for each table row.
37
+ */
14
38
  rowKey: string;
39
+ /**
40
+ * Callback when pagination changes.
41
+ */
15
42
  onPaginationChanged?: PaginationChangeEvent;
43
+ /**
44
+ * Callback for row click events.
45
+ */
16
46
  onRowClick?: RowClickEvent;
47
+ /**
48
+ * Callback for row edit events.
49
+ */
17
50
  onRowEdit?: RowEditCallback;
18
51
  }
19
52
  export interface AkitableHeaderProps {
53
+ /**
54
+ * Title of the table header.
55
+ */
20
56
  title?: string;
57
+ /**
58
+ * Additional content for the table header.
59
+ */
21
60
  extra?: ReactNode;
22
61
  }
23
62
  export interface AkitableFooterProps {
63
+ /**
64
+ * Additional content for the table footer.
65
+ */
24
66
  extra?: ReactNode;
25
67
  }
26
68
  export interface AkitableDataTableProps {
69
+ /**
70
+ * Columns definition for the table.
71
+ */
27
72
  columns: AkitableColumn[];
73
+ /**
74
+ * Data source for the table.
75
+ */
28
76
  data: AkitableData[];
77
+ /**
78
+ * Unique key for each table row.
79
+ */
29
80
  rowKey: string;
81
+ /**
82
+ * Callback for row click events.
83
+ */
30
84
  onRowClick?: RowClickEvent;
85
+ /**
86
+ * Callback for row edit events.
87
+ */
31
88
  onRowEdit?: RowEditCallback;
32
89
  }
33
90
  export type AkitablePageSizes = 20 | 50 | 100 | 250;
34
91
  export interface AkitablePaginationProps {
92
+ /**
93
+ * Current page number.
94
+ */
35
95
  page: number;
96
+ /**
97
+ * Number of rows per page.
98
+ */
36
99
  size: AkitablePageSizes;
37
100
  }
38
101
  export interface AkitableColumn extends TableColumnType<AkitableData> {
102
+ /**
103
+ * Whether the column is copyable.
104
+ */
39
105
  copyable?: boolean;
106
+ /**
107
+ * Whether the column is editable.
108
+ */
40
109
  editable?: boolean;
41
110
  }
111
+ export declare const AkitableRowStatus: {
112
+ readonly PENDING: "pending";
113
+ readonly ERROR: "error";
114
+ };
115
+ type AllAkitableRowStatuses = `${(typeof AkitableRowStatus)[keyof typeof AkitableRowStatus]}`;
42
116
  export interface AkitableData {
117
+ /**
118
+ * Status of the table row.
119
+ */
120
+ rowStatus?: AllAkitableRowStatuses;
121
+ /**
122
+ * Additional properties for the table row.
123
+ */
43
124
  [key: string]: any;
44
125
  }
45
126
  export interface AkitablePaginatedData {
127
+ /**
128
+ * Total count of rows.
129
+ */
46
130
  count: number;
131
+ /**
132
+ * URL for the next set of paginated data.
133
+ */
47
134
  next?: string | null;
135
+ /**
136
+ * URL for the previous set of paginated data.
137
+ */
48
138
  previous?: string | null;
139
+ /**
140
+ * Results of the current page.
141
+ */
49
142
  results: AkitableData[];
50
143
  }
51
144
  export interface AkitableAction {
145
+ /**
146
+ * Label for the action.
147
+ */
52
148
  label: string;
149
+ /**
150
+ * Callback when the action is selected.
151
+ */
53
152
  onSelect: (selectedRowKeys: React.Key[]) => void;
54
153
  }
55
154
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,KAAK,aAAa,GAAG,CACnB,MAAM,EAAE,YAAY,EACpB,KAAK,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,KACd,IAAI,CAAC;AAEV,KAAK,eAAe,GAAG,CACrB,cAAc,EAAE,YAAY,EAC5B,OAAO,EAAE,YAAY,KAClB,IAAI,CAAC;AAEV,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAEzE,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,IAAI,EAAE,YAAY,EAAE,GAAG,qBAAqB,CAAC;IAC7C,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,uBAAuB,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,qBAAqB,CAAC;IAC5C,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,MAAM,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC;AAEpD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,WAAW,cAAe,SAAQ,eAAe,CAAC,YAAY,CAAC;IAEnE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAE3B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,eAAe,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC;CAClD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/dist/cjs/types.js CHANGED
@@ -1,2 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AkitableRowStatus = void 0;
4
+ exports.AkitableRowStatus = {
5
+ PENDING: 'pending',
6
+ ERROR: 'error'
7
+ };
@@ -1,5 +1,16 @@
1
1
  import './akitable.css';
2
2
  import React from 'react';
3
3
  import { AkitableProps } from './types';
4
+ /**
5
+ * Akitable component for Akinon UI.
6
+ *
7
+ * The Akitable component is a versatile and feature-rich table component designed for displaying,
8
+ * editing, and interacting with tabular data. It supports custom columns, pagination, row actions,
9
+ * and event callbacks for enhanced user experience and flexibility.
10
+ *
11
+ * Features include row click/edit actions, customizable headers and footers, pagination controls,
12
+ * and integration with Akinon design system standards. It is ideal for complex data visualization
13
+ * needs in enterprise applications.
14
+ */
4
15
  export declare const Akitable: (props: AkitableProps) => React.JSX.Element;
5
16
  //# sourceMappingURL=akitable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"akitable.d.ts","sourceRoot":"","sources":["../../src/akitable.tsx"],"names":[],"mappings":"AACA,OAAO,gBAAgB,CAAC;AAGxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,OAAO,EAAuC,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7E,eAAO,MAAM,QAAQ,UAAW,aAAa,sBAgE5C,CAAC"}
1
+ {"version":3,"file":"akitable.d.ts","sourceRoot":"","sources":["../../src/akitable.tsx"],"names":[],"mappings":"AACA,OAAO,gBAAgB,CAAC;AAGxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,OAAO,EAAuC,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7E;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,QAAQ,UAAW,aAAa,sBAuF5C,CAAC"}
@@ -10,22 +10,44 @@ import { AkitableDataTable } from './components/datatable';
10
10
  import { fallbackRender } from './components/error';
11
11
  import { AkitableFooter } from './components/footer';
12
12
  import { AkitableHeader } from './components/header';
13
+ /**
14
+ * Akitable component for Akinon UI.
15
+ *
16
+ * The Akitable component is a versatile and feature-rich table component designed for displaying,
17
+ * editing, and interacting with tabular data. It supports custom columns, pagination, row actions,
18
+ * and event callbacks for enhanced user experience and flexibility.
19
+ *
20
+ * Features include row click/edit actions, customizable headers and footers, pagination controls,
21
+ * and integration with Akinon design system standards. It is ideal for complex data visualization
22
+ * needs in enterprise applications.
23
+ */
13
24
  export const Akitable = (props) => {
14
25
  const { actions, columns, data, footer, header, isLoading, pagination, rowKey, onPaginationChanged, onRowClick, onRowEdit } = props;
15
- let parsedData = [];
16
- let total;
26
+ const handleGetSplittedDataByPagination = ({ result }) => {
27
+ if (!pagination)
28
+ return result;
29
+ const { page, size } = pagination;
30
+ const startIndex = (page - 1) * size;
31
+ const endIndex = startIndex + size;
32
+ return result.slice(startIndex, endIndex);
33
+ };
17
34
  // If there is a pagination object, table data should be accessed from type AkitablePaginatedData.
18
35
  // If not, table data should be accessed from type AkitableData.
19
- if (pagination) {
36
+ const handleGetParsedData = () => {
37
+ if (pagination) {
38
+ const result = data;
39
+ const total = (result === null || result === void 0 ? void 0 : result.count) || 0;
40
+ const parsedData = handleGetSplittedDataByPagination({
41
+ result: (result === null || result === void 0 ? void 0 : result.results) || []
42
+ });
43
+ return { total, parsedData };
44
+ }
20
45
  const result = data;
21
- total = (result === null || result === void 0 ? void 0 : result.count) || 0;
22
- parsedData = (result === null || result === void 0 ? void 0 : result.results) || [];
23
- }
24
- else {
25
- const result = data;
26
- total = (result === null || result === void 0 ? void 0 : result.length) || 0;
27
- parsedData = result || [];
28
- }
46
+ const total = (result === null || result === void 0 ? void 0 : result.length) || 0;
47
+ const parsedData = result || [];
48
+ return { total, parsedData };
49
+ };
50
+ const { total, parsedData } = handleGetParsedData();
29
51
  return (React.createElement("div", { className: "akitable-container" },
30
52
  React.createElement(ErrorBoundary, { fallbackRender: fallbackRender },
31
53
  React.createElement(AkitableProvider, { actions: actions, isLoading: isLoading, pagination: Object.assign(Object.assign({}, pagination), { total, hasPagination: !!pagination }), onPaginationChanged: onPaginationChanged },
@@ -17,13 +17,13 @@ export const AkitableActions = () => {
17
17
  setSelectedAction(value);
18
18
  };
19
19
  const handleActionTrigger = () => {
20
- if (!selectedAction || !selectedRowKeys || selectedRowKeys.length === 0)
20
+ if (!selectedAction || !hasSelections)
21
21
  return;
22
22
  const action = actions === null || actions === void 0 ? void 0 : actions.find((_, index) => index === selectedAction - 1);
23
23
  action === null || action === void 0 ? void 0 : action.onSelect(selectedRowKeys);
24
24
  };
25
- return (React.createElement("div", { className: "akitable-actions" },
26
- React.createElement(Select, { placeholder: t('selectAction'), value: selectedAction, options: options, onChange: value => handleActionChange(value), disabled: isLoading || (pagination === null || pagination === void 0 ? void 0 : pagination.total) === 0, allowClear: true }),
25
+ return (React.createElement("div", { "data-testid": "akitable-actions", className: "akitable-actions" },
26
+ React.createElement(Select, { placeholder: t('selectAction'), value: selectedAction, options: options, onChange: value => handleActionChange(value), disabled: isLoading || (pagination === null || pagination === void 0 ? void 0 : pagination.total) === 0, allowClear: true, "data-testid": "akitable-actions-select" }),
27
27
  selectedAction && (React.createElement(React.Fragment, null,
28
28
  React.createElement(Button, { type: "primary", icon: "katalogkontrol", disabled: isLoading || !hasSelections, onClick: handleActionTrigger }, t('apply')),
29
29
  hasSelections && (React.createElement("span", { className: "akitable-actions-info" }, t('selectedCount', { count: selectedRowKeys === null || selectedRowKeys === void 0 ? void 0 : selectedRowKeys.length })))))));
@@ -7,8 +7,8 @@ export const AkitableControls = () => {
7
7
  const { actions, pagination } = useAkitableContext();
8
8
  if (!actions)
9
9
  return null;
10
- return (React.createElement("div", { className: "akitable-controls" },
10
+ return (React.createElement("div", { "data-testid": "akitable-controls", className: "akitable-controls" },
11
11
  actions && actions.length > 0 && React.createElement(AkitableActions, null),
12
- (pagination === null || pagination === void 0 ? void 0 : pagination.hasPagination) && (React.createElement("div", { className: "ml-auto" },
12
+ (pagination === null || pagination === void 0 ? void 0 : pagination.hasPagination) && (React.createElement("div", { "data-testid": "akitable-controls-pagination", className: "ml-auto" },
13
13
  React.createElement(AkitablePagination, null)))));
14
14
  };
@@ -1,4 +1,10 @@
1
- .akinon-table-wrapper .akinon-table-thead > tr > th {
1
+ .akitable-wrapper {
2
+ margin-left: -1.5rem;
3
+ margin-right: -1.5rem;
4
+ margin-bottom: 1rem;
5
+ }
6
+
7
+ .akitable-wrapper .akinon-table-wrapper .akinon-table-thead > tr > th {
2
8
  text-transform: uppercase;
3
9
  font-size: 0.75rem;
4
10
  font-weight: 600;
@@ -6,50 +12,91 @@
6
12
  padding-top: 0.65rem;
7
13
  }
8
14
 
9
- .akitable-wrapper {
10
- margin-left: -1.5rem;
11
- margin-right: -1.5rem;
12
- margin-bottom: 1rem;
13
- }
14
-
15
- .akinon-table-content {
15
+ .akitable-wrapper .akinon-table-content {
16
16
  scrollbar-color: auto;
17
17
  scrollbar-width: auto;
18
18
  }
19
19
 
20
- .akinon-table-content::-webkit-scrollbar {
20
+ .akitable-wrapper .akinon-table-content::-webkit-scrollbar {
21
21
  height: 8px;
22
22
  }
23
23
 
24
- .akinon-table-content::-webkit-scrollbar-track {
24
+ .akitable-wrapper .akinon-table-content::-webkit-scrollbar-track {
25
25
  background-color: var(--color-neutral-100);
26
26
  border: none;
27
27
  padding: 1px;
28
28
  }
29
29
 
30
- .akinon-table-content::-webkit-scrollbar-thumb {
30
+ .akitable-wrapper .akinon-table-content::-webkit-scrollbar-thumb {
31
31
  background-color: var(--color-neutral-300);
32
32
  border-radius: 3px;
33
33
  border: none;
34
34
  }
35
35
 
36
36
  /* Add background for alternate rows. */
37
- .akinon-table-row:nth-child(odd) td {
38
- background-color: var(--color-neutral-100);
37
+ .akitable-wrapper .akinon-table-row:nth-child(odd) {
38
+ background-color: var(--color-neutral-75);
39
39
  }
40
40
 
41
- .akinon-table-row.is-selectable {
41
+ .akitable-wrapper .akinon-table-row.is-selectable {
42
42
  cursor: pointer;
43
- }
44
-
45
- .akinon-table-row.is-selectable td {
46
43
  transition: background-color 0.2s;
47
44
  }
48
45
 
49
- .akinon-table-row.is-selectable:hover td {
50
- background-color: var(--color-blue-100) !important;
46
+ .akitable-wrapper .akinon-table-row.is-selectable:hover {
47
+ background-color: var(--color-blue-100);
51
48
  }
52
49
 
53
- .akinon-table-row.is-selectable:hover td[class*='akinon-table-cell-fix-'] {
50
+ .akitable-wrapper
51
+ .akinon-table-row.is-selectable:hover
52
+ td[class*='akinon-table-cell-fix-'] {
54
53
  background-color: var(--color-blue-200) !important;
55
54
  }
55
+
56
+ .akitable-wrapper .akinon-table-row.akitable-row-pending {
57
+ background-color: var(--color-green-952-10);
58
+ position: relative;
59
+ }
60
+
61
+ .akitable-wrapper .akinon-table-cell {
62
+ z-index: 1;
63
+ }
64
+
65
+ .akitable-wrapper .akinon-table-row.akitable-row-pending::after {
66
+ content: '';
67
+ position: absolute;
68
+ top: 0;
69
+ left: 0;
70
+ right: 0;
71
+ bottom: 0;
72
+ background: repeating-linear-gradient(
73
+ 60deg,
74
+ transparent 0px,
75
+ transparent 18px,
76
+ var(--color-green-952-15) 18px,
77
+ var(--color-green-952-15) 36px,
78
+ transparent 36px
79
+ );
80
+ animation: shimmer 20s linear infinite;
81
+ }
82
+
83
+ @keyframes shimmer {
84
+ 0% {
85
+ left: -100%;
86
+ }
87
+ 100% {
88
+ left: -4.82596083%;
89
+ }
90
+ }
91
+
92
+ .akitable-wrapper .akinon-table-row.akitable-row-error {
93
+ background-color: var(--color-red-425-10);
94
+ }
95
+
96
+ .akitable-wrapper .akinon-table-tbody tr:last-child td {
97
+ border-bottom: 1px solid var(--color-neutral-350);
98
+ }
99
+
100
+ .akitable-wrapper .akinon-table-row .akinon-table-edit-button--disable {
101
+ cursor: not-allowed;
102
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"datatable.d.ts","sourceRoot":"","sources":["../../../src/components/datatable.tsx"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,CAAC;AAOzB,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAgC,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAIhF,eAAO,MAAM,iBAAiB,UAAW,sBAAsB,sBAsH9D,CAAC"}
1
+ {"version":3,"file":"datatable.d.ts","sourceRoot":"","sources":["../../../src/components/datatable.tsx"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,CAAC;AAOzB,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAGL,sBAAsB,EAEvB,MAAM,UAAU,CAAC;AAIlB,eAAO,MAAM,iBAAiB,UAAW,sBAAsB,sBAoK9D,CAAC"}
@@ -1,3 +1,12 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import './datatable.css';
2
11
  import { Akiform } from '@akinon/akiform';
3
12
  import { Button } from '@akinon/ui-button';
@@ -7,6 +16,7 @@ import clsx from 'clsx';
7
16
  import React from 'react';
8
17
  import { useAkitableContext } from '../akitable-context';
9
18
  import { i18n } from '../i18n';
19
+ import { AkitableRowStatus } from '../types';
10
20
  import EditableCell from './EditableCell';
11
21
  const { t } = i18n;
12
22
  export const AkitableDataTable = (props) => {
@@ -15,7 +25,10 @@ export const AkitableDataTable = (props) => {
15
25
  const [form] = Akiform.useForm();
16
26
  const [localColumns, setLocalColumns] = React.useState(columns);
17
27
  const [editingKey, setEditingKey] = React.useState(null);
28
+ const [isLoadingSaveButton, setIsLoadingSaveButton] = React.useState(false);
18
29
  const hasActions = actions && actions.length > 0;
30
+ const getRowKeyData = (record) => record[rowKey];
31
+ const checkIsEditingRow = (recordId) => recordId === editingKey;
19
32
  const onSelectChange = (newSelectedRowKeys) => {
20
33
  setSelectedRowKeys === null || setSelectedRowKeys === void 0 ? void 0 : setSelectedRowKeys(newSelectedRowKeys);
21
34
  };
@@ -30,6 +43,7 @@ export const AkitableDataTable = (props) => {
30
43
  */
31
44
  React.useEffect(() => {
32
45
  if (!onRowEdit) {
46
+ setLocalColumns(columns);
33
47
  return;
34
48
  }
35
49
  const modifiedColumns = columns.map(column => {
@@ -39,40 +53,63 @@ export const AkitableDataTable = (props) => {
39
53
  record,
40
54
  dataIndex: column.dataIndex,
41
55
  title: column.title,
42
- editing: record.id === editingKey
56
+ editing: checkIsEditingRow(getRowKeyData(record))
43
57
  }) });
44
58
  });
45
59
  const editColumn = {
46
60
  key: 'edit',
47
61
  title: t('edit'),
48
62
  render: (record) => {
49
- const isRowEditing = record.id === editingKey;
50
- return isRowEditing ? (React.createElement("span", null,
51
- React.createElement(Button, { size: "small", onClick: () => {
52
- onRowEdit(record, form.getFieldsValue());
53
- setEditingKey(null);
54
- form.resetFields();
55
- } }, t('save')),
56
- React.createElement(Text, { type: "danger", onClick: () => setEditingKey(null), style: { marginLeft: 8, cursor: 'pointer' } }, t('cancel')))) : (React.createElement(Button, { type: "primary", size: "small", onClick: () => {
63
+ const isRowEditing = checkIsEditingRow(getRowKeyData(record));
64
+ const handleOnClickSaveButton = () => __awaiter(void 0, void 0, void 0, function* () {
65
+ try {
66
+ setIsLoadingSaveButton(true);
67
+ yield onRowEdit(record, form.getFieldsValue());
68
+ setEditingKey(null);
57
69
  form.resetFields();
58
- setEditingKey(record.id);
59
- } }, t('edit')));
70
+ }
71
+ finally {
72
+ setIsLoadingSaveButton(false);
73
+ }
74
+ });
75
+ const handleOnClickEditButton = (e) => {
76
+ if (!isLoadingSaveButton) {
77
+ form.resetFields();
78
+ setEditingKey(getRowKeyData(record));
79
+ }
80
+ e.stopPropagation(); // To prevent row click event
81
+ };
82
+ const handleOnClickCancelButton = () => {
83
+ setEditingKey(null);
84
+ };
85
+ return isRowEditing ? (React.createElement("span", null,
86
+ React.createElement(Button, { size: "small", onClick: handleOnClickSaveButton, loading: isLoadingSaveButton }, t('save')),
87
+ React.createElement(Text, Object.assign({ type: "danger", disabled: isLoadingSaveButton, className: "cursor-pointer ml-2" }, (!isLoadingSaveButton && {
88
+ onClick: handleOnClickCancelButton
89
+ })), t('cancel')))) : (React.createElement(Button, { type: "primary", size: "small", onClick: handleOnClickEditButton, className: clsx({
90
+ 'akinon-table-edit-button--disable': isLoadingSaveButton
91
+ }) }, t('edit')));
60
92
  },
61
93
  width: 200
62
94
  };
63
95
  setLocalColumns([...modifiedColumns, editColumn]);
64
- }, [columns, onRowEdit, editingKey]);
65
- return (React.createElement("div", { className: "akitable-wrapper" },
96
+ }, [columns, onRowEdit, editingKey, isLoadingSaveButton]);
97
+ return (React.createElement("div", { "data-testid": "akitable-datatable-wrapper", className: "akitable-wrapper" },
66
98
  React.createElement(Akiform, { form: form, component: false },
67
- React.createElement(Table, { components: {
99
+ React.createElement(Table, { "data-testid": "akitable-datatable", components: {
68
100
  body: {
69
101
  cell: EditableCell
70
102
  }
71
- }, columns: localColumns, dataSource: data, rowKey: (record) => record[rowKey], bordered: true, rowHoverable: true, pagination: false, scroll: { x: 'max-content', scrollToFirstRowOnChange: true }, loading: isLoading, onRow: (record, rowIndex) => {
72
- return {
103
+ }, columns: localColumns, dataSource: data, rowKey: (record) => getRowKeyData(record), bordered: true, rowHoverable: true, pagination: false, scroll: { x: 'max-content', scrollToFirstRowOnChange: true }, loading: isLoading, onRow: (record, rowIndex) => {
104
+ const isEditingRow = checkIsEditingRow(getRowKeyData(record));
105
+ return Object.assign({}, (!isEditingRow && {
73
106
  onClick: (event) => {
74
107
  onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(record, event, rowIndex);
75
108
  }
76
- };
77
- }, rowClassName: clsx({ 'is-selectable': !!onRowClick }), rowSelection: hasActions ? rowSelection : undefined }))));
109
+ }));
110
+ }, rowClassName: (record) => clsx({
111
+ 'is-selectable': !!onRowClick && !checkIsEditingRow(getRowKeyData(record)),
112
+ 'akitable-row-pending': record.rowStatus === AkitableRowStatus.PENDING,
113
+ 'akitable-row-error': record.rowStatus === AkitableRowStatus.ERROR
114
+ }), rowSelection: hasActions ? rowSelection : undefined }))));
78
115
  };
@@ -1 +1 @@
1
- {"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../src/components/footer.tsx"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAGtB,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAG/C,eAAO,MAAM,cAAc,UAAW,mBAAmB,6BAkBxD,CAAC"}
1
+ {"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../src/components/footer.tsx"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAGtB,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAG/C,eAAO,MAAM,cAAc,UAAW,mBAAmB,6BAsBxD,CAAC"}
@@ -8,8 +8,8 @@ export const AkitableFooter = (props) => {
8
8
  const { extra } = props;
9
9
  if (!extra && !(pagination === null || pagination === void 0 ? void 0 : pagination.hasPagination))
10
10
  return null;
11
- return (React.createElement("div", { className: "akitable-footer" },
12
- extra && (React.createElement("div", { className: "akitable-footer-extra" }, isLoading ? React.createElement(Spin, null) : extra)),
11
+ return (React.createElement("div", { "data-testid": "akitable-footer", className: "akitable-footer" },
12
+ extra && (React.createElement("div", { className: "akitable-footer-extra" }, isLoading ? (React.createElement(Spin, { "data-testid": "akitable-footer-extra-loading-skeleton" })) : (extra))),
13
13
  React.createElement("div", { className: "ml-auto" },
14
14
  React.createElement(AkitablePagination, null))));
15
15
  };
@@ -5,13 +5,40 @@
5
5
  min-height: 40px;
6
6
  }
7
7
 
8
+ .akitable-header-title-container {
9
+ display: flex;
10
+ align-items: center;
11
+ gap: 0.1rem;
12
+ color: var(--color-gray-900);
13
+ }
14
+
8
15
  .akitable-header-title {
9
16
  font-size: 1.25rem;
10
17
  font-weight: bold;
11
18
  margin: 0;
12
19
  padding: 0;
13
20
  line-height: 1;
14
- color: var(--color-gray-900);
21
+ display: flex;
22
+ align-items: center;
23
+ }
24
+
25
+ .akitable-header-title-count-skeleton {
26
+ width: 50px;
27
+ height: 20px;
28
+ margin-left: 0.7rem;
29
+ }
30
+
31
+ .akitable-header-title-count {
32
+ font-size: 1.25rem;
33
+ font-weight: bold;
34
+ margin: 0;
35
+ padding: 0;
36
+ line-height: 1;
37
+ }
38
+
39
+ .akitable-header-title-description-skeleton {
40
+ width: 120px;
41
+ height: 10px;
15
42
  }
16
43
 
17
44
  .akitable-header-description {
@@ -20,6 +47,11 @@
20
47
  margin-top: 0.5rem;
21
48
  }
22
49
 
50
+ .akitable-header-extra-content {
51
+ margin-bottom: 1rem;
52
+ color: var(--color-gray-300);
53
+ }
54
+
23
55
  .akitable-header-extra {
24
56
  margin-left: auto;
25
57
  text-align: right;
@@ -1 +1 @@
1
- {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../src/components/header.tsx"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAItB,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAG/C,eAAO,MAAM,cAAc,UAAW,mBAAmB,6BAyCxD,CAAC"}
1
+ {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../../../src/components/header.tsx"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAItB,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAG/C,eAAO,MAAM,cAAc,UAAW,mBAAmB,6BA4ExD,CAAC"}
@@ -11,17 +11,25 @@ export const AkitableHeader = (props) => {
11
11
  const hasActions = actions && (actions === null || actions === void 0 ? void 0 : actions.length) > 0;
12
12
  if (!title && !extra)
13
13
  return null;
14
- return (React.createElement("div", { className: "akitable-header" },
15
- title && (React.createElement("div", null,
16
- React.createElement("h2", { className: "akitable-header-title" },
17
- title,
18
- " ",
19
- !isLoading && `(${pagination === null || pagination === void 0 ? void 0 : pagination.total})`),
20
- !isLoading && !!(pagination === null || pagination === void 0 ? void 0 : pagination.total) && (React.createElement("span", { className: "akitable-header-description" }, i18n.t('resultsFound', { count: pagination === null || pagination === void 0 ? void 0 : pagination.total }))),
21
- !isLoading && !(pagination === null || pagination === void 0 ? void 0 : pagination.total) && (React.createElement("span", { className: "akitable-header-description" }, i18n.t('noData'))),
22
- isLoading && React.createElement(Skeleton, { count: 0.7, className: "mt-2" }))),
14
+ const renderTitle = () => {
15
+ return (React.createElement("div", { className: "akitable-header-title-container" },
16
+ React.createElement("h2", { className: "akitable-header-title" }, title),
17
+ isLoading ? (React.createElement("span", { "data-testid": "akitable-title-loading-skeleton" },
18
+ React.createElement(Skeleton.Button, { active: true, size: "small", className: "ml-1" }))) : (React.createElement("span", { className: "akitable-header-title-count" }, `(${pagination === null || pagination === void 0 ? void 0 : pagination.total})`))));
19
+ };
20
+ const renderTitleDescription = () => {
21
+ const descriptionContent = !(pagination === null || pagination === void 0 ? void 0 : pagination.total)
22
+ ? i18n.t('noData')
23
+ : i18n.t('resultsFound', { count: pagination === null || pagination === void 0 ? void 0 : pagination.total });
24
+ return (React.createElement("span", { "data-testid": "akitable-header-description", className: "akitable-header-description" }, descriptionContent));
25
+ };
26
+ return (React.createElement("div", { "data-testid": "akitable-header", className: "akitable-header" },
27
+ !!title && (React.createElement("div", { "data-testid": "akitable-header-title-container" },
28
+ renderTitle(),
29
+ isLoading ? (React.createElement("span", { "data-testid": "akitable-title-description-loading-skeleton" },
30
+ React.createElement(Skeleton.Input, { active: true, size: "small", className: "mt-2" }))) : (renderTitleDescription()))),
23
31
  React.createElement("div", { className: "akitable-header-extra" },
24
- extra && React.createElement("div", { className: "mb-4" }, isLoading ? React.createElement(Spin, null) : extra),
25
- !hasActions && (pagination === null || pagination === void 0 ? void 0 : pagination.hasPagination) && (React.createElement("div", null,
32
+ extra && (React.createElement("div", { "data-testid": "akitable-header-extra-content", className: "akitable-header-extra-content" }, isLoading ? (React.createElement(Spin, { "data-testid": "akitable-header-extra-loading-skeleton" })) : (extra))),
33
+ !hasActions && (pagination === null || pagination === void 0 ? void 0 : pagination.hasPagination) && (React.createElement("div", { "data-testid": "akitable-header-pagination" },
26
34
  React.createElement(AkitablePagination, null))))));
27
35
  };