@keenthemes/ktui 1.0.19 → 1.0.21

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 (111) hide show
  1. package/dist/ktui.js +690 -166
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +165 -31
  5. package/examples/image-input/file-upload-example.html +189 -0
  6. package/examples/select/remote-data_.html +5 -0
  7. package/examples/select/test-optimizations.html +227 -0
  8. package/examples/select/test-remote-search.html +151 -0
  9. package/examples/sticky/README.md +158 -0
  10. package/examples/sticky/debug-sticky.html +144 -0
  11. package/examples/sticky/test-runner.html +175 -0
  12. package/examples/sticky/test-sticky-logic.js +369 -0
  13. package/examples/sticky/test-sticky-positioning.html +386 -0
  14. package/examples/toast/example.html +52 -0
  15. package/lib/cjs/components/component.js +59 -5
  16. package/lib/cjs/components/component.js.map +1 -1
  17. package/lib/cjs/components/datatable/datatable-sort.js +4 -0
  18. package/lib/cjs/components/datatable/datatable-sort.js.map +1 -1
  19. package/lib/cjs/components/datatable/datatable.js +79 -12
  20. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  21. package/lib/cjs/components/image-input/image-input.js +10 -2
  22. package/lib/cjs/components/image-input/image-input.js.map +1 -1
  23. package/lib/cjs/components/select/combobox.js +50 -20
  24. package/lib/cjs/components/select/combobox.js.map +1 -1
  25. package/lib/cjs/components/select/config.js +1 -0
  26. package/lib/cjs/components/select/config.js.map +1 -1
  27. package/lib/cjs/components/select/dropdown.js +4 -2
  28. package/lib/cjs/components/select/dropdown.js.map +1 -1
  29. package/lib/cjs/components/select/index.js.map +1 -1
  30. package/lib/cjs/components/select/option.js +2 -1
  31. package/lib/cjs/components/select/option.js.map +1 -1
  32. package/lib/cjs/components/select/remote.js +50 -50
  33. package/lib/cjs/components/select/remote.js.map +1 -1
  34. package/lib/cjs/components/select/search.js +15 -5
  35. package/lib/cjs/components/select/search.js.map +1 -1
  36. package/lib/cjs/components/select/select.js +273 -32
  37. package/lib/cjs/components/select/select.js.map +1 -1
  38. package/lib/cjs/components/select/tags.js +3 -1
  39. package/lib/cjs/components/select/tags.js.map +1 -1
  40. package/lib/cjs/components/select/templates.js +6 -0
  41. package/lib/cjs/components/select/templates.js.map +1 -1
  42. package/lib/cjs/components/select/utils.js +23 -10
  43. package/lib/cjs/components/select/utils.js.map +1 -1
  44. package/lib/cjs/components/stepper/stepper.js +59 -12
  45. package/lib/cjs/components/stepper/stepper.js.map +1 -1
  46. package/lib/cjs/components/sticky/sticky.js +52 -14
  47. package/lib/cjs/components/sticky/sticky.js.map +1 -1
  48. package/lib/esm/components/component.js +59 -5
  49. package/lib/esm/components/component.js.map +1 -1
  50. package/lib/esm/components/datatable/datatable-sort.js +4 -0
  51. package/lib/esm/components/datatable/datatable-sort.js.map +1 -1
  52. package/lib/esm/components/datatable/datatable.js +78 -12
  53. package/lib/esm/components/datatable/datatable.js.map +1 -1
  54. package/lib/esm/components/image-input/image-input.js +10 -2
  55. package/lib/esm/components/image-input/image-input.js.map +1 -1
  56. package/lib/esm/components/select/combobox.js +50 -20
  57. package/lib/esm/components/select/combobox.js.map +1 -1
  58. package/lib/esm/components/select/config.js +1 -0
  59. package/lib/esm/components/select/config.js.map +1 -1
  60. package/lib/esm/components/select/dropdown.js +4 -2
  61. package/lib/esm/components/select/dropdown.js.map +1 -1
  62. package/lib/esm/components/select/index.js +1 -1
  63. package/lib/esm/components/select/index.js.map +1 -1
  64. package/lib/esm/components/select/option.js +2 -1
  65. package/lib/esm/components/select/option.js.map +1 -1
  66. package/lib/esm/components/select/remote.js +50 -50
  67. package/lib/esm/components/select/remote.js.map +1 -1
  68. package/lib/esm/components/select/search.js +16 -6
  69. package/lib/esm/components/select/search.js.map +1 -1
  70. package/lib/esm/components/select/select.js +273 -32
  71. package/lib/esm/components/select/select.js.map +1 -1
  72. package/lib/esm/components/select/tags.js +3 -1
  73. package/lib/esm/components/select/tags.js.map +1 -1
  74. package/lib/esm/components/select/templates.js +6 -0
  75. package/lib/esm/components/select/templates.js.map +1 -1
  76. package/lib/esm/components/select/utils.js +23 -10
  77. package/lib/esm/components/select/utils.js.map +1 -1
  78. package/lib/esm/components/stepper/stepper.js +59 -12
  79. package/lib/esm/components/stepper/stepper.js.map +1 -1
  80. package/lib/esm/components/sticky/sticky.js +52 -14
  81. package/lib/esm/components/sticky/sticky.js.map +1 -1
  82. package/package.json +2 -2
  83. package/src/components/component.ts +19 -4
  84. package/src/components/datatable/datatable-sort.ts +6 -0
  85. package/src/components/datatable/datatable.ts +98 -15
  86. package/src/components/datatable/types.ts +5 -1
  87. package/src/components/image-input/image-input.ts +11 -2
  88. package/src/components/image-input/types.ts +1 -0
  89. package/src/components/input/input-group.css +1 -1
  90. package/src/components/input/input.css +1 -1
  91. package/src/components/scrollable/scrollable.css +3 -3
  92. package/src/components/select/combobox.ts +84 -34
  93. package/src/components/select/config.ts +2 -0
  94. package/src/components/select/dropdown.ts +20 -11
  95. package/src/components/select/index.ts +6 -1
  96. package/src/components/select/option.ts +7 -6
  97. package/src/components/select/remote.ts +51 -52
  98. package/src/components/select/search.ts +59 -44
  99. package/src/components/select/select.css +26 -17
  100. package/src/components/select/select.ts +472 -101
  101. package/src/components/select/tags.ts +9 -3
  102. package/src/components/select/templates.ts +10 -0
  103. package/src/components/select/utils.ts +55 -20
  104. package/src/components/select/variants.css +0 -1
  105. package/src/components/stepper/stepper.ts +2 -2
  106. package/src/components/sticky/sticky.ts +47 -16
  107. package/src/components/sticky/types.ts +3 -0
  108. package/src/components/table/table.css +1 -1
  109. package/src/components/textarea/textarea.css +1 -1
  110. package/src/components/toast/toast.css +84 -47
  111. package/src/components/toast/types.ts +3 -0
@@ -0,0 +1,189 @@
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>KTUI Image Input - File Upload Example</title>
7
+ <link rel="stylesheet" href="../../dist/styles.css">
8
+ <style>
9
+ body { padding: 2rem; font-family: Arial, sans-serif; }
10
+ .example-section { margin: 2rem 0; padding: 1rem; border: 1px solid #ddd; }
11
+ .test-result { margin: 0.5rem 0; padding: 0.5rem; background: #f5f5f5; }
12
+ .success { background: #d4edda; color: #155724; }
13
+ .error { background: #f8d7da; color: #721c24; }
14
+ .info { background: #d1ecf1; color: #0c5460; }
15
+ .code-block { background: #f8f9fa; padding: 1rem; border-radius: 4px; margin: 1rem 0; }
16
+ </style>
17
+ </head>
18
+ <body>
19
+ <h1>KTUI Image Input - File Upload Example</h1>
20
+ <p>This example demonstrates how to use the KTUI Image Input component with proper file upload functionality.</p>
21
+
22
+ <div class="example-section">
23
+ <h2>Image Input Component</h2>
24
+ <div class="kt-image-input size-16" data-kt-image-input="true">
25
+ <input accept=".png, .jpg, .jpeg" name="avatar" type="file">
26
+ <input name="avatar_remove" type="hidden"/>
27
+ <button class="kt-image-input-remove" data-kt-image-input-remove="true" type="button">
28
+ <i class="ki-filled ki-cross"></i>
29
+ </button>
30
+ <div class="kt-image-input-placeholder" data-kt-image-input-placeholder="true">
31
+ <div class="kt-image-input-preview" data-kt-image-input-preview="true"></div>
32
+ </div>
33
+ </div>
34
+ </div>
35
+
36
+ <div class="example-section">
37
+ <h2>Testing Controls</h2>
38
+ <button onclick="testFileAccess()">Test File Access</button>
39
+ <button onclick="testPublicMethods()">Test Public Methods</button>
40
+ <button onclick="testFormSubmission()">Test Form Submission</button>
41
+ <button onclick="clearResults()">Clear Results</button>
42
+ </div>
43
+
44
+ <div class="example-section">
45
+ <h2>Test Results</h2>
46
+ <div id="test-results"></div>
47
+ </div>
48
+
49
+ <div class="example-section">
50
+ <h2>Form Submission Example</h2>
51
+ <p>This form demonstrates how to properly handle file uploads with KTUI Image Input:</p>
52
+ <form id="test-form" onsubmit="handleFormSubmit(event)">
53
+ <div class="kt-image-input size-16" data-kt-image-input="true">
54
+ <input accept=".png, .jpg, .jpeg" name="test_image" type="file">
55
+ <input name="test_image_remove" type="hidden"/>
56
+ <button class="kt-image-input-remove" data-kt-image-input-remove="true" type="button">
57
+ <i class="ki-filled ki-cross"></i>
58
+ </button>
59
+ <div class="kt-image-input-placeholder" data-kt-image-input-placeholder="true">
60
+ <div class="kt-image-input-preview" data-kt-image-input-preview="true"></div>
61
+ </div>
62
+ </div>
63
+ <button type="submit">Submit Form</button>
64
+ </form>
65
+ </div>
66
+
67
+ <div class="example-section">
68
+ <h2>Usage Code Example</h2>
69
+ <div class="code-block">
70
+ <h3>HTML Structure</h3>
71
+ <pre><code>&lt;div class="kt-image-input size-16" data-kt-image-input="true"&gt;
72
+ &lt;input accept=".png, .jpg, .jpeg" name="avatar" type="file"&gt;
73
+ &lt;input name="avatar_remove" type="hidden"/&gt;
74
+ &lt;button class="kt-image-input-remove" data-kt-image-input-remove="true" type="button"&gt;
75
+ &lt;i class="ki-filled ki-cross"&gt;&lt;/i&gt;
76
+ &lt;/button&gt;
77
+ &lt;div class="kt-image-input-placeholder" data-kt-image-input-placeholder="true"&gt;
78
+ &lt;div class="kt-image-input-preview" data-kt-image-input-preview="true"&gt;&lt;/div&gt;
79
+ &lt;/div&gt;
80
+ &lt;/div&gt;</code></pre>
81
+
82
+ <h3>JavaScript - File Upload</h3>
83
+ <pre><code>// Get the KTUI Image Input instance
84
+ const imageInput = KTImageInput.getInstance(element);
85
+
86
+ // Access the selected file for form submission
87
+ const selectedFile = imageInput.getSelectedFile();
88
+ if (selectedFile) {
89
+ const formData = new FormData();
90
+ formData.append('image', selectedFile);
91
+ // Submit formData to server
92
+ }
93
+
94
+ // Check component state
95
+ if (imageInput.isEmpty()) {
96
+ console.log('No file selected');
97
+ }
98
+
99
+ if (imageInput.isChanged()) {
100
+ console.log('File has been selected');
101
+ }</code></pre>
102
+ </div>
103
+ </div>
104
+
105
+ <script src="../../dist/ktui.min.js"></script>
106
+ <script>
107
+ let imageInputInstance = null;
108
+
109
+ // Initialize when DOM is ready
110
+ document.addEventListener('DOMContentLoaded', function() {
111
+ const element = document.querySelector('[data-kt-image-input]');
112
+ if (element) {
113
+ imageInputInstance = KTImageInput.getInstance(element);
114
+ addResult('Component initialized successfully', 'success');
115
+ }
116
+ });
117
+
118
+ function addResult(message, type = 'info') {
119
+ const results = document.getElementById('test-results');
120
+ const div = document.createElement('div');
121
+ div.className = `test-result ${type}`;
122
+ div.textContent = `${new Date().toLocaleTimeString()}: ${message}`;
123
+ results.appendChild(div);
124
+ }
125
+
126
+ function testFileAccess() {
127
+ if (!imageInputInstance) {
128
+ addResult('Image input instance not found', 'error');
129
+ return;
130
+ }
131
+
132
+ const file = imageInputInstance.getSelectedFile();
133
+ if (file) {
134
+ addResult(`File access successful: ${file.name} (${file.size} bytes)`, 'success');
135
+ } else {
136
+ addResult('No file selected', 'info');
137
+ }
138
+ }
139
+
140
+ function testPublicMethods() {
141
+ if (!imageInputInstance) {
142
+ addResult('Image input instance not found', 'error');
143
+ return;
144
+ }
145
+
146
+ const isEmpty = imageInputInstance.isEmpty();
147
+ const isChanged = imageInputInstance.isChanged();
148
+
149
+ addResult(`isEmpty(): ${isEmpty}`, isEmpty ? 'info' : 'success');
150
+ addResult(`isChanged(): ${isChanged}`, isChanged ? 'success' : 'info');
151
+ }
152
+
153
+ function testFormSubmission() {
154
+ const form = document.getElementById('test-form');
155
+ const fileInput = form.querySelector('input[type="file"]');
156
+ const formData = new FormData(form);
157
+
158
+ addResult('Form data created', 'info');
159
+
160
+ if (fileInput.files.length > 0) {
161
+ addResult(`File in form: ${fileInput.files[0].name}`, 'success');
162
+ } else {
163
+ addResult('No file in form data (expected - input is cleared for UI)', 'info');
164
+ }
165
+
166
+ // Test with KTUI instance
167
+ const formImageInput = KTImageInput.getInstance(form.querySelector('[data-kt-image-input]'));
168
+ if (formImageInput) {
169
+ const selectedFile = formImageInput.getSelectedFile();
170
+ if (selectedFile) {
171
+ addResult(`KTUI file access: ${selectedFile.name}`, 'success');
172
+ } else {
173
+ addResult('No file in KTUI instance', 'error');
174
+ }
175
+ }
176
+ }
177
+
178
+ function handleFormSubmit(event) {
179
+ event.preventDefault();
180
+ addResult('Form submission intercepted for testing', 'info');
181
+ testFormSubmission();
182
+ }
183
+
184
+ function clearResults() {
185
+ document.getElementById('test-results').innerHTML = '';
186
+ }
187
+ </script>
188
+ </body>
189
+ </html>
@@ -21,6 +21,11 @@
21
21
  data-kt-select-data-field-value="id"
22
22
  data-kt-select-data-field-text="name"
23
23
  data-kt-select-enable-search="true"
24
+ data-kt-select-search-param="q"
25
+ data-kt-select-search-min-length="2"
26
+ data-kt-select-search-debounce="300"
27
+ data-kt-select-debug="true"
28
+ placeholder="Search users..."
24
29
  ></select>
25
30
 
26
31
  </div>
@@ -0,0 +1,227 @@
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>Test Optimizations</title>
7
+ <link rel="stylesheet" href="../../dist/styles.css">
8
+ <style>
9
+ .test-container {
10
+ max-width: 800px;
11
+ margin: 20px auto;
12
+ padding: 20px;
13
+ }
14
+ .test-section {
15
+ margin-bottom: 20px;
16
+ padding: 15px;
17
+ border: 1px solid #e5e7eb;
18
+ border-radius: 8px;
19
+ background: white;
20
+ }
21
+ .metrics {
22
+ background: #f9fafb;
23
+ padding: 10px;
24
+ border-radius: 4px;
25
+ font-family: monospace;
26
+ font-size: 12px;
27
+ margin-top: 10px;
28
+ }
29
+ .success { color: #059669; }
30
+ .warning { color: #d97706; }
31
+ .error { color: #dc2626; }
32
+ </style>
33
+ </head>
34
+ <body class="bg-gray-50 min-h-screen">
35
+ <div class="test-container">
36
+ <h1>Remote Select Optimizations Test</h1>
37
+
38
+ <div class="test-section">
39
+ <h3>Performance Test: Multiple Remote Selects</h3>
40
+ <button onclick="testPerformance()" style="padding: 8px 16px; background: #3b82f6; color: white; border: none; border-radius: 4px; cursor: pointer;">
41
+ Test Performance (Create 10 Remote Selects)
42
+ </button>
43
+ <div id="performance-results" class="metrics">Click button to test...</div>
44
+ </div>
45
+
46
+ <div class="test-section">
47
+ <h3>Functionality Test: Basic Remote Select</h3>
48
+ <label class="block mb-2 font-medium text-gray-700">Users from JSONPlaceholder</label>
49
+ <select
50
+ id="test-select"
51
+ data-kt-select
52
+ data-kt-select-remote="true"
53
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
54
+ data-kt-select-data-field-value="id"
55
+ data-kt-select-data-field-text="name"
56
+ data-kt-select-enable-search="true"
57
+ data-kt-select-debug="true"
58
+ placeholder="Select a user..."
59
+ ></select>
60
+ <div id="functionality-results" class="metrics">Initializing...</div>
61
+ </div>
62
+
63
+ <div class="test-section">
64
+ <h3>Search Test: Remote Search Functionality</h3>
65
+ <label class="block mb-2 font-medium text-gray-700">Posts from JSONPlaceholder</label>
66
+ <select
67
+ id="search-test-select"
68
+ data-kt-select
69
+ data-kt-select-remote="true"
70
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/posts"
71
+ data-kt-select-data-field-value="id"
72
+ data-kt-select-data-field-text="title"
73
+ data-kt-select-enable-search="true"
74
+ data-kt-select-search-param="q"
75
+ data-kt-select-search-min-length="2"
76
+ data-kt-select-debug="true"
77
+ placeholder="Search posts..."
78
+ ></select>
79
+ <div id="search-results" class="metrics">Ready for search testing...</div>
80
+ </div>
81
+ </div>
82
+
83
+ <script src="../../dist/ktui.js"></script>
84
+ <script>
85
+ // Performance test function
86
+ function testPerformance() {
87
+ const resultsDiv = document.getElementById('performance-results');
88
+ resultsDiv.innerHTML = 'Running performance test...';
89
+
90
+ const startTime = performance.now();
91
+ const instances = [];
92
+
93
+ // Create 10 remote select instances
94
+ for (let i = 0; i < 10; i++) {
95
+ const element = document.createElement('select');
96
+ element.setAttribute('data-kt-select', '');
97
+ element.setAttribute('data-kt-select-remote', 'true');
98
+ element.setAttribute('data-kt-select-data-url', 'https://jsonplaceholder.typicode.com/users');
99
+ element.setAttribute('data-kt-select-data-field-value', 'id');
100
+ element.setAttribute('data-kt-select-data-field-text', 'name');
101
+ element.setAttribute('data-kt-select-debug', 'false'); // Disable debug for performance
102
+
103
+ try {
104
+ const instance = new KTSelect(element);
105
+ instances.push(instance);
106
+ } catch (error) {
107
+ console.error(`Instance ${i} creation failed:`, error);
108
+ }
109
+ }
110
+
111
+ const endTime = performance.now();
112
+ const duration = endTime - startTime;
113
+
114
+ // Cleanup
115
+ instances.forEach(instance => {
116
+ if (instance.dispose) instance.dispose();
117
+ });
118
+
119
+ resultsDiv.innerHTML = `
120
+ <span class="${duration < 1000 ? 'success' : 'warning'}">
121
+ āœ… Performance Test Results:<br>
122
+ • Created ${instances.length}/10 instances in ${duration.toFixed(2)}ms<br>
123
+ • Average: ${(duration / instances.length).toFixed(2)}ms per instance<br>
124
+ • Optimizations working: ${duration < 1000 ? 'YES' : 'NEEDS IMPROVEMENT'}
125
+ </span>
126
+ `;
127
+ }
128
+
129
+ // Functionality test
130
+ function testFunctionality() {
131
+ const resultsDiv = document.getElementById('functionality-results');
132
+ const testSelect = document.getElementById('test-select');
133
+
134
+ if (testSelect && testSelect.instance) {
135
+ try {
136
+ // Test dropdown opening
137
+ testSelect.instance.openDropdown();
138
+ setTimeout(() => {
139
+ testSelect.instance.closeDropdown();
140
+
141
+ // Test search functionality
142
+ const searchInput = testSelect.instance.getSearchInput();
143
+ if (searchInput) {
144
+ searchInput.value = 'test';
145
+ searchInput.dispatchEvent(new Event('input'));
146
+
147
+ setTimeout(() => {
148
+ searchInput.value = '';
149
+ searchInput.dispatchEvent(new Event('input'));
150
+
151
+ resultsDiv.innerHTML = `
152
+ <span class="success">
153
+ āœ… Functionality Test PASSED:<br>
154
+ • Instance created successfully<br>
155
+ • Dropdown opens/closes correctly<br>
156
+ • Search input works<br>
157
+ • Optimizations maintain functionality
158
+ </span>
159
+ `;
160
+ }, 1000);
161
+ }
162
+ }, 1000);
163
+ } catch (error) {
164
+ resultsDiv.innerHTML = `
165
+ <span class="error">
166
+ āŒ Functionality Test FAILED:<br>
167
+ Error: ${error.message}
168
+ </span>
169
+ `;
170
+ }
171
+ } else {
172
+ resultsDiv.innerHTML = `
173
+ <span class="error">
174
+ āŒ Functionality Test FAILED:<br>
175
+ Remote select instance not found
176
+ </span>
177
+ `;
178
+ }
179
+ }
180
+
181
+ // Search test
182
+ function testSearch() {
183
+ const resultsDiv = document.getElementById('search-results');
184
+ const searchSelect = document.getElementById('search-test-select');
185
+
186
+ if (searchSelect && searchSelect.instance) {
187
+ const searchInput = searchSelect.instance.getSearchInput();
188
+ if (searchInput) {
189
+ // Simulate typing
190
+ searchInput.value = 'qui';
191
+ searchInput.dispatchEvent(new Event('input'));
192
+
193
+ setTimeout(() => {
194
+ searchInput.value = '';
195
+ searchInput.dispatchEvent(new Event('input'));
196
+
197
+ resultsDiv.innerHTML = `
198
+ <span class="success">
199
+ āœ… Search Test PASSED:<br>
200
+ • Search input responds to input<br>
201
+ • Remote search triggers correctly<br>
202
+ • Optimized rendering works
203
+ </span>
204
+ `;
205
+ }, 2000);
206
+ }
207
+ }
208
+ }
209
+
210
+ // Initialize tests
211
+ document.addEventListener('DOMContentLoaded', () => {
212
+ try {
213
+ KTSelect.init();
214
+
215
+ // Wait for initialization to complete
216
+ setTimeout(() => {
217
+ testFunctionality();
218
+ testSearch();
219
+ }, 2000);
220
+ } catch (error) {
221
+ document.getElementById('functionality-results').innerHTML =
222
+ '<span class="error">āŒ Failed to initialize KTSelect: ' + error.message + '</span>';
223
+ }
224
+ });
225
+ </script>
226
+ </body>
227
+ </html>
@@ -0,0 +1,151 @@
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 Search Test</title>
8
+ <link rel="stylesheet" href="../../dist/styles.css">
9
+ <style>
10
+ .test-container {
11
+ max-width: 600px;
12
+ margin: 20px auto;
13
+ padding: 20px;
14
+ }
15
+ .test-section {
16
+ margin-bottom: 30px;
17
+ padding: 20px;
18
+ border: 1px solid #e5e7eb;
19
+ border-radius: 8px;
20
+ background: white;
21
+ }
22
+ .test-section h3 {
23
+ margin-top: 0;
24
+ color: #374151;
25
+ }
26
+ .debug-info {
27
+ background: #f9fafb;
28
+ padding: 10px;
29
+ border-radius: 4px;
30
+ font-family: monospace;
31
+ font-size: 12px;
32
+ margin-top: 10px;
33
+ }
34
+ </style>
35
+ </head>
36
+
37
+ <body class="bg-gray-50 min-h-screen">
38
+ <div class="test-container">
39
+ <h1>Remote Select Search Test</h1>
40
+
41
+ <div class="test-section">
42
+ <h3>Test 1: Basic Remote Search</h3>
43
+ <label class="block mb-2 font-medium text-gray-700">Users from JSONPlaceholder</label>
44
+ <select
45
+ data-kt-select
46
+ data-kt-select-remote="true"
47
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/users"
48
+ data-kt-select-data-field-value="id"
49
+ data-kt-select-data-field-text="name"
50
+ data-kt-select-enable-search="true"
51
+ data-kt-select-search-param="q"
52
+ data-kt-select-search-min-length="2"
53
+ data-kt-select-search-debounce="300"
54
+ data-kt-select-debug="true"
55
+ placeholder="Search users..."
56
+ ></select>
57
+ <div class="debug-info">
58
+ <strong>Expected behavior:</strong> Type at least 2 characters to search users. Options should display with proper text content.
59
+ </div>
60
+ </div>
61
+
62
+ <div class="test-section">
63
+ <h3>Test 2: Posts with Custom Field Mapping</h3>
64
+ <label class="block mb-2 font-medium text-gray-700">Posts from JSONPlaceholder</label>
65
+ <select
66
+ data-kt-select
67
+ data-kt-select-remote="true"
68
+ data-kt-select-data-url="https://jsonplaceholder.typicode.com/posts"
69
+ data-kt-select-data-field-value="id"
70
+ data-kt-select-data-field-text="title"
71
+ data-kt-select-enable-search="true"
72
+ data-kt-select-search-param="q"
73
+ data-kt-select-search-min-length="3"
74
+ data-kt-select-search-debounce="500"
75
+ data-kt-select-debug="true"
76
+ placeholder="Search posts..."
77
+ ></select>
78
+ <div class="debug-info">
79
+ <strong>Expected behavior:</strong> Type at least 3 characters to search posts. Should show post titles as options.
80
+ </div>
81
+ </div>
82
+
83
+ <div class="test-section">
84
+ <h3>Test 3: Error Handling</h3>
85
+ <label class="block mb-2 font-medium text-gray-700">Invalid URL Test</label>
86
+ <select
87
+ data-kt-select
88
+ data-kt-select-remote="true"
89
+ data-kt-select-data-url="https://invalid-url-that-does-not-exist.com/api/data"
90
+ data-kt-select-data-field-value="id"
91
+ data-kt-select-data-field-text="name"
92
+ data-kt-select-enable-search="true"
93
+ data-kt-select-search-param="q"
94
+ data-kt-select-search-min-length="1"
95
+ data-kt-select-search-debounce="300"
96
+ data-kt-select-debug="true"
97
+ placeholder="This should show error..."
98
+ ></select>
99
+ <div class="debug-info">
100
+ <strong>Expected behavior:</strong> Should show error message and restore original state after 2 seconds.
101
+ </div>
102
+ </div>
103
+
104
+ <div class="test-section">
105
+ <h3>Console Debug Info</h3>
106
+ <div class="debug-info">
107
+ Open browser developer tools console to see debug information about the remote search functionality.
108
+ </div>
109
+ </div>
110
+ </div>
111
+
112
+ <script src="../../dist/ktui.js"></script>
113
+ <script src="validation-test.js"></script>
114
+ <script>
115
+ // Initialize KTSelect components
116
+ KTSelect.init();
117
+
118
+ // Add some console logging for testing
119
+ console.log('Remote Select Test Page Loaded');
120
+ console.log('All KTSelect components should be initialized with debug logging enabled');
121
+
122
+ // Run validation tests after a short delay to ensure everything is loaded
123
+ setTimeout(() => {
124
+ console.log('\nšŸš€ Running End-to-End Validation Tests...');
125
+
126
+ // Test real API interaction
127
+ const testSelect = document.querySelector('select[data-kt-select-remote="true"]');
128
+ if (testSelect && testSelect.instance) {
129
+ console.log('āœ… E2E Test 1 PASSED: Remote select instance found');
130
+
131
+ // Test dropdown opening
132
+ try {
133
+ testSelect.instance.openDropdown();
134
+ console.log('āœ… E2E Test 2 PASSED: Dropdown opens successfully');
135
+
136
+ // Test dropdown closing
137
+ setTimeout(() => {
138
+ testSelect.instance.closeDropdown();
139
+ console.log('āœ… E2E Test 3 PASSED: Dropdown closes successfully');
140
+ }, 1000);
141
+ } catch (error) {
142
+ console.log('āŒ E2E Test 2-3 FAILED: Dropdown operation error:', error.message);
143
+ }
144
+ } else {
145
+ console.log('āŒ E2E Test 1 FAILED: Remote select instance not found');
146
+ }
147
+ }, 2000);
148
+ </script>
149
+ </body>
150
+
151
+ </html>