@keenthemes/ktui 1.2.6 → 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.
- package/README.md +14 -5
- package/dist/ktui.js +3775 -2298
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +25 -5
- package/lib/cjs/components/datatable/datatable-checkbox.d.ts +37 -1
- package/lib/cjs/components/datatable/datatable-checkbox.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-checkbox.js +143 -156
- package/lib/cjs/components/datatable/datatable-checkbox.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-column-utils.d.ts +30 -0
- package/lib/cjs/components/datatable/datatable-column-utils.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-column-utils.js +42 -0
- package/lib/cjs/components/datatable/datatable-column-utils.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-contracts.d.ts +2 -4
- package/lib/cjs/components/datatable/datatable-contracts.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-defaults.d.ts +20 -0
- package/lib/cjs/components/datatable/datatable-defaults.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-defaults.js +193 -0
- package/lib/cjs/components/datatable/datatable-defaults.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-layout-plugin.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-layout-plugin.js +11 -1
- package/lib/cjs/components/datatable/datatable-layout-plugin.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-local-provider.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-local-provider.js +80 -24
- package/lib/cjs/components/datatable/datatable-local-provider.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-pagination-renderer.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-pagination-renderer.js +3 -2
- package/lib/cjs/components/datatable/datatable-pagination-renderer.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-registry.d.ts +18 -0
- package/lib/cjs/components/datatable/datatable-registry.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-registry.js +66 -0
- package/lib/cjs/components/datatable/datatable-registry.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-remote-provider.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-remote-provider.js +1 -2
- package/lib/cjs/components/datatable/datatable-remote-provider.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-search-handler.d.ts +10 -0
- package/lib/cjs/components/datatable/datatable-search-handler.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-search-handler.js +65 -0
- package/lib/cjs/components/datatable/datatable-search-handler.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-sort.d.ts +31 -4
- package/lib/cjs/components/datatable/datatable-sort.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-sort.js +86 -58
- package/lib/cjs/components/datatable/datatable-sort.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-spinner.d.ts +30 -0
- package/lib/cjs/components/datatable/datatable-spinner.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-spinner.js +54 -0
- package/lib/cjs/components/datatable/datatable-spinner.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-state-persistence.d.ts +19 -0
- package/lib/cjs/components/datatable/datatable-state-persistence.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-state-persistence.js +59 -0
- package/lib/cjs/components/datatable/datatable-state-persistence.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-table-renderer.d.ts +2 -0
- package/lib/cjs/components/datatable/datatable-table-renderer.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-table-renderer.js +75 -16
- package/lib/cjs/components/datatable/datatable-table-renderer.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-utils.d.ts +10 -0
- package/lib/cjs/components/datatable/datatable-utils.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-utils.js +15 -0
- package/lib/cjs/components/datatable/datatable-utils.js.map +1 -0
- package/lib/cjs/components/datatable/datatable.d.ts +26 -34
- package/lib/cjs/components/datatable/datatable.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable.js +155 -492
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/datatable/index.d.ts +1 -1
- package/lib/cjs/components/datatable/index.d.ts.map +1 -1
- package/lib/cjs/components/datatable/types.d.ts +100 -11
- package/lib/cjs/components/datatable/types.d.ts.map +1 -1
- package/lib/cjs/index.d.ts +1 -1
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +6 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.d.ts +37 -1
- package/lib/esm/components/datatable/datatable-checkbox.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.js +142 -155
- package/lib/esm/components/datatable/datatable-checkbox.js.map +1 -1
- package/lib/esm/components/datatable/datatable-column-utils.d.ts +30 -0
- package/lib/esm/components/datatable/datatable-column-utils.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-column-utils.js +38 -0
- package/lib/esm/components/datatable/datatable-column-utils.js.map +1 -0
- package/lib/esm/components/datatable/datatable-contracts.d.ts +2 -4
- package/lib/esm/components/datatable/datatable-contracts.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-defaults.d.ts +20 -0
- package/lib/esm/components/datatable/datatable-defaults.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-defaults.js +190 -0
- package/lib/esm/components/datatable/datatable-defaults.js.map +1 -0
- package/lib/esm/components/datatable/datatable-layout-plugin.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-layout-plugin.js +11 -1
- package/lib/esm/components/datatable/datatable-layout-plugin.js.map +1 -1
- package/lib/esm/components/datatable/datatable-local-provider.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-local-provider.js +80 -24
- package/lib/esm/components/datatable/datatable-local-provider.js.map +1 -1
- package/lib/esm/components/datatable/datatable-pagination-renderer.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-pagination-renderer.js +3 -2
- package/lib/esm/components/datatable/datatable-pagination-renderer.js.map +1 -1
- package/lib/esm/components/datatable/datatable-registry.d.ts +18 -0
- package/lib/esm/components/datatable/datatable-registry.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-registry.js +63 -0
- package/lib/esm/components/datatable/datatable-registry.js.map +1 -0
- package/lib/esm/components/datatable/datatable-remote-provider.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-remote-provider.js +1 -2
- package/lib/esm/components/datatable/datatable-remote-provider.js.map +1 -1
- package/lib/esm/components/datatable/datatable-search-handler.d.ts +10 -0
- package/lib/esm/components/datatable/datatable-search-handler.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-search-handler.js +62 -0
- package/lib/esm/components/datatable/datatable-search-handler.js.map +1 -0
- package/lib/esm/components/datatable/datatable-sort.d.ts +31 -4
- package/lib/esm/components/datatable/datatable-sort.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-sort.js +85 -57
- package/lib/esm/components/datatable/datatable-sort.js.map +1 -1
- package/lib/esm/components/datatable/datatable-spinner.d.ts +30 -0
- package/lib/esm/components/datatable/datatable-spinner.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-spinner.js +51 -0
- package/lib/esm/components/datatable/datatable-spinner.js.map +1 -0
- package/lib/esm/components/datatable/datatable-state-persistence.d.ts +19 -0
- package/lib/esm/components/datatable/datatable-state-persistence.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-state-persistence.js +55 -0
- package/lib/esm/components/datatable/datatable-state-persistence.js.map +1 -0
- package/lib/esm/components/datatable/datatable-table-renderer.d.ts +2 -0
- package/lib/esm/components/datatable/datatable-table-renderer.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-table-renderer.js +75 -16
- package/lib/esm/components/datatable/datatable-table-renderer.js.map +1 -1
- package/lib/esm/components/datatable/datatable-utils.d.ts +10 -0
- package/lib/esm/components/datatable/datatable-utils.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-utils.js +12 -0
- package/lib/esm/components/datatable/datatable-utils.js.map +1 -0
- package/lib/esm/components/datatable/datatable.d.ts +26 -34
- package/lib/esm/components/datatable/datatable.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable.js +157 -494
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/datatable/index.d.ts +1 -1
- package/lib/esm/components/datatable/index.d.ts.map +1 -1
- package/lib/esm/components/datatable/types.d.ts +100 -11
- package/lib/esm/components/datatable/types.d.ts.map +1 -1
- package/lib/esm/index.d.ts +1 -1
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +6 -0
- package/lib/esm/index.js.map +1 -1
- package/package.json +5 -1
- package/skills/ktui/SKILL.md +711 -0
- package/skills/ktui-datatable/SKILL.md +302 -0
- package/skills/ktui-install/SKILL.md +150 -0
- package/skills/ktui-select/SKILL.md +271 -0
- package/src/components/__tests__/component.test.ts +347 -0
- package/src/components/collapse/collapse.css +2 -2
- package/src/components/datatable/__tests__/architecture-boundaries.test.ts +56 -8
- package/src/components/datatable/__tests__/currency-sort.test.ts +25 -28
- package/src/components/datatable/__tests__/datatable-checkbox.test.ts +527 -0
- package/src/components/datatable/__tests__/datatable-column-utils.test.ts +117 -0
- package/src/components/datatable/__tests__/datatable-defaults.test.ts +57 -0
- package/src/components/datatable/__tests__/datatable-finalize-extended.test.ts +361 -0
- package/src/components/datatable/__tests__/datatable-fixed-layout.test.ts +427 -0
- package/src/components/datatable/__tests__/datatable-improvements.test.ts +484 -0
- package/src/components/datatable/__tests__/datatable-pagination-extended.test.ts +508 -0
- package/src/components/datatable/__tests__/datatable-public-api.test.ts +269 -0
- package/src/components/datatable/__tests__/datatable-registry.test.ts +172 -0
- package/src/components/datatable/__tests__/datatable-remote-provider.test.ts +468 -0
- package/src/components/datatable/__tests__/datatable-search-handler.test.ts +124 -0
- package/src/components/datatable/__tests__/datatable-sort-extended.test.ts +417 -0
- package/src/components/datatable/__tests__/datatable-spinner.test.ts +95 -0
- package/src/components/datatable/__tests__/datatable-table-renderer-extended.test.ts +425 -0
- package/src/components/datatable/__tests__/datatable-types.test.ts +117 -0
- package/src/components/datatable/__tests__/datatable-utils.test.ts +52 -0
- package/src/components/datatable/__tests__/multi-row-headers.test.ts +7 -7
- package/src/components/datatable/__tests__/pagination-reset.test.ts +129 -6
- package/src/components/datatable/__tests__/race-conditions.test.ts +11 -11
- package/src/components/datatable/__tests__/setup.ts +12 -4
- package/src/components/datatable/datatable-checkbox.ts +144 -145
- package/src/components/datatable/datatable-column-utils.ts +63 -0
- package/src/components/datatable/datatable-contracts.ts +2 -3
- package/src/components/datatable/datatable-defaults.ts +204 -0
- package/src/components/datatable/datatable-layout-plugin.ts +11 -1
- package/src/components/datatable/datatable-local-provider.ts +91 -28
- package/src/components/datatable/datatable-pagination-renderer.ts +3 -2
- package/src/components/datatable/datatable-registry.ts +89 -0
- package/src/components/datatable/datatable-remote-provider.ts +1 -3
- package/src/components/datatable/datatable-search-handler.ts +97 -0
- package/src/components/datatable/datatable-sort.ts +111 -66
- package/src/components/datatable/datatable-spinner.ts +103 -0
- package/src/components/datatable/datatable-state-persistence.ts +67 -0
- package/src/components/datatable/datatable-table-renderer.ts +81 -18
- package/src/components/datatable/datatable-utils.ts +12 -0
- package/src/components/datatable/datatable.ts +191 -580
- package/src/components/datatable/index.ts +3 -0
- package/src/components/datatable/types.ts +124 -23
- package/src/helpers/__tests__/dom.test.ts +776 -0
- package/src/helpers/__tests__/utils.test.ts +332 -0
- package/src/index.ts +10 -0
- package/skills/ktui-components/SKILL.md +0 -41
- package/skills/ktui-theming/SKILL.md +0 -50
- 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)
|