@king-design/intact 3.5.2 → 3.6.0

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 (260) hide show
  1. package/components/.DS_Store +0 -0
  2. package/components/button/index.md +1 -0
  3. package/components/cascader/index.spec.ts +7 -6
  4. package/components/datepicker/basepicker.ts +26 -267
  5. package/components/datepicker/calendar.ts +8 -2
  6. package/components/datepicker/calendar.vdt +23 -6
  7. package/components/datepicker/dayjs.ts +8 -2
  8. package/components/datepicker/demos/multiple.md +1 -1
  9. package/components/datepicker/demos/yearMonth.md +1 -1
  10. package/components/datepicker/helpers.ts +10 -12
  11. package/components/datepicker/index.md +2 -2
  12. package/components/datepicker/index.spec.ts +619 -190
  13. package/components/datepicker/index.ts +22 -21
  14. package/components/datepicker/index.vdt +47 -42
  15. package/components/datepicker/shortcuts.ts +1 -1
  16. package/components/datepicker/styles.ts +112 -4
  17. package/components/datepicker/useConfirm.ts +82 -0
  18. package/components/datepicker/useDisabled.ts +31 -33
  19. package/components/datepicker/useFormats.ts +10 -4
  20. package/components/datepicker/useHighlight.ts +81 -0
  21. package/components/datepicker/useKeyboards.ts +2 -1
  22. package/components/datepicker/useMergeRange.ts +54 -0
  23. package/components/datepicker/useMonths.ts +6 -3
  24. package/components/datepicker/usePanel.ts +19 -19
  25. package/components/datepicker/useQuarters.ts +47 -0
  26. package/components/datepicker/useShowDate.ts +14 -3
  27. package/components/datepicker/useStatus.ts +34 -15
  28. package/components/datepicker/useValue.ts +41 -39
  29. package/components/datepicker/useValueBase.ts +309 -0
  30. package/components/datepicker/useWeeks.ts +58 -0
  31. package/components/datepicker/useYears.ts +7 -3
  32. package/components/descriptions/.DS_Store +0 -0
  33. package/components/dialog/useFixBody.ts +7 -64
  34. package/components/dropdown/dropdown.ts +5 -4
  35. package/components/dropdown/index.md +1 -0
  36. package/components/dropdown/item.ts +1 -1
  37. package/components/dropdown/useKeyboard.ts +0 -1
  38. package/components/ellipsis/styles.ts +4 -0
  39. package/components/form/styles.ts +1 -0
  40. package/components/input/index.spec.ts +42 -0
  41. package/components/input/index.ts +8 -0
  42. package/components/input/index.vdt +3 -4
  43. package/components/input/useAutoWidth.ts +19 -1
  44. package/components/menu/.DS_Store +0 -0
  45. package/components/menu/demos/.DS_Store +0 -0
  46. package/components/scrollSelect/index.spec.ts +3 -3
  47. package/components/scrollSelect/useMouseEvents.ts +24 -10
  48. package/components/select/base.ts +3 -2
  49. package/components/select/base.vdt +3 -1
  50. package/components/select/demos/creatable.md +13 -0
  51. package/components/select/index.md +1 -0
  52. package/components/select/index.spec.ts +225 -6
  53. package/components/select/option.ts +10 -1
  54. package/components/select/select.ts +3 -0
  55. package/components/select/styles.ts +3 -1
  56. package/components/select/useFilterable.ts +1 -1
  57. package/components/select/useInput.ts +7 -9
  58. package/components/select/useSearchable.ts +2 -2
  59. package/components/table/.DS_Store +0 -0
  60. package/components/table/index.spec.ts +69 -1
  61. package/components/table/useStickyHeader.ts +1 -1
  62. package/components/timepicker/demos/step.md +1 -1
  63. package/components/timepicker/index.spec.ts +145 -27
  64. package/components/timepicker/panelPicker.ts +10 -4
  65. package/components/timepicker/panelPicker.vdt +5 -3
  66. package/components/timepicker/useConfirm.ts +33 -0
  67. package/components/timepicker/useDefaultValue.ts +30 -0
  68. package/components/timepicker/useDisabled.ts +17 -4
  69. package/components/timepicker/useFormats.ts +1 -1
  70. package/components/timepicker/useValue.ts +22 -19
  71. package/components/tour/.DS_Store +0 -0
  72. package/components/tour/demos/basic.md +73 -0
  73. package/components/tour/demos/beforeChange.md +109 -0
  74. package/components/tour/demos/closable.md +70 -0
  75. package/components/tour/demos/custom.md +98 -0
  76. package/components/tour/demos/customText.md +94 -0
  77. package/components/tour/demos/declarative.md +72 -0
  78. package/components/tour/demos/events.md +101 -0
  79. package/components/tour/demos/maskClosable.md +76 -0
  80. package/components/tour/demos/notarget.md +59 -0
  81. package/components/tour/index.md +48 -0
  82. package/components/tour/index.spec.ts +259 -0
  83. package/components/tour/index.ts +2 -0
  84. package/components/tour/step.ts +55 -0
  85. package/components/tour/step.vdt +75 -0
  86. package/components/tour/styles.ts +283 -0
  87. package/components/tour/tour.ts +107 -0
  88. package/components/tour/tour.vdt +83 -0
  89. package/components/tour/useArrow.ts +46 -0
  90. package/components/tour/useFixBody.ts +22 -0
  91. package/components/tour/useHighlight.ts +36 -0
  92. package/components/tour/useMaskClosable.ts +26 -0
  93. package/components/tour/useNavigation.ts +46 -0
  94. package/components/tour/usePosition.ts +91 -0
  95. package/components/tour/useSteps.ts +80 -0
  96. package/components/virtualList/.DS_Store +0 -0
  97. package/components/virtualList/demos/.DS_Store +0 -0
  98. package/es/components/cascader/index.spec.js +18 -19
  99. package/es/components/datepicker/basepicker.d.ts +6 -25
  100. package/es/components/datepicker/basepicker.js +22 -234
  101. package/es/components/datepicker/calendar.d.ts +36 -6
  102. package/es/components/datepicker/calendar.js +4 -0
  103. package/es/components/datepicker/calendar.vdt.js +21 -5
  104. package/es/components/datepicker/dayjs.d.ts +2 -2
  105. package/es/components/datepicker/dayjs.js +6 -0
  106. package/es/components/datepicker/helpers.d.ts +8 -7
  107. package/es/components/datepicker/helpers.js +2 -3
  108. package/es/components/datepicker/index.d.ts +26 -19
  109. package/es/components/datepicker/index.js +21 -13
  110. package/es/components/datepicker/index.spec.js +1389 -633
  111. package/es/components/datepicker/index.vdt.js +43 -46
  112. package/es/components/datepicker/shortcuts.d.ts +1 -1
  113. package/es/components/datepicker/styles.d.ts +22 -0
  114. package/es/components/datepicker/styles.js +26 -4
  115. package/es/components/datepicker/useConfirm.d.ts +6 -0
  116. package/es/components/datepicker/useConfirm.js +65 -0
  117. package/es/components/datepicker/useDisabled.d.ts +7 -5
  118. package/es/components/datepicker/useDisabled.js +22 -27
  119. package/es/components/datepicker/useFormats.d.ts +2 -2
  120. package/es/components/datepicker/useFormats.js +9 -3
  121. package/es/components/datepicker/useHighlight.d.ts +14 -0
  122. package/es/components/datepicker/useHighlight.js +60 -0
  123. package/es/components/datepicker/useKeyboards.js +2 -1
  124. package/es/components/datepicker/useMergeRange.d.ts +5 -0
  125. package/es/components/datepicker/useMergeRange.js +45 -0
  126. package/es/components/datepicker/useMonths.js +5 -3
  127. package/es/components/datepicker/usePanel.d.ts +1 -10
  128. package/es/components/datepicker/usePanel.js +19 -32
  129. package/es/components/datepicker/useQuarters.d.ts +15 -0
  130. package/es/components/datepicker/useQuarters.js +36 -0
  131. package/es/components/datepicker/useShowDate.js +10 -2
  132. package/es/components/datepicker/useStatus.d.ts +1 -1
  133. package/es/components/datepicker/useStatus.js +33 -16
  134. package/es/components/datepicker/useValue.d.ts +12 -6
  135. package/es/components/datepicker/useValue.js +49 -45
  136. package/es/components/datepicker/useValueBase.d.ts +28 -0
  137. package/es/components/datepicker/useValueBase.js +277 -0
  138. package/es/components/datepicker/useWeeks.d.ts +19 -0
  139. package/es/components/datepicker/useWeeks.js +48 -0
  140. package/es/components/datepicker/useYears.js +6 -3
  141. package/es/components/dialog/useFixBody.js +6 -58
  142. package/es/components/dropdown/dropdown.d.ts +1 -0
  143. package/es/components/dropdown/dropdown.js +7 -4
  144. package/es/components/ellipsis/styles.js +1 -1
  145. package/es/components/form/styles.js +1 -1
  146. package/es/components/input/index.d.ts +2 -0
  147. package/es/components/input/index.js +6 -0
  148. package/es/components/input/index.spec.js +45 -0
  149. package/es/components/input/index.vdt.js +4 -3
  150. package/es/components/input/useAutoWidth.d.ts +2 -0
  151. package/es/components/input/useAutoWidth.js +19 -1
  152. package/es/components/scrollSelect/index.spec.js +4 -6
  153. package/es/components/scrollSelect/useMouseEvents.js +22 -9
  154. package/es/components/select/base.d.ts +1 -1
  155. package/es/components/select/base.js +3 -2
  156. package/es/components/select/base.vdt.js +5 -2
  157. package/es/components/select/index.spec.js +329 -82
  158. package/es/components/select/option.d.ts +1 -0
  159. package/es/components/select/option.js +10 -2
  160. package/es/components/select/select.d.ts +1 -0
  161. package/es/components/select/select.js +4 -2
  162. package/es/components/select/styles.d.ts +79 -0
  163. package/es/components/select/styles.js +1 -0
  164. package/es/components/select/useFilterable.js +2 -1
  165. package/es/components/select/useInput.d.ts +1 -1
  166. package/es/components/select/useInput.js +7 -4
  167. package/es/components/select/useSearchable.js +1 -0
  168. package/es/components/table/index.spec.js +84 -6
  169. package/es/components/table/useStickyHeader.js +1 -1
  170. package/es/components/timepicker/index.spec.js +298 -128
  171. package/es/components/timepicker/panelPicker.d.ts +23 -17
  172. package/es/components/timepicker/panelPicker.js +7 -4
  173. package/es/components/timepicker/panelPicker.vdt.js +8 -4
  174. package/es/components/timepicker/selectPicker.d.ts +5 -4
  175. package/es/components/timepicker/useConfirm.d.ts +6 -0
  176. package/es/components/timepicker/useConfirm.js +19 -0
  177. package/es/components/timepicker/useDefaultValue.d.ts +4 -0
  178. package/es/components/timepicker/useDefaultValue.js +27 -0
  179. package/es/components/timepicker/useDisabled.d.ts +7 -4
  180. package/es/components/timepicker/useDisabled.js +13 -4
  181. package/es/components/timepicker/useFormats.d.ts +1 -1
  182. package/es/components/timepicker/useValue.d.ts +14 -8
  183. package/es/components/timepicker/useValue.js +14 -15
  184. package/es/components/tour/index.d.ts +2 -0
  185. package/es/components/tour/index.js +2 -0
  186. package/es/components/tour/index.spec.d.ts +1 -0
  187. package/es/components/tour/index.spec.js +356 -0
  188. package/es/components/tour/step.d.ts +23 -0
  189. package/es/components/tour/step.js +46 -0
  190. package/es/components/tour/step.vdt.js +74 -0
  191. package/es/components/tour/styles.d.ts +7 -0
  192. package/es/components/tour/styles.js +84 -0
  193. package/es/components/tour/tour.d.ts +73 -0
  194. package/es/components/tour/tour.js +70 -0
  195. package/es/components/tour/tour.vdt.js +66 -0
  196. package/es/components/tour/useArrow.d.ts +4 -0
  197. package/es/components/tour/useArrow.js +40 -0
  198. package/es/components/tour/useFixBody.d.ts +4 -0
  199. package/es/components/tour/useFixBody.js +17 -0
  200. package/es/components/tour/useHighlight.d.ts +4 -0
  201. package/es/components/tour/useHighlight.js +31 -0
  202. package/es/components/tour/useMaskClosable.d.ts +1 -0
  203. package/es/components/tour/useMaskClosable.js +25 -0
  204. package/es/components/tour/useNavigation.d.ts +5 -0
  205. package/es/components/tour/useNavigation.js +103 -0
  206. package/es/components/tour/usePosition.d.ts +6 -0
  207. package/es/components/tour/usePosition.js +93 -0
  208. package/es/components/tour/useSteps.d.ts +6 -0
  209. package/es/components/tour/useSteps.js +68 -0
  210. package/es/hooks/useFixBody.d.ts +11 -0
  211. package/es/hooks/useFixBody.js +72 -0
  212. package/es/index.d.ts +3 -2
  213. package/es/index.js +3 -2
  214. package/es/site/data/components/datepicker/demos/multiple/react.js +2 -2
  215. package/es/site/data/components/select/demos/creatable/index.d.ts +1 -0
  216. package/es/site/data/components/select/demos/creatable/index.js +2 -1
  217. package/es/site/data/components/select/demos/creatable/react.d.ts +1 -0
  218. package/es/site/data/components/select/demos/creatable/react.js +31 -2
  219. package/es/site/data/components/tour/demos/basic/index.d.ts +17 -0
  220. package/es/site/data/components/tour/demos/basic/index.js +46 -0
  221. package/es/site/data/components/tour/demos/basic/react.d.ts +16 -0
  222. package/es/site/data/components/tour/demos/basic/react.js +82 -0
  223. package/es/site/data/components/tour/demos/beforeChange/index.d.ts +20 -0
  224. package/es/site/data/components/tour/demos/beforeChange/index.js +69 -0
  225. package/es/site/data/components/tour/demos/beforeChange/react.d.ts +19 -0
  226. package/es/site/data/components/tour/demos/beforeChange/react.js +129 -0
  227. package/es/site/data/components/tour/demos/closable/index.d.ts +18 -0
  228. package/es/site/data/components/tour/demos/closable/index.js +42 -0
  229. package/es/site/data/components/tour/demos/closable/react.d.ts +17 -0
  230. package/es/site/data/components/tour/demos/closable/react.js +85 -0
  231. package/es/site/data/components/tour/demos/custom/index.d.ts +11 -0
  232. package/es/site/data/components/tour/demos/custom/index.js +35 -0
  233. package/es/site/data/components/tour/demos/custom/react.d.ts +11 -0
  234. package/es/site/data/components/tour/demos/custom/react.js +108 -0
  235. package/es/site/data/components/tour/demos/customText/index.d.ts +33 -0
  236. package/es/site/data/components/tour/demos/customText/index.js +55 -0
  237. package/es/site/data/components/tour/demos/customText/react.d.ts +33 -0
  238. package/es/site/data/components/tour/demos/customText/react.js +99 -0
  239. package/es/site/data/components/tour/demos/declarative/index.d.ts +11 -0
  240. package/es/site/data/components/tour/demos/declarative/index.js +36 -0
  241. package/es/site/data/components/tour/demos/declarative/react.d.ts +10 -0
  242. package/es/site/data/components/tour/demos/declarative/react.js +80 -0
  243. package/es/site/data/components/tour/demos/events/index.d.ts +18 -0
  244. package/es/site/data/components/tour/demos/events/index.js +58 -0
  245. package/es/site/data/components/tour/demos/events/react.d.ts +18 -0
  246. package/es/site/data/components/tour/demos/events/react.js +101 -0
  247. package/es/site/data/components/tour/demos/maskClosable/index.d.ts +18 -0
  248. package/es/site/data/components/tour/demos/maskClosable/index.js +47 -0
  249. package/es/site/data/components/tour/demos/maskClosable/react.d.ts +17 -0
  250. package/es/site/data/components/tour/demos/maskClosable/react.js +95 -0
  251. package/es/site/data/components/tour/demos/notarget/index.d.ts +11 -0
  252. package/es/site/data/components/tour/demos/notarget/index.js +35 -0
  253. package/es/site/data/components/tour/demos/notarget/react.d.ts +10 -0
  254. package/es/site/data/components/tour/demos/notarget/react.js +61 -0
  255. package/es/site/data/components/tour/index.d.ts +57 -0
  256. package/es/site/data/components/tour/index.js +32 -0
  257. package/hooks/useFixBody.ts +87 -0
  258. package/index.ts +3 -2
  259. package/package.json +2 -2
  260. package/styles/.DS_Store +0 -0
@@ -16,12 +16,32 @@ const now = new Date();
16
16
  const year = now.getFullYear();
17
17
  const startYear = Math.floor(year / 10) * 10;
18
18
  const month = now.getMonth();
19
+ const dateString = dayjs(now).format('YYYY-MM-DD');
20
+
21
+ async function clickConfirm(content: HTMLElement) {
22
+ await wait();
23
+ const confirm = content.querySelector('.k-datepicker-footer .k-btn') as HTMLElement;
24
+ confirm.click();
25
+ await wait();
26
+
27
+ return confirm;
28
+ }
29
+
30
+ function checkDisplay(content: HTMLElement, isShow: boolean) {
31
+ const className = content.className;
32
+ const isLeave = className.includes('-leave-');
33
+ expect(isLeave).eql(!isShow);
34
+ }
35
+
36
+ function getDateString(date: number) {
37
+ return dayjs(now).date(date).format('YYYY-MM-DD');
38
+ }
19
39
 
20
40
  describe('Datepicker', () => {
21
- afterEach(async () => {
22
- unmount();
23
- await wait(500);
24
- });
41
+ // afterEach(async () => {
42
+ // unmount();
43
+ // await wait(500);
44
+ // });
25
45
 
26
46
  describe('Pick', () => {
27
47
  it('date', async () => {
@@ -32,23 +52,74 @@ describe('Datepicker', () => {
32
52
  await wait();
33
53
  const content = getElement('.k-datepicker-content')!;
34
54
  (content.querySelector('.k-calendar-item') as HTMLDivElement).click();
55
+ await wait();
35
56
  expect(instance.get('date')).to.be.string;
57
+ checkDisplay(content, false);
36
58
  });
37
59
 
38
- it('datetime', async () => {
39
- const [instance, element] = mount(DatetimeDemo);
60
+ describe('datetime', () => {
61
+ it('basic', async () => {
62
+ const [instance, element] = mount(DatetimeDemo);
40
63
 
41
- const input = element.querySelector('.k-input') as HTMLElement;
42
- input.click();
43
- await wait();
44
- const content = getElement('.k-datepicker-content')!;
45
- // change to time panel
46
- (content.querySelector('.k-calendar-item') as HTMLElement).click();
47
- await wait();
48
- dispatchEvent(content.querySelector('.k-scroll-select-item')!, 'click');
49
- (content.querySelector('.k-datepicker-footer .k-btn') as HTMLElement).click();
64
+ const input = element.querySelector('.k-input') as HTMLElement;
65
+ input.click();
66
+ await wait();
67
+ const content = getElement('.k-datepicker-content')!;
68
+ // change to time panel
69
+ (content.querySelector('.k-calendar-item') as HTMLElement).click();
70
+ await wait();
71
+ dispatchEvent(content.querySelector('.k-scroll-select-item')!, 'click');
72
+ (content.querySelector('.k-datepicker-footer .k-btn') as HTMLElement).click();
73
+
74
+ expect(instance.get<string>('datetime1').split(' ')[1]).eql('15:00:00');
75
+ });
76
+
77
+ it('skip select date and select time directly', async () => {
78
+ const [instance, element] = mount(DatetimeDemo);
50
79
 
51
- expect(instance.get<string>('datetime1').split(' ')[1]).eql('15:00:00');
80
+ const input = element.querySelector('.k-input') as HTMLElement;
81
+ let content: HTMLElement;
82
+ async function show() {
83
+ input.click();
84
+ await wait();
85
+ content = getElement('.k-datepicker-content')!;
86
+ }
87
+
88
+ await show();
89
+ dispatchEvent(content!.querySelector('.k-scroll-select-item')!, 'click');
90
+ await wait();
91
+ const inputInner = input.querySelector('.k-input-inner') as HTMLInputElement;
92
+ expect(inputInner.value).eql(`${dateString} 15:00:00`);
93
+ expect(instance.get('datetime1')).eql(null);
94
+
95
+ // hide to reset selected state
96
+ document.body.click();
97
+ await wait();
98
+ expect(inputInner.getAttribute('placeholder')).eql(`请选择日期和时间`);
99
+ expect(inputInner.value).eql('');
100
+ expect(instance.get('datetime1')).eql(null);
101
+
102
+ // show again
103
+ await show();
104
+ dispatchEvent(content!.querySelector('.k-scroll-select-item')!, 'click');
105
+ await wait();
106
+ const confirm = content!.querySelector('.k-datepicker-footer .k-btn') as HTMLElement;
107
+ confirm.click();
108
+ await wait();
109
+ expect(inputInner.value).eql(`${dateString} 15:00:00`);
110
+ expect(instance.get('datetime1')).eql(`${dateString} 15:00:00`);
111
+
112
+ checkDisplay(content!, false);
113
+
114
+ // change time
115
+ await show();
116
+ const activeHour = content!.querySelector('.k-scroll-select-item.k-active') as HTMLElement;
117
+ dispatchEvent(activeHour.nextElementSibling!, 'click');
118
+ await wait();
119
+ confirm.click();
120
+ await wait();
121
+ expect(instance.get('datetime1')).eql(`${dateString} 16:00:00`);
122
+ });
52
123
  });
53
124
 
54
125
  it('year', async () => {
@@ -79,6 +150,39 @@ describe('Datepicker', () => {
79
150
  expect(+_year).eql(year);
80
151
  expect(+_month - 1).eql(month);
81
152
  });
153
+
154
+ it('week', async () => {
155
+ const [instance, element] = mount(YearMonthDemo);
156
+ const inputs = element.querySelectorAll<HTMLElement>('.k-input');
157
+ const weekInput = inputs[2];
158
+
159
+ weekInput.click();
160
+ await wait();
161
+
162
+ const content = getElement('.k-datepicker-content')!;
163
+ const weekItem = content.querySelector('.week-row:nth-child(1) .k-week-number') as HTMLElement;
164
+ weekItem.click();
165
+
166
+ expect(instance.get<string>('week')).to.match(/^\d{4}-\d+周$/)
167
+ });
168
+
169
+ it('quarter', async () => {
170
+ const [instance, element] = mount(YearMonthDemo);
171
+ const inputs = element.querySelectorAll<HTMLElement>('.k-input');
172
+ const QuarterInput = inputs[3];
173
+
174
+ QuarterInput.click();
175
+ await wait();
176
+ const content = getElement('.k-datepicker-content')!;
177
+
178
+ // 选择第一个季度
179
+ const quarterItem = content.querySelector('.k-calendar-item:nth-child(1)') as HTMLElement;
180
+ quarterItem.click();
181
+
182
+ // 验证输入框的值是否包含Q1
183
+ expect(instance.get<string>('quarter')).to.include('Q1')
184
+ });
185
+
82
186
  });
83
187
 
84
188
  describe('Panel', async () => {
@@ -137,7 +241,7 @@ describe('Datepicker', () => {
137
241
  select.click();
138
242
  await wait();
139
243
  const content = getElement('.k-datepicker-content')!;
140
- const [panel1, panel2] = content.querySelectorAll<HTMLElement>('.k-datepicker-calendar-wrapper');
244
+ const [panel1, panel2] = content.querySelectorAll<HTMLElement>('.k-datepicker-calendar-time-wrapper');
141
245
  const [nextMonth, nextYear] = panel1.querySelectorAll<HTMLElement>('.k-next');
142
246
  const [monthValues1, monthValues2]= content.querySelectorAll<HTMLElement>('.k-month-values');
143
247
 
@@ -183,7 +287,7 @@ describe('Datepicker', () => {
183
287
  select.click();
184
288
  await wait();
185
289
  const content = getElement('.k-datepicker-content')!;
186
- const [panel1, panel2] = content.querySelectorAll<HTMLElement>('.k-datepicker-calendar-wrapper');
290
+ const [panel1, panel2] = content.querySelectorAll<HTMLElement>('.k-datepicker-calendar-time-wrapper');
187
291
  const [next] = panel1.querySelectorAll<HTMLElement>('.k-next');
188
292
  const [prev] = panel2.querySelectorAll<HTMLElement>('.k-prev');
189
293
  const [label1, label2]= content.querySelectorAll<HTMLElement>('.k-month-values');
@@ -209,7 +313,7 @@ describe('Datepicker', () => {
209
313
  select.click();
210
314
  await wait();
211
315
  const content = getElement('.k-datepicker-content')!;
212
- const [panel1, panel2] = content.querySelectorAll<HTMLElement>('.k-datepicker-calendar-wrapper');
316
+ const [panel1, panel2] = content.querySelectorAll<HTMLElement>('.k-datepicker-calendar-time-wrapper');
213
317
  const [next] = panel1.querySelectorAll<HTMLElement>('.k-next');
214
318
  const [prev] = panel2.querySelectorAll<HTMLElement>('.k-prev');
215
319
  const [label1, label2]= content.querySelectorAll<HTMLElement>('.k-month-values');
@@ -305,14 +409,14 @@ describe('Datepicker', () => {
305
409
  const content = getElement('.k-datepicker-content')!;
306
410
  dispatchEvent(content.querySelector('.k-calendar-item:nth-child(18)')!, 'click');
307
411
  await wait();
308
- dispatchEvent(content.querySelector('.k-btn')!, 'click');
412
+ dispatchEvent(content.querySelector('.k-datepicker-footer .k-btn')!, 'click');
309
413
  await wait();
310
414
  expect(instance.get('datetime')).have.lengthOf(1);
311
415
 
312
416
  // select the same datetime
313
417
  dispatchEvent(content.querySelector('.k-calendar-item:nth-child(18)')!, 'click');
314
418
  await wait();
315
- dispatchEvent(content.querySelector('.k-btn')!, 'click');
419
+ dispatchEvent(content.querySelector('.k-datepicker-footer .k-btn')!, 'click');
316
420
  await wait();
317
421
  expect(instance.get('datetime')).have.lengthOf(1);
318
422
 
@@ -321,18 +425,25 @@ describe('Datepicker', () => {
321
425
  await wait();
322
426
  dispatchEvent(content.querySelector('.k-scroll-select-item')!, 'click');
323
427
  await wait();
324
- dispatchEvent(content.querySelector('.k-btn')!, 'click');
428
+ dispatchEvent(content.querySelector('.k-datepicker-footer .k-btn')!, 'click');
325
429
  await wait();
326
430
  expect(instance.get('datetime')).have.lengthOf(2);
327
431
 
328
- // change to time panel, and remove the selections, then click confirm ok
329
- dispatchEvent(content.querySelector('.k-calendar-item:nth-child(18)')!, 'click');
432
+ // select time directly
433
+ const activeHour = content.querySelector('.k-scroll-select-item.k-active') as HTMLElement;
434
+ dispatchEvent(activeHour.nextElementSibling!, 'click');
330
435
  await wait();
331
- instance.set('datetime', []);
436
+ const confirm = await clickConfirm(content);
437
+ expect(instance.get('datetime')).have.lengthOf(3);
438
+
439
+ // select time firstly, then select date should only add one value
440
+ dispatchEvent(activeHour.nextElementSibling!.nextElementSibling!, 'click');
332
441
  await wait();
333
- dispatchEvent(content.querySelector('.k-btn')!, 'click');
442
+ dispatchEvent(content.querySelector('.k-calendar-item:nth-child(19)')!, 'click');
334
443
  await wait();
335
- expect(instance.get('datetime')).have.lengthOf(1);
444
+ confirm.click();
445
+ await wait();
446
+ expect(instance.get('datetime')).have.lengthOf(4);
336
447
  });
337
448
 
338
449
  it('year', async () => {
@@ -377,174 +488,475 @@ describe('Datepicker', () => {
377
488
  expect(instance.get('month')).have.lengthOf(1);
378
489
  });
379
490
 
380
- it('date range', async () => {
381
- const [instance, element] = mount(MultipleDemo);
491
+ describe('date range', async () => {
492
+ it('date range', async () => {
493
+ const [instance, element] = mount(MultipleDemo);
382
494
 
383
- const [, , , , select] = element.querySelectorAll<HTMLElement>('.k-datepicker');
384
- dispatchEvent(select, 'click');
385
- await wait();
386
- const content = getElement('.k-datepicker-content')!;
387
- const [calendar1, calendar2] = content.querySelectorAll('.k-datepicker-calendar-wrapper');
388
- const first = calendar1.querySelectorAll('.k-calendar-item')[17] as HTMLElement;
389
- const second = calendar2.querySelectorAll('.k-calendar-item')[17] as HTMLElement;
390
- first.click();
391
- second.click();
392
- await wait();
393
- expect(instance.get('dateRange')).have.lengthOf(1);
495
+ const [, , , , select] = element.querySelectorAll<HTMLElement>('.k-datepicker');
496
+ dispatchEvent(select, 'click');
497
+ await wait();
498
+ const content = getElement('.k-datepicker-content')!;
499
+ const [calendar1, calendar2] = content.querySelectorAll('.k-datepicker-calendar-time-wrapper');
394
500
 
395
- dispatchEvent(first.nextElementSibling!, 'click');
396
- dispatchEvent(second.nextElementSibling!, 'click');
397
- await wait();
398
- expect(instance.get('dateRange')).have.lengthOf(2);
501
+ const first = calendar1.querySelector('.k-calendar-item:not(.k-exceed)') as HTMLElement;
502
+ const second = first.nextElementSibling as HTMLElement;
503
+ first.click();
504
+ second.click();
505
+ await wait();
506
+ const value1 = [`${getDateString(1)}`, `${getDateString(2)}`]
507
+ expect(instance.get('dateRange')).eql([value1]);
399
508
 
400
- first.click();
401
- second.click();
402
- await wait();
403
- expect(instance.get('dateRange')).have.lengthOf(1);
509
+ const third = second.nextElementSibling as HTMLElement;
510
+ const fourth = third.nextElementSibling as HTMLElement;
511
+ third.click();
512
+ fourth.click();
513
+ await wait();
514
+ const value2 = [`${getDateString(3)}`, `${getDateString(4)}`]
515
+ expect(instance.get('dateRange')).eql([value1, value2]);
404
516
 
405
- instance.set('dateRange', []);
406
- await wait();
407
- first.click();
408
- second.click();
409
- await wait();
410
- expect(instance.get('dateRange')).have.lengthOf(1);
411
- });
517
+ first.click();
518
+ second.click();
519
+ await wait();
520
+ expect(instance.get('dateRange')).eql([value2]);
412
521
 
413
- it('datetime range', async () => {
414
- const [instance, element] = mount(MultipleDemo);
522
+ instance.set('dateRange', []);
523
+ await wait();
524
+ first.click();
525
+ second.click();
526
+ await wait();
527
+ expect(instance.get('dateRange')).eql([value1]);
528
+ });
415
529
 
416
- const [, , , , , select] = element.querySelectorAll<HTMLElement>('.k-datepicker');
417
- dispatchEvent(select, 'click');
418
- await wait();
419
- const content = getElement('.k-datepicker-content')!;
420
- const [calendar1, calendar2] = content.querySelectorAll('.k-datepicker-calendar-wrapper');
421
- calendar1.querySelectorAll<HTMLElement>('.k-calendar-item')[17].click();
422
- calendar2.querySelectorAll<HTMLElement>('.k-calendar-item')[17].click();
423
- await wait();
424
- content.querySelector<HTMLElement>('.k-btn')!.click();
425
- await wait();
426
- expect(instance.get('datetimeRange')).have.lengthOf(1);
530
+ it('hover status', async () => {
531
+ const [instance, element] = mount(MultipleDemo);
427
532
 
428
- calendar1.querySelectorAll<HTMLElement>('.k-calendar-item')[18].click();
429
- calendar2.querySelectorAll<HTMLElement>('.k-calendar-item')[18].click();
430
- await wait();
431
- content.querySelector<HTMLElement>('.k-btn')!.click();
432
- await wait();
433
- expect(instance.get('datetimeRange')).have.lengthOf(2);
533
+ instance.set('dateRange', [['2025-07-11', '2025-07-15']]);
534
+ const [, , , , select] = element.querySelectorAll<HTMLElement>('.k-datepicker');
535
+ dispatchEvent(select, 'click');
536
+ await wait();
537
+ const content = getElement('.k-datepicker-content')!;
538
+ const [calendar1, calendar2] = content.querySelectorAll('.k-datepicker-calendar-time-wrapper');
434
539
 
435
- // selecting the same date time will do nothing
436
- calendar1.querySelectorAll<HTMLElement>('.k-calendar-item')[17].click();
437
- calendar2.querySelectorAll<HTMLElement>('.k-calendar-item')[17].click();
438
- await wait();
439
- content.querySelector<HTMLElement>('.k-btn')!.click();
440
- await wait();
441
- expect(instance.get('datetimeRange')).have.lengthOf(2);
540
+ const first = calendar1.querySelector('.k-calendar-item:not(.k-exceed)') as HTMLElement;
541
+ const second = first.nextElementSibling as HTMLElement;
542
+ dispatchEvent(first, 'mouseenter');
543
+ await wait();
544
+ expect(second.classList.contains('k-in-range')).eql(false);
545
+ });
546
+ });
442
547
 
443
- instance.set('datetimeRange', []);
444
- await wait();
445
- calendar1.querySelectorAll<HTMLElement>('.k-calendar-item')[17].click();
446
- calendar2.querySelectorAll<HTMLElement>('.k-calendar-item')[17].click();
447
- await wait();
448
- content.querySelector<HTMLElement>('.k-btn')!.click();
449
- await wait();
450
- expect(instance.get('datetimeRange')).have.lengthOf(1);
548
+ describe('datetime range', async () => {
549
+ it('basic', async () => {
550
+ const [instance, element] = mount(MultipleDemo);
451
551
 
452
- // select the first value in end panel
453
- calendar2.querySelectorAll<HTMLElement>('.k-calendar-item')[17].click();
454
- calendar2.querySelectorAll<HTMLElement>('.k-calendar-item')[17].click();
455
- await wait();
456
- content.querySelector<HTMLElement>('.k-btn')!.click();
457
- await wait();
458
- const values = instance.get('datetimeRange')!;
459
- expect(values).have.lengthOf(2);
460
- expect(values[1][1].includes('23:59:59')).to.be.true;
552
+ const [, , , , , select] = element.querySelectorAll<HTMLElement>('.k-datepicker');
553
+ dispatchEvent(select, 'click');
554
+ await wait();
555
+ const content = getElement('.k-datepicker-content')!;
556
+ const calendar1 = content.querySelector('.k-datepicker-wrapper') as HTMLElement;
557
+ const first = calendar1.querySelector('.k-calendar-item:not(.k-exceed)') as HTMLElement;
558
+ const second = first.nextElementSibling as HTMLElement;
559
+ const inputInner = select.querySelector('.k-input-inner') as HTMLInputElement;
560
+ first.click();
561
+ await clickConfirm(content);
562
+ expect(inputInner.value).eql(`${getDateString(1)} 00:00:00 ~`);
563
+ second.click();
564
+ await wait();
565
+ expect(inputInner.value).eql(`${getDateString(1)} 00:00:00 ~ ${getDateString(2)} 00:00:00`);
566
+ await clickConfirm(content);
567
+ const value1 = [`${getDateString(1)} 00:00:00`, `${getDateString(2)} 00:00:00`];
568
+ expect(instance.get('datetimeRange')).eql([value1]);
569
+
570
+ const third = second.nextElementSibling as HTMLElement;
571
+ const fourth = third.nextElementSibling as HTMLElement;
572
+ third.click();
573
+ await clickConfirm(content);
574
+ fourth.click();
575
+ await clickConfirm(content);
576
+ const value2 = [`${getDateString(3)} 00:00:00`, `${getDateString(4)} 00:00:00`]
577
+ expect(instance.get('datetimeRange')).eql([value1, value2]);
578
+
579
+ // selecting the same date time will do nothing
580
+ third.click();
581
+ await clickConfirm(content);
582
+ fourth.click();
583
+ await clickConfirm(content);
584
+ expect(instance.get('datetimeRange')).eql([value1, value2]);
585
+
586
+ instance.set('datetimeRange', []);
587
+ await wait();
588
+ first.click();
589
+ await clickConfirm(content);
590
+ second.click();
591
+ const confirm = await clickConfirm(content);
592
+ expect(instance.get('datetimeRange')).eql([value1]);
593
+ expect(confirm.classList.contains('k-disabled')).eql(true);
594
+ });
595
+
596
+ it('select time directly', async () => {
597
+ const [instance, element] = mount(MultipleDemo);
598
+
599
+ const [, , , , , select] = element.querySelectorAll<HTMLElement>('.k-datepicker');
600
+ dispatchEvent(select, 'click');
601
+ await wait();
602
+ const content = getElement('.k-datepicker-content')!;
603
+ const calendar = content.querySelector('.k-datepicker-wrapper') as HTMLElement;
604
+
605
+ const activeHour = calendar.querySelector('.k-scroll-select-item.k-active') as HTMLElement;
606
+ (activeHour.nextElementSibling as HTMLElement).click();
607
+ await clickConfirm(content);
608
+ (activeHour.nextElementSibling as HTMLElement).click();
609
+ await clickConfirm(content);
610
+ expect(instance.get('datetimeRange')).to.eql([[`${dateString} 01:00:00`, `${dateString} 02:00:00`]]);
611
+ });
461
612
  });
462
613
  });
463
614
 
464
615
  describe('Range', () => {
465
- it('date', async () => {
466
- const [instance, element] = mount(RangeDemo);
467
-
468
- // date
469
- const select = element.querySelector('.k-datepicker') as HTMLElement;
470
- select.click();
471
- await wait();
472
- let content = getElement('.k-datepicker-content')!;
473
- // select the middle date
474
- let first = content.querySelector('.k-calendar-item:nth-child(18)') as HTMLElement;
475
- first.click();
476
- await wait();
477
- expect(instance.get('date')).to.be.null;
478
- // hover status
479
- dispatchEvent(first.nextElementSibling!.nextElementSibling!, 'mouseenter');
480
- await wait();
481
- expect(first.nextElementSibling!.classList.contains('k-in-range')).to.be.true;
482
- dispatchEvent(first.previousElementSibling!.previousElementSibling!, 'mouseenter');
483
- await wait();
484
- expect(first.previousElementSibling!.classList.contains('k-in-range')).to.be.true;
485
- expect(first.nextElementSibling!.classList.contains('k-in-range')).to.be.false;
486
- dispatchEvent(first.previousElementSibling!.previousElementSibling!, 'click');
487
- await wait();
488
- const value = instance.get('date')!;
489
- expect(value).have.lengthOf(2);
490
- expect(value[0] < value[1]).to.be.true;
616
+ describe('date', async () => {
617
+ let instance: RangeDemo;
618
+ let element: HTMLElement;
619
+ let select: HTMLElement;
620
+ let content: HTMLElement;
621
+ let first: HTMLElement;
622
+
623
+ beforeEach(async () => {
624
+ const result = mount(RangeDemo);
625
+ instance = result[0];
626
+ element = result[1];
627
+
628
+ // date
629
+ select = element.querySelector('.k-datepicker') as HTMLElement;
630
+ select.click();
631
+ await wait();
632
+ content = getElement('.k-datepicker-content')!;
633
+ // select the middle date
634
+ first = content.querySelector('.k-calendar-item:nth-child(18)') as HTMLElement;
635
+ });
491
636
 
492
- // select the same date
493
- select.click();
494
- await wait();
495
- // select the middle date
496
- first.click();
497
- first.click();
498
- await wait();
499
- const value1 = instance.get('date')!;
500
- expect(value1).have.lengthOf(2);
501
- expect(value1[0]).eql(value1[1]);
637
+ it('basic selection', async () => {
638
+ first.click();
639
+ await wait();
640
+ expect(instance.get('date')).to.be.null;
641
+ // hover status
642
+ dispatchEvent(first.nextElementSibling!.nextElementSibling!, 'mouseenter');
643
+ await wait();
644
+ expect(first.nextElementSibling!.classList.contains('k-in-range')).to.be.true;
645
+ dispatchEvent(first.previousElementSibling!.previousElementSibling!, 'mouseenter');
646
+ await wait();
647
+ expect(first.previousElementSibling!.classList.contains('k-in-range')).to.be.true;
648
+ expect(first.nextElementSibling!.classList.contains('k-in-range')).to.be.false;
649
+ dispatchEvent(first.previousElementSibling!.previousElementSibling!, 'click');
650
+ await wait();
651
+ const value = instance.get('date')!;
652
+ expect(value).have.lengthOf(2);
653
+ expect(value[0] < value[1]).to.be.true;
654
+ });
655
+
656
+ it('select the same date', async () => {
657
+ // select the middle date
658
+ first.click();
659
+ first.click();
660
+ await wait();
661
+ const value1 = instance.get('date')!;
662
+ expect(value1).have.lengthOf(2);
663
+ expect(value1[0]).eql(value1[1]);
664
+ });
665
+
666
+ it('cross months', async () => {
667
+ first.click();
668
+ let second = content.querySelector('.k-datepicker-calendar-time-wrapper:nth-child(2) .k-calendar-item:nth-child(19)') as HTMLElement;
669
+ second.click();
670
+ await wait();
671
+ expect(instance.get('date')).have.lengthOf(2);
672
+ });
502
673
 
503
- // cancel all of range values and re-select
504
- select.click();
505
- await wait();
506
- // select the middle date
507
- first.click();
508
- dispatchEvent(first.previousElementSibling!.previousElementSibling!, 'click');
509
- await wait();
510
- first.click();
511
- dispatchEvent(first.previousElementSibling!.previousElementSibling!, 'click');
512
- expect(instance.get('date')).eql(value);
674
+ it('can select end date which is less than start date on selecting', async () => {
675
+ // hide firstly
676
+ document.body.click();
677
+ await wait();
678
+ instance.set('date', ['2025-08-01', '2025-08-02']);
679
+ await wait();
680
+ // show again
681
+ select.click();
682
+ await wait();
683
+ // select date 3
684
+ const first = content.querySelector('.k-calendar-item:not(.k-exceed):not(.k-active)') as HTMLElement;
685
+ first.click();
686
+ await wait();
513
687
 
514
- // range cross months
515
- select.click();
516
- await wait();
517
- first.click();
518
- let second = content.querySelector('.k-datepicker-calendar-wrapper:nth-child(2) .k-calendar-item:nth-child(19)') as HTMLElement;
519
- second.click();
520
- await wait();
521
- expect(instance.get('date')).have.lengthOf(2);
688
+ const inputInner = select.querySelector('.k-input-inner') as HTMLInputElement;
689
+ expect(inputInner.value).eql('2025-08-03 ~ 2025-08-02');
690
+ expect(instance.get('date')).eql(['2025-08-01', '2025-08-02']);
522
691
 
692
+ // should update value after hiding
693
+ document.body.click();
694
+ await wait();
695
+ expect(inputInner.value).eql('2025-08-02 ~ 2025-08-03');
696
+ expect(instance.get('date')).eql(['2025-08-02', '2025-08-03']);
697
+ });
523
698
  });
524
699
 
525
- it('datetime', async () => {
526
- const [instance, element] = mount(RangeDemo);
700
+ describe('datetime', async () => {
701
+ let instance: RangeDemo;
702
+ let element: HTMLElement;
703
+ let datetime: HTMLElement;
527
704
 
528
- const [, datetime] = element.querySelectorAll<HTMLElement>('.k-datepicker');
529
- datetime.click();
530
- await wait();
531
- const content = getElement('.k-datepicker-content')!;
532
- const [calendar1, calendar2] = content.querySelectorAll('.k-datepicker-calendar-wrapper');
533
- const first = calendar1.querySelectorAll('.k-calendar-item')[17] as HTMLElement;
534
- const second = calendar2.querySelectorAll('.k-calendar-item')[17] as HTMLElement;
535
- first.click();
536
- // should stay at date panel
537
- await wait();
538
- expect(calendar1.querySelector('.k-days')).be.exist;
539
- second.click();
540
- await wait();
541
- dispatchEvent(calendar1.querySelector<HTMLElement>('.k-scroll-select-wrapper .k-active')!.nextElementSibling!, 'click');
542
- dispatchEvent(calendar2.querySelector<HTMLElement>('.k-scroll-select-wrapper .k-active')!.previousElementSibling!, 'click');
543
- (content.querySelector('.k-datepicker-footer .k-btn') as HTMLElement).click();
544
- await wait();
545
- const value2 = instance.get('time')!;
546
- expect(value2).have.lengthOf(2);
547
- expect(value2.map(item => item.split(' ')[1])).eql(['01:00:00', '22:59:59']);
705
+ const dateString = dayjs(now).date(1).format('YYYY-MM-DD');
706
+
707
+ function match(value: string | null, time: string) {
708
+ expect(value).to.eql(`${dateString} ${time}`);
709
+ }
710
+
711
+ async function show() {
712
+ datetime.click();
713
+ await wait();
714
+ const content = getElement('.k-datepicker-content')!;
715
+ const first = content.querySelector('.k-calendar-item:not(.k-exceed)') as HTMLElement;
716
+ first.click();
717
+ await wait();
718
+
719
+ return [content, first];
720
+ }
721
+
722
+ beforeEach(() => {
723
+ const result = mount(RangeDemo);
724
+ instance = result[0];
725
+ element = result[1];
726
+ datetime = element.querySelectorAll<HTMLElement>('.k-datepicker')[1];
727
+ });
728
+
729
+ it('basic', async () => {
730
+ const [content, first] = await show();
731
+
732
+ // should enable confirm button and show the first date string in input
733
+ const confirm = content.querySelector('.k-datepicker-footer .k-btn') as HTMLElement;
734
+ const inputInner = datetime.querySelector('.k-input-inner') as HTMLInputElement;
735
+ expect(confirm.classList.contains('k-disabled')).to.be.false;
736
+ match(inputInner.getAttribute('placeholder'), '00:00:00 ~');
737
+ match(inputInner.value, '00:00:00 ~');
738
+ expect(instance.get('time')).eql(null);
739
+
740
+ // select time
741
+ dispatchEvent(content.querySelector('.k-scroll-select-item')!, 'click');
742
+ await wait();
743
+ match(inputInner.getAttribute('placeholder'), '15:00:00 ~');
744
+ match(inputInner.value, '15:00:00 ~');
745
+ confirm.click();
746
+ await wait();
747
+ // should disable confirm button on first click
748
+ expect(confirm.classList.contains('k-disabled')).to.be.true;
749
+
750
+ // select the second datetime
751
+ const second = first.nextElementSibling as HTMLElement;
752
+ second.click();
753
+ await wait();
754
+ const endDateString = dayjs(now).date(2).format('YYYY-MM-DD');
755
+ expect(inputInner.getAttribute('placeholder')).eql(`${dateString} 15:00:00 ~ ${endDateString} 00:00:00`);
756
+ expect(inputInner.value).eql(`${dateString} 15:00:00 ~ ${endDateString} 00:00:00`);
757
+ expect(instance.get('time')).eql(null);
758
+ confirm.click();
759
+ await wait();
760
+ expect(instance.get('time')).eql([`${dateString} 15:00:00`, `${endDateString} 00:00:00`]);
761
+ });
762
+
763
+ it('skip select date and select time for the end value directly', async () => {
764
+ const [content] = await show();
765
+
766
+ const confirm = await clickConfirm(content);
767
+ // select time
768
+ dispatchEvent(content.querySelector('.k-scroll-select-item')!, 'click');
769
+ await wait();
770
+ confirm.click();
771
+ await wait();
772
+ expect(instance.get('time')).eql([`${dateString} 00:00:00`, `${dateString} 15:00:00`]);
773
+ });
774
+
775
+ it('can change date before click confirm button', async () => {
776
+ const [content, first] = await show();
777
+ const nextFirst = first.nextElementSibling as HTMLElement;
778
+ nextFirst.click();
779
+ await wait();
780
+ const inputInner = datetime.querySelector('.k-input-inner') as HTMLInputElement;
781
+ const dateString = dayjs(now).date(2).format('YYYY-MM-DD');
782
+ expect(inputInner.value).to.eql(`${dateString} 00:00:00 ~`);
783
+
784
+ const confirm = await clickConfirm(content);
785
+ const second = nextFirst.nextElementSibling as HTMLElement;
786
+ second.click();
787
+ await wait();
788
+ expect(inputInner.value).to.eql(`${dateString} 00:00:00 ~ ${getDateString(3)} 00:00:00`);
789
+ (second.nextElementSibling as HTMLElement).click();
790
+ await wait();
791
+ expect(inputInner.value).to.eql(`${dateString} 00:00:00 ~ ${getDateString(4)} 00:00:00`);
792
+
793
+ confirm.click();
794
+ await wait();
795
+ expect(inputInner.value).to.eql(`${dateString} 00:00:00 ~ ${getDateString(4)} 00:00:00`);
796
+ expect(instance.get('time')).to.eql([`${dateString} 00:00:00`, `${getDateString(4)} 00:00:00`]);
797
+ });
798
+
799
+ it('can select end date which is less than start date on selecting', async () => {
800
+ const [content, first] = await show();
801
+ const nextFirst = first.nextElementSibling as HTMLElement;
802
+ nextFirst.click();
803
+ await wait();
804
+
805
+ const inputInner = datetime.querySelector('.k-input-inner') as HTMLInputElement;
806
+ expect(inputInner.value).to.eql(`${getDateString(2)} 00:00:00 ~`);
807
+
808
+ // hide to reset the selected state
809
+ document.body.click();
810
+ await wait();
811
+ expect(inputInner.value).to.eql(``);
812
+ expect(instance.get('time')).to.be.null;
813
+
814
+ // show again
815
+ datetime.click();
816
+ await wait();
817
+ nextFirst.click();
818
+ await wait();
819
+ const confirm = await clickConfirm(content);
820
+ first.click();
821
+ await wait();
822
+ const a = `${getDateString(2)} 00:00:00`;
823
+ const b = `${getDateString(1)} 00:00:00`;
824
+ expect(inputInner.value).to.eql(`${a} ~ ${b}`);
825
+ expect(instance.get('time')).to.eql(null);
826
+
827
+ confirm.click();
828
+ await wait();
829
+ expect(instance.get('time')).to.eql([b, a]);
830
+ });
831
+
832
+ it('should reset position on clear value or set value to empty', async () => {
833
+ const a = `${getDateString(1)} 00:00:00`;
834
+ const b = `${getDateString(2)} 00:00:00`;
835
+ instance.set('time', [a, b]);
836
+ const [content, first] = await show();
837
+
838
+ // clear
839
+ dispatchEvent(datetime.querySelector('.k-select-clear')!, 'click');
840
+ await wait();
841
+ expect(instance.get('time')).eql(null);
842
+ await selectAgain();
843
+
844
+ // set time to null
845
+ datetime.click();
846
+ await wait();
847
+ instance.set('time', null);
848
+ await selectAgain();
849
+
850
+ // set time to empty array
851
+ datetime.click();
852
+ await wait();
853
+ instance.set<[]>('time', []);
854
+ await selectAgain();
855
+
856
+ async function selectAgain() {
857
+ // can select the datetime again
858
+ await wait();
859
+ first.click();
860
+ await wait();
861
+ const confirm = await clickConfirm(content);
862
+ (first.nextElementSibling as HTMLElement).click();
863
+ await wait();
864
+ confirm.click();
865
+ await wait();
866
+ expect(instance.get('time')).eql([a, b]);
867
+ }
868
+ });
869
+
870
+ it('should only auto hide after twice selection and the start and end datetime are already selected', async () => {
871
+ const [content, first] = await show();
872
+ const next = first.nextElementSibling as HTMLElement;
873
+ next.click();
874
+ await wait();
875
+ const confirm = await clickConfirm(content);
876
+ await wait();
877
+ _checkDisplay(true);
878
+
879
+ first.click();
880
+ await wait();
881
+ confirm.click();
882
+ await wait();
883
+ _checkDisplay(false);
884
+
885
+ const startDate = '2025-08-07 00:00:00';
886
+ const endDate = '2025-08-10 00:00:00'
887
+ const inputInner = datetime.querySelector('.k-input-inner') as HTMLInputElement;
888
+ const separatePos = `${dateString} 00:00:00 ~`.length;
889
+
890
+ await resetAndShow();
891
+ const newFirst = content.querySelector('.k-calendar-item:not(.k-exceed)') as HTMLElement;
892
+ newFirst.click();
893
+ await wait();
894
+ confirm.click();
895
+ await wait();
896
+ _checkDisplay(true);
897
+ expect(instance.get('time')).eql([startDate, endDate]);
898
+
899
+ // cancel the start time selection
900
+ document.body.click();
901
+ await wait();
902
+ expect(instance.get('time')).eql(['2025-08-01 00:00:00', startDate]);
903
+
904
+ // select from end position to start position
905
+ await resetAndShow();
906
+ newFirst.click();
907
+ await wait();
908
+ confirm.click();
909
+ await wait();
910
+ (newFirst.nextElementSibling as HTMLElement).click();
911
+ await wait();
912
+ _checkDisplay(true);
913
+ expect(instance.get('time')).eql([startDate, endDate]);
914
+ confirm.click();
915
+ await wait();
916
+ _checkDisplay(false);
917
+ expect(instance.get('time')).eql(['2025-08-01 00:00:00', '2025-08-02 00:00:00']);
918
+
919
+ // select the end position value then change to end position again
920
+ await resetAndShow();
921
+ newFirst.click();
922
+ await wait();
923
+ confirm.click();
924
+ await wait();
925
+ // change to the end position
926
+ setCursor(separatePos + 1);
927
+ datetime.click();
928
+ (newFirst.nextElementSibling as HTMLElement).click();
929
+ await wait();
930
+ _checkDisplay(true);
931
+ confirm.click();
932
+ // should not hide
933
+ await wait();
934
+ _checkDisplay(true);
935
+ // select the start position value
936
+ newFirst.click();
937
+ await wait();
938
+ confirm.click();
939
+ await wait();
940
+ _checkDisplay(false);
941
+ expect(instance.get('time')).eql(['2025-08-01 00:00:00', '2025-08-02 00:00:00']);
942
+
943
+ function _checkDisplay(isShow: boolean) {
944
+ checkDisplay(content, isShow);
945
+ }
946
+
947
+ function setCursor(pos: number) {
948
+ inputInner.focus();
949
+ inputInner.setSelectionRange(pos, pos);
950
+ }
951
+
952
+ async function resetAndShow() {
953
+ instance.set('time', [startDate, endDate]);
954
+ await wait();
955
+ setCursor(separatePos + 1);
956
+ datetime.click();
957
+ await wait();
958
+ }
959
+ });
548
960
  });
549
961
 
550
962
  it('year', async () => {
@@ -554,7 +966,7 @@ describe('Datepicker', () => {
554
966
  select.click();
555
967
  await wait();
556
968
  const content = getElement('.k-datepicker-content')!;
557
- const [calendar1, calendar2] = content.querySelectorAll('.k-datepicker-calendar-wrapper');
969
+ const [calendar1, calendar2] = content.querySelectorAll('.k-datepicker-calendar-time-wrapper');
558
970
  const first = calendar1.querySelector('.k-calendar-item:nth-child(2)') as HTMLElement;
559
971
  const second = calendar2.querySelector('.k-calendar-item:nth-child(2)') as HTMLElement;
560
972
  first.click();
@@ -571,7 +983,7 @@ describe('Datepicker', () => {
571
983
  select.click();
572
984
  await wait();
573
985
  const content = getElement('.k-datepicker-content')!;
574
- const [calendar1, calendar2] = content.querySelectorAll('.k-datepicker-calendar-wrapper');
986
+ const [calendar1, calendar2] = content.querySelectorAll('.k-datepicker-calendar-time-wrapper');
575
987
  const first = calendar1.querySelector('.k-calendar-item:nth-child(1)') as HTMLElement;
576
988
  const second = calendar2.querySelector('.k-calendar-item:nth-child(1)') as HTMLElement;
577
989
  first.click();
@@ -672,23 +1084,39 @@ describe('Datepicker', () => {
672
1084
  element.click();
673
1085
  await wait();
674
1086
  const content = getElement('.k-datepicker-content')!;
675
- const [calendar1, calendar2] = content.querySelectorAll('.k-datepicker-calendar-wrapper');
676
- const first = calendar1.querySelectorAll('.k-calendar-item')[17] as HTMLElement;
677
- const second = calendar2.querySelectorAll('.k-calendar-item')[17] as HTMLElement;
678
- first.click();
1087
+ const calendar = content.querySelector<HTMLElement>('.k-datepicker-calendar-time-wrapper');
1088
+ const first = calendar!.querySelector('.k-datepicker-calendar') as HTMLElement;
1089
+ const second = calendar!.querySelector('.k-datepicker-time-wrapper') as HTMLElement;
1090
+ const firstDateItem = first.querySelector('.k-calendar-item') as HTMLElement;
1091
+ firstDateItem.click();
679
1092
  expect(fn.callCount).to.eql(1);
680
1093
  expect(fn.lastCall.args[0]).have.lengthOf(1);
681
- second.click();
1094
+ const activeTimeItem = second.querySelector('.k-scroll-select-wrapper .k-active') as HTMLElement;
1095
+ const nextTimeItem = activeTimeItem.nextElementSibling as HTMLElement;
1096
+ nextTimeItem.click();
682
1097
  expect(fn.callCount).to.eql(2);
683
- expect(fn.lastCall.args[0]).have.lengthOf(2);
1098
+ expect(fn.lastCall.args[0]).have.lengthOf(1);
1099
+ const confirmBtn = content.querySelector('.k-datepicker-footer .k-btn') as HTMLElement;
1100
+ confirmBtn.click();
684
1101
  await wait();
685
- dispatchEvent(calendar1.querySelector<HTMLElement>('.k-scroll-select-wrapper .k-active')!.nextElementSibling!, 'click');
1102
+
1103
+ const endCalendar = content.querySelector<HTMLElement>('.k-datepicker-calendar-time-wrapper');
1104
+ const endFirst = endCalendar!.querySelector('.k-datepicker-calendar') as HTMLElement;
1105
+ const endSecond = endCalendar!.querySelector('.k-datepicker-time-wrapper') as HTMLElement;
1106
+
1107
+ const endDateItem = endFirst.querySelector('.k-calendar-item') as HTMLElement;
1108
+ endDateItem.click();
686
1109
  expect(fn.callCount).to.eql(3);
687
- expect(fn.lastCall.args[0]).have.lengthOf(2);
688
- dispatchEvent(calendar2.querySelector<HTMLElement>('.k-scroll-select-wrapper .k-active')!.previousElementSibling!, 'click');
1110
+ expect(fn.lastCall.args[0]).have.lengthOf(1);
1111
+
1112
+ const endActiveTimeItem = endSecond.querySelector('.k-scroll-select-wrapper .k-active') as HTMLElement;
1113
+ const endNextTimeItem = endActiveTimeItem.nextElementSibling as HTMLElement;
1114
+ endNextTimeItem.click();
689
1115
  expect(fn.callCount).to.eql(4);
690
- expect(fn.lastCall.args[0]).have.lengthOf(2);
691
- (content.querySelector('.k-datepicker-footer .k-btn') as HTMLElement).click();
1116
+ expect(fn.lastCall.args[0]).have.lengthOf(1);
1117
+
1118
+ const finalConfirmBtn = content.querySelector('.k-datepicker-footer .k-btn') as HTMLElement;
1119
+ finalConfirmBtn.click();
692
1120
  await wait();
693
1121
  expect(fn.callCount).to.eql(4);
694
1122
  });
@@ -707,6 +1135,7 @@ describe('Datepicker', () => {
707
1135
  await wait();
708
1136
  dispatchEvent(content.querySelector('.k-scroll-select:nth-child(3) .k-scroll-select-item')!, 'click');
709
1137
  (content.querySelector('.k-datepicker-footer .k-btn') as HTMLElement).click();
1138
+ await wait();
710
1139
 
711
1140
  expect(instance.get<string>('datetime2').split(' ')[1]).eql('00:00');
712
1141
  });
@@ -736,7 +1165,7 @@ describe('Datepicker', () => {
736
1165
  content = getElement('.k-datepicker-content')!;
737
1166
  content.querySelector<HTMLElement>('.k-today')!.click();
738
1167
  await wait();
739
- content.querySelector<HTMLElement>('.k-btn')!.click();
1168
+ content.querySelector<HTMLElement>('.k-datepicker-footer .k-btn')!.click();
740
1169
  await wait();
741
1170
  expect(instance.get('date3')).to.eql(dayjs().format('YYYY-MM-DD') + 'T00:00:00.000Z');
742
1171
  expect(input3.value).to.eql(dayjs().format('YYYY-MM-DD') + ' 00:00:00');
@@ -782,7 +1211,7 @@ describe('Datepicker', () => {
782
1211
  const content = getElement('.k-datepicker-content')!;
783
1212
  content.querySelector<HTMLElement>('.k-today')!.click();
784
1213
  await wait();
785
- content.querySelector<HTMLElement>('.k-btn')!.click();
1214
+ content.querySelector<HTMLElement>('.k-datepicker-footer .k-btn')!.click();
786
1215
  await wait();
787
1216
  expect(instance.get('toTime')).to.eql(`${date} ${time}`);
788
1217
  });
@@ -853,7 +1282,7 @@ describe('Datepicker', () => {
853
1282
  await myTest('2020-03-03~2020-03-04', ['2020-03-03', '2020-03-04']);
854
1283
  expect(
855
1284
  getElement('.k-datepicker-content')!
856
- .querySelector<HTMLElement>('.k-datepicker-calendar-wrapper:nth-child(1)')!
1285
+ .querySelector<HTMLElement>('.k-datepicker-calendar-time-wrapper:nth-child(1)')!
857
1286
  .innerHTML
858
1287
  ).to.matchSnapshot();
859
1288
  // clear value