@keenthemes/ktui 1.2.5 → 1.2.7

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 (196) hide show
  1. package/README.md +14 -5
  2. package/dist/ktui.js +1538 -786
  3. package/dist/ktui.min.js +1 -1
  4. package/dist/ktui.min.js.map +1 -1
  5. package/dist/styles.css +85 -5
  6. package/lib/cjs/components/datatable/datatable-checkbox.d.ts +37 -1
  7. package/lib/cjs/components/datatable/datatable-checkbox.d.ts.map +1 -1
  8. package/lib/cjs/components/datatable/datatable-checkbox.js +143 -156
  9. package/lib/cjs/components/datatable/datatable-checkbox.js.map +1 -1
  10. package/lib/cjs/components/datatable/datatable-column-utils.d.ts +30 -0
  11. package/lib/cjs/components/datatable/datatable-column-utils.d.ts.map +1 -0
  12. package/lib/cjs/components/datatable/datatable-column-utils.js +42 -0
  13. package/lib/cjs/components/datatable/datatable-column-utils.js.map +1 -0
  14. package/lib/cjs/components/datatable/datatable-contracts.d.ts +2 -4
  15. package/lib/cjs/components/datatable/datatable-contracts.d.ts.map +1 -1
  16. package/lib/cjs/components/datatable/datatable-defaults.d.ts +20 -0
  17. package/lib/cjs/components/datatable/datatable-defaults.d.ts.map +1 -0
  18. package/lib/cjs/components/datatable/datatable-defaults.js +193 -0
  19. package/lib/cjs/components/datatable/datatable-defaults.js.map +1 -0
  20. package/lib/cjs/components/datatable/datatable-layout-plugin.d.ts +7 -0
  21. package/lib/cjs/components/datatable/datatable-layout-plugin.d.ts.map +1 -0
  22. package/lib/cjs/components/datatable/datatable-layout-plugin.js +338 -0
  23. package/lib/cjs/components/datatable/datatable-layout-plugin.js.map +1 -0
  24. package/lib/cjs/components/datatable/datatable-local-provider.d.ts +2 -2
  25. package/lib/cjs/components/datatable/datatable-local-provider.d.ts.map +1 -1
  26. package/lib/cjs/components/datatable/datatable-local-provider.js +85 -27
  27. package/lib/cjs/components/datatable/datatable-local-provider.js.map +1 -1
  28. package/lib/cjs/components/datatable/datatable-pagination-renderer.d.ts.map +1 -1
  29. package/lib/cjs/components/datatable/datatable-pagination-renderer.js +13 -13
  30. package/lib/cjs/components/datatable/datatable-pagination-renderer.js.map +1 -1
  31. package/lib/cjs/components/datatable/datatable-registry.d.ts +18 -0
  32. package/lib/cjs/components/datatable/datatable-registry.d.ts.map +1 -0
  33. package/lib/cjs/components/datatable/datatable-registry.js +66 -0
  34. package/lib/cjs/components/datatable/datatable-registry.js.map +1 -0
  35. package/lib/cjs/components/datatable/datatable-remote-provider.d.ts.map +1 -1
  36. package/lib/cjs/components/datatable/datatable-remote-provider.js +1 -2
  37. package/lib/cjs/components/datatable/datatable-remote-provider.js.map +1 -1
  38. package/lib/cjs/components/datatable/datatable-search-handler.d.ts +10 -0
  39. package/lib/cjs/components/datatable/datatable-search-handler.d.ts.map +1 -0
  40. package/lib/cjs/components/datatable/datatable-search-handler.js +65 -0
  41. package/lib/cjs/components/datatable/datatable-search-handler.js.map +1 -0
  42. package/lib/cjs/components/datatable/datatable-sort.d.ts +31 -4
  43. package/lib/cjs/components/datatable/datatable-sort.d.ts.map +1 -1
  44. package/lib/cjs/components/datatable/datatable-sort.js +86 -58
  45. package/lib/cjs/components/datatable/datatable-sort.js.map +1 -1
  46. package/lib/cjs/components/datatable/datatable-spinner.d.ts +30 -0
  47. package/lib/cjs/components/datatable/datatable-spinner.d.ts.map +1 -0
  48. package/lib/cjs/components/datatable/datatable-spinner.js +54 -0
  49. package/lib/cjs/components/datatable/datatable-spinner.js.map +1 -0
  50. package/lib/cjs/components/datatable/datatable-state-persistence.d.ts +19 -0
  51. package/lib/cjs/components/datatable/datatable-state-persistence.d.ts.map +1 -0
  52. package/lib/cjs/components/datatable/datatable-state-persistence.js +59 -0
  53. package/lib/cjs/components/datatable/datatable-state-persistence.js.map +1 -0
  54. package/lib/cjs/components/datatable/datatable-table-renderer.d.ts +2 -0
  55. package/lib/cjs/components/datatable/datatable-table-renderer.d.ts.map +1 -1
  56. package/lib/cjs/components/datatable/datatable-table-renderer.js +75 -16
  57. package/lib/cjs/components/datatable/datatable-table-renderer.js.map +1 -1
  58. package/lib/cjs/components/datatable/datatable-utils.d.ts +10 -0
  59. package/lib/cjs/components/datatable/datatable-utils.d.ts.map +1 -0
  60. package/lib/cjs/components/datatable/datatable-utils.js +15 -0
  61. package/lib/cjs/components/datatable/datatable-utils.js.map +1 -0
  62. package/lib/cjs/components/datatable/datatable.d.ts +35 -34
  63. package/lib/cjs/components/datatable/datatable.d.ts.map +1 -1
  64. package/lib/cjs/components/datatable/datatable.js +233 -497
  65. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  66. package/lib/cjs/components/datatable/index.d.ts +1 -1
  67. package/lib/cjs/components/datatable/index.d.ts.map +1 -1
  68. package/lib/cjs/components/datatable/types.d.ts +127 -11
  69. package/lib/cjs/components/datatable/types.d.ts.map +1 -1
  70. package/lib/cjs/index.d.ts +1 -1
  71. package/lib/cjs/index.d.ts.map +1 -1
  72. package/lib/cjs/index.js +6 -0
  73. package/lib/cjs/index.js.map +1 -1
  74. package/lib/esm/components/datatable/datatable-checkbox.d.ts +37 -1
  75. package/lib/esm/components/datatable/datatable-checkbox.d.ts.map +1 -1
  76. package/lib/esm/components/datatable/datatable-checkbox.js +142 -155
  77. package/lib/esm/components/datatable/datatable-checkbox.js.map +1 -1
  78. package/lib/esm/components/datatable/datatable-column-utils.d.ts +30 -0
  79. package/lib/esm/components/datatable/datatable-column-utils.d.ts.map +1 -0
  80. package/lib/esm/components/datatable/datatable-column-utils.js +38 -0
  81. package/lib/esm/components/datatable/datatable-column-utils.js.map +1 -0
  82. package/lib/esm/components/datatable/datatable-contracts.d.ts +2 -4
  83. package/lib/esm/components/datatable/datatable-contracts.d.ts.map +1 -1
  84. package/lib/esm/components/datatable/datatable-defaults.d.ts +20 -0
  85. package/lib/esm/components/datatable/datatable-defaults.d.ts.map +1 -0
  86. package/lib/esm/components/datatable/datatable-defaults.js +190 -0
  87. package/lib/esm/components/datatable/datatable-defaults.js.map +1 -0
  88. package/lib/esm/components/datatable/datatable-layout-plugin.d.ts +7 -0
  89. package/lib/esm/components/datatable/datatable-layout-plugin.d.ts.map +1 -0
  90. package/lib/esm/components/datatable/datatable-layout-plugin.js +334 -0
  91. package/lib/esm/components/datatable/datatable-layout-plugin.js.map +1 -0
  92. package/lib/esm/components/datatable/datatable-local-provider.d.ts +2 -2
  93. package/lib/esm/components/datatable/datatable-local-provider.d.ts.map +1 -1
  94. package/lib/esm/components/datatable/datatable-local-provider.js +85 -27
  95. package/lib/esm/components/datatable/datatable-local-provider.js.map +1 -1
  96. package/lib/esm/components/datatable/datatable-pagination-renderer.d.ts.map +1 -1
  97. package/lib/esm/components/datatable/datatable-pagination-renderer.js +13 -13
  98. package/lib/esm/components/datatable/datatable-pagination-renderer.js.map +1 -1
  99. package/lib/esm/components/datatable/datatable-registry.d.ts +18 -0
  100. package/lib/esm/components/datatable/datatable-registry.d.ts.map +1 -0
  101. package/lib/esm/components/datatable/datatable-registry.js +63 -0
  102. package/lib/esm/components/datatable/datatable-registry.js.map +1 -0
  103. package/lib/esm/components/datatable/datatable-remote-provider.d.ts.map +1 -1
  104. package/lib/esm/components/datatable/datatable-remote-provider.js +1 -2
  105. package/lib/esm/components/datatable/datatable-remote-provider.js.map +1 -1
  106. package/lib/esm/components/datatable/datatable-search-handler.d.ts +10 -0
  107. package/lib/esm/components/datatable/datatable-search-handler.d.ts.map +1 -0
  108. package/lib/esm/components/datatable/datatable-search-handler.js +62 -0
  109. package/lib/esm/components/datatable/datatable-search-handler.js.map +1 -0
  110. package/lib/esm/components/datatable/datatable-sort.d.ts +31 -4
  111. package/lib/esm/components/datatable/datatable-sort.d.ts.map +1 -1
  112. package/lib/esm/components/datatable/datatable-sort.js +85 -57
  113. package/lib/esm/components/datatable/datatable-sort.js.map +1 -1
  114. package/lib/esm/components/datatable/datatable-spinner.d.ts +30 -0
  115. package/lib/esm/components/datatable/datatable-spinner.d.ts.map +1 -0
  116. package/lib/esm/components/datatable/datatable-spinner.js +51 -0
  117. package/lib/esm/components/datatable/datatable-spinner.js.map +1 -0
  118. package/lib/esm/components/datatable/datatable-state-persistence.d.ts +19 -0
  119. package/lib/esm/components/datatable/datatable-state-persistence.d.ts.map +1 -0
  120. package/lib/esm/components/datatable/datatable-state-persistence.js +55 -0
  121. package/lib/esm/components/datatable/datatable-state-persistence.js.map +1 -0
  122. package/lib/esm/components/datatable/datatable-table-renderer.d.ts +2 -0
  123. package/lib/esm/components/datatable/datatable-table-renderer.d.ts.map +1 -1
  124. package/lib/esm/components/datatable/datatable-table-renderer.js +75 -16
  125. package/lib/esm/components/datatable/datatable-table-renderer.js.map +1 -1
  126. package/lib/esm/components/datatable/datatable-utils.d.ts +10 -0
  127. package/lib/esm/components/datatable/datatable-utils.d.ts.map +1 -0
  128. package/lib/esm/components/datatable/datatable-utils.js +12 -0
  129. package/lib/esm/components/datatable/datatable-utils.js.map +1 -0
  130. package/lib/esm/components/datatable/datatable.d.ts +35 -34
  131. package/lib/esm/components/datatable/datatable.d.ts.map +1 -1
  132. package/lib/esm/components/datatable/datatable.js +235 -499
  133. package/lib/esm/components/datatable/datatable.js.map +1 -1
  134. package/lib/esm/components/datatable/index.d.ts +1 -1
  135. package/lib/esm/components/datatable/index.d.ts.map +1 -1
  136. package/lib/esm/components/datatable/types.d.ts +127 -11
  137. package/lib/esm/components/datatable/types.d.ts.map +1 -1
  138. package/lib/esm/index.d.ts +1 -1
  139. package/lib/esm/index.d.ts.map +1 -1
  140. package/lib/esm/index.js +6 -0
  141. package/lib/esm/index.js.map +1 -1
  142. package/package.json +5 -1
  143. package/skills/ktui/SKILL.md +711 -0
  144. package/skills/ktui-datatable/SKILL.md +302 -0
  145. package/skills/ktui-install/SKILL.md +150 -0
  146. package/skills/ktui-select/SKILL.md +271 -0
  147. package/src/components/__tests__/component.test.ts +347 -0
  148. package/src/components/collapse/collapse.css +2 -2
  149. package/src/components/datatable/__tests__/architecture-boundaries.test.ts +56 -8
  150. package/src/components/datatable/__tests__/currency-sort.test.ts +25 -28
  151. package/src/components/datatable/__tests__/datatable-checkbox.test.ts +527 -0
  152. package/src/components/datatable/__tests__/datatable-column-utils.test.ts +117 -0
  153. package/src/components/datatable/__tests__/datatable-defaults.test.ts +57 -0
  154. package/src/components/datatable/__tests__/datatable-finalize-extended.test.ts +361 -0
  155. package/src/components/datatable/__tests__/datatable-fixed-layout.test.ts +427 -0
  156. package/src/components/datatable/__tests__/datatable-improvements.test.ts +484 -0
  157. package/src/components/datatable/__tests__/datatable-pagination-extended.test.ts +508 -0
  158. package/src/components/datatable/__tests__/datatable-public-api.test.ts +269 -0
  159. package/src/components/datatable/__tests__/datatable-registry.test.ts +172 -0
  160. package/src/components/datatable/__tests__/datatable-remote-provider.test.ts +468 -0
  161. package/src/components/datatable/__tests__/datatable-search-handler.test.ts +124 -0
  162. package/src/components/datatable/__tests__/datatable-sort-extended.test.ts +417 -0
  163. package/src/components/datatable/__tests__/datatable-spinner.test.ts +95 -0
  164. package/src/components/datatable/__tests__/datatable-table-renderer-extended.test.ts +425 -0
  165. package/src/components/datatable/__tests__/datatable-types.test.ts +117 -0
  166. package/src/components/datatable/__tests__/datatable-utils.test.ts +52 -0
  167. package/src/components/datatable/__tests__/locked-layout.test.ts +257 -0
  168. package/src/components/datatable/__tests__/multi-row-headers.test.ts +7 -7
  169. package/src/components/datatable/__tests__/pagination-reset.test.ts +147 -6
  170. package/src/components/datatable/__tests__/race-conditions.test.ts +11 -11
  171. package/src/components/datatable/__tests__/setup.ts +12 -4
  172. package/src/components/datatable/datatable-checkbox.ts +139 -143
  173. package/src/components/datatable/datatable-column-utils.ts +63 -0
  174. package/src/components/datatable/datatable-contracts.ts +2 -3
  175. package/src/components/datatable/datatable-defaults.ts +204 -0
  176. package/src/components/datatable/datatable-layout-plugin.ts +459 -0
  177. package/src/components/datatable/datatable-local-provider.ts +106 -35
  178. package/src/components/datatable/datatable-pagination-renderer.ts +13 -15
  179. package/src/components/datatable/datatable-registry.ts +89 -0
  180. package/src/components/datatable/datatable-remote-provider.ts +1 -3
  181. package/src/components/datatable/datatable-search-handler.ts +97 -0
  182. package/src/components/datatable/datatable-sort.ts +111 -66
  183. package/src/components/datatable/datatable-spinner.ts +103 -0
  184. package/src/components/datatable/datatable-state-persistence.ts +67 -0
  185. package/src/components/datatable/datatable-table-renderer.ts +81 -18
  186. package/src/components/datatable/datatable-utils.ts +12 -0
  187. package/src/components/datatable/datatable.css +98 -0
  188. package/src/components/datatable/datatable.ts +288 -583
  189. package/src/components/datatable/index.ts +8 -0
  190. package/src/components/datatable/types.ts +157 -23
  191. package/src/helpers/__tests__/dom.test.ts +776 -0
  192. package/src/helpers/__tests__/utils.test.ts +332 -0
  193. package/src/index.ts +15 -0
  194. package/skills/ktui-components/SKILL.md +0 -41
  195. package/skills/ktui-theming/SKILL.md +0 -50
  196. package/src/components/datatable/datatable-event-adapter.ts +0 -21
@@ -65,20 +65,36 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
65
65
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
66
66
  }
67
67
  };
68
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
69
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
70
+ if (ar || !(i in from)) {
71
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
72
+ ar[i] = from[i];
73
+ }
74
+ }
75
+ return to.concat(ar || Array.prototype.slice.call(from));
76
+ };
68
77
  Object.defineProperty(exports, "__esModule", { value: true });
69
78
  exports.KTDataTable = void 0;
70
79
  exports.initAllDataTables = initAllDataTables;
71
80
  var component_1 = require("../component");
72
- var index_1 = require("../../index");
73
81
  var data_1 = require("../../helpers/data");
74
82
  var datatable_checkbox_1 = require("./datatable-checkbox");
75
83
  var datatable_sort_1 = require("./datatable-sort");
76
- var datatable_event_adapter_1 = require("./datatable-event-adapter");
84
+ var datatable_layout_plugin_1 = require("./datatable-layout-plugin");
85
+ var datatable_defaults_1 = require("./datatable-defaults");
86
+ var datatable_column_utils_1 = require("./datatable-column-utils");
77
87
  var datatable_local_provider_1 = require("./datatable-local-provider");
78
88
  var datatable_remote_provider_1 = require("./datatable-remote-provider");
79
89
  var datatable_state_store_1 = require("./datatable-state-store");
80
90
  var datatable_pagination_renderer_1 = require("./datatable-pagination-renderer");
81
91
  var datatable_table_renderer_1 = require("./datatable-table-renderer");
92
+ var utils_1 = require("../../helpers/utils");
93
+ var datatable_search_handler_1 = require("./datatable-search-handler");
94
+ var datatable_state_persistence_1 = require("./datatable-state-persistence");
95
+ var datatable_spinner_1 = require("./datatable-spinner");
96
+ var datatable_registry_1 = require("./datatable-registry");
97
+ var datatable_utils_1 = require("./datatable-utils");
82
98
  /**
83
99
  * Custom DataTable plugin class with server-side API, pagination, and sorting
84
100
  * @classdesc A custom KTComponent class that integrates server-side API, pagination, and sorting functionality into a table.
@@ -88,27 +104,34 @@ var datatable_table_renderer_1 = require("./datatable-table-renderer");
88
104
  * @param {HTMLElement} element The table element
89
105
  * @param {KTDataTableConfigInterface} [config] Additional configuration options
90
106
  */
107
+ var datatableRegistry = (0, datatable_registry_1.createDataTableRegistry)();
91
108
  var KTDataTable = /** @class */ (function (_super) {
92
109
  __extends(KTDataTable, _super);
93
110
  function KTDataTable(element, config) {
94
111
  var _this = _super.call(this) || this;
95
112
  _this._name = 'datatable';
96
- _this._originalTbodyClass = ''; // Store original tbody class
97
- _this._originalTrClasses = []; // Store original tr classes
98
- _this._originalTheadClass = ''; // Store original thead class
99
- _this._originalTdClasses = []; // Store original td classes as a 2D array [row][col]
100
- _this._originalThClasses = []; // Store original th classes
113
+ _this._originalClasses = {
114
+ tbody: '',
115
+ thead: '',
116
+ tr: [],
117
+ td: [],
118
+ th: [],
119
+ };
101
120
  _this._infoElement = null;
102
121
  _this._sizeElement = null;
103
122
  _this._paginationElement = null;
123
+ _this._layoutPlugin = null;
104
124
  _this._cleanupCallbacks = [];
125
+ _this._searchHandler = (0, datatable_search_handler_1.createSearchHandler)();
126
+ _this._statePersistence = (0, datatable_state_persistence_1.createStatePersistence)();
127
+ _this._spinner = (0, datatable_spinner_1.createSpinner)();
105
128
  _this._data = [];
106
129
  _this._isFetching = false;
107
130
  if (data_1.default.has(element, _this._name)) {
108
- // Already initialized (e.g. by createInstances). Merge user config so columns/sortType etc. apply.
131
+ // Already initialized (e.g. by createInstances). Merge demo config and redraw once.
109
132
  var existing = KTDataTable.getInstance(element);
110
133
  if (existing && config) {
111
- existing._mergeConfig(config);
134
+ existing._applyRuntimeConfig(config);
112
135
  }
113
136
  return _this;
114
137
  }
@@ -117,43 +140,59 @@ var KTDataTable = /** @class */ (function (_super) {
117
140
  if (!_this._element) {
118
141
  return _this;
119
142
  }
143
+ if (!_this._element.hasAttribute('data-kt-datatable')) {
144
+ _this._element.setAttribute('data-kt-datatable', 'true');
145
+ }
120
146
  _this._buildConfig();
147
+ _this._normalizePageSizeConfig();
121
148
  _this._stateStore = new datatable_state_store_1.KTDataTableConfigStateStore(_this._config);
122
- _this._eventAdapter = (0, datatable_event_adapter_1.createDataTableEventAdapter)(_this._fireEvent.bind(_this), _this._dispatchEvent.bind(_this));
149
+ _this._eventAdapter = {
150
+ emit: function (eventName, eventData) {
151
+ _this._emit(eventName, eventData);
152
+ },
153
+ };
123
154
  // Store the instance directly on the element
124
- KTDataTable.asElementWithInstance(element).instance = _this;
155
+ datatableRegistry.register(element, _this);
125
156
  _this._initElements();
157
+ _this._layoutPlugin = _this._createLayoutPlugin();
126
158
  _this._tableRenderer = new datatable_table_renderer_1.KTDataTableDomTableRenderer();
127
159
  _this._paginationRenderer = new datatable_pagination_renderer_1.KTDataTableDomPaginationRenderer();
128
160
  _this._initDataProviders();
129
161
  // Initialize checkbox handler
130
- _this._checkbox = (0, datatable_checkbox_1.createCheckboxHandler)(_this._element, _this._config, _this._emit.bind(_this));
162
+ _this._checkbox = new datatable_checkbox_1.KTDataTableCheckboxHandler(_this._element, _this._config, _this._emit.bind(_this), {
163
+ getState: function () { return _this._stateStore.getState(); },
164
+ setSelectedRows: function (rows) {
165
+ _this._stateStore.patchState({ selectedRows: rows });
166
+ },
167
+ });
131
168
  // Initialize sort handler
132
- _this._sortHandler = (0, datatable_sort_1.createSortHandler)(_this._config, _this._theadElement, function () { return ({
133
- sortField: _this.getState().sortField,
134
- sortOrder: _this.getState().sortOrder,
135
- }); }, function (field, order) {
136
- _this._stateStore.setSort(field, order);
137
- }, _this._fireEvent.bind(_this), _this._dispatchEvent.bind(_this), _this._updateData.bind(_this));
169
+ _this._sortHandler = new datatable_sort_1.KTDataTableSortHandler({
170
+ config: _this._config,
171
+ theadElement: _this._theadElement,
172
+ getState: function () { return ({
173
+ sortField: _this.getState().sortField,
174
+ sortOrder: _this.getState().sortOrder,
175
+ }); },
176
+ setState: function (field, order) {
177
+ _this._stateStore.setSort(field, order);
178
+ },
179
+ emit: _this._emit.bind(_this),
180
+ updateData: _this._updateData.bind(_this),
181
+ });
138
182
  _this._sortHandler.initSort();
139
183
  if (_this._config.stateSave === false) {
140
184
  _this._deleteState();
141
185
  }
142
186
  if (_this._config.stateSave) {
143
187
  _this._loadState();
188
+ _this._normalizePageState();
144
189
  }
145
190
  _this._updateData();
146
- _this._emit('init');
147
191
  return _this;
148
192
  }
149
- KTDataTable.asElementWithInstance = function (element) {
150
- return element;
151
- };
152
- KTDataTable.asSearchElementWithDebounce = function (element) {
153
- return element;
154
- };
155
193
  KTDataTable.prototype._emit = function (eventName, eventData) {
156
- this._eventAdapter.emit(eventName, eventData);
194
+ this._fireEvent(eventName, eventData);
195
+ this._dispatchEvent("kt.datatable.".concat(eventName), eventData);
157
196
  };
158
197
  KTDataTable.prototype._initDataProviders = function () {
159
198
  var _this = this;
@@ -176,206 +215,96 @@ var KTDataTable = /** @class */ (function (_super) {
176
215
  stateStore: this._stateStore,
177
216
  });
178
217
  };
218
+ KTDataTable.prototype._createLayoutPlugin = function () {
219
+ if (this._config.layoutPlugin) {
220
+ return this._config.layoutPlugin;
221
+ }
222
+ if (this._config.lockedLayout) {
223
+ return (0, datatable_layout_plugin_1.createStickyLayoutPlugin)();
224
+ }
225
+ return null;
226
+ };
227
+ /**
228
+ * Apply config from a late constructor call (e.g. docs demo script after auto-init).
229
+ */
230
+ KTDataTable.prototype._applyRuntimeConfig = function (config) {
231
+ this._mergeConfig(config);
232
+ this._normalizePageSizeConfig();
233
+ this._layoutPlugin = this._createLayoutPlugin();
234
+ this.reload();
235
+ };
236
+ KTDataTable.prototype._normalizePageSizeConfig = function () {
237
+ var configuredPageSizes = Array.isArray(this._config.pageSizes)
238
+ ? this._config.pageSizes
239
+ : [];
240
+ var pageSizes = configuredPageSizes
241
+ .map(function (size) { return Number(size); })
242
+ .filter(function (size) { return Number.isFinite(size) && size > 0; })
243
+ .map(function (size) { return Math.floor(size); });
244
+ var fallbackPageSizes = __spreadArray([], datatable_defaults_1.DEFAULT_PAGE_SIZES, true);
245
+ this._config.pageSizes =
246
+ pageSizes.length > 0 ? Array.from(new Set(pageSizes)) : fallbackPageSizes;
247
+ var configuredPageSize = Number(this._config.pageSize);
248
+ this._config.pageSize =
249
+ Number.isFinite(configuredPageSize) && configuredPageSize > 0
250
+ ? Math.floor(configuredPageSize)
251
+ : this._config.pageSizes[0];
252
+ };
253
+ KTDataTable.prototype._normalizePageState = function () {
254
+ var statePageSize = Number(this._config._state.pageSize);
255
+ this._config._state.pageSize =
256
+ Number.isFinite(statePageSize) && statePageSize > 0
257
+ ? Math.floor(statePageSize)
258
+ : this._config.pageSize;
259
+ var statePage = Number(this._config._state.page);
260
+ this._config._state.page =
261
+ Number.isFinite(statePage) && statePage > 0 ? Math.floor(statePage) : 1;
262
+ };
263
+ KTDataTable.prototype._getLayoutPluginContext = function () {
264
+ return {
265
+ rootElement: this._element,
266
+ tableElement: this._tableElement,
267
+ theadElement: this._theadElement,
268
+ tbodyElement: this._tbodyElement,
269
+ config: this._config,
270
+ };
271
+ };
179
272
  /**
180
273
  * Initialize default configuration for the datatable
181
274
  * @param config User-provided configuration options
182
275
  * @returns Default configuration merged with user-provided options
183
276
  */
277
+ KTDataTable.prototype._createDefaultSearchCallback = function () {
278
+ return (function (data, search) {
279
+ if (!data || !search) {
280
+ return [];
281
+ }
282
+ var searchLower = search.toLowerCase();
283
+ return data.filter(function (item) {
284
+ if (!item) {
285
+ return false;
286
+ }
287
+ return Object.values(item).some(function (value) {
288
+ if (typeof value !== 'string' &&
289
+ typeof value !== 'number' &&
290
+ typeof value !== 'boolean') {
291
+ return false;
292
+ }
293
+ var valueText = (0, datatable_utils_1.stripHtml)(value).toLowerCase();
294
+ return valueText.includes(searchLower);
295
+ });
296
+ });
297
+ });
298
+ };
184
299
  KTDataTable.prototype._initDefaultConfig = function (config) {
185
300
  var _this = this;
186
- return __assign({
187
- /**
188
- * HTTP method for server-side API call
189
- */
190
- requestMethod: 'GET',
191
- /**
192
- * Custom HTTP headers for the API request
193
- */
194
- requestHeaders: {
195
- 'Content-Type': 'application/x-www-form-urlencoded',
196
- },
197
- /**
198
- * Pagination info template
199
- */
200
- info: '{start}-{end} of {total}',
201
- /**
202
- * Info text when there is no data
203
- */
204
- infoEmpty: 'No records found',
205
- /**
206
- * Available page sizes
207
- */
208
- pageSizes: [5, 10, 20, 30, 50],
209
- /**
210
- * Default page size
211
- */
212
- pageSize: 10,
213
- /**
214
- * Enable or disable pagination more button
215
- */
216
- pageMore: true,
217
- /**
218
- * Maximum number of pages before enabling pagination more button
219
- */
220
- pageMoreLimit: 3,
221
- /**
222
- * Pagination button templates
223
- */
224
- pagination: {
225
- number: {
226
- /**
227
- * CSS classes to be added to the pagination button
228
- */
229
- class: 'kt-datatable-pagination-button',
230
- /**
231
- * Text to be displayed in the pagination button
232
- */
233
- text: '{page}',
234
- },
235
- previous: {
236
- /**
237
- * CSS classes to be added to the previous pagination button
238
- */
239
- class: 'kt-datatable-pagination-button kt-datatable-pagination-prev',
240
- /**
241
- * Text to be displayed in the previous pagination button
242
- */
243
- text: "\n\t\t\t\t\t\t<svg class=\"rtl:transform rtl:rotate-180 size-3.5 shrink-0\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n\t\t\t\t\t\t\t<path d=\"M8.86501 16.7882V12.8481H21.1459C21.3724 12.8481 21.5897 12.7581 21.7498 12.5979C21.91 12.4378 22 12.2205 22 11.994C22 11.7675 21.91 11.5503 21.7498 11.3901C21.5897 11.2299 21.3724 11.1399 21.1459 11.1399H8.86501V7.2112C8.86628 7.10375 8.83517 6.9984 8.77573 6.90887C8.7163 6.81934 8.63129 6.74978 8.53177 6.70923C8.43225 6.66869 8.32283 6.65904 8.21775 6.68155C8.11267 6.70405 8.0168 6.75766 7.94262 6.83541L2.15981 11.6182C2.1092 11.668 2.06901 11.7274 2.04157 11.7929C2.01413 11.8584 2 11.9287 2 11.9997C2 12.0707 2.01413 12.141 2.04157 12.2065C2.06901 12.272 2.1092 12.3314 2.15981 12.3812L7.94262 17.164C8.0168 17.2417 8.11267 17.2953 8.21775 17.3178C8.32283 17.3403 8.43225 17.3307 8.53177 17.2902C8.63129 17.2496 8.7163 17.18 8.77573 17.0905C8.83517 17.001 8.86628 16.8956 8.86501 16.7882Z\" fill=\"currentColor\"/>\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t",
244
- },
245
- next: {
246
- /**
247
- * CSS classes to be added to the next pagination button
248
- */
249
- class: 'kt-datatable-pagination-button kt-datatable-pagination-next',
250
- /**
251
- * Text to be displayed in the next pagination button
252
- */
253
- text: "\n\t\t\t\t\t\t<svg class=\"rtl:transform rtl:rotate-180 size-3.5 shrink-0\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n\t\t\t\t\t\t\t<path d=\"M15.135 7.21144V11.1516H2.85407C2.62756 11.1516 2.41032 11.2415 2.25015 11.4017C2.08998 11.5619 2 11.7791 2 12.0056C2 12.2321 2.08998 12.4494 2.25015 12.6096C2.41032 12.7697 2.62756 12.8597 2.85407 12.8597H15.135V16.7884C15.1337 16.8959 15.1648 17.0012 15.2243 17.0908C15.2837 17.1803 15.3687 17.2499 15.4682 17.2904C15.5677 17.3309 15.6772 17.3406 15.7822 17.3181C15.8873 17.2956 15.9832 17.242 16.0574 17.1642L21.8402 12.3814C21.8908 12.3316 21.931 12.2722 21.9584 12.2067C21.9859 12.1412 22 12.0709 22 11.9999C22 11.9289 21.9859 11.8586 21.9584 11.7931C21.931 11.7276 21.8908 11.6683 21.8402 11.6185L16.0574 6.83565C15.9832 6.75791 15.8873 6.70429 15.7822 6.68179C15.6772 6.65929 15.5677 6.66893 15.4682 6.70948C15.3687 6.75002 15.2837 6.81959 15.2243 6.90911C15.1648 6.99864 15.1337 7.10399 15.135 7.21144Z\" fill=\"currentColor\"/>\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t",
254
- },
255
- more: {
256
- /**
257
- * CSS classes to be added to the pagination more button
258
- */
259
- class: 'kt-datatable-pagination-button kt-datatable-pagination-more',
260
- /**
261
- * Text to be displayed in the pagination more button
262
- */
263
- text: '...',
264
- },
265
- },
266
- /**
267
- * Sorting options
268
- */
269
- sort: {
270
- /**
271
- * CSS classes to be added to the sortable headers
272
- */
273
- classes: {
274
- base: 'kt-table-col',
275
- asc: 'asc',
276
- desc: 'desc',
277
- },
278
- /**
279
- * Local sorting callback function
280
- * Sorts the data array based on the sort field and order
281
- * @param data Data array to be sorted
282
- * @param sortField Property name of the data object to be sorted by
283
- * @param sortOrder Sorting order (ascending or descending)
284
- * @returns Sorted data array
285
- */
286
- callback: function (data, sortField, sortOrder) {
301
+ return __assign(__assign(__assign({}, datatable_defaults_1.DATATABLE_DEFAULTS), {
302
+ // Per-instance state; DATATABLE_DEFAULTS._state is a shared singleton.
303
+ _state: {}, sort: __assign(__assign({}, datatable_defaults_1.DATATABLE_DEFAULTS.sort), { callback: function (data, sortField, sortOrder) {
287
304
  return _this._sortHandler
288
305
  ? _this._sortHandler.sortData(data, sortField, sortOrder)
289
306
  : data;
290
- },
291
- }, search: {
292
- /**
293
- * Delay in milliseconds before the search function is applied to the data array
294
- * @default 500
295
- */
296
- delay: 500, // ms
297
- /**
298
- * Local search callback function
299
- * Filters the data array based on the search string
300
- * @param data Data array to be filtered
301
- * @param search Search string used to filter the data array
302
- * @returns Filtered data array
303
- */
304
- callback: function (data, search) {
305
- if (!data || !search) {
306
- return [];
307
- }
308
- return data.filter(function (item) {
309
- if (!item) {
310
- return false;
311
- }
312
- return Object.values(item).some(function (value) {
313
- if (typeof value !== 'string' &&
314
- typeof value !== 'number' &&
315
- typeof value !== 'boolean') {
316
- return false;
317
- }
318
- var valueText = String(value)
319
- .replace(/<|>|&nbsp;/g, '')
320
- .toLowerCase();
321
- return valueText.includes(search.toLowerCase());
322
- });
323
- });
324
- },
325
- },
326
- /**
327
- * Loading spinner options
328
- */
329
- loading: {
330
- /**
331
- * Template to be displayed during data fetching process
332
- */
333
- template: "\n\t\t\t\t\t<div class=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2\">\n\t\t\t\t\t\t<div class=\"kt-datatable-loading\">\n\t\t\t\t\t\t\t<svg class=\"animate-spin -ml-1 h-5 w-5 text-gray-600\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n\t\t\t\t\t\t\t\t<circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"3\"></circle>\n\t\t\t\t\t\t\t\t<path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t{content}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t",
334
- /**
335
- * Loading text to be displayed in the template
336
- */
337
- content: 'Loading...',
338
- },
339
- /**
340
- * Selectors of the elements to be targeted
341
- */
342
- attributes: {
343
- /**
344
- * Data table element
345
- */
346
- table: 'table[data-kt-datatable-table="true"]',
347
- /**
348
- * Pagination info element
349
- */
350
- info: '[data-kt-datatable-info="true"]',
351
- /**
352
- * Page size dropdown element
353
- */
354
- size: '[data-kt-datatable-size="true"]',
355
- /**
356
- * Pagination element
357
- */
358
- pagination: '[data-kt-datatable-pagination="true"]',
359
- /**
360
- * Spinner element
361
- */
362
- spinner: '[data-kt-datatable-spinner="true"]',
363
- /**
364
- * Checkbox element
365
- */
366
- check: '[data-kt-datatable-check="true"]',
367
- checkbox: '[data-kt-datatable-row-check="true"]',
368
- },
369
- /**
370
- * Enable or disable state saving
371
- */
372
- stateSave: true, checkbox: {
373
- checkedClass: 'checked',
374
- },
375
- /**
376
- * Private properties
377
- */
378
- _state: {}, loadingClass: 'loading' }, config);
307
+ } }), search: __assign(__assign({}, datatable_defaults_1.DATATABLE_DEFAULTS.search), { callback: this._createDefaultSearchCallback() }) }), config);
379
308
  };
380
309
  /**
381
310
  * Initialize table, tbody, thead, info, size, and pagination elements
@@ -416,24 +345,24 @@ var KTDataTable = /** @class */ (function (_super) {
416
345
  var _this = this;
417
346
  // Store tbody class
418
347
  if (this._tbodyElement) {
419
- this._originalTbodyClass = this._tbodyElement.className || '';
348
+ this._originalClasses.tbody = this._tbodyElement.className || '';
420
349
  }
421
350
  // Store thead class and th classes
422
351
  if (this._theadElement) {
423
- this._originalTheadClass = this._theadElement.className || '';
352
+ this._originalClasses.thead = this._theadElement.className || '';
424
353
  // Store th classes
425
354
  var thElements = this._theadElement.querySelectorAll('th');
426
- this._originalThClasses = Array.from(thElements).map(function (th) { return th.className || ''; });
355
+ this._originalClasses.th = Array.from(thElements).map(function (th) { return th.className || ''; });
427
356
  }
428
357
  // Store tr and td classes
429
358
  if (this._tbodyElement) {
430
359
  var originalRows = this._tbodyElement.querySelectorAll('tr');
431
- this._originalTrClasses = Array.from(originalRows).map(function (row) { return row.className || ''; });
360
+ this._originalClasses.tr = Array.from(originalRows).map(function (row) { return row.className || ''; });
432
361
  // Store td classes as a 2D array
433
- this._originalTdClasses = [];
362
+ this._originalClasses.td = [];
434
363
  Array.from(originalRows).forEach(function (row, rowIndex) {
435
364
  var tdElements = row.querySelectorAll('td');
436
- _this._originalTdClasses[rowIndex] = Array.from(tdElements).map(function (td) { return td.className || ''; });
365
+ _this._originalClasses.td[rowIndex] = Array.from(tdElements).map(function (td) { return td.className || ''; });
437
366
  });
438
367
  }
439
368
  };
@@ -453,8 +382,7 @@ var KTDataTable = /** @class */ (function (_super) {
453
382
  _b.label = 1;
454
383
  case 1:
455
384
  _b.trys.push([1, , 8, 9]);
456
- this._showSpinner(); // Show spinner before fetching data
457
- this._emit('fetch');
385
+ this._spinner.show(this._element, this._config, this._tableElement); // Show spinner before fetching data
458
386
  if (!(typeof this._config.apiEndpoint === 'undefined')) return [3 /*break*/, 2];
459
387
  _a = this._localProvider.fetchSync();
460
388
  return [3 /*break*/, 4];
@@ -470,11 +398,11 @@ var KTDataTable = /** @class */ (function (_super) {
470
398
  return [4 /*yield*/, this._draw()];
471
399
  case 5:
472
400
  _b.sent();
473
- this._emit('fetched');
474
401
  _b.label = 6;
475
402
  case 6: return [4 /*yield*/, this._finalize()];
476
403
  case 7:
477
404
  _b.sent();
405
+ this._emit('update');
478
406
  return [3 /*break*/, 9];
479
407
  case 8:
480
408
  // Finally block now correctly executes after promises resolve, not immediately
@@ -490,7 +418,8 @@ var KTDataTable = /** @class */ (function (_super) {
490
418
  * @returns {void}
491
419
  */
492
420
  KTDataTable.prototype._finalize = function () {
493
- var _a;
421
+ var _this = this;
422
+ var _a, _b, _c;
494
423
  (_a = this._element) === null || _a === void 0 ? void 0 : _a.classList.add('datatable-initialized');
495
424
  // Initialize checkbox logic
496
425
  this._checkbox.init();
@@ -498,50 +427,20 @@ var KTDataTable = /** @class */ (function (_super) {
498
427
  if (this._sortHandler) {
499
428
  this._sortHandler.initSort();
500
429
  }
501
- this._attachSearchEvent();
502
- if (typeof index_1.default !== 'undefined') {
503
- index_1.default.init();
504
- }
430
+ this._searchHandler.attach(this._tableId(), this.getState().search, (_c = (_b = this._config.search) === null || _b === void 0 ? void 0 : _b.delay) !== null && _c !== void 0 ? _c : datatable_defaults_1.DEFAULT_SEARCH_DELAY, function (query) { return _this.search(query); });
505
431
  /**
506
432
  * Hide spinner
507
433
  */
508
- this._hideSpinner();
509
- };
510
- /**
511
- * Attach search event to the search input element
512
- * @returns {void}
513
- */
514
- KTDataTable.prototype._attachSearchEvent = function () {
515
- var _this = this;
516
- var _a, _b;
517
- var tableId = this._tableId();
518
- var searchElement = document.querySelector("[data-kt-datatable-search=\"#".concat(tableId, "\"]"));
519
- // Get search state
520
- var search = this.getState().search;
521
- // Set search value
522
- if (searchElement) {
523
- searchElement.value =
524
- search === undefined || search === null
525
- ? ''
526
- : typeof search === 'string'
527
- ? search
528
- : String(search);
529
- }
530
- if (searchElement) {
531
- // Check if a debounced search function already exists
532
- var searchWithDebounce = KTDataTable.asSearchElementWithDebounce(searchElement);
533
- if (searchWithDebounce._debouncedSearch) {
534
- // Remove the existing debounced event listener
535
- searchElement.removeEventListener('keyup', searchWithDebounce._debouncedSearch);
536
- }
537
- // Create a new debounced search function
538
- var debouncedSearch = this._debounce(function () {
539
- _this.search(searchElement.value);
540
- }, (_b = (_a = this._config.search) === null || _a === void 0 ? void 0 : _a.delay) !== null && _b !== void 0 ? _b : 500);
541
- // Store the new debounced function as a property of the element
542
- searchWithDebounce._debouncedSearch = debouncedSearch;
543
- // Add the new debounced event listener
544
- searchElement.addEventListener('keyup', debouncedSearch);
434
+ this._spinner.hide(this._element, this._config);
435
+ // Update content checksum AFTER all DOM modifications (checkbox init
436
+ // adds checked-class to <tr> elements which changes tbody innerHTML).
437
+ // If we save the checksum earlier (in _draw), the next fetchSync()
438
+ // sees a mismatch, re-extracts from the DOM, and loses rows that
439
+ // were on other pages — making pagination show empty.
440
+ if (!this._config.apiEndpoint) {
441
+ this._stateStore.patchState({
442
+ _contentChecksum: utils_1.default.checksum(JSON.stringify(this._tbodyElement.innerHTML)),
443
+ });
545
444
  }
546
445
  };
547
446
  /**
@@ -550,17 +449,7 @@ var KTDataTable = /** @class */ (function (_super) {
550
449
  * @returns {number} Number of data columns, or 0 if unknown
551
450
  */
552
451
  KTDataTable.prototype._getLogicalColumnCount = function () {
553
- var originalData = this.getState().originalData;
554
- if (originalData && originalData.length > 0) {
555
- return Object.keys(originalData[0]).length;
556
- }
557
- if (this._tbodyElement) {
558
- var firstRow = this._tbodyElement.querySelector('tr');
559
- if (firstRow) {
560
- return firstRow.querySelectorAll('td').length;
561
- }
562
- }
563
- return 0;
452
+ return (0, datatable_column_utils_1.getLogicalColumnCount)(this._theadElement, this._tbodyElement, this.getState().originalData);
564
453
  };
565
454
  /**
566
455
  * Creates a complete URL from a relative path or a full URL.
@@ -629,12 +518,17 @@ var KTDataTable = /** @class */ (function (_super) {
629
518
  */
630
519
  KTDataTable.prototype._draw = function () {
631
520
  return __awaiter(this, void 0, void 0, function () {
632
- return __generator(this, function (_a) {
633
- this._stateStore.patchState({
634
- totalPages: Math.ceil(this.getState().totalItems / this.getState().pageSize) || 0,
635
- });
636
- this._emit('draw');
637
- this._dispose();
521
+ var normalizedPageSize, totalPages, page;
522
+ var _a, _b, _c, _d;
523
+ return __generator(this, function (_e) {
524
+ normalizedPageSize = Math.max(1, Number(this.getState().pageSize) || Number(this._config.pageSize) || 1);
525
+ totalPages = Math.ceil(this.getState().totalItems / normalizedPageSize) || 0;
526
+ page = totalPages > 0
527
+ ? Math.min(Math.max(1, this.getState().page), totalPages)
528
+ : 1;
529
+ this._stateStore.patchState({ totalPages: totalPages, page: page });
530
+ (_b = (_a = this._layoutPlugin) === null || _a === void 0 ? void 0 : _a.beforeDraw) === null || _b === void 0 ? void 0 : _b.call(_a, this._getLayoutPluginContext());
531
+ this._cleanupForRedraw();
638
532
  // Update the table and pagination controls
639
533
  if (this._theadElement && this._tbodyElement) {
640
534
  this._updateTable();
@@ -642,7 +536,7 @@ var KTDataTable = /** @class */ (function (_super) {
642
536
  if (this._infoElement || this._sizeElement || this._paginationElement) {
643
537
  this._updatePagination();
644
538
  }
645
- this._emit('drew');
539
+ (_d = (_c = this._layoutPlugin) === null || _c === void 0 ? void 0 : _c.afterDraw) === null || _d === void 0 ? void 0 : _d.call(_c, this._getLayoutPluginContext());
646
540
  // Spinner is hidden in _finalize() to ensure it stays visible until the entire request completes
647
541
  // Removed duplicate _hideSpinner() call here to prevent premature hiding
648
542
  if (this._config.stateSave) {
@@ -657,18 +551,17 @@ var KTDataTable = /** @class */ (function (_super) {
657
551
  * @returns {HTMLTableSectionElement} The new table body element
658
552
  */
659
553
  KTDataTable.prototype._updateTable = function () {
660
- return this._tableRenderer.render({
554
+ this._tbodyElement = this._tableRenderer.render({
661
555
  config: this._config,
662
556
  context: this,
663
557
  data: this._data,
664
558
  getLogicalColumnCount: this._getLogicalColumnCount.bind(this),
665
559
  getState: this.getState.bind(this),
666
- originalTbodyClass: this._originalTbodyClass,
667
- originalTrClasses: this._originalTrClasses,
668
- originalTdClasses: this._originalTdClasses,
560
+ originalClasses: this._originalClasses,
669
561
  tableElement: this._tableElement,
670
562
  theadElement: this._theadElement,
671
563
  });
564
+ return this._tbodyElement;
672
565
  };
673
566
  /**
674
567
  * Show a notice on the table
@@ -714,91 +607,31 @@ var KTDataTable = /** @class */ (function (_super) {
714
607
  if (page < 1 || !Number.isInteger(page)) {
715
608
  return;
716
609
  }
717
- this._emit('pagination', { page: page });
718
610
  if (page >= 1 && page <= this.getState().totalPages) {
719
611
  this._stateStore.setPage(page);
720
612
  this._updateData();
721
613
  }
722
614
  };
723
- // Method to show the loading spinner
724
- KTDataTable.prototype._showSpinner = function () {
725
- var _a, _b;
726
- var root = this._element;
727
- var spinnerSel = (_a = this._config.attributes) === null || _a === void 0 ? void 0 : _a.spinner;
728
- var fromDom = root && spinnerSel
729
- ? root.querySelector(spinnerSel)
730
- : null;
731
- var spinner = fromDom !== null && fromDom !== void 0 ? fromDom : this._createSpinner();
732
- if (spinner) {
733
- spinner.style.display = 'block';
734
- }
735
- root === null || root === void 0 ? void 0 : root.classList.add((_b = this._config.loadingClass) !== null && _b !== void 0 ? _b : 'loading');
736
- };
737
- // Method to hide the loading spinner
738
- KTDataTable.prototype._hideSpinner = function () {
739
- var _a, _b;
740
- var root = this._element;
741
- var spinnerSel = (_a = this._config.attributes) === null || _a === void 0 ? void 0 : _a.spinner;
742
- var spinner = root && spinnerSel
743
- ? root.querySelector(spinnerSel)
744
- : null;
745
- if (spinner) {
746
- spinner.style.display = 'none';
747
- }
748
- root === null || root === void 0 ? void 0 : root.classList.remove((_b = this._config.loadingClass) !== null && _b !== void 0 ? _b : 'loading');
749
- };
750
- // Method to create a spinner element if it doesn't exist
751
- KTDataTable.prototype._createSpinner = function () {
752
- var loading = this._config.loading;
753
- if (!loading) {
754
- return null;
755
- }
756
- var template = document.createElement('template');
757
- template.innerHTML = loading.template
758
- .trim()
759
- .replace('{content}', loading.content);
760
- var first = template.content.firstChild;
761
- if (!first || !(first instanceof HTMLElement)) {
762
- return null;
763
- }
764
- var spinner = first;
765
- spinner.setAttribute('data-kt-datatable-spinner', 'true');
766
- this._tableElement.appendChild(spinner);
767
- return spinner;
768
- };
769
615
  /**
770
616
  * Saves the current state of the table to local storage.
771
617
  * @returns {void}
772
618
  */
773
619
  KTDataTable.prototype._saveState = function () {
774
- this._emit('stateSave');
775
- var ns = this._tableNamespace();
776
- if (ns) {
777
- localStorage.setItem(ns, JSON.stringify(this.getState()));
778
- }
620
+ this._statePersistence.save(this._tableNamespace(), this.getState());
779
621
  };
780
622
  /**
781
623
  * Loads the saved state of the table from local storage, if it exists.
782
624
  * @returns {Object} The saved state of the table, or null if no saved state exists.
783
625
  */
784
626
  KTDataTable.prototype._loadState = function () {
785
- var stateString = localStorage.getItem(this._tableNamespace());
786
- if (!stateString)
787
- return null;
788
- try {
789
- var state = JSON.parse(stateString);
790
- if (state)
791
- this._stateStore.replaceState(state);
792
- return state;
793
- }
794
- catch (_a) { }
795
- return null;
627
+ var ns = this._tableNamespace();
628
+ var saved = this._statePersistence.load(ns);
629
+ if (saved)
630
+ this._stateStore.replaceState(saved);
631
+ return saved;
796
632
  };
797
633
  KTDataTable.prototype._deleteState = function () {
798
- var ns = this._tableNamespace();
799
- if (ns) {
800
- localStorage.removeItem(ns);
801
- }
634
+ this._statePersistence.remove(this._tableNamespace());
802
635
  };
803
636
  /**
804
637
  * Gets the namespace for the table's state.
@@ -809,13 +642,7 @@ var KTDataTable = /** @class */ (function (_super) {
809
642
  * @returns {string} The namespace for the table's state.
810
643
  */
811
644
  KTDataTable.prototype._tableNamespace = function () {
812
- var _a;
813
- // Use the specified namespace, if one is given
814
- if (this._config.stateNamespace) {
815
- return this._config.stateNamespace;
816
- }
817
- // Fallback to the component's UID
818
- return (_a = this._tableId()) !== null && _a !== void 0 ? _a : this._name;
645
+ return (0, datatable_state_persistence_1.resolveTableNamespace)(this._config, this._tableElement, this._element, this._name);
819
646
  };
820
647
  KTDataTable.prototype._tableId = function () {
821
648
  var _a, _b;
@@ -833,90 +660,43 @@ var KTDataTable = /** @class */ (function (_super) {
833
660
  * Clean up all event listeners, handlers, and DOM nodes created by this instance.
834
661
  * This method is called before re-rendering or when disposing the component.
835
662
  */
836
- KTDataTable.prototype._dispose = function () {
837
- var _a, _b, _c;
838
- var root = this._element;
839
- if (!root) {
663
+ /**
664
+ * Clean up event listeners and DOM artifacts for a redraw cycle.
665
+ * Does NOT remove the instance from the registry — the datatable
666
+ * remains accessible via getInstance() during the redraw window.
667
+ */
668
+ KTDataTable.prototype._cleanupForRedraw = function () {
669
+ var _a, _b;
670
+ (_b = (_a = this._layoutPlugin) === null || _a === void 0 ? void 0 : _a.dispose) === null || _b === void 0 ? void 0 : _b.call(_a, this._getLayoutPluginContext());
671
+ if (!this._element) {
840
672
  return;
841
673
  }
842
674
  this._cleanupCallbacks.forEach(function (cleanup) { return cleanup(); });
843
675
  this._cleanupCallbacks = [];
844
- // --- 1. Remove search input event listener (debounced) ---
845
- var tableId = this._tableId();
846
- var searchElement = document.querySelector("[data-kt-datatable-search=\"#".concat(tableId, "\"]"));
847
- if (searchElement) {
848
- var searchWithDebounce = KTDataTable.asSearchElementWithDebounce(searchElement);
849
- if (searchWithDebounce._debouncedSearch) {
850
- searchElement.removeEventListener('keyup', searchWithDebounce._debouncedSearch);
851
- delete searchWithDebounce._debouncedSearch;
852
- }
853
- }
854
- // --- 2. Remove page size dropdown event listener ---
676
+ this._searchHandler.detach(this._tableId());
855
677
  if (this._sizeElement && this._sizeElement.onchange) {
856
678
  this._sizeElement.onchange = null;
857
679
  }
858
- // --- 3. Remove all pagination button event listeners ---
859
680
  if (this._paginationElement) {
860
- // Remove all child nodes (buttons) to ensure no lingering listeners
861
681
  while (this._paginationElement.firstChild) {
862
682
  this._paginationElement.removeChild(this._paginationElement.firstChild);
863
683
  }
864
684
  }
865
- // --- 4. Dispose of handler objects (checkbox, sort) ---
866
- // KTDataTableCheckboxAPI does not have a dispose method, but we can remove header checkbox listener
867
- var checkboxWithDispose = this._checkbox;
868
- if (this._checkbox && typeof checkboxWithDispose.dispose === 'function') {
869
- checkboxWithDispose.dispose();
870
- }
871
- else {
872
- var checkSel = (_a = this._config.attributes) === null || _a === void 0 ? void 0 : _a.check;
873
- if (checkSel) {
874
- var headerCheckElement = root.querySelector(checkSel);
875
- if (headerCheckElement) {
876
- headerCheckElement.replaceWith(headerCheckElement.cloneNode(true));
877
- }
878
- }
879
- }
880
- // KTDataTableSortAPI does not have a dispose method, but we can remove th click listeners by replacing them
881
- if (this._theadElement) {
882
- var ths = this._theadElement.querySelectorAll('th');
883
- ths.forEach(function (th) {
884
- th.replaceWith(th.cloneNode(true));
885
- });
886
- }
887
- // --- 5. Remove spinner DOM node if it exists ---
888
- var spinnerSel = (_b = this._config.attributes) === null || _b === void 0 ? void 0 : _b.spinner;
889
- if (spinnerSel) {
890
- var spinner = root.querySelector(spinnerSel);
891
- if (spinner === null || spinner === void 0 ? void 0 : spinner.parentNode) {
892
- spinner.parentNode.removeChild(spinner);
893
- }
894
- }
895
- root.classList.remove((_c = this._config.loadingClass) !== null && _c !== void 0 ? _c : 'loading');
896
- // --- 6. Remove instance reference from the DOM element ---
897
- var elementWithInstance = KTDataTable.asElementWithInstance(root);
898
- if (elementWithInstance.instance) {
899
- delete elementWithInstance.instance;
900
- }
901
- data_1.default.remove(root, this._name);
902
- // --- 7. (Optional) Clear localStorage state ---
903
- // Uncomment the following line if you want to clear state on dispose:
904
- // this._deleteState();
685
+ this._checkbox.dispose();
686
+ this._sortHandler.dispose();
687
+ this._spinner.remove(this._element, this._config);
905
688
  };
906
- KTDataTable.prototype._debounce = function (func, wait) {
907
- var timeout;
908
- return function () {
909
- var args = [];
910
- for (var _i = 0; _i < arguments.length; _i++) {
911
- args[_i] = arguments[_i];
912
- }
913
- var later = function () {
914
- clearTimeout(timeout);
915
- func.apply(void 0, args);
916
- };
917
- clearTimeout(timeout);
918
- timeout = window.setTimeout(later, wait);
919
- };
689
+ /**
690
+ * Full disposal — cleans up listeners AND removes the instance from
691
+ * the registry. Only called when the component is being destroyed.
692
+ */
693
+ KTDataTable.prototype._dispose = function () {
694
+ this._cleanupForRedraw();
695
+ var root = this._element;
696
+ if (root) {
697
+ datatableRegistry.remove(root);
698
+ data_1.default.remove(root, this._name);
699
+ }
920
700
  };
921
701
  /**
922
702
  * Gets the current state of the table.
@@ -927,12 +707,14 @@ var KTDataTable = /** @class */ (function (_super) {
927
707
  };
928
708
  /**
929
709
  * Sorts the data in the table by the specified field.
710
+ * When `order` is provided, applies that sort direction instead of toggling.
930
711
  * @param field The field to sort by.
712
+ * @param order Optional sort direction (`asc`, `desc`, or `''` to clear).
931
713
  */
932
- KTDataTable.prototype.sort = function (field) {
933
- // Use the sort handler to update state and trigger sorting
934
- var state = this.getState();
935
- var sortOrder = this._sortHandler.toggleSortOrder(state.sortField, state.sortOrder, field);
714
+ KTDataTable.prototype.sort = function (field, order) {
715
+ var sortOrder = order !== undefined
716
+ ? order
717
+ : this._sortHandler.toggleSortOrder(this.getState().sortField, this.getState().sortOrder, field);
936
718
  this._sortHandler.setSortIcon(field, sortOrder);
937
719
  this._stateStore.setSort(field, sortOrder);
938
720
  this._emit('sort', { field: field, order: sortOrder });
@@ -964,36 +746,28 @@ var KTDataTable = /** @class */ (function (_super) {
964
746
  this._reloadPageSize(pageSize);
965
747
  };
966
748
  /**
967
- * Reloads the data from the server and updates the table.
968
- * Triggers the 'reload' event and the 'kt.datatable.reload' custom event.
749
+ * Reloads the data from the source (API or DOM) and redraws the table.
750
+ * @returns {Promise<void>}
969
751
  */
970
752
  KTDataTable.prototype.reload = function () {
971
- this._emit('reload');
972
753
  // Fetch the data from the server using the current sort and filter settings
973
754
  this._updateData();
974
755
  };
975
756
  KTDataTable.prototype.redraw = function (page) {
976
757
  if (page === void 0) { page = 1; }
977
- this._emit('redraw');
978
758
  this._paginateData(page);
979
759
  };
980
760
  /**
981
761
  * Show the loading spinner of the data table.
982
762
  */
983
763
  KTDataTable.prototype.showSpinner = function () {
984
- /**
985
- * Show the loading spinner of the data table.
986
- */
987
- this._showSpinner();
764
+ this._spinner.show(this._element, this._config, this._tableElement);
988
765
  };
989
766
  /**
990
767
  * Hide the loading spinner of the data table.
991
768
  */
992
769
  KTDataTable.prototype.hideSpinner = function () {
993
- /**
994
- * Hide the loading spinner of the data table.
995
- */
996
- this._hideSpinner();
770
+ this._spinner.hide(this._element, this._config);
997
771
  };
998
772
  /**
999
773
  * Filter data using the specified filter object.
@@ -1020,21 +794,7 @@ var KTDataTable = /** @class */ (function (_super) {
1020
794
  * This function is now browser-guarded and must be called explicitly.
1021
795
  */
1022
796
  KTDataTable.createInstances = function () {
1023
- var _this = this;
1024
- if (typeof document === 'undefined')
1025
- return;
1026
- var elements = document.querySelectorAll('[data-kt-datatable="true"]');
1027
- elements.forEach(function (element) {
1028
- if (element.hasAttribute('data-kt-datatable') &&
1029
- !element.classList.contains('datatable-initialized')) {
1030
- /**
1031
- * Create an instance of KTDataTable for the given element
1032
- * @param element The element to create an instance for
1033
- */
1034
- var instance = new KTDataTable(element);
1035
- _this._instances.set(element, instance);
1036
- }
1037
- });
797
+ datatableRegistry.createAll(function (el) { return new KTDataTable(el); });
1038
798
  };
1039
799
  /**
1040
800
  * Get the KTDataTable instance for a given element.
@@ -1043,21 +803,13 @@ var KTDataTable = /** @class */ (function (_super) {
1043
803
  * @returns The KTDataTable instance or undefined if not found
1044
804
  */
1045
805
  KTDataTable.getInstance = function (element) {
1046
- // First check the static Map (for instances created via createInstances)
1047
- var instanceFromMap = this._instances.get(element);
1048
- if (instanceFromMap) {
1049
- return instanceFromMap;
1050
- }
1051
- // Fallback to element's instance property (for manually created instances)
1052
- return KTDataTable.asElementWithInstance(element).instance;
806
+ return datatableRegistry.get(element);
1053
807
  };
1054
808
  /**
1055
809
  * Initializes all KTDataTable instances on the page.
1056
810
  * This function is now browser-guarded and must be called explicitly.
1057
811
  */
1058
812
  KTDataTable.init = function () {
1059
- if (typeof document === 'undefined')
1060
- return;
1061
813
  KTDataTable.createInstances();
1062
814
  };
1063
815
  /**
@@ -1065,25 +817,7 @@ var KTDataTable = /** @class */ (function (_super) {
1065
817
  * Useful for Livewire wire:navigate where the DOM is replaced and new tables need to be initialized.
1066
818
  */
1067
819
  KTDataTable.reinit = function () {
1068
- if (typeof document === 'undefined')
1069
- return;
1070
- var elements = document.querySelectorAll('[data-kt-datatable="true"]');
1071
- elements.forEach(function (element) {
1072
- try {
1073
- var instance = KTDataTable.getInstance(element);
1074
- if (instance && typeof instance.dispose === 'function') {
1075
- instance.dispose();
1076
- }
1077
- data_1.default.remove(element, 'datatable');
1078
- element.removeAttribute('data-kt-datatable-initialized');
1079
- element.classList.remove('datatable-initialized');
1080
- }
1081
- catch (_a) {
1082
- // ignore per-element errors
1083
- }
1084
- });
1085
- KTDataTable._instances.clear();
1086
- KTDataTable.createInstances();
820
+ datatableRegistry.reinit(function (el) { return new KTDataTable(el); });
1087
821
  };
1088
822
  /**
1089
823
  * Check if all visible rows are checked (header checkbox state)
@@ -1123,16 +857,18 @@ var KTDataTable = /** @class */ (function (_super) {
1123
857
  return this._checkbox.getChecked();
1124
858
  };
1125
859
  /**
1126
- * Reapply checked state to visible checkboxes (after redraw/pagination)
860
+ * Re-apply checkbox checked states to visible rows after a redraw or pagination change.
1127
861
  * @returns {void}
1128
862
  */
1129
- KTDataTable.prototype.update = function () {
863
+ KTDataTable.prototype.refreshCheckboxes = function () {
1130
864
  this._checkbox.updateState();
1131
865
  };
1132
866
  /**
1133
- * Static variables
867
+ * @deprecated Use {@link refreshCheckboxes} instead.
1134
868
  */
1135
- KTDataTable._instances = new Map();
869
+ KTDataTable.prototype.update = function () {
870
+ this.refreshCheckboxes();
871
+ };
1136
872
  return KTDataTable;
1137
873
  }(component_1.default));
1138
874
  exports.KTDataTable = KTDataTable;