@keenthemes/ktui 1.2.4 → 1.2.5
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/dist/ktui.js +590 -131
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +76 -40
- package/lib/cjs/components/datatable/datatable-checkbox.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-checkbox.js +34 -15
- package/lib/cjs/components/datatable/datatable-checkbox.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-contracts.d.ts +3 -3
- package/lib/cjs/components/datatable/datatable-contracts.d.ts.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 +13 -7
- 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 +31 -15
- package/lib/cjs/components/datatable/datatable-pagination-renderer.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-remote-provider.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-remote-provider.js +3 -0
- package/lib/cjs/components/datatable/datatable-remote-provider.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-table-renderer.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-table-renderer.js +14 -6
- package/lib/cjs/components/datatable/datatable-table-renderer.js.map +1 -1
- package/lib/cjs/components/datatable/datatable.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable.js +120 -54
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.d.ts +2 -2
- package/lib/cjs/components/dropdown/dropdown.d.ts.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.js +68 -31
- package/lib/cjs/components/dropdown/dropdown.js.map +1 -1
- package/lib/cjs/components/input-number/index.d.ts +7 -0
- package/lib/cjs/components/input-number/index.d.ts.map +1 -0
- package/lib/cjs/components/input-number/index.js +10 -0
- package/lib/cjs/components/input-number/index.js.map +1 -0
- package/lib/cjs/components/input-number/input-number.d.ts +40 -0
- package/lib/cjs/components/input-number/input-number.d.ts.map +1 -0
- package/lib/cjs/components/input-number/input-number.js +248 -0
- package/lib/cjs/components/input-number/input-number.js.map +1 -0
- package/lib/cjs/components/input-number/types.d.ts +30 -0
- package/lib/cjs/components/input-number/types.d.ts.map +1 -0
- package/lib/cjs/components/input-number/types.js +7 -0
- package/lib/cjs/components/input-number/types.js.map +1 -0
- package/lib/cjs/components/select/config.d.ts +1 -0
- package/lib/cjs/components/select/config.d.ts.map +1 -1
- package/lib/cjs/components/select/config.js +2 -1
- package/lib/cjs/components/select/config.js.map +1 -1
- package/lib/cjs/components/select/select.d.ts +8 -1
- package/lib/cjs/components/select/select.d.ts.map +1 -1
- package/lib/cjs/components/select/select.js +14 -1
- package/lib/cjs/components/select/select.js.map +1 -1
- package/lib/cjs/components/select/tags.d.ts.map +1 -1
- package/lib/cjs/components/select/tags.js +10 -0
- package/lib/cjs/components/select/tags.js.map +1 -1
- package/lib/cjs/index.d.ts +4 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +5 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.js +34 -15
- package/lib/esm/components/datatable/datatable-checkbox.js.map +1 -1
- package/lib/esm/components/datatable/datatable-contracts.d.ts +3 -3
- package/lib/esm/components/datatable/datatable-contracts.d.ts.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 +13 -7
- 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 +31 -15
- package/lib/esm/components/datatable/datatable-pagination-renderer.js.map +1 -1
- package/lib/esm/components/datatable/datatable-remote-provider.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-remote-provider.js +3 -0
- package/lib/esm/components/datatable/datatable-remote-provider.js.map +1 -1
- package/lib/esm/components/datatable/datatable-table-renderer.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-table-renderer.js +14 -6
- package/lib/esm/components/datatable/datatable-table-renderer.js.map +1 -1
- package/lib/esm/components/datatable/datatable.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable.js +120 -54
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/dropdown/dropdown.d.ts +2 -2
- package/lib/esm/components/dropdown/dropdown.d.ts.map +1 -1
- package/lib/esm/components/dropdown/dropdown.js +68 -31
- package/lib/esm/components/dropdown/dropdown.js.map +1 -1
- package/lib/esm/components/input-number/index.d.ts +7 -0
- package/lib/esm/components/input-number/index.d.ts.map +1 -0
- package/lib/esm/components/input-number/index.js +6 -0
- package/lib/esm/components/input-number/index.js.map +1 -0
- package/lib/esm/components/input-number/input-number.d.ts +40 -0
- package/lib/esm/components/input-number/input-number.d.ts.map +1 -0
- package/lib/esm/components/input-number/input-number.js +245 -0
- package/lib/esm/components/input-number/input-number.js.map +1 -0
- package/lib/esm/components/input-number/types.d.ts +30 -0
- package/lib/esm/components/input-number/types.d.ts.map +1 -0
- package/lib/esm/components/input-number/types.js +6 -0
- package/lib/esm/components/input-number/types.js.map +1 -0
- package/lib/esm/components/select/config.d.ts +1 -0
- package/lib/esm/components/select/config.d.ts.map +1 -1
- package/lib/esm/components/select/config.js +2 -1
- package/lib/esm/components/select/config.js.map +1 -1
- package/lib/esm/components/select/select.d.ts +8 -1
- package/lib/esm/components/select/select.d.ts.map +1 -1
- package/lib/esm/components/select/select.js +14 -1
- package/lib/esm/components/select/select.js.map +1 -1
- package/lib/esm/components/select/tags.d.ts.map +1 -1
- package/lib/esm/components/select/tags.js +11 -1
- package/lib/esm/components/select/tags.js.map +1 -1
- package/lib/esm/index.d.ts +4 -0
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +3 -0
- package/lib/esm/index.js.map +1 -1
- package/package.json +5 -11
- package/src/components/datatable/datatable-checkbox.ts +34 -23
- package/src/components/datatable/datatable-contracts.ts +3 -3
- package/src/components/datatable/datatable-local-provider.ts +12 -13
- package/src/components/datatable/datatable-pagination-renderer.ts +34 -20
- package/src/components/datatable/datatable-remote-provider.ts +3 -0
- package/src/components/datatable/datatable-table-renderer.ts +40 -32
- package/src/components/datatable/datatable.ts +122 -79
- package/src/components/dropdown/dropdown.ts +86 -58
- package/src/components/input/input-group.css +14 -1
- package/src/components/input-number/__tests__/input-number.test.ts +278 -0
- package/src/components/input-number/index.ts +11 -0
- package/src/components/input-number/input-number.ts +267 -0
- package/src/components/input-number/types.ts +32 -0
- package/src/components/select/__tests__/ux-behaviors.test.ts +72 -0
- package/src/components/select/config.ts +3 -1
- package/src/components/select/select.css +23 -20
- package/src/components/select/select.ts +15 -1
- package/src/components/select/tags.ts +14 -1
- package/src/index.ts +9 -0
|
@@ -83,11 +83,11 @@ export interface KTDataTableTableRenderer<T extends KTDataTableDataInterface> {
|
|
|
83
83
|
export interface KTDataTablePaginationRendererInput {
|
|
84
84
|
config: KTDataTableConfigInterface;
|
|
85
85
|
dataLength: number;
|
|
86
|
-
infoElement
|
|
86
|
+
infoElement?: HTMLElement | null;
|
|
87
87
|
paginateData: (page: number) => void;
|
|
88
|
-
paginationElement
|
|
88
|
+
paginationElement?: HTMLElement | null;
|
|
89
89
|
reloadPageSize: (pageSize: number, page?: number) => void;
|
|
90
|
-
sizeElement
|
|
90
|
+
sizeElement?: HTMLSelectElement | null;
|
|
91
91
|
state: KTDataTableStateInterface;
|
|
92
92
|
}
|
|
93
93
|
|
|
@@ -63,25 +63,24 @@ export class KTDataTableLocalDataProvider<
|
|
|
63
63
|
|
|
64
64
|
if (search) {
|
|
65
65
|
const searchTerm = typeof search === 'string' ? search : '';
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
data
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
const searchCallback = this.options.config.search?.callback;
|
|
67
|
+
if (searchCallback) {
|
|
68
|
+
filteredData = data = searchCallback.call(
|
|
69
|
+
this,
|
|
70
|
+
data,
|
|
71
|
+
searchTerm,
|
|
72
|
+
) as T[];
|
|
73
|
+
}
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
const sortCallback = this.options.config.sort?.callback;
|
|
73
77
|
if (
|
|
74
78
|
sortField !== undefined &&
|
|
75
79
|
sortOrder !== undefined &&
|
|
76
80
|
sortOrder !== '' &&
|
|
77
|
-
typeof
|
|
81
|
+
typeof sortCallback === 'function'
|
|
78
82
|
) {
|
|
79
|
-
data =
|
|
80
|
-
this,
|
|
81
|
-
data,
|
|
82
|
-
sortField as string,
|
|
83
|
-
sortOrder,
|
|
84
|
-
) as T[];
|
|
83
|
+
data = sortCallback.call(this, data, sortField as string, sortOrder) as T[];
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
if (data?.length > 0) {
|
|
@@ -114,7 +113,7 @@ export class KTDataTableLocalDataProvider<
|
|
|
114
113
|
const { _state, ...restConfig } = this.options.config;
|
|
115
114
|
const checksum: string = KTUtils.checksum(JSON.stringify(restConfig));
|
|
116
115
|
|
|
117
|
-
if (_state
|
|
116
|
+
if ((_state?._configChecksum ?? '') !== checksum) {
|
|
118
117
|
this.options.stateStore.patchState({ _configChecksum: checksum });
|
|
119
118
|
return true;
|
|
120
119
|
}
|
|
@@ -13,21 +13,27 @@ export class KTDataTableDomPaginationRenderer implements KTDataTablePaginationRe
|
|
|
13
13
|
public render(
|
|
14
14
|
input: KTDataTablePaginationRendererInput,
|
|
15
15
|
): KTDataTableCleanup | void {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
if (input.sizeElement) {
|
|
17
|
+
this.removeChildElements(input.sizeElement);
|
|
18
|
+
this.createPageSizeControls(input);
|
|
19
|
+
}
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
if (input.paginationElement) {
|
|
22
|
+
this.removeChildElements(input.paginationElement);
|
|
23
|
+
this.createPaginationControls(input);
|
|
24
|
+
}
|
|
21
25
|
|
|
22
26
|
return () => {
|
|
23
27
|
if (input.sizeElement) {
|
|
24
28
|
input.sizeElement.onchange = null;
|
|
25
29
|
}
|
|
26
|
-
|
|
30
|
+
if (input.paginationElement) {
|
|
31
|
+
this.removeChildElements(input.paginationElement);
|
|
32
|
+
}
|
|
27
33
|
};
|
|
28
34
|
}
|
|
29
35
|
|
|
30
|
-
private removeChildElements(container
|
|
36
|
+
private removeChildElements(container?: HTMLElement | null): void {
|
|
31
37
|
if (!container) {
|
|
32
38
|
return;
|
|
33
39
|
}
|
|
@@ -39,13 +45,15 @@ export class KTDataTableDomPaginationRenderer implements KTDataTablePaginationRe
|
|
|
39
45
|
|
|
40
46
|
private createPageSizeControls(
|
|
41
47
|
input: KTDataTablePaginationRendererInput,
|
|
42
|
-
):
|
|
48
|
+
): void {
|
|
43
49
|
if (!input.sizeElement) {
|
|
44
|
-
return
|
|
50
|
+
return;
|
|
45
51
|
}
|
|
46
52
|
|
|
53
|
+
const pageSizes = input.config.pageSizes ?? [5, 10, 20, 30, 50];
|
|
54
|
+
|
|
47
55
|
setTimeout(() => {
|
|
48
|
-
const options =
|
|
56
|
+
const options = pageSizes.map((size: number) => {
|
|
49
57
|
const option = document.createElement('option') as HTMLOptionElement;
|
|
50
58
|
option.value = String(size);
|
|
51
59
|
option.text = String(size);
|
|
@@ -62,18 +70,12 @@ export class KTDataTableDomPaginationRenderer implements KTDataTablePaginationRe
|
|
|
62
70
|
1,
|
|
63
71
|
);
|
|
64
72
|
};
|
|
65
|
-
|
|
66
|
-
return input.sizeElement;
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
private createPaginationControls(
|
|
70
76
|
input: KTDataTablePaginationRendererInput,
|
|
71
|
-
): HTMLElement {
|
|
72
|
-
if (
|
|
73
|
-
!input.infoElement ||
|
|
74
|
-
!input.paginationElement ||
|
|
75
|
-
input.dataLength === 0
|
|
76
|
-
) {
|
|
77
|
+
): HTMLElement | null {
|
|
78
|
+
if (!input.paginationElement || input.dataLength === 0) {
|
|
77
79
|
return null;
|
|
78
80
|
}
|
|
79
81
|
|
|
@@ -86,7 +88,13 @@ export class KTDataTableDomPaginationRenderer implements KTDataTablePaginationRe
|
|
|
86
88
|
private setPaginationInfoText(
|
|
87
89
|
input: KTDataTablePaginationRendererInput,
|
|
88
90
|
): void {
|
|
89
|
-
input.infoElement
|
|
91
|
+
if (!input.infoElement) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const infoTemplate =
|
|
96
|
+
input.config.info ?? '{start}-{end} of {total}';
|
|
97
|
+
input.infoElement.textContent = infoTemplate
|
|
90
98
|
.replace(
|
|
91
99
|
'{start}',
|
|
92
100
|
(input.state.page - 1) * input.state.pageSize + 1 + '',
|
|
@@ -105,8 +113,14 @@ export class KTDataTableDomPaginationRenderer implements KTDataTablePaginationRe
|
|
|
105
113
|
paginationContainer: HTMLElement,
|
|
106
114
|
input: KTDataTablePaginationRendererInput,
|
|
107
115
|
): void {
|
|
116
|
+
const pagination = input.config.pagination;
|
|
117
|
+
if (!pagination) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
108
121
|
const { page: currentPage, totalPages } = input.state;
|
|
109
|
-
const { previous, next, number, more } =
|
|
122
|
+
const { previous, next, number, more } = pagination;
|
|
123
|
+
const pageMoreLimit = input.config.pageMoreLimit ?? 3;
|
|
110
124
|
|
|
111
125
|
const createButton = (
|
|
112
126
|
text: string,
|
|
@@ -135,7 +149,7 @@ export class KTDataTableDomPaginationRenderer implements KTDataTablePaginationRe
|
|
|
135
149
|
const range = this.calculatePageRange(
|
|
136
150
|
currentPage,
|
|
137
151
|
totalPages,
|
|
138
|
-
|
|
152
|
+
pageMoreLimit,
|
|
139
153
|
);
|
|
140
154
|
|
|
141
155
|
if (range.start > 1) {
|
|
@@ -137,6 +137,9 @@ export class KTDataTableRemoteDataProvider<
|
|
|
137
137
|
this.options.config.requestMethod;
|
|
138
138
|
let requestBody: RequestInit['body'] | undefined = undefined;
|
|
139
139
|
let apiEndpoint = this.options.config.apiEndpoint;
|
|
140
|
+
if (!apiEndpoint) {
|
|
141
|
+
throw new Error('KTDataTable: apiEndpoint is required for remote fetch');
|
|
142
|
+
}
|
|
140
143
|
|
|
141
144
|
if (this.abortController) {
|
|
142
145
|
this.abortController.abort();
|
|
@@ -130,7 +130,7 @@ export class KTDataTableDomTableRenderer<
|
|
|
130
130
|
td.innerHTML = value as string;
|
|
131
131
|
|
|
132
132
|
this.applyOriginalTdClass(input, td, rowIndex, colIndex);
|
|
133
|
-
this.applyDataRowAttributes(td, dataRowAttributes, colIndex);
|
|
133
|
+
this.applyDataRowAttributes(td, dataRowAttributes ?? null, colIndex);
|
|
134
134
|
|
|
135
135
|
row.appendChild(td);
|
|
136
136
|
}
|
|
@@ -142,39 +142,47 @@ export class KTDataTableDomTableRenderer<
|
|
|
142
142
|
item: T,
|
|
143
143
|
rowIndex: number,
|
|
144
144
|
): void {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
result instanceof HTMLElement ||
|
|
161
|
-
result instanceof DocumentFragment
|
|
162
|
-
) {
|
|
163
|
-
td.appendChild(result);
|
|
164
|
-
} else if (typeof result === 'string') {
|
|
165
|
-
td.innerHTML = result as string;
|
|
166
|
-
}
|
|
167
|
-
} else {
|
|
168
|
-
td.textContent = item[key] as string;
|
|
169
|
-
}
|
|
145
|
+
const columns = input.config.columns;
|
|
146
|
+
if (!columns) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
Object.keys(columns).forEach((key, colIndex) => {
|
|
151
|
+
const columnDef = columns[key];
|
|
152
|
+
if (!columnDef) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const colKey = key as keyof T;
|
|
156
|
+
|
|
157
|
+
const td = document.createElement('td');
|
|
158
|
+
|
|
159
|
+
this.applyOriginalTdClass(input, td, rowIndex, colIndex);
|
|
170
160
|
|
|
171
|
-
|
|
172
|
-
|
|
161
|
+
if (typeof columnDef.render === 'function') {
|
|
162
|
+
const result = columnDef.render.call(
|
|
163
|
+
input.context,
|
|
164
|
+
item[colKey],
|
|
165
|
+
item,
|
|
166
|
+
input.context,
|
|
167
|
+
);
|
|
168
|
+
if (
|
|
169
|
+
result instanceof HTMLElement ||
|
|
170
|
+
result instanceof DocumentFragment
|
|
171
|
+
) {
|
|
172
|
+
td.appendChild(result);
|
|
173
|
+
} else if (typeof result === 'string') {
|
|
174
|
+
td.innerHTML = result as string;
|
|
173
175
|
}
|
|
176
|
+
} else {
|
|
177
|
+
td.textContent = item[colKey] as string;
|
|
178
|
+
}
|
|
174
179
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
180
|
+
if (typeof columnDef.createdCell === 'function') {
|
|
181
|
+
columnDef.createdCell.call(input.context, td, item[colKey], item, row);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
row.appendChild(td);
|
|
185
|
+
});
|
|
178
186
|
}
|
|
179
187
|
|
|
180
188
|
private applyOriginalTdClass(
|
|
@@ -194,7 +202,7 @@ export class KTDataTableDomTableRenderer<
|
|
|
194
202
|
|
|
195
203
|
private applyDataRowAttributes(
|
|
196
204
|
td: HTMLTableCellElement,
|
|
197
|
-
dataRowAttributes: KTDataTableAttributeInterface,
|
|
205
|
+
dataRowAttributes: KTDataTableAttributeInterface | null,
|
|
198
206
|
colIndex: number,
|
|
199
207
|
): void {
|
|
200
208
|
if (dataRowAttributes && dataRowAttributes[colIndex]) {
|
|
@@ -74,9 +74,9 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
74
74
|
private _originalTdClasses: string[][] = []; // Store original td classes as a 2D array [row][col]
|
|
75
75
|
private _originalThClasses: string[] = []; // Store original th classes
|
|
76
76
|
|
|
77
|
-
private _infoElement: HTMLElement;
|
|
78
|
-
private _sizeElement: HTMLSelectElement;
|
|
79
|
-
private _paginationElement: HTMLElement;
|
|
77
|
+
private _infoElement: HTMLElement | null = null;
|
|
78
|
+
private _sizeElement: HTMLSelectElement | null = null;
|
|
79
|
+
private _paginationElement: HTMLElement | null = null;
|
|
80
80
|
|
|
81
81
|
private _checkbox: KTDataTableCheckboxAPI;
|
|
82
82
|
private _sortHandler: KTDataTableSortAPI<T>;
|
|
@@ -106,6 +106,9 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
106
106
|
this._defaultConfig = this._initDefaultConfig(config);
|
|
107
107
|
|
|
108
108
|
this._init(element);
|
|
109
|
+
if (!this._element) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
109
112
|
this._buildConfig();
|
|
110
113
|
this._stateStore = new KTDataTableConfigStateStore(this._config);
|
|
111
114
|
this._eventAdapter = createDataTableEventAdapter(
|
|
@@ -425,43 +428,35 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
425
428
|
* @returns {void}
|
|
426
429
|
*/
|
|
427
430
|
private _initElements(): void {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
431
|
+
const root = this._element;
|
|
432
|
+
const attrs = this._config.attributes;
|
|
433
|
+
if (!root || !attrs?.table) {
|
|
434
|
+
throw new Error('KTDataTable: root element and table selector are required');
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const tableEl = root.querySelector<HTMLTableElement>(attrs.table);
|
|
438
|
+
if (!tableEl) {
|
|
439
|
+
throw new Error(`KTDataTable: table element not found (${attrs.table})`);
|
|
440
|
+
}
|
|
441
|
+
this._tableElement = tableEl;
|
|
442
|
+
|
|
437
443
|
this._tbodyElement =
|
|
438
444
|
this._tableElement.tBodies[0] || this._tableElement.createTBody();
|
|
439
|
-
/**
|
|
440
|
-
* Table head element
|
|
441
|
-
*/
|
|
442
|
-
this._theadElement = this._tableElement.tHead!;
|
|
443
445
|
|
|
444
|
-
|
|
446
|
+
this._theadElement =
|
|
447
|
+
this._tableElement.tHead ?? this._tableElement.createTHead();
|
|
448
|
+
|
|
445
449
|
this._storeOriginalClasses();
|
|
446
450
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
this.
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
this._sizeElement = this._element.querySelector<HTMLSelectElement>(
|
|
457
|
-
this._config.attributes.size,
|
|
458
|
-
)!;
|
|
459
|
-
/**
|
|
460
|
-
* Pagination element
|
|
461
|
-
*/
|
|
462
|
-
this._paginationElement = this._element.querySelector<HTMLElement>(
|
|
463
|
-
this._config.attributes.pagination,
|
|
464
|
-
)!;
|
|
451
|
+
this._infoElement = attrs.info
|
|
452
|
+
? root.querySelector<HTMLElement>(attrs.info)
|
|
453
|
+
: null;
|
|
454
|
+
this._sizeElement = attrs.size
|
|
455
|
+
? root.querySelector<HTMLSelectElement>(attrs.size)
|
|
456
|
+
: null;
|
|
457
|
+
this._paginationElement = attrs.pagination
|
|
458
|
+
? root.querySelector<HTMLElement>(attrs.pagination)
|
|
459
|
+
: null;
|
|
465
460
|
}
|
|
466
461
|
|
|
467
462
|
/**
|
|
@@ -540,7 +535,7 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
540
535
|
* @returns {void}
|
|
541
536
|
*/
|
|
542
537
|
private _finalize(): void {
|
|
543
|
-
this._element
|
|
538
|
+
this._element?.classList.add('datatable-initialized');
|
|
544
539
|
|
|
545
540
|
// Initialize checkbox logic
|
|
546
541
|
this._checkbox.init();
|
|
@@ -600,7 +595,7 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
600
595
|
// Create a new debounced search function
|
|
601
596
|
const debouncedSearch = this._debounce(() => {
|
|
602
597
|
this.search(searchElement.value);
|
|
603
|
-
}, this._config.search
|
|
598
|
+
}, this._config.search?.delay ?? 500);
|
|
604
599
|
|
|
605
600
|
// Store the new debounced function as a property of the element
|
|
606
601
|
searchWithDebounce._debouncedSearch = debouncedSearch;
|
|
@@ -647,7 +642,9 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
647
642
|
|
|
648
643
|
private _createUrl(
|
|
649
644
|
pathOrUrl: string,
|
|
650
|
-
baseUrl: string | null = window
|
|
645
|
+
baseUrl: string | null = typeof window !== 'undefined'
|
|
646
|
+
? window.location.origin
|
|
647
|
+
: null,
|
|
651
648
|
): URL {
|
|
652
649
|
// Regular expression to check if the input is a full URL
|
|
653
650
|
const isFullUrl = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(pathOrUrl);
|
|
@@ -661,7 +658,39 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
661
658
|
? pathOrUrl
|
|
662
659
|
: `/${pathOrUrl}`;
|
|
663
660
|
|
|
664
|
-
|
|
661
|
+
// Opaque origins (e.g. srcdoc iframes) serialize as the string "null", which is not a valid URL base.
|
|
662
|
+
const bases: string[] = [];
|
|
663
|
+
if (baseUrl && baseUrl !== 'null') {
|
|
664
|
+
bases.push(baseUrl);
|
|
665
|
+
}
|
|
666
|
+
if (typeof window !== 'undefined') {
|
|
667
|
+
const href = window.location.href;
|
|
668
|
+
if (href && !bases.includes(href)) {
|
|
669
|
+
bases.push(href);
|
|
670
|
+
}
|
|
671
|
+
try {
|
|
672
|
+
if (window.parent !== window && window.parent.location?.href) {
|
|
673
|
+
const parentHref = window.parent.location.href;
|
|
674
|
+
if (parentHref && !bases.includes(parentHref)) {
|
|
675
|
+
bases.push(parentHref);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
} catch {
|
|
679
|
+
// parent is cross-origin
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
for (const base of bases) {
|
|
684
|
+
try {
|
|
685
|
+
return new URL(normalizedPath, base);
|
|
686
|
+
} catch {
|
|
687
|
+
// try next base
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
throw new Error(
|
|
692
|
+
`KTDataTable: cannot resolve relative apiEndpoint "${pathOrUrl}" (no valid base URL; use an absolute apiEndpoint).`,
|
|
693
|
+
);
|
|
665
694
|
}
|
|
666
695
|
|
|
667
696
|
/**
|
|
@@ -683,7 +712,7 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
683
712
|
this._updateTable();
|
|
684
713
|
}
|
|
685
714
|
|
|
686
|
-
if (this._infoElement
|
|
715
|
+
if (this._infoElement || this._sizeElement || this._paginationElement) {
|
|
687
716
|
this._updatePagination();
|
|
688
717
|
}
|
|
689
718
|
|
|
@@ -778,38 +807,49 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
778
807
|
|
|
779
808
|
// Method to show the loading spinner
|
|
780
809
|
private _showSpinner(): void {
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
810
|
+
const root = this._element;
|
|
811
|
+
const spinnerSel = this._config.attributes?.spinner;
|
|
812
|
+
const fromDom =
|
|
813
|
+
root && spinnerSel
|
|
814
|
+
? root.querySelector<HTMLElement>(spinnerSel)
|
|
815
|
+
: null;
|
|
816
|
+
const spinner = fromDom ?? this._createSpinner();
|
|
785
817
|
if (spinner) {
|
|
786
818
|
spinner.style.display = 'block';
|
|
787
819
|
}
|
|
788
|
-
|
|
820
|
+
root?.classList.add(this._config.loadingClass ?? 'loading');
|
|
789
821
|
}
|
|
790
822
|
|
|
791
823
|
// Method to hide the loading spinner
|
|
792
824
|
private _hideSpinner(): void {
|
|
793
|
-
const
|
|
794
|
-
|
|
795
|
-
|
|
825
|
+
const root = this._element;
|
|
826
|
+
const spinnerSel = this._config.attributes?.spinner;
|
|
827
|
+
const spinner =
|
|
828
|
+
root && spinnerSel
|
|
829
|
+
? root.querySelector<HTMLElement>(spinnerSel)
|
|
830
|
+
: null;
|
|
796
831
|
if (spinner) {
|
|
797
832
|
spinner.style.display = 'none';
|
|
798
833
|
}
|
|
799
|
-
|
|
834
|
+
root?.classList.remove(this._config.loadingClass ?? 'loading');
|
|
800
835
|
}
|
|
801
836
|
|
|
802
837
|
// Method to create a spinner element if it doesn't exist
|
|
803
|
-
private _createSpinner(): HTMLElement {
|
|
804
|
-
|
|
838
|
+
private _createSpinner(): HTMLElement | null {
|
|
839
|
+
const loading = this._config.loading;
|
|
840
|
+
if (!loading) {
|
|
805
841
|
return null;
|
|
806
842
|
}
|
|
807
843
|
|
|
808
844
|
const template = document.createElement('template');
|
|
809
|
-
template.innerHTML =
|
|
845
|
+
template.innerHTML = loading.template
|
|
810
846
|
.trim()
|
|
811
|
-
.replace('{content}',
|
|
812
|
-
const
|
|
847
|
+
.replace('{content}', loading.content);
|
|
848
|
+
const first = template.content.firstChild;
|
|
849
|
+
if (!first || !(first instanceof HTMLElement)) {
|
|
850
|
+
return null;
|
|
851
|
+
}
|
|
852
|
+
const spinner = first;
|
|
813
853
|
spinner.setAttribute('data-kt-datatable-spinner', 'true');
|
|
814
854
|
|
|
815
855
|
this._tableElement.appendChild(spinner);
|
|
@@ -878,18 +918,15 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
878
918
|
}
|
|
879
919
|
|
|
880
920
|
private _tableId(): string {
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
id = this._tableElement.getAttribute('id') as string;
|
|
921
|
+
const tableIdAttr = this._tableElement?.getAttribute('id');
|
|
922
|
+
if (tableIdAttr) {
|
|
923
|
+
return tableIdAttr;
|
|
885
924
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
id = this._element.getAttribute('id') as string;
|
|
925
|
+
const rootIdAttr = this._element?.getAttribute('id');
|
|
926
|
+
if (rootIdAttr) {
|
|
927
|
+
return rootIdAttr;
|
|
890
928
|
}
|
|
891
|
-
|
|
892
|
-
return id;
|
|
929
|
+
return '';
|
|
893
930
|
}
|
|
894
931
|
|
|
895
932
|
/**
|
|
@@ -897,6 +934,11 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
897
934
|
* This method is called before re-rendering or when disposing the component.
|
|
898
935
|
*/
|
|
899
936
|
private _dispose() {
|
|
937
|
+
const root = this._element;
|
|
938
|
+
if (!root) {
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
|
|
900
942
|
this._cleanupCallbacks.forEach((cleanup) => cleanup());
|
|
901
943
|
this._cleanupCallbacks = [];
|
|
902
944
|
|
|
@@ -939,12 +981,12 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
939
981
|
if (this._checkbox && typeof checkboxWithDispose.dispose === 'function') {
|
|
940
982
|
checkboxWithDispose.dispose();
|
|
941
983
|
} else {
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
984
|
+
const checkSel = this._config.attributes?.check;
|
|
985
|
+
if (checkSel) {
|
|
986
|
+
const headerCheckElement = root.querySelector<HTMLInputElement>(checkSel);
|
|
987
|
+
if (headerCheckElement) {
|
|
988
|
+
headerCheckElement.replaceWith(headerCheckElement.cloneNode(true));
|
|
989
|
+
}
|
|
948
990
|
}
|
|
949
991
|
}
|
|
950
992
|
// KTDataTableSortAPI does not have a dispose method, but we can remove th click listeners by replacing them
|
|
@@ -956,22 +998,23 @@ export class KTDataTable<T extends KTDataTableDataInterface>
|
|
|
956
998
|
}
|
|
957
999
|
|
|
958
1000
|
// --- 5. Remove spinner DOM node if it exists ---
|
|
959
|
-
const
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
1001
|
+
const spinnerSel = this._config.attributes?.spinner;
|
|
1002
|
+
if (spinnerSel) {
|
|
1003
|
+
const spinner = root.querySelector<HTMLElement>(spinnerSel);
|
|
1004
|
+
if (spinner?.parentNode) {
|
|
1005
|
+
spinner.parentNode.removeChild(spinner);
|
|
1006
|
+
}
|
|
964
1007
|
}
|
|
965
|
-
|
|
1008
|
+
root.classList.remove(this._config.loadingClass ?? 'loading');
|
|
966
1009
|
|
|
967
1010
|
// --- 6. Remove instance reference from the DOM element ---
|
|
968
|
-
const elementWithInstance = KTDataTable.asElementWithInstance(
|
|
969
|
-
this._element,
|
|
970
|
-
);
|
|
1011
|
+
const elementWithInstance = KTDataTable.asElementWithInstance(root);
|
|
971
1012
|
if (elementWithInstance.instance) {
|
|
972
1013
|
delete elementWithInstance.instance;
|
|
973
1014
|
}
|
|
974
1015
|
|
|
1016
|
+
KTData.remove(root, this._name);
|
|
1017
|
+
|
|
975
1018
|
// --- 7. (Optional) Clear localStorage state ---
|
|
976
1019
|
// Uncomment the following line if you want to clear state on dispose:
|
|
977
1020
|
// this._deleteState();
|