@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,387 +0,0 @@
1
- /**
2
- * time-preservation.test.ts - Tests for time preservation on calendar date clicks
3
- * Ensures time is preserved across single, range, and multi-date selection modes
4
- */
5
-
6
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
7
- import { KTDatepicker } from '../datepicker';
8
- import { dateToTimeState, applyTimeToDate } from '../utils/time-utils';
9
-
10
- describe('KTDatepicker Time Preservation', () => {
11
- let container: HTMLElement;
12
- let datepicker: KTDatepicker;
13
-
14
- beforeEach(() => {
15
- // Create a fresh container for each test
16
- container = document.createElement('div');
17
- container.innerHTML = `
18
- <div class="kt-datepicker" data-kt-datepicker>
19
- <input type="text" data-kt-datepicker-input placeholder="Select date">
20
- </div>
21
- `;
22
- document.body.innerHTML = '';
23
- document.body.appendChild(container);
24
- });
25
-
26
- afterEach(() => {
27
- if (datepicker) {
28
- datepicker.destroy();
29
- }
30
- document.body.innerHTML = '';
31
- });
32
-
33
- describe('Single Date Mode', () => {
34
- it('should preserve time when selectedTime exists', () => {
35
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
36
- const initialDate = new Date(2024, 0, 15, 14, 30, 0); // Jan 15, 2024, 2:30 PM
37
-
38
- datepicker = new KTDatepicker(element, {
39
- enableTime: true,
40
- value: initialDate,
41
- });
42
-
43
- // Verify initial date has time set
44
- const initialState = datepicker.getState();
45
- expect(initialState.selectedDate).toBeDefined();
46
- expect(initialState.selectedDate?.getHours()).toBe(14);
47
- expect(initialState.selectedDate?.getMinutes()).toBe(30);
48
-
49
- // Select a new date
50
- const newDate = new Date(2024, 0, 20, 0, 0, 0); // Jan 20, 2024, midnight
51
- datepicker.setDate(newDate);
52
-
53
- // Verify time is preserved
54
- const newState = datepicker.getState();
55
- expect(newState.selectedDate).toBeDefined();
56
- expect(newState.selectedDate?.getDate()).toBe(20);
57
- expect(newState.selectedDate?.getHours()).toBe(14);
58
- expect(newState.selectedDate?.getMinutes()).toBe(30);
59
- });
60
-
61
- it('should extract time from selectedDate when selectedTime is missing', () => {
62
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
63
- const initialDate = new Date(2024, 0, 15, 16, 45, 0); // Jan 15, 2024, 4:45 PM
64
-
65
- datepicker = new KTDatepicker(element, {
66
- enableTime: true,
67
- value: initialDate,
68
- });
69
-
70
- // Clear selectedTime state (simulate missing state)
71
- const state = datepicker.getState();
72
- (datepicker as any)._unifiedStateManager.updateState(
73
- { selectedTime: null },
74
- 'test-clear'
75
- );
76
-
77
- // Select a new date
78
- const newDate = new Date(2024, 0, 25, 0, 0, 0);
79
- datepicker.setDate(newDate);
80
-
81
- // Verify time is extracted from selectedDate
82
- const newState = datepicker.getState();
83
- expect(newState.selectedDate?.getDate()).toBe(25);
84
- expect(newState.selectedDate?.getHours()).toBe(16);
85
- expect(newState.selectedDate?.getMinutes()).toBe(45);
86
- });
87
-
88
- it('should default to current time when no time exists', () => {
89
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
90
- const now = new Date();
91
-
92
- datepicker = new KTDatepicker(element, {
93
- enableTime: true,
94
- });
95
-
96
- // Select a date
97
- const newDate = new Date(2024, 0, 15, 0, 0, 0);
98
- datepicker.setDate(newDate);
99
-
100
- // Verify time defaults to current time
101
- const state = datepicker.getState();
102
- expect(state.selectedDate).toBeDefined();
103
- expect(state.selectedDate?.getDate()).toBe(15);
104
- // Allow 1-minute tolerance for test execution time
105
- const timeDiff = Math.abs(state.selectedDate!.getHours() - now.getHours());
106
- expect(timeDiff).toBeLessThanOrEqual(1);
107
- });
108
-
109
- it('should not reset time to midnight', () => {
110
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
111
- const initialDate = new Date(2024, 0, 15, 10, 15, 30); // Jan 15, 2024, 10:15:30 AM
112
-
113
- datepicker = new KTDatepicker(element, {
114
- enableTime: true,
115
- timeGranularity: 'second',
116
- value: initialDate,
117
- });
118
-
119
- // Select a new date
120
- const newDate = new Date(2024, 0, 20, 0, 0, 0);
121
- datepicker.setDate(newDate);
122
-
123
- // Verify time is NOT midnight
124
- const state = datepicker.getState();
125
- expect(state.selectedDate?.getHours()).not.toBe(0);
126
- expect(state.selectedDate?.getMinutes()).not.toBe(0);
127
- expect(state.selectedDate?.getSeconds()).not.toBe(0);
128
- expect(state.selectedDate?.getHours()).toBe(10);
129
- expect(state.selectedDate?.getMinutes()).toBe(15);
130
- expect(state.selectedDate?.getSeconds()).toBe(30);
131
- });
132
- });
133
-
134
- describe('Range Selection Mode', () => {
135
- it('should preserve time for both start and end dates', () => {
136
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
137
- const initialDate = new Date(2024, 0, 15, 14, 30, 0); // Jan 15, 2024, 2:30 PM
138
-
139
- datepicker = new KTDatepicker(element, {
140
- range: true,
141
- enableTime: true,
142
- });
143
-
144
- // Manually set selectedTime to simulate time picker selection
145
- // Use immediate update (third parameter = true)
146
- (datepicker as any)._unifiedStateManager.updateState(
147
- { selectedTime: { hour: 14, minute: 30, second: 0 } },
148
- 'test-init',
149
- true
150
- );
151
-
152
- // Select start date (first click creates start)
153
- const startDate = new Date(2024, 0, 10, 0, 0, 0);
154
- (datepicker as any)._selectRangeDate(startDate);
155
-
156
- // Verify start has time preserved
157
- const afterStartState = datepicker.getState();
158
- expect(afterStartState.selectedRange?.start?.getDate()).toBe(10);
159
- expect(afterStartState.selectedRange?.start?.getHours()).toBe(14);
160
- expect(afterStartState.selectedRange?.start?.getMinutes()).toBe(30);
161
-
162
- // Select end date (second click creates end)
163
- const endDate = new Date(2024, 0, 20, 0, 0, 0);
164
- (datepicker as any)._selectRangeDate(endDate);
165
-
166
- // Verify both dates preserve time
167
- const newState = datepicker.getState();
168
- expect(newState.selectedRange).toBeDefined();
169
- expect(newState.selectedRange?.start).toBeDefined();
170
- expect(newState.selectedRange?.end).toBeDefined();
171
-
172
- expect(newState.selectedRange?.start?.getDate()).toBe(10);
173
- expect(newState.selectedRange?.start?.getHours()).toBe(14);
174
- expect(newState.selectedRange?.start?.getMinutes()).toBe(30);
175
-
176
- expect(newState.selectedRange?.end?.getDate()).toBe(20);
177
- expect(newState.selectedRange?.end?.getHours()).toBe(14);
178
- expect(newState.selectedRange?.end?.getMinutes()).toBe(30);
179
- });
180
-
181
- it('should not reset range dates to midnight', () => {
182
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
183
- const initialDate = new Date(2024, 0, 15, 16, 45, 0); // Jan 15, 2024, 4:45 PM
184
-
185
- datepicker = new KTDatepicker(element, {
186
- range: true,
187
- enableTime: true,
188
- value: initialDate,
189
- });
190
-
191
- // Select start and end dates
192
- const startDate = new Date(2024, 0, 10, 0, 0, 0);
193
- (datepicker as any)._selectRangeDate(startDate);
194
-
195
- const endDate = new Date(2024, 0, 25, 0, 0, 0);
196
- (datepicker as any)._selectRangeDate(endDate);
197
-
198
- // Verify time is NOT midnight for either date
199
- const state = datepicker.getState();
200
- expect(state.selectedRange?.start?.getHours()).not.toBe(0);
201
- expect(state.selectedRange?.start?.getMinutes()).not.toBe(0);
202
- expect(state.selectedRange?.end?.getHours()).not.toBe(0);
203
- expect(state.selectedRange?.end?.getMinutes()).not.toBe(0);
204
- });
205
-
206
- it('should extract time from range start when selectedTime is missing', () => {
207
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
208
-
209
- datepicker = new KTDatepicker(element, {
210
- range: true,
211
- enableTime: true,
212
- valueRange: {
213
- start: new Date(2024, 0, 10, 13, 20, 0), // Jan 10, 2024, 1:20 PM
214
- end: new Date(2024, 0, 15, 13, 20, 0), // Jan 15, 2024, 1:20 PM
215
- },
216
- });
217
-
218
- // Clear selectedTime
219
- (datepicker as any)._unifiedStateManager.updateState(
220
- { selectedTime: null },
221
- 'test-clear'
222
- );
223
-
224
- // Reset range to only have start
225
- (datepicker as any)._unifiedStateManager.setSelectedRange(
226
- {
227
- start: new Date(2024, 0, 10, 13, 20, 0),
228
- end: null,
229
- },
230
- 'test-reset'
231
- );
232
-
233
- // Select a new end date
234
- const newEndDate = new Date(2024, 0, 25, 0, 0, 0);
235
- (datepicker as any)._selectRangeDate(newEndDate);
236
-
237
- // Verify time is extracted from range start
238
- const state = datepicker.getState();
239
- expect(state.selectedRange?.end?.getDate()).toBe(25);
240
- expect(state.selectedRange?.end?.getHours()).toBe(13);
241
- expect(state.selectedRange?.end?.getMinutes()).toBe(20);
242
- });
243
- });
244
-
245
- describe('Multi-Date Selection Mode', () => {
246
- it('should preserve time for all selected dates', () => {
247
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
248
- const initialDate = new Date(2024, 0, 15, 11, 30, 0); // Jan 15, 2024, 11:30 AM
249
-
250
- datepicker = new KTDatepicker(element, {
251
- multiDate: true,
252
- enableTime: true,
253
- values: [initialDate],
254
- });
255
-
256
- // Verify initial date has time set
257
- const initialState = datepicker.getState();
258
- expect(initialState.selectedDates).toBeDefined();
259
- expect(initialState.selectedDates.length).toBe(1);
260
- expect(initialState.selectedDates[0].getHours()).toBe(11);
261
- expect(initialState.selectedDates[0].getMinutes()).toBe(30);
262
-
263
- // Select multiple dates
264
- const date1 = new Date(2024, 0, 10, 0, 0, 0);
265
- (datepicker as any)._selectMultiDate(date1);
266
-
267
- const date2 = new Date(2024, 0, 20, 0, 0, 0);
268
- (datepicker as any)._selectMultiDate(date2);
269
-
270
- const date3 = new Date(2024, 0, 25, 0, 0, 0);
271
- (datepicker as any)._selectMultiDate(date3);
272
-
273
- // Verify all dates preserve time
274
- const newState = datepicker.getState();
275
- expect(newState.selectedDates).toBeDefined();
276
- expect(newState.selectedDates.length).toBeGreaterThan(1);
277
-
278
- newState.selectedDates.forEach((date) => {
279
- expect(date.getHours()).toBe(11);
280
- expect(date.getMinutes()).toBe(30);
281
- });
282
- });
283
-
284
- it('should not reset multi-dates to midnight', () => {
285
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
286
- const initialDate = new Date(2024, 0, 15, 9, 15, 0); // Jan 15, 2024, 9:15 AM
287
-
288
- datepicker = new KTDatepicker(element, {
289
- multiDate: true,
290
- enableTime: true,
291
- value: initialDate,
292
- });
293
-
294
- // Select dates
295
- const date1 = new Date(2024, 0, 10, 0, 0, 0);
296
- (datepicker as any)._selectMultiDate(date1);
297
-
298
- const date2 = new Date(2024, 0, 20, 0, 0, 0);
299
- (datepicker as any)._selectMultiDate(date2);
300
-
301
- // Verify time is NOT midnight for any date
302
- const state = datepicker.getState();
303
- state.selectedDates.forEach((date) => {
304
- expect(date.getHours()).not.toBe(0);
305
- expect(date.getMinutes()).not.toBe(0);
306
- });
307
- });
308
-
309
- it('should extract time from existing selected dates when selectedTime is missing', () => {
310
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
311
-
312
- datepicker = new KTDatepicker(element, {
313
- multiDate: true,
314
- enableTime: true,
315
- values: [
316
- new Date(2024, 0, 10, 15, 45, 0), // Jan 10, 2024, 3:45 PM
317
- new Date(2024, 0, 15, 15, 45, 0), // Jan 15, 2024, 3:45 PM
318
- ],
319
- });
320
-
321
- // Clear selectedTime
322
- (datepicker as any)._unifiedStateManager.updateState(
323
- { selectedTime: null },
324
- 'test-clear'
325
- );
326
-
327
- // Select a new date
328
- const newDate = new Date(2024, 0, 25, 0, 0, 0);
329
- (datepicker as any)._selectMultiDate(newDate);
330
-
331
- // Verify time is extracted from existing dates
332
- const state = datepicker.getState();
333
- const addedDate = state.selectedDates.find((d) => d.getDate() === 25);
334
- expect(addedDate).toBeDefined();
335
- expect(addedDate?.getHours()).toBe(15);
336
- expect(addedDate?.getMinutes()).toBe(45);
337
- });
338
- });
339
-
340
- describe('Date-Only Mode (No Time)', () => {
341
- it('should not apply time when enableTime is false', () => {
342
- const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
343
-
344
- datepicker = new KTDatepicker(element, {
345
- enableTime: false,
346
- });
347
-
348
- // Select a date
349
- const date = new Date(2024, 0, 15, 0, 0, 0);
350
- datepicker.setDate(date);
351
-
352
- // Verify time remains at midnight (default for date-only)
353
- const state = datepicker.getState();
354
- expect(state.selectedDate?.getDate()).toBe(15);
355
- // Time should be normalized to midnight for date-only mode
356
- expect(state.selectedDate?.getHours()).toBe(0);
357
- expect(state.selectedDate?.getMinutes()).toBe(0);
358
- expect(state.selectedDate?.getSeconds()).toBe(0);
359
- });
360
- });
361
-
362
- describe('Time Utility Functions', () => {
363
- it('dateToTimeState should extract time correctly', () => {
364
- const date = new Date(2024, 0, 15, 14, 30, 45);
365
- const timeState = dateToTimeState(date);
366
-
367
- expect(timeState.hour).toBe(14);
368
- expect(timeState.minute).toBe(30);
369
- expect(timeState.second).toBe(45);
370
- });
371
-
372
- it('applyTimeToDate should preserve date and apply time', () => {
373
- const date = new Date(2024, 0, 15, 0, 0, 0);
374
- const timeState = { hour: 16, minute: 45, second: 30 };
375
-
376
- const result = applyTimeToDate(date, timeState);
377
-
378
- expect(result.getFullYear()).toBe(2024);
379
- expect(result.getMonth()).toBe(0);
380
- expect(result.getDate()).toBe(15);
381
- expect(result.getHours()).toBe(16);
382
- expect(result.getMinutes()).toBe(45);
383
- expect(result.getSeconds()).toBe(30);
384
- });
385
- });
386
- });
387
-
@@ -1,40 +0,0 @@
1
- import { KTDatepickerConfig } from './types';
2
-
3
- /**
4
- * Default configuration for KTDatepicker
5
- */
6
- export const defaultDatepickerConfig: KTDatepickerConfig = {
7
- templates: {},
8
- format: 'yyyy-MM-dd',
9
- range: false,
10
- multiDate: false,
11
- minDate: undefined,
12
- maxDate: undefined,
13
- disabled: false,
14
- locale: 'en-US',
15
- placeholder: '',
16
- value: undefined,
17
- valueRange: undefined,
18
- values: undefined,
19
- showOnFocus: true,
20
- closeOnSelect: false, // Default: don't close dropdown by default
21
- closeOnOutsideClick: true, // Default: close dropdown when clicking outside
22
- // Number of calendar months to display side-by-side (horizontal). Default: 1.
23
- visibleMonths: 1,
24
- // Time-related defaults
25
- enableTime: false,
26
- timeGranularity: 'minute',
27
- timeFormat: '24h',
28
- minTime: undefined,
29
- maxTime: undefined,
30
- timeStep: 1,
31
- // Dropdown defaults
32
- dropdownPlacement: 'bottom-end', // Position relative to calendar button (right side)
33
- dropdownOffset: '0, 5',
34
- dropdownBoundary: 'clippingParents',
35
- dropdownWidth: 'auto', // 'auto' for fixed CSS width (20rem), 'toggle' to match input width, or custom string value
36
- dropdownZindex: undefined,
37
- dropdownContainer: undefined,
38
- // Custom classes for template elements
39
- classes: {},
40
- };
@@ -1,8 +0,0 @@
1
- /*
2
- * config/index.ts - Configuration module exports
3
- * Provides types, interfaces, and default configuration for KTDatepicker
4
- */
5
-
6
- export * from './types';
7
- export * from './interfaces';
8
- export * from './config';
@@ -1,82 +0,0 @@
1
- /*
2
- * interfaces.ts - Interfaces for KTDatepicker components
3
- * Defines contracts between components to reduce coupling and improve testability.
4
- */
5
-
6
- import { KTDatepickerConfig, KTDatepickerState, KTDatepickerTemplateStrings } from './types';
7
-
8
- /**
9
- * Interface for UI rendering operations
10
- */
11
- export interface IUIRenderer {
12
- renderContainer(): HTMLElement;
13
- renderInputWrapper(calendarButtonHtml: string): HTMLElement;
14
- renderDropdown(): HTMLElement;
15
- renderDropdownContent(dropdownEl: HTMLElement): void;
16
- renderCalendarButton(): string;
17
- updateState(newState: KTDatepickerState): void;
18
- updateConfig(newConfig: KTDatepickerConfig): void;
19
- }
20
-
21
- /**
22
- * Interface for state management operations
23
- */
24
- export interface IStateManager {
25
- isOpen(): boolean;
26
- isTransitioning(): boolean;
27
- isDisabled(): boolean;
28
- open(source?: string): boolean;
29
- close(source?: string): boolean;
30
- toggle(source?: string): boolean;
31
- enable(source?: string): boolean;
32
- disable(source?: string): boolean;
33
- setFocus(focused: boolean, source?: string): boolean;
34
- getState(): any;
35
- subscribe(observer: (event: any) => void): () => void;
36
- dispose(): void;
37
- }
38
-
39
- /**
40
- * Interface for event management operations
41
- */
42
- export interface IEventManager {
43
- addListener(element: HTMLElement, event: string, handler: (e: Event) => void): void;
44
- removeListener(element: HTMLElement, event: string, handler: (e: Event) => void): void;
45
- removeAllListeners(element: HTMLElement): void;
46
- }
47
-
48
- /**
49
- * Interface for dropdown positioning operations
50
- */
51
- export interface IDropdownManager {
52
- open(): void;
53
- close(): void;
54
- isOpen(): boolean;
55
- updatePosition(): void;
56
- dispose(): void;
57
- }
58
-
59
- /**
60
- * Interface for date selection operations
61
- */
62
- export interface IDateSelector {
63
- selectDate(date: Date): void;
64
- selectRange(start: Date, end: Date): void;
65
- selectMultipleDates(dates: Date[]): void;
66
- clearSelection(): void;
67
- getSelectedDate(): Date | null;
68
- getSelectedRange(): { start: Date | null; end: Date | null } | null;
69
- getSelectedDates(): Date[];
70
- }
71
-
72
- /**
73
- * Interface for input management operations
74
- */
75
- export interface IInputManager {
76
- setValue(value: string): void;
77
- getValue(): string;
78
- setPlaceholder(placeholder: string): void;
79
- setDisabled(disabled: boolean): void;
80
- focus(): void;
81
- blur(): void;
82
- }
@@ -1,188 +0,0 @@
1
- /*
2
- * types.ts - Type definitions for KTDatepicker (revamp)
3
- * Defines config, template, and state interfaces for modular, extensible template customization.
4
- */
5
-
6
- // Template keys for all customizable UI fragments
7
- export type KTDatepickerTemplateKey =
8
- | 'container'
9
- | 'header'
10
- | 'footer'
11
- | 'calendarGrid'
12
- | 'dayCell'
13
- | 'monthYearSelect'
14
- | 'monthSelection'
15
- | 'yearSelection'
16
- | 'inputWrapper'
17
- | 'segmentedDateInput'
18
- | 'segmentedDateRangeInput'
19
- | 'placeholder'
20
- | 'displayWrapper'
21
- | 'displayElement'
22
- | 'timePanel'
23
- | 'multiDateTag'
24
- | 'emptyState'
25
- | 'calendarButton'
26
- | 'dropdown'
27
- | 'prevButton'
28
- | 'nextButton'
29
- | 'calendarTable'
30
- | 'calendarRow'
31
- | 'calendarBody'
32
- | 'todayButton'
33
- | 'clearButton'
34
- | 'applyButton'
35
- | 'multiMonthContainer'
36
- | 'dateSegment'
37
- | 'segmentSeparator'
38
- | 'timePickerWrapper'
39
- | 'timeDisplay'
40
- | 'timeControls'
41
- | 'timeUnit'
42
- | 'timeUpButton'
43
- | 'timeDownButton'
44
- | 'timeValue'
45
- | 'timeSeparator'
46
- | 'ampmControl'
47
- | 'ampmButton'
48
- | 'panel'
49
- | 'liveRegion'
50
- | 'rangeStartContainer'
51
- | 'rangeEndContainer';
52
-
53
- // Template string map
54
- export type KTDatepickerTemplateStrings = {
55
- [K in KTDatepickerTemplateKey]?: string | ((data: any) => string);
56
- };
57
-
58
- /**
59
- * Configuration options for KTDatepicker
60
- */
61
- export interface KTDatepickerConfig {
62
- /** Custom templates for UI fragments */
63
- templates?: KTDatepickerTemplateStrings;
64
- /** Date format string (e.g. 'yyyy-mm-dd', 'dd/mm/yyyy') */
65
- format?: string;
66
- /** Enable date range selection */
67
- range?: boolean;
68
- /** Enable multi-date selection */
69
- multiDate?: boolean;
70
- /** Minimum selectable date */
71
- minDate?: Date | string;
72
- /** Maximum selectable date */
73
- maxDate?: Date | string;
74
- /** Disable the datepicker */
75
- disabled?: boolean;
76
- /** Locale for date formatting (e.g. 'en-US') */
77
- locale?: string;
78
- /** Placeholder text for the input */
79
- placeholder?: string;
80
- /** Initial selected date */
81
- value?: Date | string;
82
- /** Initial selected date range */
83
- valueRange?: { start: Date | string; end: Date | string };
84
- /** Initial selected dates (multi-date) */
85
- values?: (Date | string)[];
86
- /** Custom class for the root element */
87
- className?: string;
88
- /** Whether to show the calendar on input focus (default: true) */
89
- showOnFocus?: boolean;
90
- /** Whether to close the calendar on date selection (default: true) */
91
- closeOnSelect?: boolean;
92
- /** Whether to close the calendar when clicking outside (default: true) */
93
- closeOnOutsideClick?: boolean;
94
- /**
95
- * Number of calendar months to display side-by-side (horizontal). Default: 1.
96
- */
97
- visibleMonths?: number;
98
- /** Enable time selection (default: false) */
99
- enableTime?: boolean;
100
- /** Time granularity - smallest unit to display (default: 'minute') */
101
- timeGranularity?: 'second' | 'minute' | 'hour';
102
- /** Time format - 12 or 24 hour (default: '24h') */
103
- timeFormat?: '12h' | '24h';
104
- /** Minimum time constraint (format: 'HH:MM' or 'HH:MM:SS') */
105
- minTime?: string;
106
- /** Maximum time constraint (format: 'HH:MM' or 'HH:MM:SS') */
107
- maxTime?: string;
108
- /** Time step increment in minutes (default: 1) */
109
- timeStep?: number;
110
- /** Dropdown positioning and behavior options */
111
- dropdownPlacement?: string;
112
- dropdownOffset?: string;
113
- dropdownBoundary?: string;
114
- dropdownWidth?: 'auto' | 'toggle' | string;
115
- dropdownZindex?: number;
116
- dropdownContainer?: string;
117
- /** Custom classes for template elements */
118
- classes?: {
119
- container?: string;
120
- header?: string;
121
- footer?: string;
122
- calendarGrid?: string;
123
- dayCell?: string;
124
- monthYearSelect?: string;
125
- monthSelection?: string;
126
- yearSelection?: string;
127
- inputWrapper?: string;
128
- segmentedDateInput?: string;
129
- segmentedDateRangeInput?: string;
130
- dateSegment?: string;
131
- segmentSeparator?: string;
132
- placeholder?: string;
133
- displayWrapper?: string;
134
- displayElement?: string;
135
- timePanel?: string;
136
- multiDateTag?: string;
137
- emptyState?: string;
138
- calendarButton?: string;
139
- dropdown?: string;
140
- prevButton?: string;
141
- nextButton?: string;
142
- calendarTable?: string;
143
- calendarRow?: string;
144
- calendarBody?: string;
145
- todayButton?: string;
146
- clearButton?: string;
147
- applyButton?: string;
148
- multiMonthContainer?: string;
149
- };
150
- /** Any additional custom config options */
151
- [key: string]: any;
152
- }
153
-
154
- // Time state interface
155
- export interface TimeState {
156
- hour: number;
157
- minute: number;
158
- second: number;
159
- }
160
-
161
- // State interface for KTDatepicker
162
- /**
163
- * Dropdown state interface
164
- */
165
- export interface DropdownState {
166
- isOpen: boolean;
167
- isTransitioning: boolean;
168
- isDisabled: boolean;
169
- isFocused: boolean;
170
- }
171
-
172
- export interface KTDatepickerState {
173
- currentDate: Date;
174
- selectedDate: Date | null;
175
- selectedRange: { start: Date | null; end: Date | null } | null;
176
- selectedDates: Date[];
177
- selectedTime: TimeState | null;
178
- timeGranularity: 'second' | 'minute' | 'hour';
179
- viewMode: 'days' | 'months' | 'years';
180
- isOpen: boolean;
181
- isFocused: boolean;
182
- isTransitioning: boolean;
183
- isDisabled: boolean;
184
- validationErrors: string[];
185
- isValid: boolean;
186
- // Dropdown state (consolidated from legacy state manager)
187
- dropdownState: DropdownState;
188
- }