@keenthemes/ktui 1.0.25 → 1.0.27

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 (85) hide show
  1. package/dist/ktui.js +335 -36
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +216 -13
  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.html +205 -0
  9. package/examples/modal/remote-select-dropdown.html +166 -0
  10. package/examples/modal/select-dropdown-container.html +129 -0
  11. package/examples/select/formdata-remote.html +161 -0
  12. package/examples/select/modal-positioning-test.html +338 -0
  13. package/lib/cjs/components/datatable/datatable-checkbox.js +16 -3
  14. package/lib/cjs/components/datatable/datatable-checkbox.js.map +1 -1
  15. package/lib/cjs/components/datatable/datatable.js +3 -5
  16. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  17. package/lib/cjs/components/image-input/image-input.js.map +1 -1
  18. package/lib/cjs/components/modal/modal.js +16 -2
  19. package/lib/cjs/components/modal/modal.js.map +1 -1
  20. package/lib/cjs/components/select/config.js +5 -0
  21. package/lib/cjs/components/select/config.js.map +1 -1
  22. package/lib/cjs/components/select/dropdown.js +54 -3
  23. package/lib/cjs/components/select/dropdown.js.map +1 -1
  24. package/lib/cjs/components/select/select.js +241 -23
  25. package/lib/cjs/components/select/select.js.map +1 -1
  26. package/lib/cjs/components/select/templates.js.map +1 -1
  27. package/lib/esm/components/datatable/datatable-checkbox.js +16 -3
  28. package/lib/esm/components/datatable/datatable-checkbox.js.map +1 -1
  29. package/lib/esm/components/datatable/datatable.js +3 -5
  30. package/lib/esm/components/datatable/datatable.js.map +1 -1
  31. package/lib/esm/components/image-input/image-input.js.map +1 -1
  32. package/lib/esm/components/modal/modal.js +16 -2
  33. package/lib/esm/components/modal/modal.js.map +1 -1
  34. package/lib/esm/components/select/config.js +5 -0
  35. package/lib/esm/components/select/config.js.map +1 -1
  36. package/lib/esm/components/select/dropdown.js +54 -3
  37. package/lib/esm/components/select/dropdown.js.map +1 -1
  38. package/lib/esm/components/select/select.js +241 -23
  39. package/lib/esm/components/select/select.js.map +1 -1
  40. package/lib/esm/components/select/templates.js.map +1 -1
  41. package/package.json +1 -1
  42. package/src/components/datatable/datatable-checkbox.ts +18 -3
  43. package/src/components/datatable/datatable.ts +3 -0
  44. package/src/components/datatable/types.ts +1 -0
  45. package/src/components/image-input/image-input.ts +12 -15
  46. package/src/components/modal/modal.ts +20 -2
  47. package/src/components/select/config.ts +6 -0
  48. package/src/components/select/dropdown.ts +69 -4
  49. package/src/components/select/select.ts +306 -36
  50. package/src/components/select/templates.ts +2 -1
  51. package/lib/cjs/components/config.js +0 -26
  52. package/lib/cjs/components/config.js.map +0 -1
  53. package/lib/cjs/components/config.umd.js +0 -23
  54. package/lib/cjs/components/config.umd.js.map +0 -1
  55. package/lib/cjs/components/menu/index.js +0 -6
  56. package/lib/cjs/components/menu/index.js.map +0 -1
  57. package/lib/cjs/components/menu/menu.js +0 -1021
  58. package/lib/cjs/components/menu/menu.js.map +0 -1
  59. package/lib/cjs/components/menu/types.js +0 -3
  60. package/lib/cjs/components/menu/types.js.map +0 -1
  61. package/lib/cjs/components/theme/index.js +0 -6
  62. package/lib/cjs/components/theme/index.js.map +0 -1
  63. package/lib/cjs/components/theme/theme.js +0 -147
  64. package/lib/cjs/components/theme/theme.js.map +0 -1
  65. package/lib/cjs/components/theme/types.js +0 -3
  66. package/lib/cjs/components/theme/types.js.map +0 -1
  67. package/lib/esm/components/config.js +0 -24
  68. package/lib/esm/components/config.js.map +0 -1
  69. package/lib/esm/components/config.umd.js +0 -23
  70. package/lib/esm/components/config.umd.js.map +0 -1
  71. package/lib/esm/components/menu/index.js +0 -2
  72. package/lib/esm/components/menu/index.js.map +0 -1
  73. package/lib/esm/components/menu/menu.js +0 -1018
  74. package/lib/esm/components/menu/menu.js.map +0 -1
  75. package/lib/esm/components/menu/types.js +0 -2
  76. package/lib/esm/components/menu/types.js.map +0 -1
  77. package/lib/esm/components/theme/index.js +0 -2
  78. package/lib/esm/components/theme/index.js.map +0 -1
  79. package/lib/esm/components/theme/theme.js +0 -144
  80. package/lib/esm/components/theme/theme.js.map +0 -1
  81. package/lib/esm/components/theme/types.js +0 -2
  82. package/lib/esm/components/theme/types.js.map +0 -1
  83. /package/examples/select/{dark-mode-test.html → dark-mode.html} +0 -0
  84. /package/examples/select/{dropdowncontainer-test.html → dropdowncontainer.html} +0 -0
  85. /package/examples/select/{global-config-test.html → global-config.html} +0 -0
@@ -0,0 +1,365 @@
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>DataTable Remote Data with Checkboxes Test</title>
8
+ <link rel="stylesheet" href="../../dist/styles.css">
9
+ </head>
10
+
11
+ <body class="bg-gray-50 min-h-screen p-4">
12
+ <div class="container mx-auto max-w-5xl">
13
+ <div class="bg-white rounded-lg shadow-lg p-8 mt-6 border border-gray-200">
14
+ <div class="mb-6">
15
+ <h1 class="text-xl font-bold text-gray-900">DataTable Remote Data with Checkboxes Test</h1>
16
+ <p class="text-sm text-gray-600 mt-2">Tests checkbox events with server-side data from JSONPlaceholder API</p>
17
+ </div>
18
+
19
+ <!-- Current Selection Display -->
20
+ <div class="mb-6">
21
+ <h2 class="text-lg font-semibold text-gray-800 mb-3">Current Selection</h2>
22
+ <div id="selectionDisplay" class="bg-blue-50 border border-blue-200 rounded-md p-4">
23
+ <div class="text-gray-700">
24
+ <strong>Checked IDs:</strong> <span id="checkedIds" class="font-mono">[]</span>
25
+ </div>
26
+ <div class="text-gray-700 mt-2">
27
+ <strong>Count:</strong> <span id="checkedCount" class="font-semibold">0</span>
28
+ </div>
29
+ </div>
30
+ </div>
31
+
32
+ <!-- Test Controls -->
33
+ <div class="mb-6 flex gap-3 flex-wrap">
34
+ <button
35
+ onclick="testCheckAll()"
36
+ class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors font-medium">
37
+ Check All
38
+ </button>
39
+ <button
40
+ onclick="testUncheckAll()"
41
+ class="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 transition-colors font-medium">
42
+ Uncheck All
43
+ </button>
44
+ <button
45
+ onclick="testToggle()"
46
+ class="px-4 py-2 bg-purple-600 text-white rounded-md hover:bg-purple-700 transition-colors font-medium">
47
+ Toggle All
48
+ </button>
49
+ <button
50
+ onclick="testGetChecked()"
51
+ class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors font-medium">
52
+ Get Checked
53
+ </button>
54
+ </div>
55
+
56
+ <!-- DataTable Container -->
57
+ <div class="kt-card">
58
+ <div class="kt-card-table" id="remote-datatable-container">
59
+ <div class="kt-table-wrapper kt-scrollable">
60
+ <table id="remote-checkbox-table" class="kt-table" data-kt-datatable-table="true">
61
+ <thead>
62
+ <tr>
63
+ <th scope="col" class="w-12" data-kt-datatable-column="checkbox">
64
+ <input
65
+ type="checkbox"
66
+ data-kt-datatable-check="true"
67
+ class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 focus:ring-2">
68
+ </th>
69
+ <th scope="col" class="w-20" data-kt-datatable-column="id">
70
+ <span class="kt-table-col">
71
+ <span class="kt-table-col-label">ID</span>
72
+ <span class="kt-table-col-sort"></span>
73
+ </span>
74
+ </th>
75
+ <th scope="col" class="w-48" data-kt-datatable-column="name">
76
+ <span class="kt-table-col">
77
+ <span class="kt-table-col-label">Name</span>
78
+ <span class="kt-table-col-sort"></span>
79
+ </span>
80
+ </th>
81
+ <th scope="col" class="w-64" data-kt-datatable-column="email">
82
+ <span class="kt-table-col">
83
+ <span class="kt-table-col-label">Email</span>
84
+ <span class="kt-table-col-sort"></span>
85
+ </span>
86
+ </th>
87
+ <th scope="col" class="w-40" data-kt-datatable-column="company">
88
+ <span class="kt-table-col">
89
+ <span class="kt-table-col-label">Company</span>
90
+ <span class="kt-table-col-sort"></span>
91
+ </span>
92
+ </th>
93
+ </tr>
94
+ </thead>
95
+ <tbody>
96
+ <!-- Data will be loaded from API -->
97
+ </tbody>
98
+ </table>
99
+ </div>
100
+
101
+ <!-- Pagination Info -->
102
+ <div class="flex items-center justify-between mt-4">
103
+ <div class="flex items-center space-x-2">
104
+ <span class="text-sm text-gray-700">Show</span>
105
+ <select data-kt-datatable-size="true" class="border border-gray-300 rounded px-2 py-1 bg-white text-gray-900">
106
+ <option value="5" selected>5</option>
107
+ <option value="10">10</option>
108
+ </select>
109
+ <span class="text-sm text-gray-700">entries</span>
110
+ </div>
111
+ <div data-kt-datatable-info="true" class="text-sm text-gray-700"></div>
112
+ </div>
113
+
114
+ <!-- Pagination Controls -->
115
+ <div class="flex justify-center mt-4">
116
+ <div data-kt-datatable-pagination="true" class="flex space-x-1"></div>
117
+ </div>
118
+ </div>
119
+ </div>
120
+ </div>
121
+
122
+ <!-- Event Log Section -->
123
+ <div class="bg-white rounded-lg shadow-lg p-8 mt-6 border border-gray-200">
124
+ <div class="flex items-center justify-between mb-3">
125
+ <h2 class="text-lg font-semibold text-gray-800">Event Log</h2>
126
+ <button
127
+ id="clearLog"
128
+ onclick="clearEventLog()"
129
+ class="px-3 py-1 text-sm bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition-colors">
130
+ Clear Log
131
+ </button>
132
+ </div>
133
+ <div id="eventLog" class="bg-gray-50 border border-gray-200 rounded-md p-4 h-64 overflow-y-auto font-mono text-sm">
134
+ <div class="text-gray-500">No events yet. Interact with checkboxes to see events...</div>
135
+ </div>
136
+ </div>
137
+ </div>
138
+
139
+ <script src="../../dist/ktui.js"></script>
140
+ <script>
141
+ let datatableInstance = null;
142
+
143
+ // Event log helper functions
144
+ function addEventLog(eventName, details = '') {
145
+ const logElement = document.getElementById('eventLog');
146
+ const timestamp = new Date().toLocaleTimeString();
147
+ const logEntry = document.createElement('div');
148
+ logEntry.className = 'mb-2 pb-2 border-b border-gray-200';
149
+
150
+ let eventColor = 'text-gray-700';
151
+ if (eventName === 'checked') {
152
+ eventColor = 'text-green-600';
153
+ } else if (eventName === 'unchecked') {
154
+ eventColor = 'text-red-600';
155
+ } else if (eventName === 'changed') {
156
+ eventColor = 'text-blue-600';
157
+ } else if (eventName === 'fetch' || eventName === 'fetched') {
158
+ eventColor = 'text-purple-600';
159
+ }
160
+
161
+ logEntry.innerHTML = `
162
+ <div class="flex items-start gap-2">
163
+ <span class="text-gray-500 text-xs">[${timestamp}]</span>
164
+ <span class="font-semibold ${eventColor}">${eventName.toUpperCase()}</span>
165
+ ${details ? `<span class="text-gray-600">${details}</span>` : ''}
166
+ </div>
167
+ `;
168
+
169
+ // Remove "No events yet" message if it exists
170
+ const firstChild = logElement.firstChild;
171
+ if (firstChild && firstChild.textContent.includes('No events yet')) {
172
+ logElement.removeChild(firstChild);
173
+ }
174
+
175
+ logElement.insertBefore(logEntry, logElement.firstChild);
176
+
177
+ // Keep only last 50 entries
178
+ while (logElement.children.length > 50) {
179
+ logElement.removeChild(logElement.lastChild);
180
+ }
181
+ }
182
+
183
+ function clearEventLog() {
184
+ const logElement = document.getElementById('eventLog');
185
+ logElement.innerHTML = '<div class="text-gray-500">No events yet. Interact with checkboxes to see events...</div>';
186
+ }
187
+
188
+ function updateSelectionDisplay() {
189
+ if (!datatableInstance || typeof datatableInstance.getChecked !== 'function') {
190
+ return;
191
+ }
192
+ try {
193
+ const checkedIds = datatableInstance.getChecked();
194
+ document.getElementById('checkedIds').textContent = JSON.stringify(checkedIds);
195
+ document.getElementById('checkedCount').textContent = checkedIds.length;
196
+ } catch (e) {
197
+ console.error('Error updating selection display:', e);
198
+ }
199
+ }
200
+
201
+ // Test functions
202
+ function testCheckAll() {
203
+ if (datatableInstance) {
204
+ datatableInstance.check();
205
+ }
206
+ }
207
+
208
+ function testUncheckAll() {
209
+ if (datatableInstance) {
210
+ datatableInstance.uncheck();
211
+ }
212
+ }
213
+
214
+ function testToggle() {
215
+ if (datatableInstance) {
216
+ datatableInstance.toggle();
217
+ }
218
+ }
219
+
220
+ function testGetChecked() {
221
+ if (datatableInstance) {
222
+ const checkedIds = datatableInstance.getChecked();
223
+ addEventLog('info', `Manual getChecked() call returned: [${checkedIds.join(', ')}]`);
224
+ }
225
+ }
226
+
227
+ // Initialize the datatable when page loads
228
+ document.addEventListener('DOMContentLoaded', function() {
229
+ setTimeout(() => {
230
+ try {
231
+ // Initialize KTUI components
232
+ if (typeof KTDataTable !== 'undefined') {
233
+ const container = document.getElementById('remote-datatable-container');
234
+ if (container) {
235
+ // Set data attributes for datatable initialization
236
+ container.setAttribute('data-kt-datatable', 'true');
237
+ container.setAttribute('data-kt-datatable-page-size', '5');
238
+ container.setAttribute('data-kt-datatable-api-endpoint', 'https://jsonplaceholder.typicode.com/users');
239
+
240
+ datatableInstance = new KTDataTable(container, {
241
+ apiEndpoint: 'https://jsonplaceholder.typicode.com/users',
242
+ requestMethod: 'GET',
243
+ requestHeaders: {
244
+ 'Content-Type': 'application/json'
245
+ },
246
+ columns: {
247
+ 'checkbox': {
248
+ render: function(cellData, rowData, context) {
249
+ const checkbox = document.createElement('input');
250
+ checkbox.type = 'checkbox';
251
+ checkbox.value = rowData.id;
252
+ checkbox.setAttribute('data-kt-datatable-row-check', 'true');
253
+ checkbox.className = 'w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 focus:ring-2';
254
+ return checkbox;
255
+ }
256
+ },
257
+ 'id': {
258
+ render: function(cellData, rowData, context) {
259
+ return String(cellData);
260
+ }
261
+ },
262
+ 'name': {
263
+ render: function(cellData, rowData, context) {
264
+ return String(cellData);
265
+ }
266
+ },
267
+ 'email': {
268
+ render: function(cellData, rowData, context) {
269
+ return String(cellData);
270
+ }
271
+ },
272
+ 'company': {
273
+ render: function(cellData, rowData, context) {
274
+ return String(cellData);
275
+ }
276
+ }
277
+ },
278
+ mapResponse: function(response) {
279
+ // JSONPlaceholder returns an array directly
280
+ // Transform nested objects to flat structure and format for datatable
281
+ if (Array.isArray(response)) {
282
+ const transformedData = response.map(user => ({
283
+ checkbox: '', // Empty value for checkbox column
284
+ id: user.id,
285
+ name: user.name,
286
+ email: user.email,
287
+ company: user.company ? user.company.name : ''
288
+ }));
289
+
290
+ // Get current pagination state for client-side pagination
291
+ // Since JSONPlaceholder doesn't support server-side pagination
292
+ // Use 'this' context which refers to the datatable instance
293
+ const state = this.getState();
294
+ const page = state.page || 1;
295
+ const pageSize = state.pageSize || 10;
296
+
297
+ // Slice data for current page (client-side pagination)
298
+ const startIndex = (page - 1) * pageSize;
299
+ const endIndex = startIndex + pageSize;
300
+ const paginatedData = transformedData.slice(startIndex, endIndex);
301
+
302
+ return {
303
+ data: paginatedData,
304
+ totalCount: transformedData.length
305
+ };
306
+ }
307
+ // If already in correct format, return as is
308
+ return response;
309
+ },
310
+ checkbox: {
311
+ preserveSelection: true
312
+ }
313
+ });
314
+
315
+ console.log('✅ Remote DataTable with Checkboxes initialized successfully!');
316
+
317
+ // Attach event listeners using DOM events (without kt-datatable- prefix)
318
+ container.addEventListener('checked', function(event) {
319
+ const checkedIds = datatableInstance.getChecked();
320
+ addEventLog('checked', `Selected ${checkedIds.length} rows: [${checkedIds.join(', ')}]`);
321
+ updateSelectionDisplay();
322
+ });
323
+
324
+ container.addEventListener('unchecked', function(event) {
325
+ const checkedIds = datatableInstance.getChecked();
326
+ addEventLog('unchecked', `Deselected. Remaining: ${checkedIds.length} rows: [${checkedIds.join(', ')}]`);
327
+ updateSelectionDisplay();
328
+ });
329
+
330
+ container.addEventListener('changed', function(event) {
331
+ const checkedIds = datatableInstance.getChecked();
332
+ addEventLog('changed', `Selection changed. Total: ${checkedIds.length} rows: [${checkedIds.join(', ')}]`);
333
+ updateSelectionDisplay();
334
+ });
335
+
336
+ container.addEventListener('fetch', function() {
337
+ addEventLog('fetch', 'Fetching data from server...');
338
+ });
339
+
340
+ container.addEventListener('fetched', function() {
341
+ try {
342
+ const state = datatableInstance.getState();
343
+ addEventLog('fetched', `Loaded ${state.totalItems || 0} total records`);
344
+ // Update selection display after data is loaded
345
+ updateSelectionDisplay();
346
+ } catch (e) {
347
+ console.error('Error in fetched handler:', e);
348
+ }
349
+ });
350
+ } else {
351
+ console.error('❌ DataTable container not found');
352
+ }
353
+ } else {
354
+ console.error('❌ KTDataTable is not defined');
355
+ }
356
+ } catch (error) {
357
+ console.error('❌ Error initializing Remote DataTable: ' + error.message);
358
+ }
359
+ }, 100);
360
+ });
361
+ </script>
362
+ </body>
363
+
364
+ </html>
365
+
@@ -0,0 +1,205 @@
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 Persistent Property Test</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="../../dist/styles.css">
9
+ <style>
10
+ .test-case {
11
+ margin: 1rem 0;
12
+ padding: 1.5rem;
13
+ border: 1px solid #e5e7eb;
14
+ border-radius: 0.5rem;
15
+ background: #fafafa;
16
+ }
17
+ .expected {
18
+ color: #374151;
19
+ font-weight: 500;
20
+ }
21
+ </style>
22
+ </head>
23
+ <body class="p-8 bg-white min-h-screen flex items-start justify-center">
24
+ <div class="w-full max-w-3xl">
25
+ <h1 class="text-3xl font-bold mb-2 text-gray-900">Modal Persistent Property Test</h1>
26
+ <p class="text-gray-600 mb-8">Testing the interaction between <code class="bg-gray-100 px-2 py-1 rounded text-sm">persistent</code> and <code class="bg-gray-100 px-2 py-1 rounded text-sm">backdropStatic</code> properties.</p>
27
+
28
+ <div class="mb-8 p-4 border border-gray-200 rounded bg-gray-50">
29
+ <h2 class="text-lg font-semibold mb-3 text-gray-900">Test Instructions</h2>
30
+ <ol class="list-decimal list-inside space-y-2 text-gray-700">
31
+ <li>Click each "Open Modal" button below</li>
32
+ <li>Try clicking on the modal backdrop (gray area around the modal content)</li>
33
+ <li>Try clicking on the invisible area below the modal content</li>
34
+ <li>Verify the behavior matches the expected result</li>
35
+ </ol>
36
+ </div>
37
+
38
+ <!-- Test Case 1: persistent=false, backdropStatic=false -->
39
+ <div class="test-case">
40
+ <h3 class="text-base font-semibold mb-3 text-gray-900">Test Case 1</h3>
41
+ <p class="mb-2 text-sm text-gray-700">
42
+ <code class="bg-white px-2 py-1 rounded border border-gray-200">persistent: false</code>,
43
+ <code class="bg-white px-2 py-1 rounded border border-gray-200">backdropStatic: false</code>
44
+ </p>
45
+ <p class="expected mb-4 text-sm">✓ Expected: Modal SHOULD close when clicking on backdrop or invisible area</p>
46
+ <button
47
+ data-kt-modal-toggle="#modal-test-1"
48
+ class="px-4 py-2 bg-gray-900 text-white rounded hover:bg-gray-700 text-sm font-medium">
49
+ Open Modal
50
+ </button>
51
+ </div>
52
+
53
+ <!-- Test Case 2: persistent=true, backdropStatic=false -->
54
+ <div class="test-case">
55
+ <h3 class="text-base font-semibold mb-3 text-gray-900">Test Case 2 <span class="text-xs font-normal text-gray-500">(Bug Fix Verification)</span></h3>
56
+ <p class="mb-2 text-sm text-gray-700">
57
+ <code class="bg-white px-2 py-1 rounded border border-gray-200">persistent: true</code>,
58
+ <code class="bg-white px-2 py-1 rounded border border-gray-200">backdropStatic: false</code>
59
+ </p>
60
+ <p class="expected mb-4 text-sm">✓ Expected: Modal should NOT close when clicking on backdrop or invisible area</p>
61
+ <button
62
+ data-kt-modal-toggle="#modal-test-2"
63
+ class="px-4 py-2 bg-gray-900 text-white rounded hover:bg-gray-700 text-sm font-medium">
64
+ Open Modal
65
+ </button>
66
+ </div>
67
+
68
+ <!-- Test Case 3: persistent=false, backdropStatic=true -->
69
+ <div class="test-case">
70
+ <h3 class="text-base font-semibold mb-3 text-gray-900">Test Case 3</h3>
71
+ <p class="mb-2 text-sm text-gray-700">
72
+ <code class="bg-white px-2 py-1 rounded border border-gray-200">persistent: false</code>,
73
+ <code class="bg-white px-2 py-1 rounded border border-gray-200">backdropStatic: true</code>
74
+ </p>
75
+ <p class="expected mb-4 text-sm">✓ Expected: Modal should NOT close when clicking on backdrop (backdropStatic takes precedence)</p>
76
+ <button
77
+ data-kt-modal-toggle="#modal-test-3"
78
+ class="px-4 py-2 bg-gray-900 text-white rounded hover:bg-gray-700 text-sm font-medium">
79
+ Open Modal
80
+ </button>
81
+ </div>
82
+
83
+ <!-- Test Case 4: persistent=true, backdropStatic=true -->
84
+ <div class="test-case">
85
+ <h3 class="text-base font-semibold mb-3 text-gray-900">Test Case 4</h3>
86
+ <p class="mb-2 text-sm text-gray-700">
87
+ <code class="bg-white px-2 py-1 rounded border border-gray-200">persistent: true</code>,
88
+ <code class="bg-white px-2 py-1 rounded border border-gray-200">backdropStatic: true</code>
89
+ </p>
90
+ <p class="expected mb-4 text-sm">✓ Expected: Modal should NOT close when clicking on backdrop or invisible area</p>
91
+ <button
92
+ data-kt-modal-toggle="#modal-test-4"
93
+ class="px-4 py-2 bg-gray-900 text-white rounded hover:bg-gray-700 text-sm font-medium">
94
+ Open Modal
95
+ </button>
96
+ </div>
97
+ </div>
98
+
99
+ <!-- Modal 1: persistent=false, backdropStatic=false -->
100
+ <div
101
+ id="modal-test-1"
102
+ class="hidden fixed inset-0 z-50 flex items-center justify-center"
103
+ data-kt-modal="true"
104
+ data-kt-modal-persistent="false"
105
+ data-kt-modal-backdrop-static="false">
106
+ <div class="bg-white rounded-lg shadow-xl p-6 max-w-md w-full mx-4 border border-gray-200">
107
+ <h2 class="text-lg font-semibold mb-4 text-gray-900">Test Case 1</h2>
108
+ <p class="mb-3 text-sm text-gray-700">
109
+ This modal has <code class="bg-gray-100 px-1 text-xs">persistent: false</code> and
110
+ <code class="bg-gray-100 px-1 text-xs">backdropStatic: false</code>.
111
+ </p>
112
+ <p class="mb-4 text-sm text-gray-600">
113
+ Click on the gray area around this modal or below it. The modal should close.
114
+ </p>
115
+ <button
116
+ data-kt-modal-dismiss="true"
117
+ class="px-4 py-2 bg-gray-900 text-white rounded hover:bg-gray-700 text-sm">
118
+ Close
119
+ </button>
120
+ </div>
121
+ </div>
122
+
123
+ <!-- Modal 2: persistent=true, backdropStatic=false -->
124
+ <div
125
+ id="modal-test-2"
126
+ class="hidden fixed inset-0 z-50 flex items-center justify-center"
127
+ data-kt-modal="true"
128
+ data-kt-modal-persistent="true"
129
+ data-kt-modal-backdrop-static="false">
130
+ <div class="bg-white rounded-lg shadow-xl p-6 max-w-md w-full mx-4 border border-gray-200">
131
+ <h2 class="text-lg font-semibold mb-4 text-gray-900">Test Case 2 <span class="text-xs font-normal text-gray-500">(Bug Fix)</span></h2>
132
+ <p class="mb-3 text-sm text-gray-700">
133
+ This modal has <code class="bg-gray-100 px-1 text-xs">persistent: true</code> and
134
+ <code class="bg-gray-100 px-1 text-xs">backdropStatic: false</code>.
135
+ </p>
136
+ <p class="mb-4 text-sm text-gray-600 border-l-2 border-gray-400 pl-3">
137
+ Click on the gray area around this modal or below it. The modal should NOT close.
138
+ </p>
139
+ <button
140
+ data-kt-modal-dismiss="true"
141
+ class="px-4 py-2 bg-gray-900 text-white rounded hover:bg-gray-700 text-sm">
142
+ Close
143
+ </button>
144
+ </div>
145
+ </div>
146
+
147
+ <!-- Modal 3: persistent=false, backdropStatic=true -->
148
+ <div
149
+ id="modal-test-3"
150
+ class="hidden fixed inset-0 z-50 flex items-center justify-center"
151
+ data-kt-modal="true"
152
+ data-kt-modal-persistent="false"
153
+ data-kt-modal-backdrop-static="true">
154
+ <div class="bg-white rounded-lg shadow-xl p-6 max-w-md w-full mx-4 border border-gray-200">
155
+ <h2 class="text-lg font-semibold mb-4 text-gray-900">Test Case 3</h2>
156
+ <p class="mb-3 text-sm text-gray-700">
157
+ This modal has <code class="bg-gray-100 px-1 text-xs">persistent: false</code> and
158
+ <code class="bg-gray-100 px-1 text-xs">backdropStatic: true</code>.
159
+ </p>
160
+ <p class="mb-4 text-sm text-gray-600">
161
+ Click on the gray area around this modal or below it. The modal should NOT close (backdropStatic prevents it).
162
+ </p>
163
+ <button
164
+ data-kt-modal-dismiss="true"
165
+ class="px-4 py-2 bg-gray-900 text-white rounded hover:bg-gray-700 text-sm">
166
+ Close
167
+ </button>
168
+ </div>
169
+ </div>
170
+
171
+ <!-- Modal 4: persistent=true, backdropStatic=true -->
172
+ <div
173
+ id="modal-test-4"
174
+ class="hidden fixed inset-0 z-50 flex items-center justify-center"
175
+ data-kt-modal="true"
176
+ data-kt-modal-persistent="true"
177
+ data-kt-modal-backdrop-static="true">
178
+ <div class="bg-white rounded-lg shadow-xl p-6 max-w-md w-full mx-4 border border-gray-200">
179
+ <h2 class="text-lg font-semibold mb-4 text-gray-900">Test Case 4</h2>
180
+ <p class="mb-3 text-sm text-gray-700">
181
+ This modal has <code class="bg-gray-100 px-1 text-xs">persistent: true</code> and
182
+ <code class="bg-gray-100 px-1 text-xs">backdropStatic: true</code>.
183
+ </p>
184
+ <p class="mb-4 text-sm text-gray-600">
185
+ Click on the gray area around this modal or below it. The modal should NOT close (both properties prevent it).
186
+ </p>
187
+ <button
188
+ data-kt-modal-dismiss="true"
189
+ class="px-4 py-2 bg-gray-900 text-white rounded hover:bg-gray-700 text-sm">
190
+ Close
191
+ </button>
192
+ </div>
193
+ </div>
194
+
195
+ <script src="../../dist/ktui.js"></script>
196
+ <script>
197
+ // Initialize modals
198
+ document.addEventListener('DOMContentLoaded', function() {
199
+ KTModal.init();
200
+ console.log('Modal test page loaded. All modals initialized.');
201
+ });
202
+ </script>
203
+ </body>
204
+ </html>
205
+