@keenthemes/ktui 1.2.2 → 1.2.4

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 (166) hide show
  1. package/dist/ktui.js +1738 -986
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +110 -197
  5. package/lib/cjs/components/context-menu/context-menu.d.ts +66 -0
  6. package/lib/cjs/components/context-menu/context-menu.d.ts.map +1 -0
  7. package/lib/cjs/components/context-menu/context-menu.js +423 -0
  8. package/lib/cjs/components/context-menu/context-menu.js.map +1 -0
  9. package/lib/cjs/components/context-menu/index.d.ts +7 -0
  10. package/lib/cjs/components/context-menu/index.d.ts.map +1 -0
  11. package/lib/cjs/components/context-menu/index.js +10 -0
  12. package/lib/cjs/components/context-menu/index.js.map +1 -0
  13. package/lib/cjs/components/context-menu/types.d.ts +30 -0
  14. package/lib/cjs/components/context-menu/types.d.ts.map +1 -0
  15. package/lib/cjs/components/context-menu/types.js +7 -0
  16. package/lib/cjs/components/context-menu/types.js.map +1 -0
  17. package/lib/cjs/components/datatable/datatable-contracts.d.ts +66 -0
  18. package/lib/cjs/components/datatable/datatable-contracts.d.ts.map +1 -0
  19. package/lib/cjs/components/datatable/datatable-contracts.js +7 -0
  20. package/lib/cjs/components/datatable/datatable-contracts.js.map +1 -0
  21. package/lib/cjs/components/datatable/datatable-event-adapter.d.ts +7 -0
  22. package/lib/cjs/components/datatable/datatable-event-adapter.d.ts.map +1 -0
  23. package/lib/cjs/components/datatable/datatable-event-adapter.js +16 -0
  24. package/lib/cjs/components/datatable/datatable-event-adapter.js.map +1 -0
  25. package/lib/cjs/components/datatable/datatable-local-provider.d.ts +25 -0
  26. package/lib/cjs/components/datatable/datatable-local-provider.d.ts.map +1 -0
  27. package/lib/cjs/components/datatable/datatable-local-provider.js +184 -0
  28. package/lib/cjs/components/datatable/datatable-local-provider.js.map +1 -0
  29. package/lib/cjs/components/datatable/datatable-pagination-renderer.d.ts +15 -0
  30. package/lib/cjs/components/datatable/datatable-pagination-renderer.d.ts.map +1 -0
  31. package/lib/cjs/components/datatable/datatable-pagination-renderer.js +128 -0
  32. package/lib/cjs/components/datatable/datatable-pagination-renderer.js.map +1 -0
  33. package/lib/cjs/components/datatable/datatable-remote-provider.d.ts +25 -0
  34. package/lib/cjs/components/datatable/datatable-remote-provider.d.ts.map +1 -0
  35. package/lib/cjs/components/datatable/datatable-remote-provider.js +188 -0
  36. package/lib/cjs/components/datatable/datatable-remote-provider.js.map +1 -0
  37. package/lib/cjs/components/datatable/datatable-state-store.d.ts +21 -0
  38. package/lib/cjs/components/datatable/datatable-state-store.d.ts.map +1 -0
  39. package/lib/cjs/components/datatable/datatable-state-store.js +81 -0
  40. package/lib/cjs/components/datatable/datatable-state-store.js.map +1 -0
  41. package/lib/cjs/components/datatable/datatable-table-renderer.d.ts +16 -0
  42. package/lib/cjs/components/datatable/datatable-table-renderer.d.ts.map +1 -0
  43. package/lib/cjs/components/datatable/datatable-table-renderer.js +133 -0
  44. package/lib/cjs/components/datatable/datatable-table-renderer.js.map +1 -0
  45. package/lib/cjs/components/datatable/datatable.d.ts +9 -87
  46. package/lib/cjs/components/datatable/datatable.d.ts.map +1 -1
  47. package/lib/cjs/components/datatable/datatable.js +115 -687
  48. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  49. package/lib/cjs/components/modal/modal.d.ts.map +1 -1
  50. package/lib/cjs/components/modal/modal.js +19 -13
  51. package/lib/cjs/components/modal/modal.js.map +1 -1
  52. package/lib/cjs/components/select/index.d.ts +1 -1
  53. package/lib/cjs/components/select/index.d.ts.map +1 -1
  54. package/lib/cjs/components/theme-switch/theme-switch.d.ts +3 -0
  55. package/lib/cjs/components/theme-switch/theme-switch.d.ts.map +1 -1
  56. package/lib/cjs/components/theme-switch/theme-switch.js +17 -4
  57. package/lib/cjs/components/theme-switch/theme-switch.js.map +1 -1
  58. package/lib/cjs/components/toggle/toggle.d.ts +2 -0
  59. package/lib/cjs/components/toggle/toggle.d.ts.map +1 -1
  60. package/lib/cjs/components/toggle/toggle.js +11 -2
  61. package/lib/cjs/components/toggle/toggle.js.map +1 -1
  62. package/lib/cjs/index.d.ts +5 -1
  63. package/lib/cjs/index.d.ts.map +1 -1
  64. package/lib/cjs/index.js +7 -7
  65. package/lib/cjs/index.js.map +1 -1
  66. package/lib/cjs/init-all.d.ts +6 -0
  67. package/lib/cjs/init-all.d.ts.map +1 -0
  68. package/lib/cjs/init-all.js +17 -0
  69. package/lib/cjs/init-all.js.map +1 -0
  70. package/lib/cjs/legacy.d.ts +8 -0
  71. package/lib/cjs/legacy.d.ts.map +1 -0
  72. package/lib/cjs/legacy.js +26 -0
  73. package/lib/cjs/legacy.js.map +1 -0
  74. package/lib/esm/components/context-menu/context-menu.d.ts +66 -0
  75. package/lib/esm/components/context-menu/context-menu.d.ts.map +1 -0
  76. package/lib/esm/components/context-menu/context-menu.js +420 -0
  77. package/lib/esm/components/context-menu/context-menu.js.map +1 -0
  78. package/lib/esm/components/context-menu/index.d.ts +7 -0
  79. package/lib/esm/components/context-menu/index.d.ts.map +1 -0
  80. package/lib/esm/components/context-menu/index.js +6 -0
  81. package/lib/esm/components/context-menu/index.js.map +1 -0
  82. package/lib/esm/components/context-menu/types.d.ts +30 -0
  83. package/lib/esm/components/context-menu/types.d.ts.map +1 -0
  84. package/lib/esm/components/context-menu/types.js +6 -0
  85. package/lib/esm/components/context-menu/types.js.map +1 -0
  86. package/lib/esm/components/datatable/datatable-contracts.d.ts +66 -0
  87. package/lib/esm/components/datatable/datatable-contracts.d.ts.map +1 -0
  88. package/lib/esm/components/datatable/datatable-contracts.js +6 -0
  89. package/lib/esm/components/datatable/datatable-contracts.js.map +1 -0
  90. package/lib/esm/components/datatable/datatable-event-adapter.d.ts +7 -0
  91. package/lib/esm/components/datatable/datatable-event-adapter.d.ts.map +1 -0
  92. package/lib/esm/components/datatable/datatable-event-adapter.js +13 -0
  93. package/lib/esm/components/datatable/datatable-event-adapter.js.map +1 -0
  94. package/lib/esm/components/datatable/datatable-local-provider.d.ts +25 -0
  95. package/lib/esm/components/datatable/datatable-local-provider.d.ts.map +1 -0
  96. package/lib/esm/components/datatable/datatable-local-provider.js +181 -0
  97. package/lib/esm/components/datatable/datatable-local-provider.js.map +1 -0
  98. package/lib/esm/components/datatable/datatable-pagination-renderer.d.ts +15 -0
  99. package/lib/esm/components/datatable/datatable-pagination-renderer.d.ts.map +1 -0
  100. package/lib/esm/components/datatable/datatable-pagination-renderer.js +125 -0
  101. package/lib/esm/components/datatable/datatable-pagination-renderer.js.map +1 -0
  102. package/lib/esm/components/datatable/datatable-remote-provider.d.ts +25 -0
  103. package/lib/esm/components/datatable/datatable-remote-provider.d.ts.map +1 -0
  104. package/lib/esm/components/datatable/datatable-remote-provider.js +185 -0
  105. package/lib/esm/components/datatable/datatable-remote-provider.js.map +1 -0
  106. package/lib/esm/components/datatable/datatable-state-store.d.ts +21 -0
  107. package/lib/esm/components/datatable/datatable-state-store.d.ts.map +1 -0
  108. package/lib/esm/components/datatable/datatable-state-store.js +78 -0
  109. package/lib/esm/components/datatable/datatable-state-store.js.map +1 -0
  110. package/lib/esm/components/datatable/datatable-table-renderer.d.ts +16 -0
  111. package/lib/esm/components/datatable/datatable-table-renderer.d.ts.map +1 -0
  112. package/lib/esm/components/datatable/datatable-table-renderer.js +130 -0
  113. package/lib/esm/components/datatable/datatable-table-renderer.js.map +1 -0
  114. package/lib/esm/components/datatable/datatable.d.ts +9 -87
  115. package/lib/esm/components/datatable/datatable.d.ts.map +1 -1
  116. package/lib/esm/components/datatable/datatable.js +115 -687
  117. package/lib/esm/components/datatable/datatable.js.map +1 -1
  118. package/lib/esm/components/modal/modal.d.ts.map +1 -1
  119. package/lib/esm/components/modal/modal.js +19 -13
  120. package/lib/esm/components/modal/modal.js.map +1 -1
  121. package/lib/esm/components/select/index.d.ts +1 -1
  122. package/lib/esm/components/select/index.d.ts.map +1 -1
  123. package/lib/esm/components/theme-switch/theme-switch.d.ts +3 -0
  124. package/lib/esm/components/theme-switch/theme-switch.d.ts.map +1 -1
  125. package/lib/esm/components/theme-switch/theme-switch.js +17 -4
  126. package/lib/esm/components/theme-switch/theme-switch.js.map +1 -1
  127. package/lib/esm/components/toggle/toggle.d.ts +2 -0
  128. package/lib/esm/components/toggle/toggle.d.ts.map +1 -1
  129. package/lib/esm/components/toggle/toggle.js +11 -2
  130. package/lib/esm/components/toggle/toggle.js.map +1 -1
  131. package/lib/esm/index.d.ts +5 -1
  132. package/lib/esm/index.d.ts.map +1 -1
  133. package/lib/esm/index.js +4 -5
  134. package/lib/esm/index.js.map +1 -1
  135. package/lib/esm/init-all.d.ts +6 -0
  136. package/lib/esm/init-all.d.ts.map +1 -0
  137. package/lib/esm/init-all.js +13 -0
  138. package/lib/esm/init-all.js.map +1 -0
  139. package/lib/esm/legacy.d.ts +8 -0
  140. package/lib/esm/legacy.d.ts.map +1 -0
  141. package/lib/esm/legacy.js +8 -0
  142. package/lib/esm/legacy.js.map +1 -0
  143. package/package.json +34 -4
  144. package/src/__tests__/entrypoints.test.ts +71 -0
  145. package/src/components/context-menu/__tests__/context-menu.test.ts +117 -0
  146. package/src/components/context-menu/context-menu.css +32 -0
  147. package/src/components/context-menu/context-menu.ts +529 -0
  148. package/src/components/context-menu/index.ts +10 -0
  149. package/src/components/context-menu/types.ts +32 -0
  150. package/src/components/datatable/__tests__/architecture-boundaries.test.ts +259 -0
  151. package/src/components/datatable/datatable-contracts.ts +96 -0
  152. package/src/components/datatable/datatable-event-adapter.ts +21 -0
  153. package/src/components/datatable/datatable-local-provider.ts +194 -0
  154. package/src/components/datatable/datatable-pagination-renderer.ts +211 -0
  155. package/src/components/datatable/datatable-remote-provider.ts +175 -0
  156. package/src/components/datatable/datatable-state-store.ts +94 -0
  157. package/src/components/datatable/datatable-table-renderer.ts +206 -0
  158. package/src/components/datatable/datatable.ts +128 -839
  159. package/src/components/modal/modal.ts +22 -14
  160. package/src/components/select/index.ts +1 -1
  161. package/src/components/theme-switch/theme-switch.ts +22 -4
  162. package/src/components/toggle/toggle.ts +12 -2
  163. package/src/index.ts +9 -5
  164. package/src/init-all.ts +15 -0
  165. package/src/legacy.ts +9 -0
  166. package/styles.css +1 -0
@@ -64,32 +64,17 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
64
64
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
65
65
  }
66
66
  };
67
- var __rest = (this && this.__rest) || function (s, e) {
68
- var t = {};
69
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
70
- t[p] = s[p];
71
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
72
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
73
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
74
- t[p[i]] = s[p[i]];
75
- }
76
- return t;
77
- };
78
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
79
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
80
- if (ar || !(i in from)) {
81
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
82
- ar[i] = from[i];
83
- }
84
- }
85
- return to.concat(ar || Array.prototype.slice.call(from));
86
- };
87
67
  import KTComponent from '../component';
88
- import KTUtils from '../../helpers/utils';
89
68
  import KTComponents from '../../index';
90
69
  import KTData from '../../helpers/data';
91
70
  import { createCheckboxHandler, } from './datatable-checkbox';
92
71
  import { createSortHandler } from './datatable-sort';
72
+ import { createDataTableEventAdapter } from './datatable-event-adapter';
73
+ import { KTDataTableLocalDataProvider } from './datatable-local-provider';
74
+ import { KTDataTableRemoteDataProvider } from './datatable-remote-provider';
75
+ import { KTDataTableConfigStateStore } from './datatable-state-store';
76
+ import { KTDataTableDomPaginationRenderer } from './datatable-pagination-renderer';
77
+ import { KTDataTableDomTableRenderer } from './datatable-table-renderer';
93
78
  /**
94
79
  * Custom DataTable plugin class with server-side API, pagination, and sorting
95
80
  * @classdesc A custom KTComponent class that integrates server-side API, pagination, and sorting functionality into a table.
@@ -109,18 +94,9 @@ var KTDataTable = /** @class */ (function (_super) {
109
94
  _this._originalTheadClass = ''; // Store original thead class
110
95
  _this._originalTdClasses = []; // Store original td classes as a 2D array [row][col]
111
96
  _this._originalThClasses = []; // Store original th classes
97
+ _this._cleanupCallbacks = [];
112
98
  _this._data = [];
113
99
  _this._isFetching = false;
114
- /**
115
- * AbortController for cancelling previous fetch requests
116
- * Used to prevent race conditions when multiple requests are triggered rapidly
117
- */
118
- _this._abortController = null;
119
- /**
120
- * Request ID counter for tracking request sequence
121
- * Used to detect and ignore stale responses from older requests
122
- */
123
- _this._requestId = 0;
124
100
  if (KTData.has(element, _this._name)) {
125
101
  // Already initialized (e.g. by createInstances). Merge user config so columns/sortType etc. apply.
126
102
  var existing = KTDataTable.getInstance(element);
@@ -132,21 +108,22 @@ var KTDataTable = /** @class */ (function (_super) {
132
108
  _this._defaultConfig = _this._initDefaultConfig(config);
133
109
  _this._init(element);
134
110
  _this._buildConfig();
111
+ _this._stateStore = new KTDataTableConfigStateStore(_this._config);
112
+ _this._eventAdapter = createDataTableEventAdapter(_this._fireEvent.bind(_this), _this._dispatchEvent.bind(_this));
135
113
  // Store the instance directly on the element
136
114
  KTDataTable.asElementWithInstance(element).instance = _this;
137
115
  _this._initElements();
116
+ _this._tableRenderer = new KTDataTableDomTableRenderer();
117
+ _this._paginationRenderer = new KTDataTableDomPaginationRenderer();
118
+ _this._initDataProviders();
138
119
  // Initialize checkbox handler
139
- _this._checkbox = createCheckboxHandler(_this._element, _this._config, function (eventName, eventData) {
140
- _this._fireEvent(eventName, eventData);
141
- _this._dispatchEvent(eventName, eventData);
142
- });
120
+ _this._checkbox = createCheckboxHandler(_this._element, _this._config, _this._emit.bind(_this));
143
121
  // Initialize sort handler
144
122
  _this._sortHandler = createSortHandler(_this._config, _this._theadElement, function () { return ({
145
123
  sortField: _this.getState().sortField,
146
124
  sortOrder: _this.getState().sortOrder,
147
125
  }); }, function (field, order) {
148
- _this._config._state.sortField = field;
149
- _this._config._state.sortOrder = order;
126
+ _this._stateStore.setSort(field, order);
150
127
  }, _this._fireEvent.bind(_this), _this._dispatchEvent.bind(_this), _this._updateData.bind(_this));
151
128
  _this._sortHandler.initSort();
152
129
  if (_this._config.stateSave === false) {
@@ -156,8 +133,7 @@ var KTDataTable = /** @class */ (function (_super) {
156
133
  _this._loadState();
157
134
  }
158
135
  _this._updateData();
159
- _this._fireEvent('init');
160
- _this._dispatchEvent('init');
136
+ _this._emit('init');
161
137
  return _this;
162
138
  }
163
139
  KTDataTable.asElementWithInstance = function (element) {
@@ -166,6 +142,30 @@ var KTDataTable = /** @class */ (function (_super) {
166
142
  KTDataTable.asSearchElementWithDebounce = function (element) {
167
143
  return element;
168
144
  };
145
+ KTDataTable.prototype._emit = function (eventName, eventData) {
146
+ this._eventAdapter.emit(eventName, eventData);
147
+ };
148
+ KTDataTable.prototype._initDataProviders = function () {
149
+ var _this = this;
150
+ this._localProvider = new KTDataTableLocalDataProvider({
151
+ config: this._config,
152
+ elements: function () { return ({
153
+ tableElement: _this._tableElement,
154
+ tbodyElement: _this._tbodyElement,
155
+ theadElement: _this._theadElement,
156
+ }); },
157
+ getLogicalColumnCount: this._getLogicalColumnCount.bind(this),
158
+ storeOriginalClasses: this._storeOriginalClasses.bind(this),
159
+ stateStore: this._stateStore,
160
+ });
161
+ this._remoteProvider = new KTDataTableRemoteDataProvider({
162
+ config: this._config,
163
+ createUrl: this._createUrl.bind(this),
164
+ eventAdapter: this._eventAdapter,
165
+ noticeOnTable: this._noticeOnTable.bind(this),
166
+ stateStore: this._stateStore,
167
+ });
168
+ };
169
169
  /**
170
170
  * Initialize default configuration for the datatable
171
171
  * @param config User-provided configuration options
@@ -306,7 +306,7 @@ var KTDataTable = /** @class */ (function (_super) {
306
306
  return false;
307
307
  }
308
308
  var valueText = String(value)
309
- .replace(/<[^>]*>|&nbsp;/g, '')
309
+ .replace(/<|>|&nbsp;/g, '')
310
310
  .toLowerCase();
311
311
  return valueText.includes(search.toLowerCase());
312
312
  });
@@ -435,32 +435,39 @@ var KTDataTable = /** @class */ (function (_super) {
435
435
  */
436
436
  KTDataTable.prototype._updateData = function () {
437
437
  return __awaiter(this, void 0, void 0, function () {
438
- return __generator(this, function (_a) {
439
- switch (_a.label) {
438
+ var result, _a;
439
+ return __generator(this, function (_b) {
440
+ switch (_b.label) {
440
441
  case 0:
441
442
  if (this._isFetching)
442
443
  return [2 /*return*/]; // Prevent duplicate fetches
443
444
  this._isFetching = true;
444
- _a.label = 1;
445
+ _b.label = 1;
445
446
  case 1:
446
- _a.trys.push([1, , 8, 9]);
447
+ _b.trys.push([1, , 8, 9]);
447
448
  this._showSpinner(); // Show spinner before fetching data
448
- if (!(typeof this._config.apiEndpoint === 'undefined')) return [3 /*break*/, 4];
449
- return [4 /*yield*/, this._fetchDataFromLocal()];
450
- case 2:
451
- _a.sent();
452
- return [4 /*yield*/, this._finalize()];
449
+ this._emit('fetch');
450
+ if (!(typeof this._config.apiEndpoint === 'undefined')) return [3 /*break*/, 2];
451
+ _a = this._localProvider.fetchSync();
452
+ return [3 /*break*/, 4];
453
+ case 2: return [4 /*yield*/, this._remoteProvider.fetch()];
453
454
  case 3:
454
- _a.sent();
455
- return [3 /*break*/, 7];
456
- case 4: return [4 /*yield*/, this._fetchDataFromServer()];
455
+ _a = _b.sent();
456
+ _b.label = 4;
457
+ case 4:
458
+ result = _a;
459
+ if (!!result.skipped) return [3 /*break*/, 6];
460
+ this._data = result.data;
461
+ this._stateStore.patchState({ totalItems: result.totalItems });
462
+ return [4 /*yield*/, this._draw()];
457
463
  case 5:
458
- _a.sent();
459
- return [4 /*yield*/, this._finalize()];
460
- case 6:
461
- _a.sent();
462
- _a.label = 7;
463
- case 7: return [3 /*break*/, 9];
464
+ _b.sent();
465
+ this._emit('fetched');
466
+ _b.label = 6;
467
+ case 6: return [4 /*yield*/, this._finalize()];
468
+ case 7:
469
+ _b.sent();
470
+ return [3 /*break*/, 9];
464
471
  case 8:
465
472
  // Finally block now correctly executes after promises resolve, not immediately
466
473
  this._isFetching = false;
@@ -527,152 +534,6 @@ var KTDataTable = /** @class */ (function (_super) {
527
534
  searchElement.addEventListener('keyup', debouncedSearch);
528
535
  }
529
536
  };
530
- /**
531
- * Fetch data from the DOM
532
- * Fetch data from the table element and save it to the `originalData` state property.
533
- * This method is used when the data is not fetched from the server via an API endpoint.
534
- */
535
- KTDataTable.prototype._fetchDataFromLocal = function () {
536
- return __awaiter(this, void 0, void 0, function () {
537
- var _a, sortField, sortOrder, page, pageSize, search, originalData, _b, originalData_1, originalDataAttributes, _temp, searchTerm, startIndex, endIndex;
538
- var _c;
539
- return __generator(this, function (_d) {
540
- switch (_d.label) {
541
- case 0:
542
- this._fireEvent('fetch');
543
- this._dispatchEvent('fetch');
544
- _a = this.getState(), sortField = _a.sortField, sortOrder = _a.sortOrder, page = _a.page, pageSize = _a.pageSize, search = _a.search;
545
- originalData = this.getState().originalData;
546
- // If the table element or the original data is not defined, bail
547
- if (!this._tableElement ||
548
- originalData === undefined ||
549
- this._tableConfigInvalidate() ||
550
- this._localTableHeaderInvalidate() ||
551
- this._localTableContentInvalidate()) {
552
- this._deleteState();
553
- _b = this._localExtractTableContent(), originalData_1 = _b.originalData, originalDataAttributes = _b.originalDataAttributes;
554
- this._config._state.originalData = originalData_1;
555
- this._config._state.originalDataAttributes = originalDataAttributes;
556
- }
557
- // Update the original data variable
558
- originalData = this.getState().originalData;
559
- _temp = (this._data = __spreadArray([], originalData, true));
560
- if (search) {
561
- searchTerm = typeof search === 'string' ? search : '';
562
- _temp = this._data = this._config.search.callback.call(this, this._data, searchTerm);
563
- }
564
- // If sorting is defined, sort the data
565
- if (sortField !== undefined &&
566
- sortOrder !== undefined &&
567
- sortOrder !== '') {
568
- if (typeof this._config.sort.callback === 'function') {
569
- this._data = this._config.sort.callback.call(this, this._data, sortField, sortOrder);
570
- }
571
- }
572
- // If there is data, slice it to the current page size
573
- if (((_c = this._data) === null || _c === void 0 ? void 0 : _c.length) > 0) {
574
- startIndex = (page - 1) * pageSize;
575
- endIndex = startIndex + pageSize;
576
- this._data = this._data.slice(startIndex, endIndex);
577
- }
578
- // Determine number of total rows
579
- this._config._state.totalItems = _temp.length;
580
- // Draw the data
581
- return [4 /*yield*/, this._draw()];
582
- case 1:
583
- // Draw the data
584
- _d.sent();
585
- this._fireEvent('fetched');
586
- this._dispatchEvent('fetched');
587
- return [2 /*return*/];
588
- }
589
- });
590
- });
591
- };
592
- /**
593
- * Checks if the table content has been invalidated by comparing the current checksum of the table body
594
- * with the stored checksum in the state. If the checksums are different, the state is updated with the
595
- * new checksum and `true` is returned. Otherwise, `false` is returned.
596
- *
597
- * @returns {boolean} `true` if the table content has been invalidated, `false` otherwise.
598
- */
599
- KTDataTable.prototype._localTableContentInvalidate = function () {
600
- var checksum = KTUtils.checksum(JSON.stringify(this._tbodyElement.innerHTML));
601
- if (this.getState()._contentChecksum !== checksum) {
602
- this._config._state._contentChecksum = checksum;
603
- return true;
604
- }
605
- return false;
606
- };
607
- KTDataTable.prototype._tableConfigInvalidate = function () {
608
- // Remove _data and _state from config
609
- var _a = this._config, _state = _a._state, restConfig = __rest(_a, ["_state"]);
610
- var checksum = KTUtils.checksum(JSON.stringify(restConfig));
611
- if (_state._configChecksum !== checksum) {
612
- this._config._state._configChecksum = checksum;
613
- return true;
614
- }
615
- return false;
616
- };
617
- /**
618
- * Extract the table content and returns it as an object containing an array of original data and an array of original data attributes.
619
- *
620
- * @returns {{originalData: T[], originalDataAttributes: KTDataTableAttributeInterface[]}} - An object containing an array of original data and an array of original data attributes.
621
- */
622
- KTDataTable.prototype._localExtractTableContent = function () {
623
- var originalData = [];
624
- var originalDataAttributes = [];
625
- this._storeOriginalClasses();
626
- var rows = this._tbodyElement.querySelectorAll('tr');
627
- // Filter th elements to only include those with data-kt-datatable-column attribute
628
- var allThs = this._theadElement
629
- ? this._theadElement.querySelectorAll('th')
630
- : [];
631
- var ths = Array.from(allThs).filter(function (th) {
632
- return th.hasAttribute('data-kt-datatable-column');
633
- });
634
- rows.forEach(function (row) {
635
- var dataRow = {};
636
- var dataRowAttribute = {};
637
- row.querySelectorAll('td').forEach(function (td, index) {
638
- var _a, _b, _c;
639
- var colName = (_a = ths[index]) === null || _a === void 0 ? void 0 : _a.getAttribute('data-kt-datatable-column');
640
- if (colName) {
641
- dataRow[colName] = (_b = td.innerHTML) === null || _b === void 0 ? void 0 : _b.trim();
642
- }
643
- else {
644
- // Store the original HTML for fallback
645
- dataRow[index] = (_c = td.innerHTML) === null || _c === void 0 ? void 0 : _c.trim();
646
- }
647
- });
648
- if (Object.keys(dataRow).length > 0) {
649
- originalData.push(dataRow);
650
- originalDataAttributes.push(dataRowAttribute);
651
- }
652
- });
653
- return { originalData: originalData, originalDataAttributes: originalDataAttributes };
654
- };
655
- /**
656
- * Check if the table header is invalidated
657
- * @returns {boolean} - Returns true if the table header is invalidated, false otherwise
658
- */
659
- KTDataTable.prototype._localTableHeaderInvalidate = function () {
660
- var originalData = this.getState().originalData;
661
- var totalColumns = originalData.length
662
- ? Object.keys(originalData[0]).length
663
- : 0;
664
- // Count th elements with data-kt-datatable-column; when none (e.g. multi-row headers), use logical column count so we don't falsely invalidate
665
- var allThs = this._theadElement
666
- ? this._theadElement.querySelectorAll('th')
667
- : [];
668
- var thsWithColumn = Array.from(allThs).filter(function (th) {
669
- return th.hasAttribute('data-kt-datatable-column');
670
- });
671
- var currentTableHeaders = thsWithColumn.length > 0
672
- ? thsWithColumn.length
673
- : this._getLogicalColumnCount();
674
- return currentTableHeaders !== totalColumns;
675
- };
676
537
  /**
677
538
  * Returns the logical data column count (number of data columns), used for multi-row headers
678
539
  * where querySelectorAll('th') would overcount. Prefers state.originalData, then first tbody row td count.
@@ -691,162 +552,6 @@ var KTDataTable = /** @class */ (function (_super) {
691
552
  }
692
553
  return 0;
693
554
  };
694
- /**
695
- * Fetch data from the server
696
- */
697
- KTDataTable.prototype._fetchDataFromServer = function () {
698
- return __awaiter(this, void 0, void 0, function () {
699
- var currentRequestId, queryParams, response, error_1, responseData, error_2;
700
- return __generator(this, function (_a) {
701
- switch (_a.label) {
702
- case 0:
703
- currentRequestId = ++this._requestId;
704
- this._fireEvent('fetch');
705
- this._dispatchEvent('fetch');
706
- queryParams = this._getQueryParamsForFetchRequest();
707
- _a.label = 1;
708
- case 1:
709
- _a.trys.push([1, 3, , 4]);
710
- return [4 /*yield*/, this._performFetchRequest(queryParams)];
711
- case 2:
712
- response = _a.sent();
713
- return [3 /*break*/, 4];
714
- case 3:
715
- error_1 = _a.sent();
716
- // Silently ignore AbortError - request was cancelled
717
- if (error_1.name === 'AbortError') {
718
- return [2 /*return*/];
719
- }
720
- throw error_1;
721
- case 4:
722
- // Check if this response is stale (a newer request has been initiated)
723
- if (currentRequestId !== this._requestId) {
724
- // Ignore stale response - a more recent request is in progress or has completed
725
- return [2 /*return*/];
726
- }
727
- responseData = null;
728
- _a.label = 5;
729
- case 5:
730
- _a.trys.push([5, 7, , 8]);
731
- return [4 /*yield*/, response.json()];
732
- case 6:
733
- responseData = _a.sent();
734
- return [3 /*break*/, 8];
735
- case 7:
736
- error_2 = _a.sent();
737
- // Fire event with complete error context for application handling
738
- this._fireEvent('parseError', {
739
- response: response,
740
- error: String(error_2),
741
- status: response.status,
742
- statusText: response.statusText,
743
- });
744
- this._dispatchEvent('parseError', {
745
- response: response,
746
- error: String(error_2),
747
- status: response.status,
748
- statusText: response.statusText,
749
- });
750
- return [2 /*return*/];
751
- case 8:
752
- // Double-check request ID after JSON parsing (additional safety)
753
- if (currentRequestId !== this._requestId) {
754
- return [2 /*return*/];
755
- }
756
- this._fireEvent('fetched', { response: responseData });
757
- this._dispatchEvent('fetched', { response: responseData });
758
- // Use the mapResponse function to transform the data if provided
759
- if (typeof this._config.mapResponse === 'function') {
760
- responseData = this._config.mapResponse.call(this, responseData);
761
- }
762
- this._data = responseData.data;
763
- this._config._state.totalItems = responseData.totalCount;
764
- return [4 /*yield*/, this._draw()];
765
- case 9:
766
- _a.sent();
767
- this._fireEvent('fetched');
768
- this._dispatchEvent('fetched');
769
- return [2 /*return*/];
770
- }
771
- });
772
- });
773
- };
774
- /**
775
- * Get the query params for a fetch request
776
- * @returns The query params for the fetch request
777
- */
778
- KTDataTable.prototype._getQueryParamsForFetchRequest = function () {
779
- // Get the current state of the datatable
780
- var _a = this.getState(), page = _a.page, pageSize = _a.pageSize, sortField = _a.sortField, sortOrder = _a.sortOrder, filters = _a.filters, search = _a.search;
781
- // Create a new URLSearchParams object to store the query params
782
- var queryParams = new URLSearchParams();
783
- // Add the current page number and page size to the query params
784
- queryParams.set('page', String(page));
785
- queryParams.set('size', String(pageSize));
786
- // If there is a sort order and field set, add them to the query params
787
- if (sortOrder !== undefined) {
788
- queryParams.set('sortOrder', String(sortOrder));
789
- }
790
- if (sortField !== undefined) {
791
- queryParams.set('sortField', String(sortField));
792
- }
793
- // If there are any filters set, add them to the query params
794
- if (Array.isArray(filters) && filters.length) {
795
- queryParams.set('filters', JSON.stringify(filters.map(function (filter) { return ({
796
- // Map the filter object to a simpler object with just the necessary properties
797
- column: filter.column,
798
- type: filter.type,
799
- value: filter.value,
800
- }); })));
801
- }
802
- if (search) {
803
- queryParams.set('search', typeof search === 'object' ? JSON.stringify(search) : search);
804
- }
805
- // If a mapRequest function is provided, call it with the query params object
806
- if (typeof this._config.mapRequest === 'function') {
807
- queryParams = this._config.mapRequest.call(this, queryParams);
808
- }
809
- // Return the query params object
810
- return queryParams;
811
- };
812
- KTDataTable.prototype._performFetchRequest = function (queryParams) {
813
- return __awaiter(this, void 0, void 0, function () {
814
- var requestMethod, requestBody, apiEndpointWithQueryParams;
815
- var _this = this;
816
- return __generator(this, function (_a) {
817
- requestMethod = this._config.requestMethod;
818
- requestBody = undefined;
819
- // Cancel previous request to prevent race conditions
820
- if (this._abortController) {
821
- this._abortController.abort();
822
- }
823
- // Create new AbortController for this request
824
- this._abortController = new AbortController();
825
- // If the request method is POST, send the query params as the request body
826
- if (requestMethod === 'POST') {
827
- requestBody = queryParams;
828
- }
829
- else if (requestMethod === 'GET') {
830
- apiEndpointWithQueryParams = this._createUrl(this._config.apiEndpoint);
831
- apiEndpointWithQueryParams.search = queryParams.toString();
832
- this._config.apiEndpoint = apiEndpointWithQueryParams.toString();
833
- }
834
- return [2 /*return*/, fetch(this._config.apiEndpoint, __assign(__assign({ method: requestMethod, body: requestBody, headers: this._config.requestHeaders }, (this._config.requestCredentials && {
835
- credentials: this._config.requestCredentials,
836
- })), (this._abortController && { signal: this._abortController.signal }))).catch(function (error) {
837
- // Silently ignore AbortError - this is expected when requests are cancelled
838
- if (error.name === 'AbortError') {
839
- return Promise.reject(error);
840
- }
841
- // Trigger an error event for non-abort errors
842
- _this._fireEvent('error', { error: error });
843
- _this._dispatchEvent('error', { error: error });
844
- _this._noticeOnTable('Error performing fetch request: ' + String(error));
845
- throw error;
846
- })];
847
- });
848
- });
849
- };
850
555
  /**
851
556
  * Creates a complete URL from a relative path or a full URL.
852
557
  *
@@ -881,10 +586,10 @@ var KTDataTable = /** @class */ (function (_super) {
881
586
  KTDataTable.prototype._draw = function () {
882
587
  return __awaiter(this, void 0, void 0, function () {
883
588
  return __generator(this, function (_a) {
884
- this._config._state.totalPages =
885
- Math.ceil(this.getState().totalItems / this.getState().pageSize) || 0;
886
- this._fireEvent('draw');
887
- this._dispatchEvent('draw');
589
+ this._stateStore.patchState({
590
+ totalPages: Math.ceil(this.getState().totalItems / this.getState().pageSize) || 0,
591
+ });
592
+ this._emit('draw');
888
593
  this._dispose();
889
594
  // Update the table and pagination controls
890
595
  if (this._theadElement && this._tbodyElement) {
@@ -893,8 +598,7 @@ var KTDataTable = /** @class */ (function (_super) {
893
598
  if (this._infoElement && this._paginationElement) {
894
599
  this._updatePagination();
895
600
  }
896
- this._fireEvent('drew');
897
- this._dispatchEvent('drew');
601
+ this._emit('drew');
898
602
  // Spinner is hidden in _finalize() to ensure it stays visible until the entire request completes
899
603
  // Removed duplicate _hideSpinner() call here to prevent premature hiding
900
604
  if (this._config.stateSave) {
@@ -909,115 +613,18 @@ var KTDataTable = /** @class */ (function (_super) {
909
613
  * @returns {HTMLTableSectionElement} The new table body element
910
614
  */
911
615
  KTDataTable.prototype._updateTable = function () {
912
- // Clear the existing table contents using a more efficient method
913
- while (this._tableElement.tBodies.length) {
914
- this._tableElement.removeChild(this._tableElement.tBodies[0]);
915
- }
916
- // Create the table body with the new data
917
- var tbodyElement = this._tableElement.createTBody();
918
- // Apply the original class to the new tbody element
919
- if (this._originalTbodyClass) {
920
- tbodyElement.className = this._originalTbodyClass;
921
- }
922
- this._updateTableContent(tbodyElement);
923
- return tbodyElement;
924
- };
925
- /**
926
- * Update the table content
927
- * @param tbodyElement The table body element
928
- * @returns {HTMLTableSectionElement} The updated table body element
929
- */
930
- KTDataTable.prototype._updateTableContent = function (tbodyElement) {
931
- var _this = this;
932
- var fragment = document.createDocumentFragment();
933
- tbodyElement.textContent = ''; // Clear the tbody element
934
- if (this._data.length === 0) {
935
- this._noticeOnTable(this._config.infoEmpty || '');
936
- return tbodyElement;
937
- }
938
- // Filter th elements to only include those with data-kt-datatable-column attribute
939
- // This prevents creating blank td elements for merged header cells (colspan/rowspan)
940
- var allThs = this._theadElement
941
- ? this._theadElement.querySelectorAll('th')
942
- : [];
943
- var ths = Array.from(allThs).filter(function (th) {
944
- return th.hasAttribute('data-kt-datatable-column');
616
+ return this._tableRenderer.render({
617
+ config: this._config,
618
+ context: this,
619
+ data: this._data,
620
+ getLogicalColumnCount: this._getLogicalColumnCount.bind(this),
621
+ getState: this.getState.bind(this),
622
+ originalTbodyClass: this._originalTbodyClass,
623
+ originalTrClasses: this._originalTrClasses,
624
+ originalTdClasses: this._originalTdClasses,
625
+ tableElement: this._tableElement,
626
+ theadElement: this._theadElement,
945
627
  });
946
- // When no th has data-kt-datatable-column (e.g. multi-row headers), use logical column count from tbody so we don't overcount thead cells
947
- var columnsToRender = ths.length > 0 ? ths : [];
948
- var logicalColumnCount = ths.length > 0 ? ths.length : this._getLogicalColumnCount();
949
- this._data.forEach(function (item, rowIndex) {
950
- var row = document.createElement('tr');
951
- // Apply original tr class if available
952
- if (_this._originalTrClasses && _this._originalTrClasses[rowIndex]) {
953
- row.className = _this._originalTrClasses[rowIndex];
954
- }
955
- if (!_this._config.columns) {
956
- var dataRowAttributes = _this.getState().originalDataAttributes
957
- ? _this.getState().originalDataAttributes[rowIndex]
958
- : null;
959
- for (var colIndex = 0; colIndex < logicalColumnCount; colIndex++) {
960
- var th = columnsToRender[colIndex];
961
- var colName = th === null || th === void 0 ? void 0 : th.getAttribute('data-kt-datatable-column');
962
- var td = document.createElement('td');
963
- var value = void 0;
964
- if (colName && Object.prototype.hasOwnProperty.call(item, colName)) {
965
- value = item[colName];
966
- }
967
- else if (Object.prototype.hasOwnProperty.call(item, colIndex)) {
968
- value = item[colIndex];
969
- }
970
- else {
971
- value = '';
972
- }
973
- td.innerHTML = value;
974
- // Apply original td class if available
975
- if (_this._originalTdClasses &&
976
- _this._originalTdClasses[rowIndex] &&
977
- _this._originalTdClasses[rowIndex][colIndex]) {
978
- td.className = _this._originalTdClasses[rowIndex][colIndex];
979
- }
980
- if (dataRowAttributes && dataRowAttributes[colIndex]) {
981
- for (var attr in dataRowAttributes[colIndex]) {
982
- td.setAttribute(attr, dataRowAttributes[colIndex][attr]);
983
- }
984
- }
985
- row.appendChild(td);
986
- }
987
- }
988
- else {
989
- Object.keys(_this._config.columns).forEach(function (key, colIndex) {
990
- var td = document.createElement('td');
991
- var columnDef = _this._config.columns[key];
992
- // Apply original td class if available
993
- if (_this._originalTdClasses &&
994
- _this._originalTdClasses[rowIndex] &&
995
- _this._originalTdClasses[rowIndex][colIndex]) {
996
- td.className = _this._originalTdClasses[rowIndex][colIndex];
997
- }
998
- if (typeof columnDef.render === 'function') {
999
- var result = columnDef.render.call(_this, item[key], item, _this);
1000
- if (result instanceof HTMLElement ||
1001
- result instanceof DocumentFragment) {
1002
- td.appendChild(result);
1003
- }
1004
- else if (typeof result === 'string') {
1005
- td.innerHTML = result;
1006
- }
1007
- }
1008
- else {
1009
- td.textContent = item[key];
1010
- }
1011
- if (typeof columnDef.createdCell === 'function') {
1012
- columnDef.createdCell.call(_this, td, item[key], item, row);
1013
- }
1014
- row.appendChild(td);
1015
- });
1016
- }
1017
- fragment.appendChild(row);
1018
- });
1019
- tbodyElement.appendChild(fragment);
1020
- return tbodyElement;
1021
628
  };
1022
629
  /**
1023
630
  * Show a notice on the table
@@ -1026,66 +633,22 @@ var KTDataTable = /** @class */ (function (_super) {
1026
633
  */
1027
634
  KTDataTable.prototype._noticeOnTable = function (message) {
1028
635
  if (message === void 0) { message = ''; }
1029
- var row = this._tableElement.tBodies[0].insertRow();
1030
- var cell = row.insertCell();
1031
- var logicalCount = this._getLogicalColumnCount();
1032
- // Use logical column count so multi-row headers don't overcount; fallback to 1 when 0 so message still displays
1033
- cell.colSpan = logicalCount > 0 ? logicalCount : 1;
1034
- cell.innerHTML = message;
636
+ this._tableRenderer.notice(this._tableElement, this._getLogicalColumnCount.bind(this), message);
1035
637
  };
1036
638
  KTDataTable.prototype._updatePagination = function () {
1037
- this._removeChildElements(this._sizeElement);
1038
- this._createPageSizeControls(this._sizeElement);
1039
- this._removeChildElements(this._paginationElement);
1040
- this._createPaginationControls(this._infoElement, this._paginationElement);
1041
- };
1042
- /**
1043
- * Removes all child elements from the given container element.
1044
- * @param container The container element to remove the child elements from.
1045
- */
1046
- KTDataTable.prototype._removeChildElements = function (container) {
1047
- if (!container) {
1048
- return;
1049
- }
1050
- // Loop through all child elements of the container and remove them one by one
1051
- while (container.firstChild) {
1052
- // Remove the first child element (which is the first element in the list of child elements)
1053
- container.removeChild(container.firstChild);
1054
- }
1055
- };
1056
- /**
1057
- * Creates a container element for the items per page selector.
1058
- * @param _sizeElement The element to create the page size controls in.
1059
- * @returns The container element.
1060
- */
1061
- KTDataTable.prototype._createPageSizeControls = function (_sizeElement) {
1062
- var _this = this;
1063
- // If no element is provided, return early
1064
- if (!_sizeElement) {
1065
- return _sizeElement;
639
+ var cleanup = this._paginationRenderer.render({
640
+ config: this._config,
641
+ dataLength: this._data.length,
642
+ infoElement: this._infoElement,
643
+ paginateData: this._paginateData.bind(this),
644
+ paginationElement: this._paginationElement,
645
+ reloadPageSize: this._reloadPageSize.bind(this),
646
+ sizeElement: this._sizeElement,
647
+ state: this.getState(),
648
+ });
649
+ if (typeof cleanup === 'function') {
650
+ this._cleanupCallbacks.push(cleanup);
1066
651
  }
1067
- // Wait for the element to be attached to the DOM
1068
- setTimeout(function () {
1069
- // Create <option> elements for each page size option
1070
- var options = _this._config.pageSizes.map(function (size) {
1071
- var option = document.createElement('option');
1072
- option.value = String(size);
1073
- option.text = String(size);
1074
- option.selected = _this.getState().pageSize === size;
1075
- return option;
1076
- });
1077
- // Add the <option> elements to the provided element
1078
- _sizeElement.append.apply(_sizeElement, options);
1079
- }, 100);
1080
- // Create an event listener for the "change" event on the element
1081
- var _pageSizeControlsEvent = function (event) {
1082
- // When the element changes, reload the page with the new page size and page number 1
1083
- _this._reloadPageSize(Number(event.target.value), 1);
1084
- };
1085
- // Bind the event listener to the component instance
1086
- _sizeElement.onchange = _pageSizeControlsEvent.bind(this);
1087
- // Return the element
1088
- return _sizeElement;
1089
652
  };
1090
653
  /**
1091
654
  * Reloads the data with the specified page size and optional page number.
@@ -1095,120 +658,10 @@ var KTDataTable = /** @class */ (function (_super) {
1095
658
  KTDataTable.prototype._reloadPageSize = function (pageSize, page) {
1096
659
  if (page === void 0) { page = 1; }
1097
660
  // Update the page size and page number in the state
1098
- this._config._state.pageSize = pageSize;
1099
- this._config._state.page = page;
661
+ this._stateStore.setPageSize(pageSize, page);
1100
662
  // Update the data with the new page size and page number
1101
663
  this._updateData();
1102
664
  };
1103
- /**
1104
- * Creates the pagination controls for the component.
1105
- * @param _infoElement The element to set the info text in.
1106
- * @param _paginationElement The element to create the pagination controls in.
1107
- * @return {HTMLElement} The element containing the pagination controls.
1108
- */
1109
- KTDataTable.prototype._createPaginationControls = function (_infoElement, _paginationElement) {
1110
- if (!_infoElement || !_paginationElement || this._data.length === 0) {
1111
- return null;
1112
- }
1113
- this._setPaginationInfoText(_infoElement);
1114
- var paginationContainer = this._createPaginationContainer(_paginationElement);
1115
- if (paginationContainer) {
1116
- this._createPaginationButtons(paginationContainer);
1117
- }
1118
- return paginationContainer;
1119
- };
1120
- /**
1121
- * Sets the info text for the pagination controls.
1122
- * @param _infoElement The element to set the info text in.
1123
- */
1124
- KTDataTable.prototype._setPaginationInfoText = function (_infoElement) {
1125
- _infoElement.textContent = this._config.info
1126
- .replace('{start}', (this.getState().page - 1) * this.getState().pageSize + 1 + '')
1127
- .replace('{end}', Math.min(this.getState().page * this.getState().pageSize, this.getState().totalItems) + '')
1128
- .replace('{total}', this.getState().totalItems + '');
1129
- };
1130
- /**
1131
- * Creates the container element for the pagination controls.
1132
- * @param _paginationElement The element to create the pagination controls in.
1133
- * @return {HTMLElement} The container element.
1134
- */
1135
- KTDataTable.prototype._createPaginationContainer = function (_paginationElement) {
1136
- // No longer create a wrapping div. Just return the pagination element itself.
1137
- return _paginationElement;
1138
- };
1139
- /**
1140
- * Creates the pagination buttons for the component.
1141
- * @param paginationContainer The container element for the pagination controls.
1142
- */
1143
- KTDataTable.prototype._createPaginationButtons = function (paginationContainer) {
1144
- var _this = this;
1145
- var _a = this.getState(), currentPage = _a.page, totalPages = _a.totalPages;
1146
- var _b = this._config.pagination, previous = _b.previous, next = _b.next, number = _b.number, more = _b.more;
1147
- // Helper function to create a button
1148
- var createButton = function (text, className, disabled, handleClick) {
1149
- var button = document.createElement('button');
1150
- button.className = className;
1151
- button.innerHTML = text;
1152
- button.disabled = disabled;
1153
- button.onclick = handleClick;
1154
- return button;
1155
- };
1156
- // Add Previous Button
1157
- paginationContainer.appendChild(createButton(previous.text, "".concat(previous.class).concat(currentPage === 1 ? ' disabled' : ''), currentPage === 1, function () { return _this._paginateData(currentPage - 1); }));
1158
- // Calculate range of pages
1159
- var pageMoreEnabled = this._config.pageMore;
1160
- if (pageMoreEnabled) {
1161
- var maxButtons = this._config.pageMoreLimit;
1162
- var range_1 = this._calculatePageRange(currentPage, totalPages, maxButtons);
1163
- // Add start ellipsis
1164
- if (range_1.start > 1) {
1165
- paginationContainer.appendChild(createButton(more.text, more.class, false, function () {
1166
- return _this._paginateData(Math.max(1, range_1.start - 1));
1167
- }));
1168
- }
1169
- var _loop_1 = function (i) {
1170
- paginationContainer.appendChild(createButton(number.text.replace('{page}', i.toString()), "".concat(number.class).concat(currentPage === i ? ' active disabled' : ''), currentPage === i, function () { return _this._paginateData(i); }));
1171
- };
1172
- // Add page buttons
1173
- for (var i = range_1.start; i <= range_1.end; i++) {
1174
- _loop_1(i);
1175
- }
1176
- // Add end ellipsis
1177
- if (pageMoreEnabled && range_1.end < totalPages) {
1178
- paginationContainer.appendChild(createButton(more.text, more.class, false, function () {
1179
- return _this._paginateData(Math.min(totalPages, range_1.end + 1));
1180
- }));
1181
- }
1182
- }
1183
- else {
1184
- var _loop_2 = function (i) {
1185
- paginationContainer.appendChild(createButton(number.text.replace('{page}', i.toString()), "".concat(number.class).concat(currentPage === i ? ' active disabled' : ''), currentPage === i, function () { return _this._paginateData(i); }));
1186
- };
1187
- // Add page buttons
1188
- for (var i = 1; i <= totalPages; i++) {
1189
- _loop_2(i);
1190
- }
1191
- }
1192
- // Add Next Button
1193
- paginationContainer.appendChild(createButton(next.text, "".concat(next.class).concat(currentPage === totalPages ? ' disabled' : ''), currentPage === totalPages, function () { return _this._paginateData(currentPage + 1); }));
1194
- };
1195
- // New helper method to calculate page range
1196
- KTDataTable.prototype._calculatePageRange = function (currentPage, totalPages, maxButtons) {
1197
- var startPage, endPage;
1198
- var halfMaxButtons = Math.floor(maxButtons / 2);
1199
- if (totalPages <= maxButtons) {
1200
- startPage = 1;
1201
- endPage = totalPages;
1202
- }
1203
- else {
1204
- startPage = Math.max(currentPage - halfMaxButtons, 1);
1205
- endPage = Math.min(startPage + maxButtons - 1, totalPages);
1206
- if (endPage - startPage < maxButtons - 1) {
1207
- startPage = Math.max(endPage - maxButtons + 1, 1);
1208
- }
1209
- }
1210
- return { start: startPage, end: endPage };
1211
- };
1212
665
  /**
1213
666
  * Method for handling pagination
1214
667
  * @param page - The page number to navigate to
@@ -1217,10 +670,9 @@ var KTDataTable = /** @class */ (function (_super) {
1217
670
  if (page < 1 || !Number.isInteger(page)) {
1218
671
  return;
1219
672
  }
1220
- this._fireEvent('pagination', { page: page });
1221
- this._dispatchEvent('pagination', { page: page });
673
+ this._emit('pagination', { page: page });
1222
674
  if (page >= 1 && page <= this.getState().totalPages) {
1223
- this._config._state.page = page;
675
+ this._stateStore.setPage(page);
1224
676
  this._updateData();
1225
677
  }
1226
678
  };
@@ -1259,8 +711,7 @@ var KTDataTable = /** @class */ (function (_super) {
1259
711
  * @returns {void}
1260
712
  */
1261
713
  KTDataTable.prototype._saveState = function () {
1262
- this._fireEvent('stateSave');
1263
- this._dispatchEvent('stateSave');
714
+ this._emit('stateSave');
1264
715
  var ns = this._tableNamespace();
1265
716
  if (ns) {
1266
717
  localStorage.setItem(ns, JSON.stringify(this.getState()));
@@ -1277,7 +728,7 @@ var KTDataTable = /** @class */ (function (_super) {
1277
728
  try {
1278
729
  var state = JSON.parse(stateString);
1279
730
  if (state)
1280
- this._config._state = state;
731
+ this._stateStore.replaceState(state);
1281
732
  return state;
1282
733
  }
1283
734
  catch (_a) { }
@@ -1324,16 +775,17 @@ var KTDataTable = /** @class */ (function (_super) {
1324
775
  * This method is called before re-rendering or when disposing the component.
1325
776
  */
1326
777
  KTDataTable.prototype._dispose = function () {
778
+ this._cleanupCallbacks.forEach(function (cleanup) { return cleanup(); });
779
+ this._cleanupCallbacks = [];
1327
780
  // --- 1. Remove search input event listener (debounced) ---
1328
781
  var tableId = this._tableId();
1329
782
  var searchElement = document.querySelector("[data-kt-datatable-search=\"#".concat(tableId, "\"]"));
1330
783
  if (searchElement) {
1331
784
  var searchWithDebounce = KTDataTable.asSearchElementWithDebounce(searchElement);
1332
- if (!searchWithDebounce._debouncedSearch) {
1333
- return;
785
+ if (searchWithDebounce._debouncedSearch) {
786
+ searchElement.removeEventListener('keyup', searchWithDebounce._debouncedSearch);
787
+ delete searchWithDebounce._debouncedSearch;
1334
788
  }
1335
- searchElement.removeEventListener('keyup', searchWithDebounce._debouncedSearch);
1336
- delete searchWithDebounce._debouncedSearch;
1337
789
  }
1338
790
  // --- 2. Remove page size dropdown event listener ---
1339
791
  if (this._sizeElement && this._sizeElement.onchange) {
@@ -1401,23 +853,7 @@ var KTDataTable = /** @class */ (function (_super) {
1401
853
  * @returns {KTDataTableStateInterface} The current state of the table.
1402
854
  */
1403
855
  KTDataTable.prototype.getState = function () {
1404
- return __assign({
1405
- /**
1406
- * The current page number.
1407
- */
1408
- page: 1,
1409
- /**
1410
- * The field that the data is sorted by.
1411
- */
1412
- sortField: null,
1413
- /**
1414
- * The sort order (ascending or descending).
1415
- */
1416
- sortOrder: '',
1417
- /**
1418
- * The number of rows to display per page.
1419
- */
1420
- pageSize: this._config.pageSize, filters: [] }, this._config._state);
856
+ return this._stateStore.getState();
1421
857
  };
1422
858
  /**
1423
859
  * Sorts the data in the table by the specified field.
@@ -1428,10 +864,8 @@ var KTDataTable = /** @class */ (function (_super) {
1428
864
  var state = this.getState();
1429
865
  var sortOrder = this._sortHandler.toggleSortOrder(state.sortField, state.sortOrder, field);
1430
866
  this._sortHandler.setSortIcon(field, sortOrder);
1431
- this._config._state.sortField = field;
1432
- this._config._state.sortOrder = sortOrder;
1433
- this._fireEvent('sort', { field: field, order: sortOrder });
1434
- this._dispatchEvent('sort', { field: field, order: sortOrder });
867
+ this._stateStore.setSort(field, sortOrder);
868
+ this._emit('sort', { field: field, order: sortOrder });
1435
869
  this._updateData();
1436
870
  };
1437
871
  /**
@@ -1464,15 +898,13 @@ var KTDataTable = /** @class */ (function (_super) {
1464
898
  * Triggers the 'reload' event and the 'kt.datatable.reload' custom event.
1465
899
  */
1466
900
  KTDataTable.prototype.reload = function () {
1467
- this._fireEvent('reload');
1468
- this._dispatchEvent('reload');
901
+ this._emit('reload');
1469
902
  // Fetch the data from the server using the current sort and filter settings
1470
903
  this._updateData();
1471
904
  };
1472
905
  KTDataTable.prototype.redraw = function (page) {
1473
906
  if (page === void 0) { page = 1; }
1474
- this._fireEvent('redraw');
1475
- this._dispatchEvent('redraw');
907
+ this._emit('redraw');
1476
908
  this._paginateData(page);
1477
909
  };
1478
910
  /**
@@ -1501,18 +933,16 @@ var KTDataTable = /** @class */ (function (_super) {
1501
933
  * @throws Error if the filter object is null or undefined.
1502
934
  */
1503
935
  KTDataTable.prototype.setFilter = function (filter) {
1504
- this._config._state.filters = __spreadArray(__spreadArray([], (this.getState().filters || []).filter(function (f) { return f.column !== filter.column; }), true), [
1505
- filter,
1506
- ], false);
1507
- this._config._state.page = 1;
936
+ this._stateStore.setFilter(filter);
1508
937
  return this;
1509
938
  };
1510
939
  KTDataTable.prototype.dispose = function () {
940
+ var _a;
941
+ (_a = this._remoteProvider) === null || _a === void 0 ? void 0 : _a.dispose();
1511
942
  this._dispose();
1512
943
  };
1513
944
  KTDataTable.prototype.search = function (query) {
1514
- this._config._state.search = query;
1515
- this._config._state.page = 1;
945
+ this._stateStore.setSearch(query);
1516
946
  this.reload();
1517
947
  };
1518
948
  /**
@@ -1605,8 +1035,7 @@ var KTDataTable = /** @class */ (function (_super) {
1605
1035
  */
1606
1036
  KTDataTable.prototype.check = function () {
1607
1037
  this._checkbox.check();
1608
- this._fireEvent('checked');
1609
- this._dispatchEvent('checked');
1038
+ this._emit('checked');
1610
1039
  };
1611
1040
  /**
1612
1041
  * Uncheck all visible row checkboxes
@@ -1614,8 +1043,7 @@ var KTDataTable = /** @class */ (function (_super) {
1614
1043
  */
1615
1044
  KTDataTable.prototype.uncheck = function () {
1616
1045
  this._checkbox.uncheck();
1617
- this._fireEvent('unchecked');
1618
- this._dispatchEvent('unchecked');
1046
+ this._emit('unchecked');
1619
1047
  };
1620
1048
  /**
1621
1049
  * Get all checked row IDs (across all pages if preserveSelection is true)