@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
@@ -64,17 +64,33 @@ 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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
68
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
69
+ if (ar || !(i in from)) {
70
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
71
+ ar[i] = from[i];
72
+ }
73
+ }
74
+ return to.concat(ar || Array.prototype.slice.call(from));
75
+ };
67
76
  import KTComponent from '../component';
68
- import KTComponents from '../../index';
69
77
  import KTData from '../../helpers/data';
70
- import { createCheckboxHandler, } from './datatable-checkbox';
71
- import { createSortHandler } from './datatable-sort';
72
- import { createDataTableEventAdapter } from './datatable-event-adapter';
78
+ import { KTDataTableCheckboxHandler, } from './datatable-checkbox';
79
+ import { KTDataTableSortHandler } from './datatable-sort';
80
+ import { createStickyLayoutPlugin } from './datatable-layout-plugin';
81
+ import { DATATABLE_DEFAULTS, DEFAULT_PAGE_SIZES, DEFAULT_SEARCH_DELAY } from './datatable-defaults';
82
+ import { getLogicalColumnCount } from './datatable-column-utils';
73
83
  import { KTDataTableLocalDataProvider } from './datatable-local-provider';
74
84
  import { KTDataTableRemoteDataProvider } from './datatable-remote-provider';
75
85
  import { KTDataTableConfigStateStore } from './datatable-state-store';
76
86
  import { KTDataTableDomPaginationRenderer } from './datatable-pagination-renderer';
77
87
  import { KTDataTableDomTableRenderer } from './datatable-table-renderer';
88
+ import KTUtils from '../../helpers/utils';
89
+ import { createSearchHandler } from './datatable-search-handler';
90
+ import { createStatePersistence, resolveTableNamespace, } from './datatable-state-persistence';
91
+ import { createSpinner } from './datatable-spinner';
92
+ import { createDataTableRegistry } from './datatable-registry';
93
+ import { stripHtml } from './datatable-utils';
78
94
  /**
79
95
  * Custom DataTable plugin class with server-side API, pagination, and sorting
80
96
  * @classdesc A custom KTComponent class that integrates server-side API, pagination, and sorting functionality into a table.
@@ -84,27 +100,34 @@ import { KTDataTableDomTableRenderer } from './datatable-table-renderer';
84
100
  * @param {HTMLElement} element The table element
85
101
  * @param {KTDataTableConfigInterface} [config] Additional configuration options
86
102
  */
103
+ var datatableRegistry = createDataTableRegistry();
87
104
  var KTDataTable = /** @class */ (function (_super) {
88
105
  __extends(KTDataTable, _super);
89
106
  function KTDataTable(element, config) {
90
107
  var _this = _super.call(this) || this;
91
108
  _this._name = 'datatable';
92
- _this._originalTbodyClass = ''; // Store original tbody class
93
- _this._originalTrClasses = []; // Store original tr classes
94
- _this._originalTheadClass = ''; // Store original thead class
95
- _this._originalTdClasses = []; // Store original td classes as a 2D array [row][col]
96
- _this._originalThClasses = []; // Store original th classes
109
+ _this._originalClasses = {
110
+ tbody: '',
111
+ thead: '',
112
+ tr: [],
113
+ td: [],
114
+ th: [],
115
+ };
97
116
  _this._infoElement = null;
98
117
  _this._sizeElement = null;
99
118
  _this._paginationElement = null;
119
+ _this._layoutPlugin = null;
100
120
  _this._cleanupCallbacks = [];
121
+ _this._searchHandler = createSearchHandler();
122
+ _this._statePersistence = createStatePersistence();
123
+ _this._spinner = createSpinner();
101
124
  _this._data = [];
102
125
  _this._isFetching = false;
103
126
  if (KTData.has(element, _this._name)) {
104
- // Already initialized (e.g. by createInstances). Merge user config so columns/sortType etc. apply.
127
+ // Already initialized (e.g. by createInstances). Merge demo config and redraw once.
105
128
  var existing = KTDataTable.getInstance(element);
106
129
  if (existing && config) {
107
- existing._mergeConfig(config);
130
+ existing._applyRuntimeConfig(config);
108
131
  }
109
132
  return _this;
110
133
  }
@@ -113,43 +136,59 @@ var KTDataTable = /** @class */ (function (_super) {
113
136
  if (!_this._element) {
114
137
  return _this;
115
138
  }
139
+ if (!_this._element.hasAttribute('data-kt-datatable')) {
140
+ _this._element.setAttribute('data-kt-datatable', 'true');
141
+ }
116
142
  _this._buildConfig();
143
+ _this._normalizePageSizeConfig();
117
144
  _this._stateStore = new KTDataTableConfigStateStore(_this._config);
118
- _this._eventAdapter = createDataTableEventAdapter(_this._fireEvent.bind(_this), _this._dispatchEvent.bind(_this));
145
+ _this._eventAdapter = {
146
+ emit: function (eventName, eventData) {
147
+ _this._emit(eventName, eventData);
148
+ },
149
+ };
119
150
  // Store the instance directly on the element
120
- KTDataTable.asElementWithInstance(element).instance = _this;
151
+ datatableRegistry.register(element, _this);
121
152
  _this._initElements();
153
+ _this._layoutPlugin = _this._createLayoutPlugin();
122
154
  _this._tableRenderer = new KTDataTableDomTableRenderer();
123
155
  _this._paginationRenderer = new KTDataTableDomPaginationRenderer();
124
156
  _this._initDataProviders();
125
157
  // Initialize checkbox handler
126
- _this._checkbox = createCheckboxHandler(_this._element, _this._config, _this._emit.bind(_this));
158
+ _this._checkbox = new KTDataTableCheckboxHandler(_this._element, _this._config, _this._emit.bind(_this), {
159
+ getState: function () { return _this._stateStore.getState(); },
160
+ setSelectedRows: function (rows) {
161
+ _this._stateStore.patchState({ selectedRows: rows });
162
+ },
163
+ });
127
164
  // Initialize sort handler
128
- _this._sortHandler = createSortHandler(_this._config, _this._theadElement, function () { return ({
129
- sortField: _this.getState().sortField,
130
- sortOrder: _this.getState().sortOrder,
131
- }); }, function (field, order) {
132
- _this._stateStore.setSort(field, order);
133
- }, _this._fireEvent.bind(_this), _this._dispatchEvent.bind(_this), _this._updateData.bind(_this));
165
+ _this._sortHandler = new KTDataTableSortHandler({
166
+ config: _this._config,
167
+ theadElement: _this._theadElement,
168
+ getState: function () { return ({
169
+ sortField: _this.getState().sortField,
170
+ sortOrder: _this.getState().sortOrder,
171
+ }); },
172
+ setState: function (field, order) {
173
+ _this._stateStore.setSort(field, order);
174
+ },
175
+ emit: _this._emit.bind(_this),
176
+ updateData: _this._updateData.bind(_this),
177
+ });
134
178
  _this._sortHandler.initSort();
135
179
  if (_this._config.stateSave === false) {
136
180
  _this._deleteState();
137
181
  }
138
182
  if (_this._config.stateSave) {
139
183
  _this._loadState();
184
+ _this._normalizePageState();
140
185
  }
141
186
  _this._updateData();
142
- _this._emit('init');
143
187
  return _this;
144
188
  }
145
- KTDataTable.asElementWithInstance = function (element) {
146
- return element;
147
- };
148
- KTDataTable.asSearchElementWithDebounce = function (element) {
149
- return element;
150
- };
151
189
  KTDataTable.prototype._emit = function (eventName, eventData) {
152
- this._eventAdapter.emit(eventName, eventData);
190
+ this._fireEvent(eventName, eventData);
191
+ this._dispatchEvent("kt.datatable.".concat(eventName), eventData);
153
192
  };
154
193
  KTDataTable.prototype._initDataProviders = function () {
155
194
  var _this = this;
@@ -172,206 +211,96 @@ var KTDataTable = /** @class */ (function (_super) {
172
211
  stateStore: this._stateStore,
173
212
  });
174
213
  };
214
+ KTDataTable.prototype._createLayoutPlugin = function () {
215
+ if (this._config.layoutPlugin) {
216
+ return this._config.layoutPlugin;
217
+ }
218
+ if (this._config.lockedLayout) {
219
+ return createStickyLayoutPlugin();
220
+ }
221
+ return null;
222
+ };
223
+ /**
224
+ * Apply config from a late constructor call (e.g. docs demo script after auto-init).
225
+ */
226
+ KTDataTable.prototype._applyRuntimeConfig = function (config) {
227
+ this._mergeConfig(config);
228
+ this._normalizePageSizeConfig();
229
+ this._layoutPlugin = this._createLayoutPlugin();
230
+ this.reload();
231
+ };
232
+ KTDataTable.prototype._normalizePageSizeConfig = function () {
233
+ var configuredPageSizes = Array.isArray(this._config.pageSizes)
234
+ ? this._config.pageSizes
235
+ : [];
236
+ var pageSizes = configuredPageSizes
237
+ .map(function (size) { return Number(size); })
238
+ .filter(function (size) { return Number.isFinite(size) && size > 0; })
239
+ .map(function (size) { return Math.floor(size); });
240
+ var fallbackPageSizes = __spreadArray([], DEFAULT_PAGE_SIZES, true);
241
+ this._config.pageSizes =
242
+ pageSizes.length > 0 ? Array.from(new Set(pageSizes)) : fallbackPageSizes;
243
+ var configuredPageSize = Number(this._config.pageSize);
244
+ this._config.pageSize =
245
+ Number.isFinite(configuredPageSize) && configuredPageSize > 0
246
+ ? Math.floor(configuredPageSize)
247
+ : this._config.pageSizes[0];
248
+ };
249
+ KTDataTable.prototype._normalizePageState = function () {
250
+ var statePageSize = Number(this._config._state.pageSize);
251
+ this._config._state.pageSize =
252
+ Number.isFinite(statePageSize) && statePageSize > 0
253
+ ? Math.floor(statePageSize)
254
+ : this._config.pageSize;
255
+ var statePage = Number(this._config._state.page);
256
+ this._config._state.page =
257
+ Number.isFinite(statePage) && statePage > 0 ? Math.floor(statePage) : 1;
258
+ };
259
+ KTDataTable.prototype._getLayoutPluginContext = function () {
260
+ return {
261
+ rootElement: this._element,
262
+ tableElement: this._tableElement,
263
+ theadElement: this._theadElement,
264
+ tbodyElement: this._tbodyElement,
265
+ config: this._config,
266
+ };
267
+ };
175
268
  /**
176
269
  * Initialize default configuration for the datatable
177
270
  * @param config User-provided configuration options
178
271
  * @returns Default configuration merged with user-provided options
179
272
  */
273
+ KTDataTable.prototype._createDefaultSearchCallback = function () {
274
+ return (function (data, search) {
275
+ if (!data || !search) {
276
+ return [];
277
+ }
278
+ var searchLower = search.toLowerCase();
279
+ return data.filter(function (item) {
280
+ if (!item) {
281
+ return false;
282
+ }
283
+ return Object.values(item).some(function (value) {
284
+ if (typeof value !== 'string' &&
285
+ typeof value !== 'number' &&
286
+ typeof value !== 'boolean') {
287
+ return false;
288
+ }
289
+ var valueText = stripHtml(value).toLowerCase();
290
+ return valueText.includes(searchLower);
291
+ });
292
+ });
293
+ });
294
+ };
180
295
  KTDataTable.prototype._initDefaultConfig = function (config) {
181
296
  var _this = this;
182
- return __assign({
183
- /**
184
- * HTTP method for server-side API call
185
- */
186
- requestMethod: 'GET',
187
- /**
188
- * Custom HTTP headers for the API request
189
- */
190
- requestHeaders: {
191
- 'Content-Type': 'application/x-www-form-urlencoded',
192
- },
193
- /**
194
- * Pagination info template
195
- */
196
- info: '{start}-{end} of {total}',
197
- /**
198
- * Info text when there is no data
199
- */
200
- infoEmpty: 'No records found',
201
- /**
202
- * Available page sizes
203
- */
204
- pageSizes: [5, 10, 20, 30, 50],
205
- /**
206
- * Default page size
207
- */
208
- pageSize: 10,
209
- /**
210
- * Enable or disable pagination more button
211
- */
212
- pageMore: true,
213
- /**
214
- * Maximum number of pages before enabling pagination more button
215
- */
216
- pageMoreLimit: 3,
217
- /**
218
- * Pagination button templates
219
- */
220
- pagination: {
221
- number: {
222
- /**
223
- * CSS classes to be added to the pagination button
224
- */
225
- class: 'kt-datatable-pagination-button',
226
- /**
227
- * Text to be displayed in the pagination button
228
- */
229
- text: '{page}',
230
- },
231
- previous: {
232
- /**
233
- * CSS classes to be added to the previous pagination button
234
- */
235
- class: 'kt-datatable-pagination-button kt-datatable-pagination-prev',
236
- /**
237
- * Text to be displayed in the previous pagination button
238
- */
239
- 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",
240
- },
241
- next: {
242
- /**
243
- * CSS classes to be added to the next pagination button
244
- */
245
- class: 'kt-datatable-pagination-button kt-datatable-pagination-next',
246
- /**
247
- * Text to be displayed in the next pagination button
248
- */
249
- 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",
250
- },
251
- more: {
252
- /**
253
- * CSS classes to be added to the pagination more button
254
- */
255
- class: 'kt-datatable-pagination-button kt-datatable-pagination-more',
256
- /**
257
- * Text to be displayed in the pagination more button
258
- */
259
- text: '...',
260
- },
261
- },
262
- /**
263
- * Sorting options
264
- */
265
- sort: {
266
- /**
267
- * CSS classes to be added to the sortable headers
268
- */
269
- classes: {
270
- base: 'kt-table-col',
271
- asc: 'asc',
272
- desc: 'desc',
273
- },
274
- /**
275
- * Local sorting callback function
276
- * Sorts the data array based on the sort field and order
277
- * @param data Data array to be sorted
278
- * @param sortField Property name of the data object to be sorted by
279
- * @param sortOrder Sorting order (ascending or descending)
280
- * @returns Sorted data array
281
- */
282
- callback: function (data, sortField, sortOrder) {
297
+ return __assign(__assign(__assign({}, DATATABLE_DEFAULTS), {
298
+ // Per-instance state; DATATABLE_DEFAULTS._state is a shared singleton.
299
+ _state: {}, sort: __assign(__assign({}, DATATABLE_DEFAULTS.sort), { callback: function (data, sortField, sortOrder) {
283
300
  return _this._sortHandler
284
301
  ? _this._sortHandler.sortData(data, sortField, sortOrder)
285
302
  : data;
286
- },
287
- }, search: {
288
- /**
289
- * Delay in milliseconds before the search function is applied to the data array
290
- * @default 500
291
- */
292
- delay: 500, // ms
293
- /**
294
- * Local search callback function
295
- * Filters the data array based on the search string
296
- * @param data Data array to be filtered
297
- * @param search Search string used to filter the data array
298
- * @returns Filtered data array
299
- */
300
- callback: function (data, search) {
301
- if (!data || !search) {
302
- return [];
303
- }
304
- return data.filter(function (item) {
305
- if (!item) {
306
- return false;
307
- }
308
- return Object.values(item).some(function (value) {
309
- if (typeof value !== 'string' &&
310
- typeof value !== 'number' &&
311
- typeof value !== 'boolean') {
312
- return false;
313
- }
314
- var valueText = String(value)
315
- .replace(/<|>|&nbsp;/g, '')
316
- .toLowerCase();
317
- return valueText.includes(search.toLowerCase());
318
- });
319
- });
320
- },
321
- },
322
- /**
323
- * Loading spinner options
324
- */
325
- loading: {
326
- /**
327
- * Template to be displayed during data fetching process
328
- */
329
- 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",
330
- /**
331
- * Loading text to be displayed in the template
332
- */
333
- content: 'Loading...',
334
- },
335
- /**
336
- * Selectors of the elements to be targeted
337
- */
338
- attributes: {
339
- /**
340
- * Data table element
341
- */
342
- table: 'table[data-kt-datatable-table="true"]',
343
- /**
344
- * Pagination info element
345
- */
346
- info: '[data-kt-datatable-info="true"]',
347
- /**
348
- * Page size dropdown element
349
- */
350
- size: '[data-kt-datatable-size="true"]',
351
- /**
352
- * Pagination element
353
- */
354
- pagination: '[data-kt-datatable-pagination="true"]',
355
- /**
356
- * Spinner element
357
- */
358
- spinner: '[data-kt-datatable-spinner="true"]',
359
- /**
360
- * Checkbox element
361
- */
362
- check: '[data-kt-datatable-check="true"]',
363
- checkbox: '[data-kt-datatable-row-check="true"]',
364
- },
365
- /**
366
- * Enable or disable state saving
367
- */
368
- stateSave: true, checkbox: {
369
- checkedClass: 'checked',
370
- },
371
- /**
372
- * Private properties
373
- */
374
- _state: {}, loadingClass: 'loading' }, config);
303
+ } }), search: __assign(__assign({}, DATATABLE_DEFAULTS.search), { callback: this._createDefaultSearchCallback() }) }), config);
375
304
  };
376
305
  /**
377
306
  * Initialize table, tbody, thead, info, size, and pagination elements
@@ -412,24 +341,24 @@ var KTDataTable = /** @class */ (function (_super) {
412
341
  var _this = this;
413
342
  // Store tbody class
414
343
  if (this._tbodyElement) {
415
- this._originalTbodyClass = this._tbodyElement.className || '';
344
+ this._originalClasses.tbody = this._tbodyElement.className || '';
416
345
  }
417
346
  // Store thead class and th classes
418
347
  if (this._theadElement) {
419
- this._originalTheadClass = this._theadElement.className || '';
348
+ this._originalClasses.thead = this._theadElement.className || '';
420
349
  // Store th classes
421
350
  var thElements = this._theadElement.querySelectorAll('th');
422
- this._originalThClasses = Array.from(thElements).map(function (th) { return th.className || ''; });
351
+ this._originalClasses.th = Array.from(thElements).map(function (th) { return th.className || ''; });
423
352
  }
424
353
  // Store tr and td classes
425
354
  if (this._tbodyElement) {
426
355
  var originalRows = this._tbodyElement.querySelectorAll('tr');
427
- this._originalTrClasses = Array.from(originalRows).map(function (row) { return row.className || ''; });
356
+ this._originalClasses.tr = Array.from(originalRows).map(function (row) { return row.className || ''; });
428
357
  // Store td classes as a 2D array
429
- this._originalTdClasses = [];
358
+ this._originalClasses.td = [];
430
359
  Array.from(originalRows).forEach(function (row, rowIndex) {
431
360
  var tdElements = row.querySelectorAll('td');
432
- _this._originalTdClasses[rowIndex] = Array.from(tdElements).map(function (td) { return td.className || ''; });
361
+ _this._originalClasses.td[rowIndex] = Array.from(tdElements).map(function (td) { return td.className || ''; });
433
362
  });
434
363
  }
435
364
  };
@@ -449,8 +378,7 @@ var KTDataTable = /** @class */ (function (_super) {
449
378
  _b.label = 1;
450
379
  case 1:
451
380
  _b.trys.push([1, , 8, 9]);
452
- this._showSpinner(); // Show spinner before fetching data
453
- this._emit('fetch');
381
+ this._spinner.show(this._element, this._config, this._tableElement); // Show spinner before fetching data
454
382
  if (!(typeof this._config.apiEndpoint === 'undefined')) return [3 /*break*/, 2];
455
383
  _a = this._localProvider.fetchSync();
456
384
  return [3 /*break*/, 4];
@@ -466,11 +394,11 @@ var KTDataTable = /** @class */ (function (_super) {
466
394
  return [4 /*yield*/, this._draw()];
467
395
  case 5:
468
396
  _b.sent();
469
- this._emit('fetched');
470
397
  _b.label = 6;
471
398
  case 6: return [4 /*yield*/, this._finalize()];
472
399
  case 7:
473
400
  _b.sent();
401
+ this._emit('update');
474
402
  return [3 /*break*/, 9];
475
403
  case 8:
476
404
  // Finally block now correctly executes after promises resolve, not immediately
@@ -486,7 +414,8 @@ var KTDataTable = /** @class */ (function (_super) {
486
414
  * @returns {void}
487
415
  */
488
416
  KTDataTable.prototype._finalize = function () {
489
- var _a;
417
+ var _this = this;
418
+ var _a, _b, _c;
490
419
  (_a = this._element) === null || _a === void 0 ? void 0 : _a.classList.add('datatable-initialized');
491
420
  // Initialize checkbox logic
492
421
  this._checkbox.init();
@@ -494,50 +423,20 @@ var KTDataTable = /** @class */ (function (_super) {
494
423
  if (this._sortHandler) {
495
424
  this._sortHandler.initSort();
496
425
  }
497
- this._attachSearchEvent();
498
- if (typeof KTComponents !== 'undefined') {
499
- KTComponents.init();
500
- }
426
+ 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 : DEFAULT_SEARCH_DELAY, function (query) { return _this.search(query); });
501
427
  /**
502
428
  * Hide spinner
503
429
  */
504
- this._hideSpinner();
505
- };
506
- /**
507
- * Attach search event to the search input element
508
- * @returns {void}
509
- */
510
- KTDataTable.prototype._attachSearchEvent = function () {
511
- var _this = this;
512
- var _a, _b;
513
- var tableId = this._tableId();
514
- var searchElement = document.querySelector("[data-kt-datatable-search=\"#".concat(tableId, "\"]"));
515
- // Get search state
516
- var search = this.getState().search;
517
- // Set search value
518
- if (searchElement) {
519
- searchElement.value =
520
- search === undefined || search === null
521
- ? ''
522
- : typeof search === 'string'
523
- ? search
524
- : String(search);
525
- }
526
- if (searchElement) {
527
- // Check if a debounced search function already exists
528
- var searchWithDebounce = KTDataTable.asSearchElementWithDebounce(searchElement);
529
- if (searchWithDebounce._debouncedSearch) {
530
- // Remove the existing debounced event listener
531
- searchElement.removeEventListener('keyup', searchWithDebounce._debouncedSearch);
532
- }
533
- // Create a new debounced search function
534
- var debouncedSearch = this._debounce(function () {
535
- _this.search(searchElement.value);
536
- }, (_b = (_a = this._config.search) === null || _a === void 0 ? void 0 : _a.delay) !== null && _b !== void 0 ? _b : 500);
537
- // Store the new debounced function as a property of the element
538
- searchWithDebounce._debouncedSearch = debouncedSearch;
539
- // Add the new debounced event listener
540
- searchElement.addEventListener('keyup', debouncedSearch);
430
+ this._spinner.hide(this._element, this._config);
431
+ // Update content checksum AFTER all DOM modifications (checkbox init
432
+ // adds checked-class to <tr> elements which changes tbody innerHTML).
433
+ // If we save the checksum earlier (in _draw), the next fetchSync()
434
+ // sees a mismatch, re-extracts from the DOM, and loses rows that
435
+ // were on other pages — making pagination show empty.
436
+ if (!this._config.apiEndpoint) {
437
+ this._stateStore.patchState({
438
+ _contentChecksum: KTUtils.checksum(JSON.stringify(this._tbodyElement.innerHTML)),
439
+ });
541
440
  }
542
441
  };
543
442
  /**
@@ -546,17 +445,7 @@ var KTDataTable = /** @class */ (function (_super) {
546
445
  * @returns {number} Number of data columns, or 0 if unknown
547
446
  */
548
447
  KTDataTable.prototype._getLogicalColumnCount = function () {
549
- var originalData = this.getState().originalData;
550
- if (originalData && originalData.length > 0) {
551
- return Object.keys(originalData[0]).length;
552
- }
553
- if (this._tbodyElement) {
554
- var firstRow = this._tbodyElement.querySelector('tr');
555
- if (firstRow) {
556
- return firstRow.querySelectorAll('td').length;
557
- }
558
- }
559
- return 0;
448
+ return getLogicalColumnCount(this._theadElement, this._tbodyElement, this.getState().originalData);
560
449
  };
561
450
  /**
562
451
  * Creates a complete URL from a relative path or a full URL.
@@ -625,12 +514,17 @@ var KTDataTable = /** @class */ (function (_super) {
625
514
  */
626
515
  KTDataTable.prototype._draw = function () {
627
516
  return __awaiter(this, void 0, void 0, function () {
628
- return __generator(this, function (_a) {
629
- this._stateStore.patchState({
630
- totalPages: Math.ceil(this.getState().totalItems / this.getState().pageSize) || 0,
631
- });
632
- this._emit('draw');
633
- this._dispose();
517
+ var normalizedPageSize, totalPages, page;
518
+ var _a, _b, _c, _d;
519
+ return __generator(this, function (_e) {
520
+ normalizedPageSize = Math.max(1, Number(this.getState().pageSize) || Number(this._config.pageSize) || 1);
521
+ totalPages = Math.ceil(this.getState().totalItems / normalizedPageSize) || 0;
522
+ page = totalPages > 0
523
+ ? Math.min(Math.max(1, this.getState().page), totalPages)
524
+ : 1;
525
+ this._stateStore.patchState({ totalPages: totalPages, page: page });
526
+ (_b = (_a = this._layoutPlugin) === null || _a === void 0 ? void 0 : _a.beforeDraw) === null || _b === void 0 ? void 0 : _b.call(_a, this._getLayoutPluginContext());
527
+ this._cleanupForRedraw();
634
528
  // Update the table and pagination controls
635
529
  if (this._theadElement && this._tbodyElement) {
636
530
  this._updateTable();
@@ -638,7 +532,7 @@ var KTDataTable = /** @class */ (function (_super) {
638
532
  if (this._infoElement || this._sizeElement || this._paginationElement) {
639
533
  this._updatePagination();
640
534
  }
641
- this._emit('drew');
535
+ (_d = (_c = this._layoutPlugin) === null || _c === void 0 ? void 0 : _c.afterDraw) === null || _d === void 0 ? void 0 : _d.call(_c, this._getLayoutPluginContext());
642
536
  // Spinner is hidden in _finalize() to ensure it stays visible until the entire request completes
643
537
  // Removed duplicate _hideSpinner() call here to prevent premature hiding
644
538
  if (this._config.stateSave) {
@@ -653,18 +547,17 @@ var KTDataTable = /** @class */ (function (_super) {
653
547
  * @returns {HTMLTableSectionElement} The new table body element
654
548
  */
655
549
  KTDataTable.prototype._updateTable = function () {
656
- return this._tableRenderer.render({
550
+ this._tbodyElement = this._tableRenderer.render({
657
551
  config: this._config,
658
552
  context: this,
659
553
  data: this._data,
660
554
  getLogicalColumnCount: this._getLogicalColumnCount.bind(this),
661
555
  getState: this.getState.bind(this),
662
- originalTbodyClass: this._originalTbodyClass,
663
- originalTrClasses: this._originalTrClasses,
664
- originalTdClasses: this._originalTdClasses,
556
+ originalClasses: this._originalClasses,
665
557
  tableElement: this._tableElement,
666
558
  theadElement: this._theadElement,
667
559
  });
560
+ return this._tbodyElement;
668
561
  };
669
562
  /**
670
563
  * Show a notice on the table
@@ -710,91 +603,31 @@ var KTDataTable = /** @class */ (function (_super) {
710
603
  if (page < 1 || !Number.isInteger(page)) {
711
604
  return;
712
605
  }
713
- this._emit('pagination', { page: page });
714
606
  if (page >= 1 && page <= this.getState().totalPages) {
715
607
  this._stateStore.setPage(page);
716
608
  this._updateData();
717
609
  }
718
610
  };
719
- // Method to show the loading spinner
720
- KTDataTable.prototype._showSpinner = function () {
721
- var _a, _b;
722
- var root = this._element;
723
- var spinnerSel = (_a = this._config.attributes) === null || _a === void 0 ? void 0 : _a.spinner;
724
- var fromDom = root && spinnerSel
725
- ? root.querySelector(spinnerSel)
726
- : null;
727
- var spinner = fromDom !== null && fromDom !== void 0 ? fromDom : this._createSpinner();
728
- if (spinner) {
729
- spinner.style.display = 'block';
730
- }
731
- root === null || root === void 0 ? void 0 : root.classList.add((_b = this._config.loadingClass) !== null && _b !== void 0 ? _b : 'loading');
732
- };
733
- // Method to hide the loading spinner
734
- KTDataTable.prototype._hideSpinner = function () {
735
- var _a, _b;
736
- var root = this._element;
737
- var spinnerSel = (_a = this._config.attributes) === null || _a === void 0 ? void 0 : _a.spinner;
738
- var spinner = root && spinnerSel
739
- ? root.querySelector(spinnerSel)
740
- : null;
741
- if (spinner) {
742
- spinner.style.display = 'none';
743
- }
744
- root === null || root === void 0 ? void 0 : root.classList.remove((_b = this._config.loadingClass) !== null && _b !== void 0 ? _b : 'loading');
745
- };
746
- // Method to create a spinner element if it doesn't exist
747
- KTDataTable.prototype._createSpinner = function () {
748
- var loading = this._config.loading;
749
- if (!loading) {
750
- return null;
751
- }
752
- var template = document.createElement('template');
753
- template.innerHTML = loading.template
754
- .trim()
755
- .replace('{content}', loading.content);
756
- var first = template.content.firstChild;
757
- if (!first || !(first instanceof HTMLElement)) {
758
- return null;
759
- }
760
- var spinner = first;
761
- spinner.setAttribute('data-kt-datatable-spinner', 'true');
762
- this._tableElement.appendChild(spinner);
763
- return spinner;
764
- };
765
611
  /**
766
612
  * Saves the current state of the table to local storage.
767
613
  * @returns {void}
768
614
  */
769
615
  KTDataTable.prototype._saveState = function () {
770
- this._emit('stateSave');
771
- var ns = this._tableNamespace();
772
- if (ns) {
773
- localStorage.setItem(ns, JSON.stringify(this.getState()));
774
- }
616
+ this._statePersistence.save(this._tableNamespace(), this.getState());
775
617
  };
776
618
  /**
777
619
  * Loads the saved state of the table from local storage, if it exists.
778
620
  * @returns {Object} The saved state of the table, or null if no saved state exists.
779
621
  */
780
622
  KTDataTable.prototype._loadState = function () {
781
- var stateString = localStorage.getItem(this._tableNamespace());
782
- if (!stateString)
783
- return null;
784
- try {
785
- var state = JSON.parse(stateString);
786
- if (state)
787
- this._stateStore.replaceState(state);
788
- return state;
789
- }
790
- catch (_a) { }
791
- return null;
623
+ var ns = this._tableNamespace();
624
+ var saved = this._statePersistence.load(ns);
625
+ if (saved)
626
+ this._stateStore.replaceState(saved);
627
+ return saved;
792
628
  };
793
629
  KTDataTable.prototype._deleteState = function () {
794
- var ns = this._tableNamespace();
795
- if (ns) {
796
- localStorage.removeItem(ns);
797
- }
630
+ this._statePersistence.remove(this._tableNamespace());
798
631
  };
799
632
  /**
800
633
  * Gets the namespace for the table's state.
@@ -805,13 +638,7 @@ var KTDataTable = /** @class */ (function (_super) {
805
638
  * @returns {string} The namespace for the table's state.
806
639
  */
807
640
  KTDataTable.prototype._tableNamespace = function () {
808
- var _a;
809
- // Use the specified namespace, if one is given
810
- if (this._config.stateNamespace) {
811
- return this._config.stateNamespace;
812
- }
813
- // Fallback to the component's UID
814
- return (_a = this._tableId()) !== null && _a !== void 0 ? _a : this._name;
641
+ return resolveTableNamespace(this._config, this._tableElement, this._element, this._name);
815
642
  };
816
643
  KTDataTable.prototype._tableId = function () {
817
644
  var _a, _b;
@@ -829,90 +656,43 @@ var KTDataTable = /** @class */ (function (_super) {
829
656
  * Clean up all event listeners, handlers, and DOM nodes created by this instance.
830
657
  * This method is called before re-rendering or when disposing the component.
831
658
  */
832
- KTDataTable.prototype._dispose = function () {
833
- var _a, _b, _c;
834
- var root = this._element;
835
- if (!root) {
659
+ /**
660
+ * Clean up event listeners and DOM artifacts for a redraw cycle.
661
+ * Does NOT remove the instance from the registry — the datatable
662
+ * remains accessible via getInstance() during the redraw window.
663
+ */
664
+ KTDataTable.prototype._cleanupForRedraw = function () {
665
+ var _a, _b;
666
+ (_b = (_a = this._layoutPlugin) === null || _a === void 0 ? void 0 : _a.dispose) === null || _b === void 0 ? void 0 : _b.call(_a, this._getLayoutPluginContext());
667
+ if (!this._element) {
836
668
  return;
837
669
  }
838
670
  this._cleanupCallbacks.forEach(function (cleanup) { return cleanup(); });
839
671
  this._cleanupCallbacks = [];
840
- // --- 1. Remove search input event listener (debounced) ---
841
- var tableId = this._tableId();
842
- var searchElement = document.querySelector("[data-kt-datatable-search=\"#".concat(tableId, "\"]"));
843
- if (searchElement) {
844
- var searchWithDebounce = KTDataTable.asSearchElementWithDebounce(searchElement);
845
- if (searchWithDebounce._debouncedSearch) {
846
- searchElement.removeEventListener('keyup', searchWithDebounce._debouncedSearch);
847
- delete searchWithDebounce._debouncedSearch;
848
- }
849
- }
850
- // --- 2. Remove page size dropdown event listener ---
672
+ this._searchHandler.detach(this._tableId());
851
673
  if (this._sizeElement && this._sizeElement.onchange) {
852
674
  this._sizeElement.onchange = null;
853
675
  }
854
- // --- 3. Remove all pagination button event listeners ---
855
676
  if (this._paginationElement) {
856
- // Remove all child nodes (buttons) to ensure no lingering listeners
857
677
  while (this._paginationElement.firstChild) {
858
678
  this._paginationElement.removeChild(this._paginationElement.firstChild);
859
679
  }
860
680
  }
861
- // --- 4. Dispose of handler objects (checkbox, sort) ---
862
- // KTDataTableCheckboxAPI does not have a dispose method, but we can remove header checkbox listener
863
- var checkboxWithDispose = this._checkbox;
864
- if (this._checkbox && typeof checkboxWithDispose.dispose === 'function') {
865
- checkboxWithDispose.dispose();
866
- }
867
- else {
868
- var checkSel = (_a = this._config.attributes) === null || _a === void 0 ? void 0 : _a.check;
869
- if (checkSel) {
870
- var headerCheckElement = root.querySelector(checkSel);
871
- if (headerCheckElement) {
872
- headerCheckElement.replaceWith(headerCheckElement.cloneNode(true));
873
- }
874
- }
875
- }
876
- // KTDataTableSortAPI does not have a dispose method, but we can remove th click listeners by replacing them
877
- if (this._theadElement) {
878
- var ths = this._theadElement.querySelectorAll('th');
879
- ths.forEach(function (th) {
880
- th.replaceWith(th.cloneNode(true));
881
- });
882
- }
883
- // --- 5. Remove spinner DOM node if it exists ---
884
- var spinnerSel = (_b = this._config.attributes) === null || _b === void 0 ? void 0 : _b.spinner;
885
- if (spinnerSel) {
886
- var spinner = root.querySelector(spinnerSel);
887
- if (spinner === null || spinner === void 0 ? void 0 : spinner.parentNode) {
888
- spinner.parentNode.removeChild(spinner);
889
- }
890
- }
891
- root.classList.remove((_c = this._config.loadingClass) !== null && _c !== void 0 ? _c : 'loading');
892
- // --- 6. Remove instance reference from the DOM element ---
893
- var elementWithInstance = KTDataTable.asElementWithInstance(root);
894
- if (elementWithInstance.instance) {
895
- delete elementWithInstance.instance;
896
- }
897
- KTData.remove(root, this._name);
898
- // --- 7. (Optional) Clear localStorage state ---
899
- // Uncomment the following line if you want to clear state on dispose:
900
- // this._deleteState();
681
+ this._checkbox.dispose();
682
+ this._sortHandler.dispose();
683
+ this._spinner.remove(this._element, this._config);
901
684
  };
902
- KTDataTable.prototype._debounce = function (func, wait) {
903
- var timeout;
904
- return function () {
905
- var args = [];
906
- for (var _i = 0; _i < arguments.length; _i++) {
907
- args[_i] = arguments[_i];
908
- }
909
- var later = function () {
910
- clearTimeout(timeout);
911
- func.apply(void 0, args);
912
- };
913
- clearTimeout(timeout);
914
- timeout = window.setTimeout(later, wait);
915
- };
685
+ /**
686
+ * Full disposal — cleans up listeners AND removes the instance from
687
+ * the registry. Only called when the component is being destroyed.
688
+ */
689
+ KTDataTable.prototype._dispose = function () {
690
+ this._cleanupForRedraw();
691
+ var root = this._element;
692
+ if (root) {
693
+ datatableRegistry.remove(root);
694
+ KTData.remove(root, this._name);
695
+ }
916
696
  };
917
697
  /**
918
698
  * Gets the current state of the table.
@@ -923,12 +703,14 @@ var KTDataTable = /** @class */ (function (_super) {
923
703
  };
924
704
  /**
925
705
  * Sorts the data in the table by the specified field.
706
+ * When `order` is provided, applies that sort direction instead of toggling.
926
707
  * @param field The field to sort by.
708
+ * @param order Optional sort direction (`asc`, `desc`, or `''` to clear).
927
709
  */
928
- KTDataTable.prototype.sort = function (field) {
929
- // Use the sort handler to update state and trigger sorting
930
- var state = this.getState();
931
- var sortOrder = this._sortHandler.toggleSortOrder(state.sortField, state.sortOrder, field);
710
+ KTDataTable.prototype.sort = function (field, order) {
711
+ var sortOrder = order !== undefined
712
+ ? order
713
+ : this._sortHandler.toggleSortOrder(this.getState().sortField, this.getState().sortOrder, field);
932
714
  this._sortHandler.setSortIcon(field, sortOrder);
933
715
  this._stateStore.setSort(field, sortOrder);
934
716
  this._emit('sort', { field: field, order: sortOrder });
@@ -960,36 +742,28 @@ var KTDataTable = /** @class */ (function (_super) {
960
742
  this._reloadPageSize(pageSize);
961
743
  };
962
744
  /**
963
- * Reloads the data from the server and updates the table.
964
- * Triggers the 'reload' event and the 'kt.datatable.reload' custom event.
745
+ * Reloads the data from the source (API or DOM) and redraws the table.
746
+ * @returns {Promise<void>}
965
747
  */
966
748
  KTDataTable.prototype.reload = function () {
967
- this._emit('reload');
968
749
  // Fetch the data from the server using the current sort and filter settings
969
750
  this._updateData();
970
751
  };
971
752
  KTDataTable.prototype.redraw = function (page) {
972
753
  if (page === void 0) { page = 1; }
973
- this._emit('redraw');
974
754
  this._paginateData(page);
975
755
  };
976
756
  /**
977
757
  * Show the loading spinner of the data table.
978
758
  */
979
759
  KTDataTable.prototype.showSpinner = function () {
980
- /**
981
- * Show the loading spinner of the data table.
982
- */
983
- this._showSpinner();
760
+ this._spinner.show(this._element, this._config, this._tableElement);
984
761
  };
985
762
  /**
986
763
  * Hide the loading spinner of the data table.
987
764
  */
988
765
  KTDataTable.prototype.hideSpinner = function () {
989
- /**
990
- * Hide the loading spinner of the data table.
991
- */
992
- this._hideSpinner();
766
+ this._spinner.hide(this._element, this._config);
993
767
  };
994
768
  /**
995
769
  * Filter data using the specified filter object.
@@ -1016,21 +790,7 @@ var KTDataTable = /** @class */ (function (_super) {
1016
790
  * This function is now browser-guarded and must be called explicitly.
1017
791
  */
1018
792
  KTDataTable.createInstances = function () {
1019
- var _this = this;
1020
- if (typeof document === 'undefined')
1021
- return;
1022
- var elements = document.querySelectorAll('[data-kt-datatable="true"]');
1023
- elements.forEach(function (element) {
1024
- if (element.hasAttribute('data-kt-datatable') &&
1025
- !element.classList.contains('datatable-initialized')) {
1026
- /**
1027
- * Create an instance of KTDataTable for the given element
1028
- * @param element The element to create an instance for
1029
- */
1030
- var instance = new KTDataTable(element);
1031
- _this._instances.set(element, instance);
1032
- }
1033
- });
793
+ datatableRegistry.createAll(function (el) { return new KTDataTable(el); });
1034
794
  };
1035
795
  /**
1036
796
  * Get the KTDataTable instance for a given element.
@@ -1039,21 +799,13 @@ var KTDataTable = /** @class */ (function (_super) {
1039
799
  * @returns The KTDataTable instance or undefined if not found
1040
800
  */
1041
801
  KTDataTable.getInstance = function (element) {
1042
- // First check the static Map (for instances created via createInstances)
1043
- var instanceFromMap = this._instances.get(element);
1044
- if (instanceFromMap) {
1045
- return instanceFromMap;
1046
- }
1047
- // Fallback to element's instance property (for manually created instances)
1048
- return KTDataTable.asElementWithInstance(element).instance;
802
+ return datatableRegistry.get(element);
1049
803
  };
1050
804
  /**
1051
805
  * Initializes all KTDataTable instances on the page.
1052
806
  * This function is now browser-guarded and must be called explicitly.
1053
807
  */
1054
808
  KTDataTable.init = function () {
1055
- if (typeof document === 'undefined')
1056
- return;
1057
809
  KTDataTable.createInstances();
1058
810
  };
1059
811
  /**
@@ -1061,25 +813,7 @@ var KTDataTable = /** @class */ (function (_super) {
1061
813
  * Useful for Livewire wire:navigate where the DOM is replaced and new tables need to be initialized.
1062
814
  */
1063
815
  KTDataTable.reinit = function () {
1064
- if (typeof document === 'undefined')
1065
- return;
1066
- var elements = document.querySelectorAll('[data-kt-datatable="true"]');
1067
- elements.forEach(function (element) {
1068
- try {
1069
- var instance = KTDataTable.getInstance(element);
1070
- if (instance && typeof instance.dispose === 'function') {
1071
- instance.dispose();
1072
- }
1073
- KTData.remove(element, 'datatable');
1074
- element.removeAttribute('data-kt-datatable-initialized');
1075
- element.classList.remove('datatable-initialized');
1076
- }
1077
- catch (_a) {
1078
- // ignore per-element errors
1079
- }
1080
- });
1081
- KTDataTable._instances.clear();
1082
- KTDataTable.createInstances();
816
+ datatableRegistry.reinit(function (el) { return new KTDataTable(el); });
1083
817
  };
1084
818
  /**
1085
819
  * Check if all visible rows are checked (header checkbox state)
@@ -1119,16 +853,18 @@ var KTDataTable = /** @class */ (function (_super) {
1119
853
  return this._checkbox.getChecked();
1120
854
  };
1121
855
  /**
1122
- * Reapply checked state to visible checkboxes (after redraw/pagination)
856
+ * Re-apply checkbox checked states to visible rows after a redraw or pagination change.
1123
857
  * @returns {void}
1124
858
  */
1125
- KTDataTable.prototype.update = function () {
859
+ KTDataTable.prototype.refreshCheckboxes = function () {
1126
860
  this._checkbox.updateState();
1127
861
  };
1128
862
  /**
1129
- * Static variables
863
+ * @deprecated Use {@link refreshCheckboxes} instead.
1130
864
  */
1131
- KTDataTable._instances = new Map();
865
+ KTDataTable.prototype.update = function () {
866
+ this.refreshCheckboxes();
867
+ };
1132
868
  return KTDataTable;
1133
869
  }(KTComponent));
1134
870
  export { KTDataTable };