@keenthemes/ktui 1.0.24 → 1.0.26

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 (53) hide show
  1. package/dist/ktui.js +337 -18
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +319 -11
  5. package/examples/datatable/checkbox-events-test.html +400 -0
  6. package/examples/datatable/credentials-test.html +423 -0
  7. package/examples/datatable/remote-checkbox-test.html +365 -0
  8. package/examples/modal/persistent-test.html +205 -0
  9. package/examples/select/dark-mode-test.html +93 -0
  10. package/examples/select/dropdowncontainer-test.html +111 -0
  11. package/examples/select/dynamic-methods.html +273 -0
  12. package/examples/select/formdata-remote-test.html +161 -0
  13. package/examples/select/modal-positioning-test.html +336 -0
  14. package/examples/select/remote-data-preselected.html +283 -0
  15. package/lib/cjs/components/datatable/datatable-checkbox.js +16 -3
  16. package/lib/cjs/components/datatable/datatable-checkbox.js.map +1 -1
  17. package/lib/cjs/components/datatable/datatable.js +3 -5
  18. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  19. package/lib/cjs/components/image-input/image-input.js.map +1 -1
  20. package/lib/cjs/components/modal/modal.js +3 -1
  21. package/lib/cjs/components/modal/modal.js.map +1 -1
  22. package/lib/cjs/components/select/config.js +5 -0
  23. package/lib/cjs/components/select/config.js.map +1 -1
  24. package/lib/cjs/components/select/dropdown.js +25 -2
  25. package/lib/cjs/components/select/dropdown.js.map +1 -1
  26. package/lib/cjs/components/select/select.js +285 -7
  27. package/lib/cjs/components/select/select.js.map +1 -1
  28. package/lib/cjs/components/select/templates.js.map +1 -1
  29. package/lib/esm/components/datatable/datatable-checkbox.js +16 -3
  30. package/lib/esm/components/datatable/datatable-checkbox.js.map +1 -1
  31. package/lib/esm/components/datatable/datatable.js +3 -5
  32. package/lib/esm/components/datatable/datatable.js.map +1 -1
  33. package/lib/esm/components/image-input/image-input.js.map +1 -1
  34. package/lib/esm/components/modal/modal.js +3 -1
  35. package/lib/esm/components/modal/modal.js.map +1 -1
  36. package/lib/esm/components/select/config.js +5 -0
  37. package/lib/esm/components/select/config.js.map +1 -1
  38. package/lib/esm/components/select/dropdown.js +25 -2
  39. package/lib/esm/components/select/dropdown.js.map +1 -1
  40. package/lib/esm/components/select/select.js +285 -7
  41. package/lib/esm/components/select/select.js.map +1 -1
  42. package/lib/esm/components/select/templates.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/components/datatable/datatable-checkbox.ts +18 -3
  45. package/src/components/datatable/datatable.ts +3 -0
  46. package/src/components/datatable/types.ts +1 -0
  47. package/src/components/image-input/image-input.ts +12 -15
  48. package/src/components/modal/modal.ts +5 -1
  49. package/src/components/select/config.ts +6 -0
  50. package/src/components/select/dropdown.ts +32 -3
  51. package/src/components/select/select.css +4 -4
  52. package/src/components/select/select.ts +350 -9
  53. package/src/components/select/templates.ts +2 -1
@@ -0,0 +1,336 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Modal Positioning Test</title>
7
+ <link rel="stylesheet" href="../../dist/styles.css" />
8
+ </head>
9
+
10
+ <body class="bg-gray-50 min-h-screen">
11
+ <div class="bg-white rounded-lg shadow p-8 w-full max-w-2xl mt-10 mx-auto">
12
+ <h1 class="text-xl font-semibold text-gray-900 mb-2">
13
+ Modal Positioning Test
14
+ </h1>
15
+ <p class="text-sm text-gray-600 mb-6">
16
+ Verifies KTSelect dropdowns position correctly inside modals.
17
+ </p>
18
+
19
+ <div class="flex flex-col gap-4">
20
+ <button
21
+ data-kt-modal-toggle="#modal-basic"
22
+ class="px-4 py-2 bg-white border border-gray-300 text-gray-700 text-sm font-medium rounded hover:bg-gray-50 text-left">
23
+ <div class="font-medium">Basic Modal</div>
24
+ <div class="text-xs text-gray-500 mt-0.5">
25
+ Standard modal without centering
26
+ </div>
27
+ </button>
28
+
29
+ <button
30
+ data-kt-modal-toggle="#modal-centered"
31
+ class="px-4 py-2 bg-white border border-gray-300 text-gray-700 text-sm font-medium rounded hover:bg-gray-50 text-left">
32
+ <div class="font-medium">Centered Modal (kt-modal-center)</div>
33
+ <div class="text-xs text-gray-500 mt-0.5">
34
+ Critical test - previously caused bottom-right bug
35
+ </div>
36
+ </button>
37
+
38
+ <button
39
+ data-kt-modal-toggle="#modal-remote"
40
+ class="px-4 py-2 bg-white border border-gray-300 text-gray-700 text-sm font-medium rounded hover:bg-gray-50 text-left">
41
+ <div class="font-medium">Modal with Remote Select</div>
42
+ <div class="text-xs text-gray-500 mt-0.5">
43
+ Tests reload() and clearSelection() methods
44
+ </div>
45
+ </button>
46
+ </div>
47
+
48
+ <div class="mt-6 p-4 bg-gray-50 border border-gray-200 rounded">
49
+ <div class="font-medium text-gray-900 mb-2 text-sm">Control Test</div>
50
+ <select
51
+ data-kt-select="true"
52
+ class="kt-select"
53
+ data-kt-select-placeholder="Select an option...">
54
+ <option value="">Select an option...</option>
55
+ <option value="1">Option 1</option>
56
+ <option value="2">Option 2</option>
57
+ <option value="3">Option 3</option>
58
+ <option value="4">Option 4</option>
59
+ <option value="5">Option 5</option>
60
+ </select>
61
+ <p class="text-xs text-gray-500 mt-2">
62
+ Baseline - should position normally
63
+ </p>
64
+ </div>
65
+ </div>
66
+
67
+ <!-- Basic Modal -->
68
+ <div
69
+ id="modal-basic"
70
+ data-kt-modal="true"
71
+ class="hidden fixed inset-0 z-50 overflow-y-auto">
72
+ <div
73
+ class="flex min-h-full items-center justify-center p-4">
74
+ <div
75
+ data-kt-modal-backdrop="true"
76
+ class="fixed inset-0 bg-gray-900 bg-opacity-50"></div>
77
+
78
+ <div
79
+ class="relative bg-white rounded-lg shadow-xl w-full max-w-lg border border-gray-200">
80
+ <div class="border-b border-gray-200 px-6 py-4">
81
+ <h3 class="text-base font-semibold text-gray-900">Basic Modal</h3>
82
+ </div>
83
+
84
+ <div class="px-6 py-5">
85
+ <label class="block mb-2 font-medium text-gray-700">
86
+ Select in Basic Modal
87
+ </label>
88
+ <select
89
+ data-kt-select="true"
90
+ class="kt-select"
91
+ data-kt-select-placeholder="Choose option...">
92
+ <option value="">Choose option...</option>
93
+ <option value="1">Option 1</option>
94
+ <option value="2">Option 2</option>
95
+ <option value="3">Option 3</option>
96
+ <option value="4">Option 4</option>
97
+ <option value="5">Option 5</option>
98
+ <option value="6">Option 6</option>
99
+ <option value="7">Option 7</option>
100
+ <option value="8">Option 8</option>
101
+ </select>
102
+ <p class="text-xs text-gray-500 mt-3">
103
+ Expected: Dropdown appears below/above select
104
+ </p>
105
+ </div>
106
+
107
+ <div class="border-t border-gray-200 px-6 py-4 flex justify-end">
108
+ <button
109
+ type="button"
110
+ data-kt-modal-dismiss="true"
111
+ class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50">
112
+ Close
113
+ </button>
114
+ </div>
115
+ </div>
116
+ </div>
117
+ </div>
118
+
119
+ <!-- Centered Modal -->
120
+ <div
121
+ id="modal-centered"
122
+ data-kt-modal="true"
123
+ class="hidden fixed inset-0 z-50 overflow-y-auto">
124
+ <div
125
+ class="flex min-h-full items-center justify-center p-4 kt-modal-center">
126
+ <div
127
+ data-kt-modal-backdrop="true"
128
+ class="fixed inset-0 bg-gray-900 bg-opacity-50"></div>
129
+
130
+ <div
131
+ class="relative bg-white rounded-lg shadow-xl w-full max-w-lg border border-gray-200">
132
+ <div class="border-b border-gray-200 px-6 py-4">
133
+ <h3 class="text-base font-semibold text-gray-900">
134
+ Centered Modal (kt-modal-center)
135
+ </h3>
136
+ </div>
137
+
138
+ <div class="px-6 py-5">
139
+ <label class="block mb-2 font-medium text-gray-700">
140
+ Select in Centered Modal
141
+ </label>
142
+ <select
143
+ data-kt-select="true"
144
+ class="kt-select"
145
+ data-kt-select-placeholder="Choose option..."
146
+ data-kt-select-enable-search="true">
147
+ <option value="">Choose option...</option>
148
+ <option value="1">Option 1</option>
149
+ <option value="2">Option 2</option>
150
+ <option value="3">Option 3</option>
151
+ <option value="4">Option 4</option>
152
+ <option value="5">Option 5</option>
153
+ <option value="6">Option 6</option>
154
+ <option value="7">Option 7</option>
155
+ <option value="8">Option 8</option>
156
+ <option value="9">Option 9</option>
157
+ <option value="10">Option 10</option>
158
+ </select>
159
+ <p class="text-xs text-gray-500 mt-3 p-2 bg-gray-50 border border-gray-200 rounded">
160
+ <strong>Critical:</strong> Dropdown should NOT appear in
161
+ bottom-right corner
162
+ </p>
163
+ </div>
164
+
165
+ <div class="border-t border-gray-200 px-6 py-4 flex justify-end">
166
+ <button
167
+ type="button"
168
+ data-kt-modal-dismiss="true"
169
+ class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50">
170
+ Close
171
+ </button>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ </div>
176
+
177
+ <!-- Modal with Remote Select -->
178
+ <div
179
+ id="modal-remote"
180
+ data-kt-modal="true"
181
+ class="hidden fixed inset-0 z-50 overflow-y-auto">
182
+ <div
183
+ class="flex min-h-full items-center justify-center p-4 kt-modal-center">
184
+ <div
185
+ data-kt-modal-backdrop="true"
186
+ class="fixed inset-0 bg-gray-900 bg-opacity-50"></div>
187
+
188
+ <div
189
+ class="relative bg-white rounded-lg shadow-xl w-full max-w-lg border border-gray-200">
190
+ <div class="border-b border-gray-200 px-6 py-4">
191
+ <h3 class="text-base font-semibold text-gray-900">
192
+ Remote Select in Modal
193
+ </h3>
194
+ </div>
195
+
196
+ <div class="px-6 py-5">
197
+ <label class="block mb-2 font-medium text-gray-700">
198
+ Remote Select
199
+ </label>
200
+ <select
201
+ id="remoteSelectInModal"
202
+ data-kt-select="true"
203
+ class="kt-select"
204
+ data-kt-select-remote="true"
205
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
206
+ data-kt-select-data-value-field="id"
207
+ data-kt-select-data-field-text="name"
208
+ data-kt-select-placeholder="Select a user..."
209
+ data-kt-select-enable-search="true">
210
+ <option value="">Select a user...</option>
211
+ </select>
212
+
213
+ <div class="mt-4 flex gap-2">
214
+ <button
215
+ id="reloadBtn"
216
+ type="button"
217
+ class="px-3 py-1.5 text-xs font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50">
218
+ Test reload()
219
+ </button>
220
+ <button
221
+ id="clearBtn"
222
+ type="button"
223
+ class="px-3 py-1.5 text-xs font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50">
224
+ Test clearSelection()
225
+ </button>
226
+ </div>
227
+
228
+ <div id="modalResults" class="mt-4 text-xs min-h-[3rem]"></div>
229
+ </div>
230
+
231
+ <div class="border-t border-gray-200 px-6 py-4 flex justify-end">
232
+ <button
233
+ type="button"
234
+ data-kt-modal-dismiss="true"
235
+ class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50">
236
+ Close
237
+ </button>
238
+ </div>
239
+ </div>
240
+ </div>
241
+ </div>
242
+
243
+ <script>
244
+ document.addEventListener('DOMContentLoaded', function () {
245
+ const form = document.getElementById('testForm');
246
+ const resultsDiv = document.getElementById('results');
247
+ const remoteSelectEl = document.querySelector(
248
+ 'select[name="remoteSelect"]',
249
+ );
250
+
251
+ form.addEventListener('submit', function (e) {
252
+ e.preventDefault();
253
+ resultsDiv.innerHTML = '';
254
+
255
+ const formData = new FormData(form);
256
+ const entries = Array.from(formData.entries());
257
+
258
+ const resultDiv = document.createElement('div');
259
+ resultDiv.className = 'p-3 bg-white border border-gray-200 rounded';
260
+ resultDiv.innerHTML = `
261
+ <div class="font-medium text-gray-900 mb-2">FormData Entries (${entries.length})</div>
262
+ <ul class="space-y-1">
263
+ ${entries
264
+ .map(
265
+ ([key, value]) =>
266
+ `<li class="text-xs font-mono text-gray-700"><span class="font-medium">${key}:</span> "${value}"</li>`,
267
+ )
268
+ .join('')}
269
+ </ul>
270
+ `;
271
+ resultsDiv.appendChild(resultDiv);
272
+
273
+ const remoteSelectValue = formData.get('remoteSelect');
274
+ const verdict = document.createElement('div');
275
+ verdict.className = `p-3 mt-3 rounded border font-medium ${
276
+ remoteSelectValue
277
+ ? 'bg-white border-gray-900 text-gray-900'
278
+ : 'bg-gray-100 border-gray-400 text-gray-700'
279
+ }`;
280
+ verdict.textContent = remoteSelectValue
281
+ ? 'PASS: Remote select included'
282
+ : 'FAIL: Remote select missing';
283
+ resultsDiv.appendChild(verdict);
284
+ });
285
+
286
+ const modal = document.getElementById('modal-remote');
287
+ const remoteSelectInModal = document.getElementById(
288
+ 'remoteSelectInModal',
289
+ );
290
+ const resultsModalDiv = document.getElementById('modalResults');
291
+ const reloadBtn = document.getElementById('reloadBtn');
292
+ const clearBtn = document.getElementById('clearBtn');
293
+
294
+ modal.addEventListener('kt.modal.show', function () {
295
+ const instance = KTSelect.getInstance(remoteSelectInModal);
296
+
297
+ if (instance) {
298
+ reloadBtn.addEventListener('click', async function () {
299
+ resultsModalDiv.innerHTML =
300
+ '<div class="p-2 bg-gray-100 border border-gray-200 rounded">Reloading...</div>';
301
+
302
+ try {
303
+ await instance.reload();
304
+ resultsModalDiv.innerHTML = `
305
+ <div class="p-2 bg-white border border-gray-200 rounded">
306
+ <div class="font-medium text-gray-900">reload() completed</div>
307
+ </div>
308
+ `;
309
+ } catch (error) {
310
+ resultsModalDiv.innerHTML = `
311
+ <div class="p-2 bg-gray-100 border border-gray-300 rounded">
312
+ <div class="font-medium text-gray-900">reload() failed</div>
313
+ <div class="text-gray-600">${error.message}</div>
314
+ </div>
315
+ `;
316
+ }
317
+ });
318
+
319
+ clearBtn.addEventListener('click', function () {
320
+ instance.clearSelection();
321
+ const selectedOptions = instance.getSelectedOptions();
322
+
323
+ resultsModalDiv.innerHTML = `
324
+ <div class="p-2 bg-white border border-gray-200 rounded">
325
+ <div class="font-medium text-gray-900">clearSelection() called</div>
326
+ <div class="text-gray-600">Placeholder visible: ${selectedOptions.length === 0 ? 'Yes' : 'No'}</div>
327
+ </div>
328
+ `;
329
+ });
330
+ }
331
+ });
332
+ });
333
+ </script>
334
+ <script src="../../dist/ktui.js"></script>
335
+ </body>
336
+ </html>
@@ -0,0 +1,283 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Remote Data with Pre-Selected Options</title>
8
+ <link rel="stylesheet" href="../../dist/styles.css">
9
+ </head>
10
+
11
+ <body class="bg-gray-50 min-h-screen p-8">
12
+ <div class="max-w-4xl mx-auto">
13
+ <h1 class="text-3xl font-bold mb-8">Remote Data with Pre-Selected Options</h1>
14
+
15
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
16
+ <!-- Test 1: Native selected attribute with remote data -->
17
+ <div class="bg-white rounded-lg shadow p-6">
18
+ <h2 class="text-xl font-semibold mb-4">Test 1: Native &lt;option selected&gt;</h2>
19
+ <p class="text-sm text-gray-600 mb-4">Single-select with native selected attribute (user ID 5)</p>
20
+
21
+ <select
22
+ id="test-1"
23
+ class="kt-select"
24
+ data-kt-select
25
+ data-kt-select-remote="true"
26
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
27
+ data-kt-select-data-field-value="id"
28
+ data-kt-select-data-field-text="name"
29
+ data-kt-select-enable-search="true"
30
+ data-kt-select-debug="true"
31
+ placeholder="Select a user..."
32
+ >
33
+ <option value="5" selected>Loading...</option>
34
+ </select>
35
+
36
+ <div class="mt-4 p-3 bg-gray-100 rounded text-sm">
37
+ <strong>Expected:</strong> User with ID 5 should be selected after remote data loads
38
+ </div>
39
+ </div>
40
+
41
+ <!-- Test 2: data-kt-select-pre-selected attribute -->
42
+ <div class="bg-white rounded-lg shadow p-6">
43
+ <h2 class="text-xl font-semibold mb-4">Test 2: data-kt-select-pre-selected</h2>
44
+ <p class="text-sm text-gray-600 mb-4">Using pre-selected attribute (user ID 3)</p>
45
+
46
+ <select
47
+ id="test-2"
48
+ class="kt-select"
49
+ data-kt-select
50
+ data-kt-select-remote="true"
51
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
52
+ data-kt-select-data-field-value="id"
53
+ data-kt-select-data-field-text="name"
54
+ data-kt-select-pre-selected="3"
55
+ data-kt-select-enable-search="true"
56
+ data-kt-select-debug="true"
57
+ placeholder="Select a user..."
58
+ ></select>
59
+
60
+ <div class="mt-4 p-3 bg-gray-100 rounded text-sm">
61
+ <strong>Expected:</strong> User with ID 3 should be selected after remote data loads
62
+ </div>
63
+ </div>
64
+
65
+ <!-- Test 3: Multiple pre-selected with native selected -->
66
+ <div class="bg-white rounded-lg shadow p-6">
67
+ <h2 class="text-xl font-semibold mb-4">Test 3: Multiple Pre-Selected (Native)</h2>
68
+ <p class="text-sm text-gray-600 mb-4">Multiple select with native selected attributes</p>
69
+
70
+ <select
71
+ id="test-3"
72
+ class="kt-select"
73
+ multiple
74
+ data-kt-select
75
+ data-kt-select-remote="true"
76
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
77
+ data-kt-select-data-field-value="id"
78
+ data-kt-select-data-field-text="name"
79
+ data-kt-select-multiple="true"
80
+ data-kt-select-enable-search="true"
81
+ data-kt-select-debug="true"
82
+ placeholder="Select users..."
83
+ >
84
+ <option value="2" selected>Loading...</option>
85
+ <option value="4" selected>Loading...</option>
86
+ <option value="7" selected>Loading...</option>
87
+ </select>
88
+
89
+ <div class="mt-4 p-3 bg-gray-100 rounded text-sm">
90
+ <strong>Expected:</strong> Users with IDs 2, 4, and 7 should be selected
91
+ </div>
92
+ </div>
93
+
94
+ <!-- Test 4: Multiple pre-selected with data attribute -->
95
+ <div class="bg-white rounded-lg shadow p-6">
96
+ <h2 class="text-xl font-semibold mb-4">Test 4: Multiple Pre-Selected (Attribute)</h2>
97
+ <p class="text-sm text-gray-600 mb-4">Multiple select with data-kt-select-pre-selected</p>
98
+
99
+ <select
100
+ id="test-4"
101
+ class="kt-select"
102
+ multiple
103
+ data-kt-select
104
+ data-kt-select-remote="true"
105
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
106
+ data-kt-select-data-field-value="id"
107
+ data-kt-select-data-field-text="name"
108
+ data-kt-select-multiple="true"
109
+ data-kt-select-pre-selected="1,6,9"
110
+ data-kt-select-enable-search="true"
111
+ data-kt-select-debug="true"
112
+ placeholder="Select users..."
113
+ ></select>
114
+
115
+ <div class="mt-4 p-3 bg-gray-100 rounded text-sm">
116
+ <strong>Expected:</strong> Users with IDs 1, 6, and 9 should be selected
117
+ </div>
118
+ </div>
119
+
120
+ <!-- Test 5: Combination of both methods -->
121
+ <div class="bg-white rounded-lg shadow p-6">
122
+ <h2 class="text-xl font-semibold mb-4">Test 5: Combined Methods</h2>
123
+ <p class="text-sm text-gray-600 mb-4">Both native selected and data attribute</p>
124
+
125
+ <select
126
+ id="test-5"
127
+ class="kt-select"
128
+ multiple
129
+ data-kt-select
130
+ data-kt-select-remote="true"
131
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
132
+ data-kt-select-data-field-value="id"
133
+ data-kt-select-data-field-text="name"
134
+ data-kt-select-multiple="true"
135
+ data-kt-select-pre-selected="8,10"
136
+ data-kt-select-enable-search="true"
137
+ data-kt-select-debug="true"
138
+ placeholder="Select users..."
139
+ >
140
+ <option value="3" selected>Loading...</option>
141
+ <option value="5" selected>Loading...</option>
142
+ </select>
143
+
144
+ <div class="mt-4 p-3 bg-gray-100 rounded text-sm">
145
+ <strong>Expected:</strong> Users with IDs 3, 5, 8, and 10 should be selected
146
+ </div>
147
+ </div>
148
+
149
+ <!-- Test 6: Non-existent values -->
150
+ <div class="bg-white rounded-lg shadow p-6">
151
+ <h2 class="text-xl font-semibold mb-4">Test 6: Non-Existent Values</h2>
152
+ <p class="text-sm text-gray-600 mb-4">Pre-selected values that don't exist in remote data</p>
153
+
154
+ <select
155
+ id="test-6"
156
+ class="kt-select"
157
+ multiple
158
+ data-kt-select
159
+ data-kt-select-remote="true"
160
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
161
+ data-kt-select-data-field-value="id"
162
+ data-kt-select-data-field-text="name"
163
+ data-kt-select-multiple="true"
164
+ data-kt-select-enable-search="true"
165
+ data-kt-select-debug="true"
166
+ placeholder="Select users..."
167
+ >
168
+ <option value="999" selected>Non-existent user</option>
169
+ <option value="4" selected>Should work</option>
170
+ <option value="888" selected>Another fake</option>
171
+ </select>
172
+
173
+ <div class="mt-4 p-3 bg-gray-100 rounded text-sm">
174
+ <strong>Expected:</strong> Only user with ID 4 should be selected (IDs 999 and 888 don't exist)
175
+ </div>
176
+ </div>
177
+
178
+ <!-- Test 7: Single select with multiple native selected (edge case) -->
179
+ <div class="bg-white rounded-lg shadow p-6">
180
+ <h2 class="text-xl font-semibold mb-4">Test 7: Single Select Edge Case</h2>
181
+ <p class="text-sm text-gray-600 mb-4">Single-select with multiple selected options (should use first)</p>
182
+
183
+ <select
184
+ id="test-7"
185
+ class="kt-select"
186
+ data-kt-select
187
+ data-kt-select-remote="true"
188
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
189
+ data-kt-select-data-field-value="id"
190
+ data-kt-select-data-field-text="name"
191
+ data-kt-select-enable-search="true"
192
+ data-kt-select-debug="true"
193
+ placeholder="Select a user..."
194
+ >
195
+ <option value="6" selected>First selected</option>
196
+ <option value="8" selected>Second selected</option>
197
+ <option value="10" selected>Third selected</option>
198
+ </select>
199
+
200
+ <div class="mt-4 p-3 bg-gray-100 rounded text-sm">
201
+ <strong>Expected:</strong> Only user with ID 6 (first) should be selected in single-select mode
202
+ </div>
203
+ </div>
204
+
205
+ <!-- Test 8: With Tags enabled -->
206
+ <div class="bg-white rounded-lg shadow p-6">
207
+ <h2 class="text-xl font-semibold mb-4">Test 8: With Tags</h2>
208
+ <p class="text-sm text-gray-600 mb-4">Multiple select with tags and pre-selected values</p>
209
+
210
+ <select
211
+ id="test-8"
212
+ class="kt-select"
213
+ multiple
214
+ data-kt-select
215
+ data-kt-select-remote="true"
216
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
217
+ data-kt-select-data-field-value="id"
218
+ data-kt-select-data-field-text="name"
219
+ data-kt-select-multiple="true"
220
+ data-kt-select-tags="true"
221
+ data-kt-select-enable-search="true"
222
+ data-kt-select-debug="true"
223
+ placeholder="Select users..."
224
+ >
225
+ <option value="1" selected>Loading...</option>
226
+ <option value="5" selected>Loading...</option>
227
+ <option value="9" selected>Loading...</option>
228
+ </select>
229
+
230
+ <div class="mt-4 p-3 bg-gray-100 rounded text-sm">
231
+ <strong>Expected:</strong> Users with IDs 1, 5, and 9 should be selected and displayed as tags
232
+ </div>
233
+ </div>
234
+ </div>
235
+
236
+ <!-- Debug Console -->
237
+ <div class="bg-white rounded-lg shadow p-6 mt-8">
238
+ <h2 class="text-xl font-semibold mb-4">Debug Console</h2>
239
+ <p class="text-sm text-gray-600 mb-4">Check browser console (F12) for debug output</p>
240
+
241
+ <div class="space-y-2">
242
+ <button onclick="checkAllSelections()" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
243
+ Check All Selections
244
+ </button>
245
+ <button onclick="resetAll()" class="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 ml-2">
246
+ Reset All
247
+ </button>
248
+ </div>
249
+
250
+ <pre id="debug-output" class="mt-4 p-4 bg-gray-900 text-green-400 rounded text-xs overflow-auto max-h-64"></pre>
251
+ </div>
252
+ </div>
253
+
254
+ <script src="../../dist/ktui.js"></script>
255
+ <script>
256
+ function checkAllSelections() {
257
+ const output = [];
258
+ for (let i = 1; i <= 8; i++) {
259
+ const select = document.getElementById(`test-${i}`);
260
+ if (select) {
261
+ const selectedOptions = Array.from(select.selectedOptions).map(opt => ({
262
+ value: opt.value,
263
+ text: opt.text
264
+ }));
265
+ output.push(`Test ${i}: ${selectedOptions.length > 0 ? JSON.stringify(selectedOptions, null, 2) : 'No selection'}`);
266
+ }
267
+ }
268
+ document.getElementById('debug-output').textContent = output.join('\n\n');
269
+ }
270
+
271
+ function resetAll() {
272
+ location.reload();
273
+ }
274
+
275
+ // Auto-check selections after remote data loads
276
+ setTimeout(() => {
277
+ checkAllSelections();
278
+ }, 3000);
279
+ </script>
280
+ </body>
281
+
282
+ </html>
283
+
@@ -74,8 +74,11 @@ function createCheckboxHandler(element, config, fireEvent) {
74
74
  return;
75
75
  var value = input.value;
76
76
  var selectedRows = getSelectedRows();
77
- if (input.checked) {
78
- if (!selectedRows.includes(value))
77
+ var wasChecked = selectedRows.includes(value);
78
+ var isNowChecked = input.checked;
79
+ // Update state first
80
+ if (isNowChecked) {
81
+ if (!wasChecked)
79
82
  selectedRows.push(value);
80
83
  }
81
84
  else {
@@ -83,14 +86,24 @@ function createCheckboxHandler(element, config, fireEvent) {
83
86
  }
84
87
  setSelectedRows(selectedRows);
85
88
  updateHeaderCheckboxState();
89
+ // Fire specific checked/unchecked events after state is updated
90
+ if (isNowChecked && !wasChecked) {
91
+ fireEvent('checked');
92
+ }
93
+ else if (!isNowChecked && wasChecked) {
94
+ fireEvent('unchecked');
95
+ }
96
+ // Always fire changed event for backward compatibility
86
97
  fireEvent('changed');
87
98
  }
88
99
  // When the header checkbox is toggled
89
100
  function checkboxToggle(event) {
90
101
  var checked = !isChecked();
102
+ // Update state first, then fire events
103
+ change(checked);
104
+ // Fire checked/unchecked events after state is updated
91
105
  var eventType = checked ? 'checked' : 'unchecked';
92
106
  fireEvent(eventType);
93
- change(checked);
94
107
  }
95
108
  // Change all visible checkboxes and update selectedRows
96
109
  function change(checked) {