@keenthemes/ktui 1.0.20 → 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 (98) hide show
  1. package/dist/ktui.js +418 -144
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +139 -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 +5 -3
  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 +9 -3
  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/dropdown.js +4 -2
  26. package/lib/cjs/components/select/dropdown.js.map +1 -1
  27. package/lib/cjs/components/select/index.js.map +1 -1
  28. package/lib/cjs/components/select/option.js +2 -1
  29. package/lib/cjs/components/select/option.js.map +1 -1
  30. package/lib/cjs/components/select/remote.js +50 -50
  31. package/lib/cjs/components/select/remote.js.map +1 -1
  32. package/lib/cjs/components/select/search.js +7 -5
  33. package/lib/cjs/components/select/search.js.map +1 -1
  34. package/lib/cjs/components/select/select.js +199 -33
  35. package/lib/cjs/components/select/select.js.map +1 -1
  36. package/lib/cjs/components/select/tags.js +3 -1
  37. package/lib/cjs/components/select/tags.js.map +1 -1
  38. package/lib/cjs/components/select/templates.js.map +1 -1
  39. package/lib/cjs/components/select/utils.js +23 -10
  40. package/lib/cjs/components/select/utils.js.map +1 -1
  41. package/lib/cjs/components/sticky/sticky.js +52 -14
  42. package/lib/cjs/components/sticky/sticky.js.map +1 -1
  43. package/lib/esm/components/component.js +5 -3
  44. package/lib/esm/components/component.js.map +1 -1
  45. package/lib/esm/components/datatable/datatable-sort.js +4 -0
  46. package/lib/esm/components/datatable/datatable-sort.js.map +1 -1
  47. package/lib/esm/components/datatable/datatable.js +9 -3
  48. package/lib/esm/components/datatable/datatable.js.map +1 -1
  49. package/lib/esm/components/image-input/image-input.js +10 -2
  50. package/lib/esm/components/image-input/image-input.js.map +1 -1
  51. package/lib/esm/components/select/combobox.js +50 -20
  52. package/lib/esm/components/select/combobox.js.map +1 -1
  53. package/lib/esm/components/select/dropdown.js +4 -2
  54. package/lib/esm/components/select/dropdown.js.map +1 -1
  55. package/lib/esm/components/select/index.js +1 -1
  56. package/lib/esm/components/select/index.js.map +1 -1
  57. package/lib/esm/components/select/option.js +2 -1
  58. package/lib/esm/components/select/option.js.map +1 -1
  59. package/lib/esm/components/select/remote.js +50 -50
  60. package/lib/esm/components/select/remote.js.map +1 -1
  61. package/lib/esm/components/select/search.js +8 -6
  62. package/lib/esm/components/select/search.js.map +1 -1
  63. package/lib/esm/components/select/select.js +199 -33
  64. package/lib/esm/components/select/select.js.map +1 -1
  65. package/lib/esm/components/select/tags.js +3 -1
  66. package/lib/esm/components/select/tags.js.map +1 -1
  67. package/lib/esm/components/select/templates.js.map +1 -1
  68. package/lib/esm/components/select/utils.js +23 -10
  69. package/lib/esm/components/select/utils.js.map +1 -1
  70. package/lib/esm/components/sticky/sticky.js +52 -14
  71. package/lib/esm/components/sticky/sticky.js.map +1 -1
  72. package/package.json +1 -1
  73. package/src/components/component.ts +12 -11
  74. package/src/components/datatable/datatable-sort.ts +6 -0
  75. package/src/components/datatable/datatable.ts +90 -81
  76. package/src/components/image-input/image-input.ts +11 -2
  77. package/src/components/image-input/types.ts +1 -0
  78. package/src/components/input/input-group.css +1 -1
  79. package/src/components/input/input.css +1 -1
  80. package/src/components/scrollable/scrollable.css +3 -3
  81. package/src/components/select/combobox.ts +84 -34
  82. package/src/components/select/dropdown.ts +20 -11
  83. package/src/components/select/index.ts +6 -1
  84. package/src/components/select/option.ts +7 -6
  85. package/src/components/select/remote.ts +51 -52
  86. package/src/components/select/search.ts +51 -45
  87. package/src/components/select/select.css +12 -11
  88. package/src/components/select/select.ts +371 -102
  89. package/src/components/select/tags.ts +9 -3
  90. package/src/components/select/templates.ts +1 -4
  91. package/src/components/select/utils.ts +55 -20
  92. package/src/components/select/variants.css +0 -1
  93. package/src/components/sticky/sticky.ts +47 -16
  94. package/src/components/sticky/types.ts +3 -0
  95. package/src/components/table/table.css +1 -1
  96. package/src/components/textarea/textarea.css +1 -1
  97. package/src/components/toast/toast.css +84 -47
  98. package/src/components/toast/types.ts +3 -0
@@ -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>
@@ -0,0 +1,158 @@
1
+ # KTUI Sticky Component - Testing Suite
2
+
3
+ This directory contains comprehensive tests for the KTUI Sticky component, specifically designed to verify the changes from [PR #27](https://github.com/keenthemes/ktui/pull/27).
4
+
5
+ ## 🎯 What We're Testing
6
+
7
+ The tests verify the following new features and improvements:
8
+
9
+ ### New Positioning Features
10
+ - ✅ **Middle positioning** - Vertical centering (`inset-block-start: 50%`)
11
+ - ✅ **Center positioning** - Horizontal centering (`inset-inline-start: 50%`)
12
+ - ✅ **Bottom positioning** - Sticky to bottom with offset
13
+ - ✅ **Combined positioning** - Middle + Center for full centering
14
+
15
+ ### Improved Logic
16
+ - ✅ **Exclusive positioning** - Only one of `top`/`bottom` and `start`/`end` applied
17
+ - ✅ **Auto handling** - Proper fallback values for `'auto'` inputs
18
+ - ✅ **Offset calculation** - Dynamic positioning using `KTDom.offset()`
19
+
20
+ ### Modern CSS Support
21
+ - ✅ **Logical properties** - `insetBlockStart`, `insetInlineStart`, `insetInlineEnd`
22
+ - ✅ **RTL/LTR compatibility** - Better support for right-to-left layouts
23
+
24
+ ## 📁 Test Files
25
+
26
+ ### 1. `test-sticky-positioning.html`
27
+ **Visual/Interactive Test**
28
+ - Comprehensive visual test with 8 different positioning scenarios
29
+ - Real-time position indicator showing computed styles
30
+ - RTL toggle functionality
31
+ - Scroll indicators and controls
32
+
33
+ **How to use:**
34
+ ```bash
35
+ # Open in browser
36
+ open examples/sticky/test-sticky-positioning.html
37
+ ```
38
+
39
+ ### 2. `test-sticky-logic.js`
40
+ **Programmatic Test Suite**
41
+ - Automated tests for all positioning logic
42
+ - Validates computed CSS properties
43
+ - Tests exclusive positioning rules
44
+ - Verifies auto fallback values
45
+
46
+ ### 3. `test-runner.html`
47
+ **Test Runner Interface**
48
+ - Clean UI for running automated tests
49
+ - Detailed test results with pass/fail status
50
+ - Console output capture
51
+ - Visual test summary
52
+
53
+ **How to use:**
54
+ ```bash
55
+ # Open in browser
56
+ open examples/sticky/test-runner.html
57
+ ```
58
+
59
+ ## 🧪 Running the Tests
60
+
61
+ ### Option 1: Visual Testing (Recommended)
62
+ 1. Open `test-sticky-positioning.html` in your browser
63
+ 2. Scroll through the page to see each sticky element in action
64
+ 3. Use the position indicator to verify computed styles
65
+ 4. Test RTL layout by clicking "Toggle RTL Layout"
66
+
67
+ ### Option 2: Automated Testing
68
+ 1. Open `test-runner.html` in your browser
69
+ 2. Click "Run All Tests" to execute the automated test suite
70
+ 3. Review the detailed results and console output
71
+
72
+ ### Option 3: Console Testing
73
+ 1. Open browser developer tools
74
+ 2. Import and run the test suite directly:
75
+ ```javascript
76
+ import StickyTestSuite from './examples/sticky/test-sticky-logic.js';
77
+ const testSuite = new StickyTestSuite();
78
+ await testSuite.runAllTests();
79
+ ```
80
+
81
+ ## 📋 Test Scenarios
82
+
83
+ ### 1. Basic Positioning
84
+ - **Top**: `data-kt-sticky-top="20"` → `inset-block-start: 20px`
85
+ - **Bottom**: `data-kt-sticky-bottom="20"` → `inset-block-end: 20px`
86
+
87
+ ### 2. Centering
88
+ - **Middle**: `data-kt-sticky-middle="true"` → `inset-block-start: 50%`
89
+ - **Center**: `data-kt-sticky-center="true"` → `inset-inline-start: 50%`
90
+ - **Both**: `data-kt-sticky-middle="true" data-kt-sticky-center="true"` → Fully centered
91
+
92
+ ### 3. Auto Positioning
93
+ - **Auto Top**: `data-kt-sticky-top="auto"` → `inset-block-start: 0px`
94
+ - **Auto Start**: `data-kt-sticky-start="auto"` → Calculated offset using `KTDom.offset()`
95
+
96
+ ### 4. Exclusive Logic
97
+ - **Top + Bottom**: Only top is applied (top takes precedence)
98
+ - **Start + End**: Only start is applied (start takes precedence)
99
+
100
+ ### 5. RTL Support
101
+ - **End positioning**: `data-kt-sticky-end="20"` → `inset-inline-end: 20px`
102
+ - **Logical properties**: Works correctly in both LTR and RTL layouts
103
+
104
+ ## 🔍 What to Look For
105
+
106
+ ### ✅ Success Indicators
107
+ - Elements stick to the correct positions when scrolling
108
+ - Computed styles match expected values
109
+ - RTL layout works correctly
110
+ - Auto positioning calculates proper offsets
111
+ - Exclusive positioning rules are followed
112
+
113
+ ### ❌ Failure Indicators
114
+ - Elements don't stick or stick to wrong positions
115
+ - Computed styles don't match expected values
116
+ - RTL layout breaks positioning
117
+ - Auto positioning doesn't calculate offsets
118
+ - Multiple positioning properties conflict
119
+
120
+ ## 🛠️ Troubleshooting
121
+
122
+ ### Common Issues
123
+
124
+ 1. **Tests not running**
125
+ - Ensure you're serving files from a web server (not file://)
126
+ - Check browser console for import errors
127
+ - Verify KTUI library is built and accessible
128
+
129
+ 2. **Positioning not working**
130
+ - Check if sticky element has proper dimensions
131
+ - Verify scroll container is correct
132
+ - Ensure CSS logical properties are supported
133
+
134
+ 3. **RTL not working**
135
+ - Check if `dir="rtl"` is set on `<html>` element
136
+ - Verify browser supports logical properties
137
+ - Test with different RTL content
138
+
139
+ ### Debug Mode
140
+ Enable debug logging by adding this to the console:
141
+ ```javascript
142
+ localStorage.setItem('ktui-debug', 'true');
143
+ ```
144
+
145
+ ## 📊 Expected Results
146
+
147
+ When all tests pass, you should see:
148
+ - ✅ 8/8 tests passed
149
+ - All positioning scenarios working correctly
150
+ - Logical properties being used
151
+ - RTL layout functioning properly
152
+ - Auto positioning calculating offsets
153
+
154
+ ## 🔗 Related Links
155
+
156
+ - [PR #27](https://github.com/keenthemes/ktui/pull/27) - Original pull request
157
+ - [Sticky Component Documentation](../src/components/sticky/) - Component source code
158
+ - [KTUI Main Documentation](../../README.md) - Main project documentation
@@ -0,0 +1,144 @@
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>Debug Sticky Component</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ .debug-sticky {
10
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
11
+ color: white;
12
+ padding: 1rem;
13
+ border-radius: 8px;
14
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
15
+ font-weight: 600;
16
+ text-align: center;
17
+ width: 200px;
18
+ height: 80px;
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ }
23
+
24
+ .debug-sticky.active {
25
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
26
+ }
27
+
28
+ .debug-info {
29
+ position: fixed;
30
+ top: 10px;
31
+ left: 10px;
32
+ background: rgba(0, 0, 0, 0.8);
33
+ color: white;
34
+ padding: 1rem;
35
+ border-radius: 4px;
36
+ font-family: monospace;
37
+ font-size: 12px;
38
+ max-width: 400px;
39
+ z-index: 9999;
40
+ }
41
+ </style>
42
+ </head>
43
+ <body class="bg-gray-50">
44
+ <div class="debug-info" id="debugInfo">
45
+ Loading...
46
+ </div>
47
+
48
+ <!-- Simple test section -->
49
+ <div style="height: 100vh; padding: 2rem;">
50
+ <h1>Debug Sticky Component</h1>
51
+ <p>Scroll down to test the sticky element</p>
52
+ </div>
53
+
54
+ <!-- Single sticky element for testing -->
55
+ <div class="debug-sticky"
56
+ data-kt-sticky="true"
57
+ data-kt-sticky-top="20"
58
+ data-kt-sticky-offset="100"
59
+ data-kt-sticky-zindex="1000"
60
+ data-kt-sticky-name="debug-test">
61
+ Debug Sticky
62
+ </div>
63
+
64
+ <!-- Content to scroll through -->
65
+ <div style="height: 200vh; padding: 2rem;">
66
+ <h2>Scroll Content</h2>
67
+ <p>This content is here to allow scrolling and test the sticky element.</p>
68
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
69
+ <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
70
+ <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
71
+ <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
72
+ </div>
73
+
74
+ <!-- Load KTUI -->
75
+ <script src="../../dist/ktui.js"></script>
76
+ <script>
77
+ document.addEventListener('DOMContentLoaded', function() {
78
+ const debugInfo = document.getElementById('debugInfo');
79
+
80
+ function updateDebugInfo() {
81
+ const stickyElement = document.querySelector('[data-kt-sticky]');
82
+ const initializedElement = document.querySelector('[data-kt-sticky-initialized]');
83
+ const activeElement = document.querySelector('[data-kt-sticky-initialized].active');
84
+
85
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
86
+ const viewportHeight = window.innerHeight;
87
+
88
+ let info = `
89
+ <strong>Debug Info:</strong><br>
90
+ Scroll: ${scrollTop}px<br>
91
+ Viewport Height: ${viewportHeight}px<br>
92
+ KTSticky Available: ${!!window.KTSticky}<br>
93
+ Sticky Elements: ${document.querySelectorAll('[data-kt-sticky]').length}<br>
94
+ Initialized Elements: ${document.querySelectorAll('[data-kt-sticky-initialized]').length}<br>
95
+ Active Elements: ${document.querySelectorAll('[data-kt-sticky-initialized].active').length}<br>
96
+ `;
97
+
98
+ if (stickyElement) {
99
+ const computedStyle = window.getComputedStyle(stickyElement);
100
+ const height = stickyElement.offsetHeight;
101
+ const top = stickyElement.getAttribute('data-kt-sticky-top') || '0';
102
+ const offset = stickyElement.getAttribute('data-kt-sticky-offset') || '0';
103
+
104
+ info += `
105
+ <br><strong>Sticky Element:</strong><br>
106
+ Height: ${height}px<br>
107
+ Top: ${top}px<br>
108
+ Offset: ${offset}px<br>
109
+ Height + Top: ${height + parseInt(top)}px<br>
110
+ Position: ${computedStyle.position}<br>
111
+ Z-Index: ${computedStyle.zIndex}<br>
112
+ InsetBlockStart: ${computedStyle.insetBlockStart}<br>
113
+ `;
114
+ }
115
+
116
+ if (initializedElement) {
117
+ info += `<br><strong>Initialized Element:</strong><br>`;
118
+ info += `Classes: ${initializedElement.className}<br>`;
119
+ info += `Data Attributes: ${Array.from(initializedElement.attributes).filter(attr => attr.name.startsWith('data-kt-sticky')).map(attr => `${attr.name}="${attr.value}"`).join(', ')}<br>`;
120
+ }
121
+
122
+ debugInfo.innerHTML = info;
123
+ }
124
+
125
+ // Initialize KTUI
126
+ if (window.KTSticky) {
127
+ console.log('Initializing KTSticky...');
128
+ window.KTSticky.init();
129
+ console.log('KTSticky initialized');
130
+ } else {
131
+ console.error('KTSticky not found!');
132
+ }
133
+
134
+ // Update debug info initially and on scroll
135
+ updateDebugInfo();
136
+ window.addEventListener('scroll', updateDebugInfo);
137
+ window.addEventListener('resize', updateDebugInfo);
138
+
139
+ // Update every second to catch any changes
140
+ setInterval(updateDebugInfo, 1000);
141
+ });
142
+ </script>
143
+ </body>
144
+ </html>