@keenthemes/ktui 1.1.0 → 1.1.1

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 (222) hide show
  1. package/README.md +0 -27
  2. package/dist/ktui.js +6790 -14063
  3. package/dist/ktui.min.js +1 -1
  4. package/dist/ktui.min.js.map +1 -1
  5. package/dist/styles.css +1132 -2705
  6. package/lib/cjs/components/datatable/__tests__/pagination-reset.test.js +596 -0
  7. package/lib/cjs/components/datatable/__tests__/pagination-reset.test.js.map +1 -0
  8. package/lib/cjs/components/datatable/__tests__/race-conditions.test.js +548 -0
  9. package/lib/cjs/components/datatable/__tests__/race-conditions.test.js.map +1 -0
  10. package/lib/cjs/components/datatable/__tests__/setup.js +63 -0
  11. package/lib/cjs/components/datatable/__tests__/setup.js.map +1 -0
  12. package/lib/cjs/components/datatable/datatable.js +92 -30
  13. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  14. package/lib/cjs/index.js +1 -10
  15. package/lib/cjs/index.js.map +1 -1
  16. package/lib/esm/components/datatable/__tests__/pagination-reset.test.js +594 -0
  17. package/lib/esm/components/datatable/__tests__/pagination-reset.test.js.map +1 -0
  18. package/lib/esm/components/datatable/__tests__/race-conditions.test.js +546 -0
  19. package/lib/esm/components/datatable/__tests__/race-conditions.test.js.map +1 -0
  20. package/lib/esm/components/datatable/__tests__/setup.js +58 -0
  21. package/lib/esm/components/datatable/__tests__/setup.js.map +1 -0
  22. package/lib/esm/components/datatable/datatable.js +92 -30
  23. package/lib/esm/components/datatable/datatable.js.map +1 -1
  24. package/lib/esm/index.js +0 -7
  25. package/lib/esm/index.js.map +1 -1
  26. package/package.json +7 -9
  27. package/src/components/alert/alert.css +188 -429
  28. package/src/components/datatable/__tests__/pagination-reset.test.ts +657 -0
  29. package/src/components/datatable/__tests__/race-conditions.test.ts +455 -0
  30. package/src/components/datatable/__tests__/setup.ts +67 -0
  31. package/src/components/datatable/datatable.ts +66 -11
  32. package/src/components/input/input.css +0 -1
  33. package/src/components/select/select.css +0 -1
  34. package/src/components/select/variants.css +4 -0
  35. package/src/components/textarea/textarea.css +0 -1
  36. package/src/index.ts +0 -10
  37. package/styles.css +0 -1
  38. package/lib/cjs/components/alert/alert.js +0 -1025
  39. package/lib/cjs/components/alert/alert.js.map +0 -1
  40. package/lib/cjs/components/alert/index.js +0 -20
  41. package/lib/cjs/components/alert/index.js.map +0 -1
  42. package/lib/cjs/components/alert/templates.js +0 -120
  43. package/lib/cjs/components/alert/templates.js.map +0 -1
  44. package/lib/cjs/components/alert/types.js +0 -7
  45. package/lib/cjs/components/alert/types.js.map +0 -1
  46. package/lib/cjs/components/datepicker/config/config.js +0 -42
  47. package/lib/cjs/components/datepicker/config/config.js.map +0 -1
  48. package/lib/cjs/components/datepicker/config/index.js +0 -24
  49. package/lib/cjs/components/datepicker/config/index.js.map +0 -1
  50. package/lib/cjs/components/datepicker/config/interfaces.js +0 -7
  51. package/lib/cjs/components/datepicker/config/interfaces.js.map +0 -1
  52. package/lib/cjs/components/datepicker/config/types.js +0 -7
  53. package/lib/cjs/components/datepicker/config/types.js.map +0 -1
  54. package/lib/cjs/components/datepicker/core/event-manager.js +0 -135
  55. package/lib/cjs/components/datepicker/core/event-manager.js.map +0 -1
  56. package/lib/cjs/components/datepicker/core/focus-manager.js +0 -167
  57. package/lib/cjs/components/datepicker/core/focus-manager.js.map +0 -1
  58. package/lib/cjs/components/datepicker/core/helpers.js +0 -219
  59. package/lib/cjs/components/datepicker/core/helpers.js.map +0 -1
  60. package/lib/cjs/components/datepicker/core/index.js +0 -25
  61. package/lib/cjs/components/datepicker/core/index.js.map +0 -1
  62. package/lib/cjs/components/datepicker/core/unified-state-manager.js +0 -394
  63. package/lib/cjs/components/datepicker/core/unified-state-manager.js.map +0 -1
  64. package/lib/cjs/components/datepicker/datepicker.js +0 -2252
  65. package/lib/cjs/components/datepicker/datepicker.js.map +0 -1
  66. package/lib/cjs/components/datepicker/index.js +0 -24
  67. package/lib/cjs/components/datepicker/index.js.map +0 -1
  68. package/lib/cjs/components/datepicker/ui/index.js +0 -23
  69. package/lib/cjs/components/datepicker/ui/index.js.map +0 -1
  70. package/lib/cjs/components/datepicker/ui/input/dropdown.js +0 -489
  71. package/lib/cjs/components/datepicker/ui/input/dropdown.js.map +0 -1
  72. package/lib/cjs/components/datepicker/ui/input/index.js +0 -23
  73. package/lib/cjs/components/datepicker/ui/input/index.js.map +0 -1
  74. package/lib/cjs/components/datepicker/ui/input/segmented-input.js +0 -640
  75. package/lib/cjs/components/datepicker/ui/input/segmented-input.js.map +0 -1
  76. package/lib/cjs/components/datepicker/ui/renderers/calendar.js +0 -446
  77. package/lib/cjs/components/datepicker/ui/renderers/calendar.js.map +0 -1
  78. package/lib/cjs/components/datepicker/ui/renderers/footer.js +0 -42
  79. package/lib/cjs/components/datepicker/ui/renderers/footer.js.map +0 -1
  80. package/lib/cjs/components/datepicker/ui/renderers/header.js +0 -32
  81. package/lib/cjs/components/datepicker/ui/renderers/header.js.map +0 -1
  82. package/lib/cjs/components/datepicker/ui/renderers/index.js +0 -25
  83. package/lib/cjs/components/datepicker/ui/renderers/index.js.map +0 -1
  84. package/lib/cjs/components/datepicker/ui/renderers/time-picker.js +0 -384
  85. package/lib/cjs/components/datepicker/ui/renderers/time-picker.js.map +0 -1
  86. package/lib/cjs/components/datepicker/ui/templates/index.js +0 -22
  87. package/lib/cjs/components/datepicker/ui/templates/index.js.map +0 -1
  88. package/lib/cjs/components/datepicker/ui/templates/templates.js +0 -253
  89. package/lib/cjs/components/datepicker/ui/templates/templates.js.map +0 -1
  90. package/lib/cjs/components/datepicker/utils/date-formatters.js +0 -88
  91. package/lib/cjs/components/datepicker/utils/date-formatters.js.map +0 -1
  92. package/lib/cjs/components/datepicker/utils/date-utils.js +0 -194
  93. package/lib/cjs/components/datepicker/utils/date-utils.js.map +0 -1
  94. package/lib/cjs/components/datepicker/utils/index.js +0 -24
  95. package/lib/cjs/components/datepicker/utils/index.js.map +0 -1
  96. package/lib/cjs/components/datepicker/utils/time-utils.js +0 -213
  97. package/lib/cjs/components/datepicker/utils/time-utils.js.map +0 -1
  98. package/lib/esm/components/alert/alert.js +0 -1022
  99. package/lib/esm/components/alert/alert.js.map +0 -1
  100. package/lib/esm/components/alert/index.js +0 -4
  101. package/lib/esm/components/alert/index.js.map +0 -1
  102. package/lib/esm/components/alert/templates.js +0 -112
  103. package/lib/esm/components/alert/templates.js.map +0 -1
  104. package/lib/esm/components/alert/types.js +0 -6
  105. package/lib/esm/components/alert/types.js.map +0 -1
  106. package/lib/esm/components/datepicker/config/config.js +0 -39
  107. package/lib/esm/components/datepicker/config/config.js.map +0 -1
  108. package/lib/esm/components/datepicker/config/index.js +0 -8
  109. package/lib/esm/components/datepicker/config/index.js.map +0 -1
  110. package/lib/esm/components/datepicker/config/interfaces.js +0 -6
  111. package/lib/esm/components/datepicker/config/interfaces.js.map +0 -1
  112. package/lib/esm/components/datepicker/config/types.js +0 -6
  113. package/lib/esm/components/datepicker/config/types.js.map +0 -1
  114. package/lib/esm/components/datepicker/core/event-manager.js +0 -133
  115. package/lib/esm/components/datepicker/core/event-manager.js.map +0 -1
  116. package/lib/esm/components/datepicker/core/focus-manager.js +0 -164
  117. package/lib/esm/components/datepicker/core/focus-manager.js.map +0 -1
  118. package/lib/esm/components/datepicker/core/helpers.js +0 -211
  119. package/lib/esm/components/datepicker/core/helpers.js.map +0 -1
  120. package/lib/esm/components/datepicker/core/index.js +0 -9
  121. package/lib/esm/components/datepicker/core/index.js.map +0 -1
  122. package/lib/esm/components/datepicker/core/unified-state-manager.js +0 -391
  123. package/lib/esm/components/datepicker/core/unified-state-manager.js.map +0 -1
  124. package/lib/esm/components/datepicker/datepicker.js +0 -2248
  125. package/lib/esm/components/datepicker/datepicker.js.map +0 -1
  126. package/lib/esm/components/datepicker/index.js +0 -7
  127. package/lib/esm/components/datepicker/index.js.map +0 -1
  128. package/lib/esm/components/datepicker/ui/index.js +0 -7
  129. package/lib/esm/components/datepicker/ui/index.js.map +0 -1
  130. package/lib/esm/components/datepicker/ui/input/dropdown.js +0 -486
  131. package/lib/esm/components/datepicker/ui/input/dropdown.js.map +0 -1
  132. package/lib/esm/components/datepicker/ui/input/index.js +0 -7
  133. package/lib/esm/components/datepicker/ui/input/index.js.map +0 -1
  134. package/lib/esm/components/datepicker/ui/input/segmented-input.js +0 -637
  135. package/lib/esm/components/datepicker/ui/input/segmented-input.js.map +0 -1
  136. package/lib/esm/components/datepicker/ui/renderers/calendar.js +0 -443
  137. package/lib/esm/components/datepicker/ui/renderers/calendar.js.map +0 -1
  138. package/lib/esm/components/datepicker/ui/renderers/footer.js +0 -39
  139. package/lib/esm/components/datepicker/ui/renderers/footer.js.map +0 -1
  140. package/lib/esm/components/datepicker/ui/renderers/header.js +0 -29
  141. package/lib/esm/components/datepicker/ui/renderers/header.js.map +0 -1
  142. package/lib/esm/components/datepicker/ui/renderers/index.js +0 -9
  143. package/lib/esm/components/datepicker/ui/renderers/index.js.map +0 -1
  144. package/lib/esm/components/datepicker/ui/renderers/time-picker.js +0 -381
  145. package/lib/esm/components/datepicker/ui/renderers/time-picker.js.map +0 -1
  146. package/lib/esm/components/datepicker/ui/templates/index.js +0 -6
  147. package/lib/esm/components/datepicker/ui/templates/index.js.map +0 -1
  148. package/lib/esm/components/datepicker/ui/templates/templates.js +0 -242
  149. package/lib/esm/components/datepicker/ui/templates/templates.js.map +0 -1
  150. package/lib/esm/components/datepicker/utils/date-formatters.js +0 -83
  151. package/lib/esm/components/datepicker/utils/date-formatters.js.map +0 -1
  152. package/lib/esm/components/datepicker/utils/date-utils.js +0 -184
  153. package/lib/esm/components/datepicker/utils/date-utils.js.map +0 -1
  154. package/lib/esm/components/datepicker/utils/index.js +0 -8
  155. package/lib/esm/components/datepicker/utils/index.js.map +0 -1
  156. package/lib/esm/components/datepicker/utils/time-utils.js +0 -201
  157. package/lib/esm/components/datepicker/utils/time-utils.js.map +0 -1
  158. package/src/components/alert/alert.ts +0 -990
  159. package/src/components/alert/index.ts +0 -4
  160. package/src/components/alert/templates.ts +0 -110
  161. package/src/components/alert/tests/accessibility/aria-roles.test.ts +0 -19
  162. package/src/components/alert/tests/accessibility/focus-management.test.ts +0 -19
  163. package/src/components/alert/tests/accessibility/keyboard-nav.test.ts +0 -22
  164. package/src/components/alert/tests/actions/confirm-cancel.test.ts +0 -122
  165. package/src/components/alert/tests/actions/input-field.test.ts +0 -180
  166. package/src/components/alert/tests/alert.basic.test.ts +0 -126
  167. package/src/components/alert/tests/alert.config.test.ts +0 -75
  168. package/src/components/alert/tests/alert.templates.test.ts +0 -17
  169. package/src/components/alert/tests/config/attribute-config.test.ts +0 -94
  170. package/src/components/alert/tests/config/json-config.test.ts +0 -119
  171. package/src/components/alert/tests/config/merging.test.ts +0 -89
  172. package/src/components/alert/tests/dismissal/auto-dismiss.test.ts +0 -96
  173. package/src/components/alert/tests/dismissal/escape-key-dismiss.test.ts +0 -105
  174. package/src/components/alert/tests/dismissal/manual-dismiss.test.ts +0 -90
  175. package/src/components/alert/tests/dismissal/outside-click-dismiss.test.ts +0 -91
  176. package/src/components/alert/tests/edge-cases/invalid-config.test.ts +0 -19
  177. package/src/components/alert/tests/edge-cases/multiple-alerts.test.ts +0 -19
  178. package/src/components/alert/tests/rendering/custom-content.test.ts +0 -81
  179. package/src/components/alert/tests/rendering/info-alert.test.ts +0 -84
  180. package/src/components/alert/tests/rendering/success-alert.test.ts +0 -100
  181. package/src/components/alert/tests/templates/default-templates.test.ts +0 -16
  182. package/src/components/alert/tests/templates/user-templates.test.ts +0 -16
  183. package/src/components/alert/types.ts +0 -145
  184. package/src/components/datepicker/__tests__/datepicker-events.test.ts +0 -356
  185. package/src/components/datepicker/__tests__/datepicker-init.test.ts +0 -343
  186. package/src/components/datepicker/__tests__/datepicker-integration.test.ts +0 -435
  187. package/src/components/datepicker/__tests__/datepicker-timezone.test.ts +0 -220
  188. package/src/components/datepicker/__tests__/segmented-input-focus.test.ts +0 -380
  189. package/src/components/datepicker/__tests__/selective-state-updates.test.ts +0 -400
  190. package/src/components/datepicker/__tests__/state-manager.test.ts +0 -421
  191. package/src/components/datepicker/__tests__/time-preservation.test.ts +0 -387
  192. package/src/components/datepicker/config/config.ts +0 -40
  193. package/src/components/datepicker/config/index.ts +0 -8
  194. package/src/components/datepicker/config/interfaces.ts +0 -82
  195. package/src/components/datepicker/config/types.ts +0 -188
  196. package/src/components/datepicker/core/event-manager.ts +0 -159
  197. package/src/components/datepicker/core/focus-manager.ts +0 -201
  198. package/src/components/datepicker/core/helpers.ts +0 -231
  199. package/src/components/datepicker/core/index.ts +0 -9
  200. package/src/components/datepicker/core/unified-state-manager.ts +0 -459
  201. package/src/components/datepicker/datepicker.css +0 -435
  202. package/src/components/datepicker/datepicker.ts +0 -2548
  203. package/src/components/datepicker/index.ts +0 -8
  204. package/src/components/datepicker/ui/index.ts +0 -7
  205. package/src/components/datepicker/ui/input/dropdown.ts +0 -552
  206. package/src/components/datepicker/ui/input/index.ts +0 -7
  207. package/src/components/datepicker/ui/input/segmented-input.ts +0 -638
  208. package/src/components/datepicker/ui/renderers/__tests__/calendar-optimizations.test.ts +0 -611
  209. package/src/components/datepicker/ui/renderers/calendar.ts +0 -530
  210. package/src/components/datepicker/ui/renderers/footer.ts +0 -43
  211. package/src/components/datepicker/ui/renderers/header.ts +0 -33
  212. package/src/components/datepicker/ui/renderers/index.ts +0 -9
  213. package/src/components/datepicker/ui/renderers/time-picker.ts +0 -438
  214. package/src/components/datepicker/ui/templates/index.ts +0 -6
  215. package/src/components/datepicker/ui/templates/templates.ts +0 -306
  216. package/src/components/datepicker/utils/__tests__/date-formatters.test.ts +0 -160
  217. package/src/components/datepicker/utils/__tests__/date-utils-keys.test.ts +0 -86
  218. package/src/components/datepicker/utils/__tests__/date-utils-timezone.test.ts +0 -215
  219. package/src/components/datepicker/utils/date-formatters.ts +0 -85
  220. package/src/components/datepicker/utils/date-utils.ts +0 -172
  221. package/src/components/datepicker/utils/index.ts +0 -8
  222. package/src/components/datepicker/utils/time-utils.ts +0 -221
@@ -1,356 +0,0 @@
1
- /**
2
- * datepicker-events.test.ts - Test suite for KTDatepicker event handling
3
- * Tests the fixes for state management and synchronous event firing
4
- */
5
-
6
- import { describe, it, expect, beforeEach, vi } from 'vitest';
7
- import { KTDatepicker } from '../datepicker';
8
- import { KTDatepickerConfig } from '../config/types';
9
-
10
- describe('KTDatepicker Event Handling', () => {
11
- let element: HTMLElement;
12
- let mockOnChange: ReturnType<typeof vi.fn>;
13
- let mockOnOpen: ReturnType<typeof vi.fn>;
14
- let mockOnClose: ReturnType<typeof vi.fn>;
15
-
16
- beforeEach(() => {
17
- // Create a mock DOM element with proper structure
18
- element = document.createElement('div');
19
- element.innerHTML = `
20
- <div class="kt-datepicker" data-kt-datepicker-segmented>
21
- <input type="text" data-kt-datepicker-input placeholder="Select date">
22
- </div>
23
- `;
24
-
25
- // Reset mocks for each test
26
- mockOnChange = vi.fn();
27
- mockOnOpen = vi.fn();
28
- mockOnClose = vi.fn();
29
-
30
- // Clear any existing event listeners or state
31
- document.body.innerHTML = '';
32
- document.body.appendChild(element);
33
- });
34
-
35
- describe('Event Handler Configuration', () => {
36
- it('should accept event handler configuration', () => {
37
- const config: KTDatepickerConfig = {
38
- format: 'dd/MM/yyyy',
39
- onChange: mockOnChange,
40
- onOpen: mockOnOpen,
41
- onClose: mockOnClose
42
- };
43
-
44
- expect(() => {
45
- new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
46
- }).not.toThrow();
47
- });
48
-
49
- it('should handle undefined event handlers gracefully', () => {
50
- const config: KTDatepickerConfig = {
51
- format: 'dd/MM/yyyy'
52
- // No event handlers defined
53
- };
54
-
55
- expect(() => {
56
- new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
57
- }).not.toThrow();
58
- });
59
- });
60
-
61
- describe('onChange Event', () => {
62
- it('should fire onChange immediately when date is set programmatically', async () => {
63
- const config: KTDatepickerConfig = {
64
- format: 'dd/MM/yyyy',
65
- onChange: mockOnChange
66
- };
67
-
68
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
69
-
70
- // Clear any initial calls
71
- mockOnChange.mockClear();
72
-
73
- // Set date programmatically
74
- const testDate = new Date(2024, 0, 15); // January 15, 2024
75
- datepicker.setDate(testDate);
76
-
77
- // onChange should be called immediately (not batched)
78
- expect(mockOnChange).toHaveBeenCalledTimes(1);
79
- expect(mockOnChange).toHaveBeenCalledWith(testDate, datepicker);
80
- });
81
-
82
- it('should fire onChange with correct date format', async () => {
83
- const config: KTDatepickerConfig = {
84
- format: 'yyyy-MM-dd',
85
- onChange: mockOnChange
86
- };
87
-
88
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
89
-
90
- // Clear any initial calls
91
- mockOnChange.mockClear();
92
-
93
- const testDate = new Date(2024, 0, 15);
94
- datepicker.setDate(testDate);
95
-
96
- expect(mockOnChange).toHaveBeenCalledWith(testDate, datepicker);
97
- });
98
-
99
- it('should not fire onChange when event handler throws error', async () => {
100
- const errorHandler = vi.fn().mockImplementation(() => {
101
- throw new Error('Event handler error');
102
- });
103
-
104
- const config: KTDatepickerConfig = {
105
- format: 'dd/MM/yyyy',
106
- onChange: errorHandler
107
- };
108
-
109
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
110
-
111
- // Should not throw when setting date
112
- expect(() => {
113
- datepicker.setDate(new Date(2024, 0, 15));
114
- }).not.toThrow();
115
-
116
- // Error handler should still be called
117
- expect(errorHandler).toHaveBeenCalledTimes(1);
118
- });
119
- });
120
-
121
- describe('onOpen/onClose Events', () => {
122
- it('should fire onOpen immediately when dropdown opens', async () => {
123
- const config: KTDatepickerConfig = {
124
- onOpen: mockOnOpen,
125
- onClose: mockOnClose
126
- };
127
-
128
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
129
-
130
- // Clear any initial calls
131
- mockOnOpen.mockClear();
132
- mockOnClose.mockClear();
133
-
134
- // Open dropdown
135
- datepicker.open();
136
-
137
- // onOpen should be called immediately
138
- expect(mockOnOpen).toHaveBeenCalledTimes(1);
139
- expect(mockOnOpen).toHaveBeenCalledWith(datepicker);
140
-
141
- // onClose should not have been called
142
- expect(mockOnClose).not.toHaveBeenCalled();
143
- });
144
-
145
- it('should fire onClose immediately when dropdown closes', async () => {
146
- const config: KTDatepickerConfig = {
147
- onOpen: mockOnOpen,
148
- onClose: mockOnClose
149
- };
150
-
151
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
152
-
153
- // First open the dropdown
154
- datepicker.open();
155
- mockOnOpen.mockClear();
156
- mockOnClose.mockClear();
157
-
158
- // Close dropdown
159
- datepicker.close();
160
-
161
- // onClose should be called immediately
162
- expect(mockOnClose).toHaveBeenCalledTimes(1);
163
- expect(mockOnClose).toHaveBeenCalledWith(datepicker);
164
-
165
- // onOpen should not be called again
166
- expect(mockOnOpen).not.toHaveBeenCalled();
167
- });
168
-
169
- it('should handle rapid open/close sequences', async () => {
170
- const config: KTDatepickerConfig = {
171
- onOpen: mockOnOpen,
172
- onClose: mockOnClose
173
- };
174
-
175
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
176
-
177
- // Clear any initial calls
178
- mockOnOpen.mockClear();
179
- mockOnClose.mockClear();
180
-
181
- // Open and close rapidly
182
- datepicker.open();
183
- datepicker.close();
184
- datepicker.open();
185
-
186
- // Should have correct call counts
187
- expect(mockOnOpen).toHaveBeenCalledTimes(2);
188
- expect(mockOnClose).toHaveBeenCalledTimes(1);
189
- });
190
- });
191
-
192
- describe('State Management Integration', () => {
193
- it('should maintain state consistency during event firing', async () => {
194
- let capturedState: any = null;
195
-
196
- const config: KTDatepickerConfig = {
197
- onChange: (date, datepicker) => {
198
- // Capture the datepicker state during event firing
199
- capturedState = {
200
- date,
201
- isOpen: datepicker.isOpen?.() || false
202
- };
203
- }
204
- };
205
-
206
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
207
-
208
- const testDate = new Date(2024, 0, 15);
209
- datepicker.setDate(testDate);
210
-
211
- // State should be captured correctly during event firing
212
- expect(capturedState).not.toBeNull();
213
- expect(capturedState.date).toEqual(testDate);
214
- });
215
-
216
- it('should handle multiple datepicker instances independently', async () => {
217
- // Create second datepicker element
218
- const element2 = document.createElement('div');
219
- element2.innerHTML = `
220
- <div class="kt-datepicker" data-kt-datepicker-segmented>
221
- <input type="text" data-kt-datepicker-input placeholder="Select date 2">
222
- </div>
223
- `;
224
- document.body.appendChild(element2);
225
-
226
- const mockOnChange2 = vi.fn();
227
-
228
- const config1: KTDatepickerConfig = {
229
- onChange: mockOnChange
230
- };
231
-
232
- const config2: KTDatepickerConfig = {
233
- onChange: mockOnChange2
234
- };
235
-
236
- const datepicker1 = new KTDatepicker(element.querySelector('.kt-datepicker')!, config1);
237
- const datepicker2 = new KTDatepicker(element2.querySelector('.kt-datepicker')!, config2);
238
-
239
- // Set dates on both datepickers
240
- const date1 = new Date(2024, 0, 15);
241
- const date2 = new Date(2024, 1, 20);
242
-
243
- datepicker1.setDate(date1);
244
- datepicker2.setDate(date2);
245
-
246
- // Each datepicker should fire its own event
247
- expect(mockOnChange).toHaveBeenCalledWith(date1, datepicker1);
248
- expect(mockOnChange2).toHaveBeenCalledWith(date2, datepicker2);
249
-
250
- // Cleanup
251
- document.body.removeChild(element2);
252
- });
253
- });
254
-
255
- describe('Error Handling', () => {
256
- it('should not crash when event handler throws error', async () => {
257
- const errorOnChange = vi.fn().mockImplementation(() => {
258
- throw new Error('Test error');
259
- });
260
-
261
- const config: KTDatepickerConfig = {
262
- onChange: errorOnChange
263
- };
264
-
265
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
266
-
267
- // Should not throw despite error in event handler
268
- expect(() => {
269
- datepicker.setDate(new Date(2024, 0, 15));
270
- }).not.toThrow();
271
-
272
- expect(errorOnChange).toHaveBeenCalledTimes(1);
273
- });
274
-
275
- it('should continue functioning after event handler error', async () => {
276
- let callCount = 0;
277
- const errorOnChange = vi.fn().mockImplementation(() => {
278
- callCount++;
279
- if (callCount === 1) {
280
- throw new Error('First call error');
281
- }
282
- });
283
-
284
- const config: KTDatepickerConfig = {
285
- onChange: errorOnChange
286
- };
287
-
288
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
289
-
290
- // First call should throw but not crash
291
- datepicker.setDate(new Date(2024, 0, 15));
292
-
293
- // Second call should still work
294
- datepicker.setDate(new Date(2024, 1, 20));
295
-
296
- expect(errorOnChange).toHaveBeenCalledTimes(2);
297
- });
298
- });
299
-
300
- describe('Performance and Timing', () => {
301
- it('should fire events synchronously for immediate state updates', async () => {
302
- const callOrder: string[] = [];
303
-
304
- const config: KTDatepickerConfig = {
305
- onChange: () => {
306
- callOrder.push('onChange');
307
- }
308
- };
309
-
310
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
311
-
312
- callOrder.push('before-setDate');
313
- datepicker.setDate(new Date(2024, 0, 15));
314
- callOrder.push('after-setDate');
315
-
316
- // onChange should be called synchronously between setDate calls
317
- expect(callOrder).toEqual(['before-setDate', 'onChange', 'after-setDate']);
318
- });
319
-
320
- it('should fire events quickly for user interactions', async () => {
321
- const eventTimestamps: number[] = [];
322
-
323
- const config: KTDatepickerConfig = {
324
- onChange: () => {
325
- eventTimestamps.push(Date.now());
326
- },
327
- onOpen: () => {
328
- eventTimestamps.push(Date.now());
329
- },
330
- onClose: () => {
331
- eventTimestamps.push(Date.now());
332
- }
333
- };
334
-
335
- const datepicker = new KTDatepicker(element.querySelector('.kt-datepicker')!, config);
336
-
337
- const startTime = Date.now();
338
-
339
- datepicker.setDate(new Date(2024, 0, 15));
340
- datepicker.open();
341
- datepicker.close();
342
-
343
- const endTime = Date.now();
344
-
345
- // All events should fire relatively quickly (within reasonable time for user interactions)
346
- expect(eventTimestamps.length).toBe(3);
347
- eventTimestamps.forEach(timestamp => {
348
- expect(timestamp - startTime).toBeLessThan(50); // Allow reasonable time for DOM operations
349
- });
350
-
351
- // Events should fire in correct order: change, open, close
352
- expect(eventTimestamps[0]).toBeLessThanOrEqual(eventTimestamps[1]); // change before open
353
- expect(eventTimestamps[1]).toBeLessThanOrEqual(eventTimestamps[2]); // open before close
354
- });
355
- });
356
- });
@@ -1,343 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import { KTDatepicker, initDatepickers } from '../datepicker';
3
-
4
- describe('KTDatepicker Initialization', () => {
5
- let container: HTMLElement;
6
-
7
- beforeEach(() => {
8
- container = document.createElement('div');
9
- document.body.appendChild(container);
10
- });
11
-
12
- afterEach(() => {
13
- document.body.removeChild(container);
14
- });
15
-
16
- describe('initDatepickers', () => {
17
- it('should initialize datepickers for elements with data-kt-datepicker attribute', () => {
18
- // Create multiple elements with the data attribute
19
- const element1 = document.createElement('div');
20
- element1.setAttribute('data-kt-datepicker', '');
21
- container.appendChild(element1);
22
-
23
- const element2 = document.createElement('div');
24
- element2.setAttribute('data-kt-datepicker', 'true');
25
- container.appendChild(element2);
26
-
27
- const element3 = document.createElement('div');
28
- element3.setAttribute('data-kt-datepicker', '');
29
- container.appendChild(element3);
30
-
31
- // Call initDatepickers
32
- initDatepickers();
33
-
34
- // Check that datepicker instances were created
35
- expect((element1 as any).instance).toBeInstanceOf(KTDatepicker);
36
- expect((element2 as any).instance).toBeInstanceOf(KTDatepicker);
37
- expect((element3 as any).instance).toBeInstanceOf(KTDatepicker);
38
- });
39
-
40
- it('should skip elements that already have datepicker instances', () => {
41
- // Create an element with existing instance
42
- const element = document.createElement('div');
43
- element.setAttribute('data-kt-datepicker', '');
44
- container.appendChild(element);
45
-
46
- // Manually create a datepicker instance
47
- const existingDatepicker = new KTDatepicker(element);
48
- (element as any).instance = existingDatepicker;
49
-
50
- // Spy on KTDatepicker constructor
51
- const constructorSpy = vi.spyOn(KTDatepicker.prototype, 'constructor' as any);
52
-
53
- // Call initDatepickers
54
- initDatepickers();
55
-
56
- // Constructor should not be called again for the element with existing instance
57
- expect(constructorSpy).not.toHaveBeenCalled();
58
- expect((element as any).instance).toBe(existingDatepicker);
59
- });
60
-
61
- it('should not initialize elements without data-kt-datepicker attribute', () => {
62
- // Create elements without the data attribute
63
- const element1 = document.createElement('div');
64
- container.appendChild(element1);
65
-
66
- const element2 = document.createElement('div');
67
- element2.className = 'some-datepicker-class';
68
- container.appendChild(element2);
69
-
70
- // Call initDatepickers
71
- initDatepickers();
72
-
73
- // Check that no instances were created
74
- expect((element1 as any).instance).toBeUndefined();
75
- expect((element2 as any).instance).toBeUndefined();
76
- });
77
-
78
- it('should handle empty result set gracefully', () => {
79
- // Call initDatepickers when no elements exist
80
- expect(() => initDatepickers()).not.toThrow();
81
- });
82
-
83
- it('should initialize datepickers in document order', () => {
84
- // Create elements in a specific order
85
- const elements: HTMLElement[] = [];
86
- for (let i = 0; i < 5; i++) {
87
- const element = document.createElement('div');
88
- element.setAttribute('data-kt-datepicker', '');
89
- element.setAttribute('data-order', i.toString());
90
- container.appendChild(element);
91
- elements.push(element);
92
- }
93
-
94
- // Call initDatepickers
95
- initDatepickers();
96
-
97
- // Verify all elements have instances and are in correct order
98
- elements.forEach((element, index) => {
99
- expect((element as any).instance).toBeInstanceOf(KTDatepicker);
100
- expect(element.getAttribute('data-order')).toBe(index.toString());
101
- });
102
- });
103
- });
104
-
105
- describe('Public API Methods', () => {
106
- it('should return correct isOpen state', () => {
107
- const element = document.createElement('div');
108
- element.setAttribute('data-kt-datepicker', '');
109
- container.appendChild(element);
110
-
111
- const datepicker = new KTDatepicker(element);
112
-
113
- // Initially should be closed
114
- expect(datepicker.isOpen()).toBe(false);
115
-
116
- // After opening, should be open
117
- datepicker.open();
118
- expect(datepicker.isOpen()).toBe(true);
119
-
120
- // After closing, should be closed again
121
- datepicker.close();
122
- expect(datepicker.isOpen()).toBe(false);
123
- });
124
-
125
- it('should return complete state object via getState', () => {
126
- const element = document.createElement('div');
127
- element.setAttribute('data-kt-datepicker', '');
128
- container.appendChild(element);
129
-
130
- const datepicker = new KTDatepicker(element);
131
- const testDate = new Date(2024, 0, 15);
132
-
133
- // Set a date to change state
134
- datepicker.setDate(testDate);
135
-
136
- // Get state
137
- const state = datepicker.getState();
138
-
139
- // Should return a complete state object
140
- expect(state).toBeDefined();
141
- expect(typeof state).toBe('object');
142
- expect(state).toHaveProperty('selectedDate');
143
- expect(state).toHaveProperty('isOpen');
144
- expect(state).toHaveProperty('isDisabled');
145
- expect(state).toHaveProperty('isFocused');
146
- expect(state).toHaveProperty('isTransitioning');
147
- expect(state).toHaveProperty('validationErrors');
148
- expect(state).toHaveProperty('isValid');
149
-
150
- // Should be a copy, not the original reference
151
- expect(state).not.toBe(datepicker.getState()); // Different object references
152
- });
153
-
154
- it('should getState return independent copies', () => {
155
- const element = document.createElement('div');
156
- element.setAttribute('data-kt-datepicker', '');
157
- container.appendChild(element);
158
-
159
- const datepicker = new KTDatepicker(element);
160
- const testDate = new Date(2024, 0, 15);
161
-
162
- // Set a date
163
- datepicker.setDate(testDate);
164
-
165
- // Get two state objects
166
- const state1 = datepicker.getState();
167
- const state2 = datepicker.getState();
168
-
169
- // Should be different objects (copies)
170
- expect(state1).not.toBe(state2);
171
-
172
- // But should have same content initially
173
- expect(state1.selectedDate).toEqual(state2.selectedDate);
174
- expect(state1.isOpen).toEqual(state2.isOpen);
175
-
176
- // Note: getState returns a shallow copy, so Date objects are shared references
177
- // This is expected behavior - consumers should treat state as read-only
178
- if (state1.selectedDate) {
179
- state1.selectedDate.setFullYear(2025);
180
- expect(state2.selectedDate?.getFullYear()).toBe(2025); // Both affected due to shared reference
181
- }
182
- });
183
- });
184
-
185
- describe('Public API Methods', () => {
186
- it('should return correct isOpen state', () => {
187
- const element = document.createElement('div');
188
- element.setAttribute('data-kt-datepicker', '');
189
- container.appendChild(element);
190
-
191
- const datepicker = new KTDatepicker(element);
192
-
193
- // Initially should be closed
194
- expect(datepicker.isOpen()).toBe(false);
195
-
196
- // After opening, should be open
197
- datepicker.open();
198
- expect(datepicker.isOpen()).toBe(true);
199
-
200
- // After closing, should be closed again
201
- datepicker.close();
202
- expect(datepicker.isOpen()).toBe(false);
203
- });
204
-
205
- it('should return complete state object via getState', () => {
206
- const element = document.createElement('div');
207
- element.setAttribute('data-kt-datepicker', '');
208
- container.appendChild(element);
209
-
210
- const datepicker = new KTDatepicker(element);
211
- const testDate = new Date(2024, 0, 15);
212
-
213
- // Set a date to change state
214
- datepicker.setDate(testDate);
215
-
216
- // Get state
217
- const state = datepicker.getState();
218
-
219
- // Should return a complete state object
220
- expect(state).toBeDefined();
221
- expect(typeof state).toBe('object');
222
- expect(state).toHaveProperty('selectedDate');
223
- expect(state).toHaveProperty('isOpen');
224
- expect(state).toHaveProperty('isDisabled');
225
- expect(state).toHaveProperty('isFocused');
226
- expect(state).toHaveProperty('isTransitioning');
227
- expect(state).toHaveProperty('validationErrors');
228
- expect(state).toHaveProperty('isValid');
229
-
230
- // Should be a copy, not the original reference
231
- expect(state).not.toBe(datepicker.getState()); // Different object references
232
- });
233
-
234
- it('should getState return independent copies', () => {
235
- const element = document.createElement('div');
236
- element.setAttribute('data-kt-datepicker', '');
237
- container.appendChild(element);
238
-
239
- const datepicker = new KTDatepicker(element);
240
- const testDate = new Date(2024, 0, 15);
241
-
242
- // Set a date
243
- datepicker.setDate(testDate);
244
-
245
- // Get two state objects
246
- const state1 = datepicker.getState();
247
- const state2 = datepicker.getState();
248
-
249
- // Should be different objects (copies)
250
- expect(state1).not.toBe(state2);
251
-
252
- // But should have same content initially
253
- expect(state1.selectedDate).toEqual(state2.selectedDate);
254
- expect(state1.isOpen).toEqual(state2.isOpen);
255
-
256
- // Note: getState returns a shallow copy, so Date objects are shared references
257
- // This is expected behavior - consumers should treat state as read-only
258
- if (state1.selectedDate) {
259
- state1.selectedDate.setFullYear(2025);
260
- expect(state2.selectedDate?.getFullYear()).toBe(2025); // Both affected due to shared reference
261
- }
262
- });
263
-
264
- it('should toggle between open and closed states', () => {
265
- const element = document.createElement('div');
266
- element.setAttribute('data-kt-datepicker', '');
267
- container.appendChild(element);
268
-
269
- const datepicker = new KTDatepicker(element);
270
-
271
- // Initially closed
272
- expect(datepicker.isOpen()).toBe(false);
273
-
274
- // Toggle to open
275
- datepicker.toggle();
276
- expect(datepicker.isOpen()).toBe(true);
277
-
278
- // Toggle to close
279
- datepicker.toggle();
280
- expect(datepicker.isOpen()).toBe(false);
281
-
282
- // Toggle to open again
283
- datepicker.toggle();
284
- expect(datepicker.isOpen()).toBe(true);
285
- });
286
- });
287
-
288
- describe('getDropdownState', () => {
289
- it('should return the current dropdown state from state manager', () => {
290
- const element = document.createElement('div');
291
- element.setAttribute('data-kt-datepicker', '');
292
- container.appendChild(element);
293
-
294
- const datepicker = new KTDatepicker(element);
295
-
296
- // Get dropdown state
297
- const state = datepicker.getDropdownState();
298
-
299
- // Should return an object with expected properties
300
- expect(state).toBeDefined();
301
- expect(typeof state).toBe('object');
302
- expect(state).toHaveProperty('isOpen');
303
- expect(state).toHaveProperty('isTransitioning');
304
- expect(state).toHaveProperty('isDisabled');
305
- expect(state).toHaveProperty('isFocused');
306
- });
307
-
308
- it('should return consistent state after opening dropdown', () => {
309
- const element = document.createElement('div');
310
- element.setAttribute('data-kt-datepicker', '');
311
- container.appendChild(element);
312
-
313
- const datepicker = new KTDatepicker(element);
314
-
315
- // Initially closed
316
- const initialState = datepicker.getDropdownState();
317
- expect(initialState.isOpen).toBe(false);
318
-
319
- // Open dropdown
320
- datepicker.open();
321
-
322
- // Check state after opening
323
- const openState = datepicker.getDropdownState();
324
- expect(openState.isOpen).toBe(true);
325
- });
326
-
327
- it('should return consistent state after closing dropdown', () => {
328
- const element = document.createElement('div');
329
- element.setAttribute('data-kt-datepicker', '');
330
- container.appendChild(element);
331
-
332
- const datepicker = new KTDatepicker(element);
333
-
334
- // Open then close
335
- datepicker.open();
336
- datepicker.close();
337
-
338
- // Check state after closing
339
- const closedState = datepicker.getDropdownState();
340
- expect(closedState.isOpen).toBe(false);
341
- });
342
- });
343
- });