@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.
- package/README.md +14 -5
- package/dist/ktui.js +1538 -786
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +85 -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 +7 -0
- package/lib/cjs/components/datatable/datatable-layout-plugin.d.ts.map +1 -0
- package/lib/cjs/components/datatable/datatable-layout-plugin.js +338 -0
- package/lib/cjs/components/datatable/datatable-layout-plugin.js.map +1 -0
- package/lib/cjs/components/datatable/datatable-local-provider.d.ts +2 -2
- package/lib/cjs/components/datatable/datatable-local-provider.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-local-provider.js +85 -27
- 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 +13 -13
- 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 +35 -34
- package/lib/cjs/components/datatable/datatable.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable.js +233 -497
- 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 +127 -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 +7 -0
- package/lib/esm/components/datatable/datatable-layout-plugin.d.ts.map +1 -0
- package/lib/esm/components/datatable/datatable-layout-plugin.js +334 -0
- package/lib/esm/components/datatable/datatable-layout-plugin.js.map +1 -0
- package/lib/esm/components/datatable/datatable-local-provider.d.ts +2 -2
- package/lib/esm/components/datatable/datatable-local-provider.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-local-provider.js +85 -27
- 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 +13 -13
- 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 +35 -34
- package/lib/esm/components/datatable/datatable.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable.js +235 -499
- 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 +127 -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__/locked-layout.test.ts +257 -0
- package/src/components/datatable/__tests__/multi-row-headers.test.ts +7 -7
- package/src/components/datatable/__tests__/pagination-reset.test.ts +147 -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 +139 -143
- 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 +459 -0
- package/src/components/datatable/datatable-local-provider.ts +106 -35
- package/src/components/datatable/datatable-pagination-renderer.ts +13 -15
- 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.css +98 -0
- package/src/components/datatable/datatable.ts +288 -583
- package/src/components/datatable/index.ts +8 -0
- package/src/components/datatable/types.ts +157 -23
- package/src/helpers/__tests__/dom.test.ts +776 -0
- package/src/helpers/__tests__/utils.test.ts +332 -0
- package/src/index.ts +15 -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
|
@@ -8,11 +8,15 @@
|
|
|
8
8
|
import {
|
|
9
9
|
KTDataTableConfigInterface,
|
|
10
10
|
KTDataTableCheckChangePayloadInterface,
|
|
11
|
-
KTDataTableStateInterface,
|
|
12
11
|
} from './types';
|
|
13
12
|
import KTEventHandler from '../../helpers/event-handler';
|
|
14
13
|
import { KTCallableType } from '../../types';
|
|
15
14
|
|
|
15
|
+
export interface KTDataTableCheckboxDeps {
|
|
16
|
+
getState: () => { selectedRows?: string[] };
|
|
17
|
+
setSelectedRows: (rows: string[]) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
export interface KTDataTableCheckboxAPI {
|
|
17
21
|
init(): void;
|
|
18
22
|
check(): void;
|
|
@@ -21,244 +25,236 @@ export interface KTDataTableCheckboxAPI {
|
|
|
21
25
|
isChecked(): boolean;
|
|
22
26
|
getChecked(): string[];
|
|
23
27
|
updateState(): void;
|
|
28
|
+
dispose(): void;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
export class KTDataTableCheckboxHandler implements KTDataTableCheckboxAPI {
|
|
32
|
+
private _element: HTMLElement;
|
|
33
|
+
private _config: KTDataTableConfigInterface;
|
|
34
|
+
private _fireEvent: (eventName: string, eventData?: object) => void;
|
|
35
|
+
private _deps: KTDataTableCheckboxDeps;
|
|
36
|
+
private _headerChecked = false;
|
|
37
|
+
private _headerCheckElement: HTMLInputElement | null = null;
|
|
38
|
+
private _targetElements: NodeListOf<HTMLInputElement> | null = null;
|
|
39
|
+
private _delegatedEventId: string | null = null;
|
|
40
|
+
private readonly _preserveSelection: boolean;
|
|
35
41
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
constructor(
|
|
43
|
+
element: HTMLElement,
|
|
44
|
+
config: KTDataTableConfigInterface,
|
|
45
|
+
fireEvent: (eventName: string, eventData?: object) => void,
|
|
46
|
+
deps: KTDataTableCheckboxDeps,
|
|
47
|
+
) {
|
|
48
|
+
this._element = element;
|
|
49
|
+
this._config = config;
|
|
50
|
+
this._fireEvent = fireEvent;
|
|
51
|
+
this._deps = deps;
|
|
52
|
+
this._preserveSelection = config.checkbox?.preserveSelection !== false;
|
|
46
53
|
}
|
|
47
54
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
private _checkboxListener = (event: MouseEvent) => {
|
|
56
|
+
this._checkboxToggle(event);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
private _getSelectedRows(): string[] {
|
|
60
|
+
const rows = this._deps.getState().selectedRows;
|
|
61
|
+
return Array.isArray(rows) ? rows.map(String) : [];
|
|
53
62
|
}
|
|
54
63
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const state = ensureState();
|
|
58
|
-
state.selectedRows = Array.from(new Set(rows.map(String)));
|
|
64
|
+
private _setSelectedRows(rows: string[]) {
|
|
65
|
+
this._deps.setSelectedRows(Array.from(new Set(rows.map(String))));
|
|
59
66
|
}
|
|
60
67
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return Array.from(targetElements)
|
|
68
|
+
private _getVisibleRowIds(): string[] {
|
|
69
|
+
if (!this._targetElements) return [];
|
|
70
|
+
return Array.from(this._targetElements)
|
|
65
71
|
.map((el) => el.value)
|
|
66
72
|
.filter((v) => v != null && v !== '');
|
|
67
73
|
}
|
|
68
74
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
checkboxToggle(event);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
function init() {
|
|
75
|
-
const attrs = config.attributes;
|
|
75
|
+
public init() {
|
|
76
|
+
const attrs = this._config.attributes;
|
|
76
77
|
if (!attrs?.check || !attrs.checkbox) {
|
|
77
78
|
return;
|
|
78
79
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
this._headerCheckElement =
|
|
81
|
+
this._element.querySelector<HTMLInputElement>(attrs.check);
|
|
82
|
+
if (!this._headerCheckElement) return;
|
|
83
|
+
this._headerChecked = this._headerCheckElement.checked;
|
|
84
|
+
this._targetElements =
|
|
85
|
+
this._element.querySelectorAll<HTMLInputElement>(attrs.checkbox);
|
|
86
|
+
this._checkboxHandler();
|
|
87
|
+
this._reapplyCheckedStates();
|
|
88
|
+
this._updateHeaderCheckboxState();
|
|
86
89
|
}
|
|
87
90
|
|
|
88
|
-
|
|
89
|
-
if (!
|
|
90
|
-
const rowCheckboxSelector =
|
|
91
|
+
private _checkboxHandler() {
|
|
92
|
+
if (!this._headerCheckElement) return;
|
|
93
|
+
const rowCheckboxSelector = this._config.attributes?.checkbox;
|
|
91
94
|
if (!rowCheckboxSelector) return;
|
|
92
|
-
|
|
93
|
-
KTEventHandler.on(
|
|
94
|
-
|
|
95
|
+
this._headerCheckElement.addEventListener('click', this._checkboxListener);
|
|
96
|
+
this._delegatedEventId = KTEventHandler.on(
|
|
97
|
+
this._element,
|
|
95
98
|
rowCheckboxSelector,
|
|
96
99
|
'input',
|
|
97
100
|
((event?: Event) => {
|
|
98
|
-
if (event)
|
|
101
|
+
if (event) this._handleRowCheckboxChange(event);
|
|
99
102
|
}) as KTCallableType,
|
|
100
103
|
);
|
|
101
104
|
}
|
|
102
105
|
|
|
103
|
-
|
|
104
|
-
function handleRowCheckboxChange(event: Event) {
|
|
106
|
+
private _handleRowCheckboxChange(event: Event) {
|
|
105
107
|
const input = event.target as HTMLInputElement;
|
|
106
108
|
if (!input) return;
|
|
107
109
|
const value = input.value;
|
|
108
|
-
let selectedRows =
|
|
110
|
+
let selectedRows = this._getSelectedRows();
|
|
109
111
|
const wasChecked = selectedRows.includes(value);
|
|
110
112
|
const isNowChecked = input.checked;
|
|
111
113
|
|
|
112
|
-
// Update state first
|
|
113
114
|
if (isNowChecked) {
|
|
114
115
|
if (!wasChecked) selectedRows.push(value);
|
|
115
116
|
} else {
|
|
116
117
|
selectedRows = selectedRows.filter((v) => v !== value);
|
|
117
118
|
}
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
this._setSelectedRows(selectedRows);
|
|
120
|
+
this._updateHeaderCheckboxState();
|
|
120
121
|
|
|
121
|
-
// Fire specific checked/unchecked events after state is updated
|
|
122
122
|
if (isNowChecked && !wasChecked) {
|
|
123
|
-
|
|
123
|
+
this._fireEvent('checked', { value });
|
|
124
124
|
} else if (!isNowChecked && wasChecked) {
|
|
125
|
-
|
|
125
|
+
this._fireEvent('unchecked', { value });
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
fireEvent('changed');
|
|
128
|
+
this._fireEvent('changed');
|
|
130
129
|
}
|
|
131
130
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// Update state first, then fire events
|
|
136
|
-
change(checked);
|
|
137
|
-
// Fire checked/unchecked events after state is updated
|
|
131
|
+
private _checkboxToggle(_event?: Event) {
|
|
132
|
+
const checked = !this.isChecked();
|
|
133
|
+
this._change(checked);
|
|
138
134
|
const eventType = checked ? 'checked' : 'unchecked';
|
|
139
|
-
|
|
135
|
+
this._fireEvent(eventType);
|
|
140
136
|
}
|
|
141
137
|
|
|
142
|
-
|
|
143
|
-
function change(checked: boolean) {
|
|
138
|
+
private _change(checked: boolean) {
|
|
144
139
|
const payload: KTDataTableCheckChangePayloadInterface = { cancel: false };
|
|
145
|
-
|
|
140
|
+
this._fireEvent('change', payload);
|
|
146
141
|
if (payload.cancel === true) return;
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
if (
|
|
150
|
-
const visibleIds =
|
|
151
|
-
let selectedRows =
|
|
142
|
+
this._headerChecked = checked;
|
|
143
|
+
if (this._headerCheckElement) this._headerCheckElement.checked = checked;
|
|
144
|
+
if (this._targetElements) {
|
|
145
|
+
const visibleIds = this._getVisibleRowIds();
|
|
146
|
+
let selectedRows = this._getSelectedRows();
|
|
152
147
|
if (checked) {
|
|
153
|
-
|
|
154
|
-
selectedRows = preserveSelection
|
|
148
|
+
selectedRows = this._preserveSelection
|
|
155
149
|
? Array.from(new Set([...selectedRows, ...visibleIds]))
|
|
156
150
|
: visibleIds;
|
|
157
151
|
} else {
|
|
158
|
-
|
|
159
|
-
selectedRows = preserveSelection
|
|
152
|
+
selectedRows = this._preserveSelection
|
|
160
153
|
? selectedRows.filter((v) => !visibleIds.includes(v))
|
|
161
154
|
: [];
|
|
162
155
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
targetElements.forEach((element: HTMLInputElement) => {
|
|
156
|
+
this._setSelectedRows(selectedRows);
|
|
157
|
+
this._targetElements.forEach((element: HTMLInputElement) => {
|
|
166
158
|
if (element) {
|
|
167
159
|
element.checked = checked;
|
|
168
160
|
}
|
|
169
161
|
});
|
|
170
162
|
}
|
|
171
|
-
|
|
172
|
-
|
|
163
|
+
this._updateHeaderCheckboxState();
|
|
164
|
+
this._fireEvent('changed');
|
|
173
165
|
}
|
|
174
166
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
targetElements.forEach((element: HTMLInputElement) => {
|
|
167
|
+
private _reapplyCheckedStates() {
|
|
168
|
+
const selectedRows = this._getSelectedRows();
|
|
169
|
+
if (!this._targetElements) return;
|
|
170
|
+
this._targetElements.forEach((element: HTMLInputElement) => {
|
|
180
171
|
if (!element) return;
|
|
181
172
|
const value = element.value;
|
|
182
173
|
element.checked = selectedRows.includes(value);
|
|
183
|
-
// Update row class
|
|
184
174
|
const row = element.closest('tr');
|
|
185
|
-
if (row &&
|
|
175
|
+
if (row && this._config.checkbox?.checkedClass) {
|
|
186
176
|
if (element.checked) {
|
|
187
|
-
row.classList.add(
|
|
177
|
+
row.classList.add(this._config.checkbox.checkedClass);
|
|
188
178
|
} else {
|
|
189
|
-
row.classList.remove(
|
|
179
|
+
row.classList.remove(this._config.checkbox.checkedClass);
|
|
190
180
|
}
|
|
191
181
|
}
|
|
192
182
|
});
|
|
193
183
|
}
|
|
194
184
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const total = targetElements.length;
|
|
185
|
+
private _updateHeaderCheckboxState() {
|
|
186
|
+
if (!this._headerCheckElement || !this._targetElements) return;
|
|
187
|
+
const total = this._targetElements.length;
|
|
199
188
|
let checked = 0;
|
|
200
189
|
for (let i = 0; i < total; i++) {
|
|
201
|
-
if (
|
|
190
|
+
if (this._targetElements[i].checked) checked++;
|
|
202
191
|
}
|
|
203
192
|
if (checked === 0) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
193
|
+
this._headerCheckElement.indeterminate = false;
|
|
194
|
+
this._headerCheckElement.checked = false;
|
|
195
|
+
this._headerChecked = false;
|
|
207
196
|
} else if (checked > 0 && checked < total) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
197
|
+
this._headerCheckElement.indeterminate = true;
|
|
198
|
+
this._headerCheckElement.checked = false;
|
|
199
|
+
this._headerChecked = false;
|
|
211
200
|
} else if (checked === total) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
201
|
+
this._headerCheckElement.indeterminate = false;
|
|
202
|
+
this._headerCheckElement.checked = true;
|
|
203
|
+
this._headerChecked = true;
|
|
215
204
|
}
|
|
216
205
|
}
|
|
217
206
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
return headerChecked;
|
|
207
|
+
public isChecked(): boolean {
|
|
208
|
+
return this._headerChecked;
|
|
221
209
|
}
|
|
222
210
|
|
|
223
|
-
|
|
224
|
-
return
|
|
211
|
+
public getChecked(): string[] {
|
|
212
|
+
return this._getSelectedRows();
|
|
225
213
|
}
|
|
226
214
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
215
|
+
public check() {
|
|
216
|
+
this._change(true);
|
|
217
|
+
this._reapplyCheckedStates();
|
|
218
|
+
this._updateHeaderCheckboxState();
|
|
231
219
|
}
|
|
232
220
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
221
|
+
public uncheck() {
|
|
222
|
+
this._change(false);
|
|
223
|
+
this._reapplyCheckedStates();
|
|
224
|
+
this._updateHeaderCheckboxState();
|
|
237
225
|
}
|
|
238
226
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
227
|
+
public toggle() {
|
|
228
|
+
this._checkboxToggle();
|
|
229
|
+
this._reapplyCheckedStates();
|
|
230
|
+
this._updateHeaderCheckboxState();
|
|
243
231
|
}
|
|
244
232
|
|
|
245
|
-
|
|
246
|
-
const rowCheckSel =
|
|
233
|
+
public updateState() {
|
|
234
|
+
const rowCheckSel = this._config.attributes?.checkbox;
|
|
247
235
|
if (!rowCheckSel) {
|
|
248
236
|
return;
|
|
249
237
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
238
|
+
this._targetElements =
|
|
239
|
+
this._element.querySelectorAll<HTMLInputElement>(rowCheckSel);
|
|
240
|
+
this._reapplyCheckedStates();
|
|
241
|
+
this._updateHeaderCheckboxState();
|
|
253
242
|
}
|
|
254
243
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
244
|
+
public dispose() {
|
|
245
|
+
if (this._headerCheckElement) {
|
|
246
|
+
this._headerCheckElement.removeEventListener(
|
|
247
|
+
'click',
|
|
248
|
+
this._checkboxListener,
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
const rowCheckboxSelector = this._config.attributes?.checkbox;
|
|
252
|
+
if (this._delegatedEventId && rowCheckboxSelector) {
|
|
253
|
+
KTEventHandler.off(this._element, 'input', this._delegatedEventId);
|
|
254
|
+
this._delegatedEventId = null;
|
|
255
|
+
}
|
|
256
|
+
this._headerCheckElement = null;
|
|
257
|
+
this._targetElements = null;
|
|
258
|
+
}
|
|
264
259
|
}
|
|
260
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
|
|
3
|
+
* Copyright 2025 by Keenthemes Inc
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Shared column resolution utilities for KTDataTable.
|
|
8
|
+
* Eliminates duplicated column discovery logic across local-provider,
|
|
9
|
+
* table-renderer, and the main datatable class.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export interface ResolvedColumns {
|
|
13
|
+
/** All <th> elements from the thead */
|
|
14
|
+
allThs: HTMLTableCellElement[];
|
|
15
|
+
/** Only <th> elements that have data-kt-datatable-column attribute */
|
|
16
|
+
typedThs: HTMLTableCellElement[];
|
|
17
|
+
/** The column list to use for rendering: typedThs if all ths have the attr, else allThs */
|
|
18
|
+
columnsByIndex: HTMLTableCellElement[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Resolve column headers from a thead element.
|
|
23
|
+
* Returns both the raw th list and the typed (data-kt-datatable-column) subset.
|
|
24
|
+
* When some ths lack the attribute, columnsByIndex falls back to all ths by index.
|
|
25
|
+
*/
|
|
26
|
+
export function resolveColumns(
|
|
27
|
+
theadElement: HTMLTableSectionElement | null,
|
|
28
|
+
): ResolvedColumns {
|
|
29
|
+
const allThs: HTMLTableCellElement[] = theadElement
|
|
30
|
+
? Array.from(theadElement.querySelectorAll('th'))
|
|
31
|
+
: [];
|
|
32
|
+
|
|
33
|
+
const typedThs = allThs.filter((th) =>
|
|
34
|
+
th.hasAttribute('data-kt-datatable-column'),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const columnsByIndex = typedThs.length > 0 ? typedThs : allThs;
|
|
38
|
+
|
|
39
|
+
return { allThs, typedThs, columnsByIndex };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get the logical column count: number of data columns.
|
|
44
|
+
* Prefers originalData keys, falls back to first tbody row td count,
|
|
45
|
+
* then to resolved columns from thead.
|
|
46
|
+
*/
|
|
47
|
+
export function getLogicalColumnCount(
|
|
48
|
+
theadElement: HTMLTableSectionElement | null,
|
|
49
|
+
tbodyElement: HTMLTableSectionElement | null,
|
|
50
|
+
originalData?: Array<Record<string, unknown>>,
|
|
51
|
+
): number {
|
|
52
|
+
if (originalData && originalData.length > 0) {
|
|
53
|
+
return Object.keys(originalData[0]).length;
|
|
54
|
+
}
|
|
55
|
+
if (tbodyElement) {
|
|
56
|
+
const firstRow = tbodyElement.querySelector<HTMLTableRowElement>('tr');
|
|
57
|
+
if (firstRow) {
|
|
58
|
+
return firstRow.querySelectorAll('td').length;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const { columnsByIndex } = resolveColumns(theadElement);
|
|
62
|
+
return columnsByIndex.length;
|
|
63
|
+
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
KTDataTableInterface,
|
|
12
12
|
KTDataTableSortOrderInterface,
|
|
13
13
|
KTDataTableStateInterface,
|
|
14
|
+
OriginalTableClasses,
|
|
14
15
|
} from './types';
|
|
15
16
|
|
|
16
17
|
export type KTDataTableEmit = (eventName: string, eventData?: object) => void;
|
|
@@ -64,9 +65,7 @@ export interface KTDataTableTableRendererInput<
|
|
|
64
65
|
data: T[];
|
|
65
66
|
getLogicalColumnCount: () => number;
|
|
66
67
|
getState: () => KTDataTableStateInterface;
|
|
67
|
-
|
|
68
|
-
originalTrClasses: string[];
|
|
69
|
-
originalTdClasses: string[][];
|
|
68
|
+
originalClasses: OriginalTableClasses;
|
|
70
69
|
tableElement: HTMLTableElement;
|
|
71
70
|
theadElement: HTMLTableSectionElement;
|
|
72
71
|
}
|