@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
@@ -0,0 +1,302 @@
1
+ ---
2
+ name: ktui-datatable
3
+ description: >
4
+ KtUI DataTable (KTDataTable) — local/remote data, sorting, filtering, pagination,
5
+ checkbox selection, state persistence, fixed layouts, event system, and architecture.
6
+ Use this skill when building, debugging, or customizing DataTable components.
7
+ ---
8
+
9
+ # KTDataTable — AI Agent Reference
10
+
11
+ Full reference for the DataTable component in [KtUI](https://ktui.io).
12
+ Package: `@keenthemes/ktui`. Class: `KTDataTable`. Root attribute: `data-kt-datatable`.
13
+
14
+ > **Always prefer [ktui.io/docs/datatable](https://ktui.io/docs/datatable) docs and examples over guessing markup or options.**
15
+
16
+ ---
17
+
18
+ ## 1. Basic Usage
19
+
20
+ ```html
21
+ <div data-kt-datatable="true">
22
+ <table>
23
+ <thead>
24
+ <tr>
25
+ <th data-kt-datatable-column="name">Name</th>
26
+ <th data-kt-datatable-column="email">Email</th>
27
+ </tr>
28
+ </thead>
29
+ <tbody></tbody>
30
+ </table>
31
+ </div>
32
+ ```
33
+
34
+ ```ts
35
+ import { KTDataTable } from '@keenthemes/ktui';
36
+
37
+ const dt = KTDataTable.getInstance(tableEl);
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 2. Config Options
43
+
44
+ | Option | Type | Description |
45
+ |--------|------|-------------|
46
+ | `apiEndpoint` | string | Remote data URL |
47
+ | `requestMethod` | string | HTTP method (default `'POST'`) |
48
+ | `requestHeaders` | object | Custom headers |
49
+ | `mapResponse` | function | Transform API response |
50
+ | `mapRequest` | function | Transform request params |
51
+ | `pageSize` | number | Rows per page |
52
+ | `pageSizes` | number[] | Page size options |
53
+ | `stateSave` | boolean | Persist state in localStorage |
54
+ | `columns` | object | Column config (render, checkbox, sortType, sortValue, createdCell) |
55
+ | `sort` | object | Sort config with classes and callback |
56
+ | `search` | object | Search config with delay and callback |
57
+ | `pagination` | object | Pagination markup config |
58
+ | `loading` | object | Spinner template |
59
+ | `checkbox` | object | Row checkbox config (checkedClass, preserveSelection) |
60
+ | `lockedLayout` | object | Sticky headers/columns |
61
+ | `tableLayout` | string | `'fixed'` for fixed column widths (use with `<colgroup>`) |
62
+ | `filter` | object | Column filter config (type, value) |
63
+ | `infoEmpty` | string | Empty state HTML (supports innerHTML) |
64
+
65
+ ---
66
+
67
+ ## 3. Programmatic API
68
+
69
+ ```ts
70
+ const dt = KTDataTable.getInstance(tableEl);
71
+
72
+ dt.sort('name');
73
+ dt.sort('name', 'desc'); // explicit sort order
74
+ dt.goPage(2);
75
+ dt.setPageSize(25);
76
+ dt.search('query');
77
+ dt.setFilter({ column: 'status', type: 'text', value: 'active' });
78
+ dt.reload(); // re-fetch from API
79
+ dt.redraw(); // re-render current data
80
+ dt.getState(); // { page, sortField, sortOrder, pageSize, ... }
81
+ dt.check(value); // check a row by value
82
+ dt.uncheck(value); // uncheck a row by value
83
+ dt.getChecked(); // get array of checked row values
84
+ dt.dispose();
85
+ ```
86
+
87
+ ### Instance management
88
+
89
+ | Static method | Returns |
90
+ |--------------|---------|
91
+ | `KTDataTable.getInstance(el)` | Existing instance or `null` |
92
+ | `KTDataTable.getOrCreateInstance(el, config?)` | Existing or new instance |
93
+ | `KTDataTable.init()` | Scans DOM, creates instances |
94
+
95
+ ---
96
+
97
+ ## 4. Column Config
98
+
99
+ ```ts
100
+ columns: {
101
+ name: {
102
+ title: 'Full Name',
103
+ render: (item, data, ctx) => `<strong>${item}</strong>`,
104
+ sortType: 'string', // or 'numeric'
105
+ sortValue: (cellValue, rowData) => rowData.firstName + ' ' + rowData.lastName,
106
+ createdCell: (cell, cellData, rowData, row) => {
107
+ cell.classList.add('text-primary');
108
+ },
109
+ },
110
+ actions: {
111
+ checkbox: true,
112
+ },
113
+ }
114
+ ```
115
+
116
+ ---
117
+
118
+ ## 5. Remote Data Provider
119
+
120
+ ### Response shape
121
+
122
+ ```ts
123
+ interface KTDataTableResponseDataInterface {
124
+ data: KTDataTableDataInterface[];
125
+ totalCount: number;
126
+ }
127
+ ```
128
+
129
+ ### Config
130
+
131
+ ```ts
132
+ {
133
+ apiEndpoint: 'https://api.example.com/users',
134
+ requestMethod: 'POST',
135
+ requestHeaders: { 'Authorization': 'Bearer ...' },
136
+ mapResponse: (response) => ({ data: response.items, totalCount: response.total }),
137
+ mapRequest: (params) => ({ ...params, page: params.page + 1 }),
138
+ }
139
+ ```
140
+
141
+ ---
142
+
143
+ ## 6. Fixed Column Widths
144
+
145
+ Use `tableLayout: 'fixed'` with `<colgroup>` for consistent column widths across pages:
146
+
147
+ ```html
148
+ <table data-kt-datatable-table="true" style="table-layout: fixed; width: 100%;">
149
+ <colgroup>
150
+ <col style="width: 40px"> <!-- checkbox -->
151
+ <col style="width: 70px"> <!-- ID -->
152
+ <col> <!-- Name (auto-fill) -->
153
+ <col style="width: 120px"> <!-- Status -->
154
+ </colgroup>
155
+ </table>
156
+ ```
157
+
158
+ ---
159
+
160
+ ## 7. Column Filters
161
+
162
+ Client-side filtering with `setFilter()`:
163
+
164
+ ```ts
165
+ dt.setFilter({ column: 'status', type: 'text', value: 'active' });
166
+ dt.setFilter({ column: 'price', type: 'numeric', value: { min: 10, max: 100 } });
167
+ ```
168
+
169
+ Filter pipeline runs between search and sort.
170
+
171
+ ---
172
+
173
+ ## 8. Empty State
174
+
175
+ **Default:** When `data.length === 0`, renders a single row with `infoEmpty` text (default: `"No records found"`). Supports HTML.
176
+
177
+ **Custom via data attribute:**
178
+
179
+ ```html
180
+ <div data-kt-datatable="true"
181
+ data-kt-datatable-info-empty='<div class="py-10 text-center">No records found</div>'>
182
+ ```
183
+
184
+ **Pitfall — never hardcode empty state HTML in `<tbody>`:** The DataTable reads tbody rows as "data" on init. Hardcoded content gets treated as 1 row and disappears on re-render. Always use `data-kt-datatable-info-empty` or the JS `infoEmpty` config.
185
+
186
+ ---
187
+
188
+ ## 9. Event System
189
+
190
+ All events dispatch through dual channel:
191
+ 1. **Internal callbacks** (`.on()`) — bare name
192
+ 2. **DOM CustomEvents** (`addEventListener`) — namespaced as `kt.datatable.<event>`
193
+
194
+ | Event | Payload | When |
195
+ |-------|---------|------|
196
+ | `update` | — | Data changed. Call `getState()` for details. |
197
+ | `sort` | `{ field, order }` | Column header click |
198
+ | `change` | `{ cancel }` | Before checkbox toggle (cancelable) |
199
+ | `changed` | — | After checkbox change. Call `getChecked()`. |
200
+ | `checked` | `{ value }` | Row checked |
201
+ | `unchecked` | `{ value }` | Row unchecked |
202
+ | `fetchError` | `{ response, error, status, statusText }` | Remote JSON parse failure |
203
+ | `error` | `{ error }` | Network fetch failure |
204
+
205
+ ```ts
206
+ // Internal callback
207
+ dt.on('sort', (payload) => { console.log(payload.field); });
208
+
209
+ // DOM CustomEvent
210
+ el.addEventListener('kt.datatable.sort', (e) => {
211
+ console.log(e.detail.payload.field);
212
+ });
213
+ ```
214
+
215
+ ---
216
+
217
+ ## 10. Architecture
218
+
219
+ Source: `src/components/datatable/`
220
+
221
+ | File | Purpose |
222
+ |------|---------|
223
+ | `datatable.ts` | Main class — constructor, `_updateData()`, `_draw()`, `_finalize()`, `_dispose()` |
224
+ | `datatable-local-provider.ts` | Local mode data fetch with checksum-based DOM invalidation |
225
+ | `datatable-remote-provider.ts` | Remote API mode with AbortController |
226
+ | `datatable-state-store.ts` | State management — `patchState()`, `setPage()`, `setSort()` |
227
+ | `datatable-checkbox.ts` | Checkbox handler — header check, row check, `reapplyCheckedStates()` |
228
+ | `datatable-table-renderer.ts` | Renders data rows into `<tbody>` |
229
+ | `datatable-pagination-renderer.ts` | Renders pagination buttons, page size selector |
230
+ | `datatable-sort.ts` | Column sort handler with AbortController-based cleanup |
231
+ | `datatable-defaults.ts` | `DATATABLE_DEFAULTS` — static config constants |
232
+ | `datatable-utils.ts` | Shared `stripHtml()` utility |
233
+ | `datatable-search-handler.ts` | Debounced search input handler |
234
+ | `datatable-state-persistence.ts` | localStorage save/load with try/catch guards |
235
+ | `datatable-registry.ts` | Instance Map + DOM fallback |
236
+ | `datatable-layout-plugin.ts` | Sticky header/locked columns plugin |
237
+ | `datatable-spinner.ts` | Loading spinner show/hide |
238
+ | `datatable-contracts.ts` | Interfaces and type contracts |
239
+ | `datatable-column-utils.ts` | Column resolution utilities |
240
+ | `types.ts` | Type definitions (config, state, data interfaces) |
241
+ | `index.ts` | Barrel exports |
242
+
243
+ ### Lifecycle (Critical)
244
+
245
+ Every data update follows this sequence:
246
+
247
+ ```
248
+ _updateData()
249
+ ├── fetchSync() or fetch() ← reads from DOM or API
250
+ ├── _draw()
251
+ │ ├── _cleanupForRedraw() ← cleans listeners + DOM artifacts (NOT registry)
252
+ │ ├── _updateTable() ← re-renders tbody rows
253
+ │ ├── _updatePagination() ← re-renders pagination buttons
254
+ │ ├── afterDraw layoutPlugin hook
255
+ │ └── _saveState() ← persists to localStorage
256
+ ├── _finalize()
257
+ │ ├── _checkbox.init() ← re-queries DOM, calls reapplyCheckedStates()
258
+ │ ├── _sortHandler.initSort()
259
+ │ ├── searchHandler.attach()
260
+ │ ├── KTComponents.init()
261
+ │ ├── spinner.hide()
262
+ │ └── update _contentChecksum ← MUST be last (after DOM modifications)
263
+ └── emit 'update'
264
+ ```
265
+
266
+ **ORDER MATTERS.** `_finalize()` modifies the DOM. Any checksum saved before `_finalize()` will be stale.
267
+
268
+ ---
269
+
270
+ ## 11. Pitfalls
271
+
272
+ | Problem | Cause | Fix |
273
+ |---------|-------|-----|
274
+ | Empty pagination after checkbox select | `_contentChecksum` saved before `_finalize()` | Save checksum at END of `_finalize()` |
275
+ | Corrupted localStorage persists | State shrank `originalData` to current page | `localStorage.removeItem('kt_datatable_<id>')` |
276
+ | Sort listener leak | `cloneNode(true)` destroys th attrs | Uses AbortController pattern internally |
277
+ | Filter stored but never applied | `setFilter()` writes to state but `fetchSync()` ignores it | Filter pipeline runs between search and sort |
278
+ | Hardcoded empty state in `<tbody>` | DataTable reads tbody rows as "data" on init | Use `data-kt-datatable-info-empty` attribute instead |
279
+ | Column widths shift on pagination | `table-layout: auto` recalculates per page | Use `table-layout: fixed` with `<colgroup>` |
280
+ | Checkbox events invisible to `addEventListener` | Was only internal callbacks | Now dispatches as `kt.datatable.*` CustomEvents |
281
+ | Parallel refactoring on shared repo fails | Tight coupling between files | Execute sequentially on single branch |
282
+
283
+ ---
284
+
285
+ ## 12. Build & Testing
286
+
287
+ ```bash
288
+ cd ~/Sites/keenthemes/ktui/ktui
289
+ npx vitest run src/components/datatable # all pass
290
+ npx tsc --noEmit # typecheck
291
+ npm run build:webpack # full bundle
292
+ npm run build:lib # ESM + CJS library builds
293
+ ```
294
+
295
+ **Do NOT edit `lib/esm/` or `lib/cjs/` directly** — they're generated from `npm run build:lib`.
296
+
297
+ ---
298
+
299
+ ## 13. Documentation
300
+
301
+ - **DataTable docs:** [ktui.io/docs/datatable](https://ktui.io/docs/datatable)
302
+ - **Changelog:** [ktui.io/docs/changelog](https://ktui.io/docs/changelog)
@@ -0,0 +1,150 @@
1
+ ---
2
+ name: ktui-install
3
+ description: >
4
+ Install, configure, and initialize KtUI (Keenthemes Tailwind UI) in any project.
5
+ Use this skill when setting up KtUI for the first time, adding it to a new project,
6
+ configuring Tailwind for KtUI, or troubleshooting initialization issues.
7
+ ---
8
+
9
+ # KtUI Installation & Setup
10
+
11
+ ## 1. Install the package
12
+
13
+ ```bash
14
+ npm install @keenthemes/ktui
15
+ ```
16
+
17
+ ## 2. Tailwind CSS config
18
+
19
+ Add KtUI source paths to your Tailwind content array so Tailwind scans KtUI classes:
20
+
21
+ ```js
22
+ // tailwind.config.js
23
+ module.exports = {
24
+ content: [
25
+ './node_modules/@keenthemes/ktui/src/**/*.{ts,js}',
26
+ // your app files...
27
+ ],
28
+ };
29
+ ```
30
+
31
+ ## 3. Import styles
32
+
33
+ Import KtUI's built-in CSS (or use your own build of the source):
34
+
35
+ ```ts
36
+ import '@keenthemes/ktui/dist/styles.css';
37
+ ```
38
+
39
+ ## 4. Import and initialize components
40
+
41
+ ```ts
42
+ import { KTComponents } from '@keenthemes/ktui';
43
+
44
+ // Call once after DOM is ready
45
+ KTComponents.init();
46
+ ```
47
+
48
+ ### Per-framework placement
49
+
50
+ | Framework | Where to call `KTComponents.init()` |
51
+ |-----------|--------------------------------------|
52
+ | Vanilla JS | `DOMContentLoaded` listener or `<script>` at bottom of `<body>` |
53
+ | React | `useEffect(() => { KTComponents.init(); }, [])` |
54
+ | Vue 3 | `onMounted(() => { KTComponents.init(); })` |
55
+ | Next.js | Inside a client component's `useEffect` (never during SSR) |
56
+ | Nuxt | Inside `onMounted` or a client-only plugin |
57
+ | Laravel Livewire | Automatic — `livewire:navigate` triggers re-init |
58
+
59
+ ### SSR safety
60
+
61
+ Never call `init()` during server-side rendering. Guard with:
62
+
63
+ ```ts
64
+ if (typeof window !== 'undefined') {
65
+ KTComponents.init();
66
+ }
67
+ ```
68
+
69
+ ### Dynamic content (SPAs, lazy-loaded views)
70
+
71
+ After injecting new KtUI markup (route change, AJAX-loaded modal, etc.), re-initialize:
72
+
73
+ ```ts
74
+ // Re-init everything (safe — existing instances are skipped)
75
+ KTComponents.init();
76
+
77
+ // Or per-component
78
+ import { KTModal } from '@keenthemes/ktui';
79
+ KTModal.init();
80
+ ```
81
+
82
+ ## 5. TypeScript types
83
+
84
+ All config and interface types are exported from the package root — no deep paths:
85
+
86
+ ```ts
87
+ import type {
88
+ KTModalConfigInterface,
89
+ KTDataTableConfigInterface,
90
+ KTDropdownConfigInterface,
91
+ KTSelectConfigInterface,
92
+ KTToastConfigInterface,
93
+ // ... etc
94
+ } from '@keenthemes/ktui';
95
+ ```
96
+
97
+ ## 6. CSS variables (theming)
98
+
99
+ KtUI requires CSS custom variables defined on `:root`. At minimum:
100
+
101
+ ```css
102
+ :root {
103
+ --background: oklch(1 0 0);
104
+ --foreground: oklch(14.1% 0.005 285.823);
105
+ --primary: oklch(62.3% 0.214 259.815);
106
+ --primary-foreground: oklch(1 0 0);
107
+ --border: oklch(92% 0.004 264.531);
108
+ --radius: 0.5rem;
109
+ }
110
+ ```
111
+
112
+ See the `ktui` skill or [ktui.io/docs/theming](https://ktui.io/docs/theming) for the full variable list.
113
+
114
+ ## 7. Dark mode setup
115
+
116
+ Add the Tailwind dark variant:
117
+
118
+ ```css
119
+ @custom-variant dark (&:is(.dark *));
120
+ ```
121
+
122
+ Override the same CSS variables under `.dark`:
123
+
124
+ ```css
125
+ .dark {
126
+ --background: oklch(14.1% 0.005 285.823);
127
+ --foreground: oklch(98.5% 0 0);
128
+ --primary: oklch(70.7% 0.165 254.624);
129
+ --primary-foreground: oklch(14.1% 0.005 285.823);
130
+ }
131
+ ```
132
+
133
+ Toggle `.dark` on `<html>` or use the `KTThemeSwitch` component.
134
+
135
+ ## 8. Troubleshooting
136
+
137
+ | Problem | Cause | Fix |
138
+ |---------|-------|-----|
139
+ | Components not interactive | `init()` not called | Call `KTComponents.init()` after DOM ready |
140
+ | Tailwind classes not applied | Missing content path | Add `ktui/src/**` to Tailwind config |
141
+ | Styles look broken | CSS variables not defined | Define required variables on `:root` |
142
+ | SSR hydration mismatch | `init()` on server | Guard with `typeof window !== 'undefined'` |
143
+ | Re-init after navigation | SPA didn't re-init | Call `KTComponents.init()` after route change |
144
+
145
+ ## Documentation
146
+
147
+ - **Installation:** [ktui.io/docs/installation](https://ktui.io/docs/installation)
148
+ - **Theming:** [ktui.io/docs/theming](https://ktui.io/docs/theming)
149
+ - **Dark mode:** [ktui.io/docs/dark-mode](https://ktui.io/docs/dark-mode)
150
+ - **TypeScript:** [ktui.io/docs/typescript](https://ktui.io/docs/typescript)