@keenthemes/ktui 1.0.28 → 1.1.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 (288) hide show
  1. package/README.md +27 -0
  2. package/dist/ktui.js +8780 -6199
  3. package/dist/ktui.min.js +1 -1
  4. package/dist/ktui.min.js.map +1 -1
  5. package/dist/styles.css +2744 -1367
  6. package/lib/cjs/components/alert/alert.js +1025 -0
  7. package/lib/cjs/components/alert/alert.js.map +1 -0
  8. package/lib/cjs/components/alert/index.js +20 -0
  9. package/lib/cjs/components/alert/index.js.map +1 -0
  10. package/lib/cjs/components/alert/templates.js +120 -0
  11. package/lib/cjs/components/alert/templates.js.map +1 -0
  12. package/lib/cjs/components/alert/types.js +7 -0
  13. package/lib/cjs/components/alert/types.js.map +1 -0
  14. package/lib/cjs/components/datepicker/config/config.js +42 -0
  15. package/lib/cjs/components/datepicker/config/config.js.map +1 -0
  16. package/lib/cjs/components/datepicker/config/index.js +24 -0
  17. package/lib/cjs/components/datepicker/config/index.js.map +1 -0
  18. package/lib/cjs/components/datepicker/config/interfaces.js +7 -0
  19. package/lib/cjs/components/datepicker/config/interfaces.js.map +1 -0
  20. package/lib/cjs/components/datepicker/config/types.js +7 -0
  21. package/lib/cjs/components/datepicker/config/types.js.map +1 -0
  22. package/lib/cjs/components/datepicker/core/event-manager.js +135 -0
  23. package/lib/cjs/components/datepicker/core/event-manager.js.map +1 -0
  24. package/lib/cjs/components/datepicker/core/focus-manager.js +167 -0
  25. package/lib/cjs/components/datepicker/core/focus-manager.js.map +1 -0
  26. package/lib/cjs/components/datepicker/core/helpers.js +219 -0
  27. package/lib/cjs/components/datepicker/core/helpers.js.map +1 -0
  28. package/lib/cjs/components/datepicker/core/index.js +25 -0
  29. package/lib/cjs/components/datepicker/core/index.js.map +1 -0
  30. package/lib/cjs/components/datepicker/core/unified-state-manager.js +394 -0
  31. package/lib/cjs/components/datepicker/core/unified-state-manager.js.map +1 -0
  32. package/lib/cjs/components/datepicker/datepicker.js +2066 -763
  33. package/lib/cjs/components/datepicker/datepicker.js.map +1 -1
  34. package/lib/cjs/components/datepicker/index.js +19 -8
  35. package/lib/cjs/components/datepicker/index.js.map +1 -1
  36. package/lib/cjs/components/datepicker/ui/index.js +23 -0
  37. package/lib/cjs/components/datepicker/ui/index.js.map +1 -0
  38. package/lib/cjs/components/datepicker/ui/input/dropdown.js +489 -0
  39. package/lib/cjs/components/datepicker/ui/input/dropdown.js.map +1 -0
  40. package/lib/cjs/components/datepicker/ui/input/index.js +23 -0
  41. package/lib/cjs/components/datepicker/ui/input/index.js.map +1 -0
  42. package/lib/cjs/components/datepicker/ui/input/segmented-input.js +640 -0
  43. package/lib/cjs/components/datepicker/ui/input/segmented-input.js.map +1 -0
  44. package/lib/cjs/components/datepicker/ui/renderers/calendar.js +446 -0
  45. package/lib/cjs/components/datepicker/ui/renderers/calendar.js.map +1 -0
  46. package/lib/cjs/components/datepicker/ui/renderers/footer.js +42 -0
  47. package/lib/cjs/components/datepicker/ui/renderers/footer.js.map +1 -0
  48. package/lib/cjs/components/datepicker/ui/renderers/header.js +32 -0
  49. package/lib/cjs/components/datepicker/ui/renderers/header.js.map +1 -0
  50. package/lib/cjs/components/datepicker/ui/renderers/index.js +25 -0
  51. package/lib/cjs/components/datepicker/ui/renderers/index.js.map +1 -0
  52. package/lib/cjs/components/datepicker/ui/renderers/time-picker.js +384 -0
  53. package/lib/cjs/components/datepicker/ui/renderers/time-picker.js.map +1 -0
  54. package/lib/cjs/components/datepicker/ui/templates/index.js +22 -0
  55. package/lib/cjs/components/datepicker/ui/templates/index.js.map +1 -0
  56. package/lib/cjs/components/datepicker/ui/templates/templates.js +253 -0
  57. package/lib/cjs/components/datepicker/ui/templates/templates.js.map +1 -0
  58. package/lib/cjs/components/datepicker/utils/date-formatters.js +88 -0
  59. package/lib/cjs/components/datepicker/utils/date-formatters.js.map +1 -0
  60. package/lib/cjs/components/datepicker/utils/date-utils.js +194 -0
  61. package/lib/cjs/components/datepicker/utils/date-utils.js.map +1 -0
  62. package/lib/cjs/components/datepicker/utils/index.js +24 -0
  63. package/lib/cjs/components/datepicker/utils/index.js.map +1 -0
  64. package/lib/cjs/components/datepicker/utils/time-utils.js +213 -0
  65. package/lib/cjs/components/datepicker/utils/time-utils.js.map +1 -0
  66. package/lib/cjs/index.js +6 -1
  67. package/lib/cjs/index.js.map +1 -1
  68. package/lib/esm/components/alert/alert.js +1022 -0
  69. package/lib/esm/components/alert/alert.js.map +1 -0
  70. package/lib/esm/components/alert/index.js +4 -0
  71. package/lib/esm/components/alert/index.js.map +1 -0
  72. package/lib/esm/components/alert/templates.js +112 -0
  73. package/lib/esm/components/alert/templates.js.map +1 -0
  74. package/lib/esm/components/alert/types.js +6 -0
  75. package/lib/esm/components/alert/types.js.map +1 -0
  76. package/lib/esm/components/datepicker/config/config.js +39 -0
  77. package/lib/esm/components/datepicker/config/config.js.map +1 -0
  78. package/lib/esm/components/datepicker/config/index.js +8 -0
  79. package/lib/esm/components/datepicker/config/index.js.map +1 -0
  80. package/lib/esm/components/datepicker/config/interfaces.js +6 -0
  81. package/lib/esm/components/datepicker/config/interfaces.js.map +1 -0
  82. package/lib/esm/components/datepicker/config/types.js +6 -0
  83. package/lib/esm/components/datepicker/config/types.js.map +1 -0
  84. package/lib/esm/components/datepicker/core/event-manager.js +133 -0
  85. package/lib/esm/components/datepicker/core/event-manager.js.map +1 -0
  86. package/lib/esm/components/datepicker/core/focus-manager.js +164 -0
  87. package/lib/esm/components/datepicker/core/focus-manager.js.map +1 -0
  88. package/lib/esm/components/datepicker/core/helpers.js +211 -0
  89. package/lib/esm/components/datepicker/core/helpers.js.map +1 -0
  90. package/lib/esm/components/datepicker/core/index.js +9 -0
  91. package/lib/esm/components/datepicker/core/index.js.map +1 -0
  92. package/lib/esm/components/datepicker/core/unified-state-manager.js +391 -0
  93. package/lib/esm/components/datepicker/core/unified-state-manager.js.map +1 -0
  94. package/lib/esm/components/datepicker/datepicker.js +2065 -763
  95. package/lib/esm/components/datepicker/datepicker.js.map +1 -1
  96. package/lib/esm/components/datepicker/index.js +6 -8
  97. package/lib/esm/components/datepicker/index.js.map +1 -1
  98. package/lib/esm/components/datepicker/ui/index.js +7 -0
  99. package/lib/esm/components/datepicker/ui/index.js.map +1 -0
  100. package/lib/esm/components/datepicker/ui/input/dropdown.js +486 -0
  101. package/lib/esm/components/datepicker/ui/input/dropdown.js.map +1 -0
  102. package/lib/esm/components/datepicker/ui/input/index.js +7 -0
  103. package/lib/esm/components/datepicker/ui/input/index.js.map +1 -0
  104. package/lib/esm/components/datepicker/ui/input/segmented-input.js +637 -0
  105. package/lib/esm/components/datepicker/ui/input/segmented-input.js.map +1 -0
  106. package/lib/esm/components/datepicker/ui/renderers/calendar.js +443 -0
  107. package/lib/esm/components/datepicker/ui/renderers/calendar.js.map +1 -0
  108. package/lib/esm/components/datepicker/ui/renderers/footer.js +39 -0
  109. package/lib/esm/components/datepicker/ui/renderers/footer.js.map +1 -0
  110. package/lib/esm/components/datepicker/ui/renderers/header.js +29 -0
  111. package/lib/esm/components/datepicker/ui/renderers/header.js.map +1 -0
  112. package/lib/esm/components/datepicker/ui/renderers/index.js +9 -0
  113. package/lib/esm/components/datepicker/ui/renderers/index.js.map +1 -0
  114. package/lib/esm/components/datepicker/ui/renderers/time-picker.js +381 -0
  115. package/lib/esm/components/datepicker/ui/renderers/time-picker.js.map +1 -0
  116. package/lib/esm/components/datepicker/ui/templates/index.js +6 -0
  117. package/lib/esm/components/datepicker/ui/templates/index.js.map +1 -0
  118. package/lib/esm/components/datepicker/ui/templates/templates.js +242 -0
  119. package/lib/esm/components/datepicker/ui/templates/templates.js.map +1 -0
  120. package/lib/esm/components/datepicker/utils/date-formatters.js +83 -0
  121. package/lib/esm/components/datepicker/utils/date-formatters.js.map +1 -0
  122. package/lib/esm/components/datepicker/utils/date-utils.js +184 -0
  123. package/lib/esm/components/datepicker/utils/date-utils.js.map +1 -0
  124. package/lib/esm/components/datepicker/utils/index.js +8 -0
  125. package/lib/esm/components/datepicker/utils/index.js.map +1 -0
  126. package/lib/esm/components/datepicker/utils/time-utils.js +201 -0
  127. package/lib/esm/components/datepicker/utils/time-utils.js.map +1 -0
  128. package/lib/esm/index.js +4 -0
  129. package/lib/esm/index.js.map +1 -1
  130. package/package.json +22 -3
  131. package/src/components/alert/alert.css +429 -188
  132. package/src/components/alert/alert.ts +990 -0
  133. package/src/components/alert/index.ts +4 -0
  134. package/src/components/alert/templates.ts +110 -0
  135. package/src/components/alert/tests/accessibility/aria-roles.test.ts +19 -0
  136. package/src/components/alert/tests/accessibility/focus-management.test.ts +19 -0
  137. package/src/components/alert/tests/accessibility/keyboard-nav.test.ts +22 -0
  138. package/src/components/alert/tests/actions/confirm-cancel.test.ts +122 -0
  139. package/src/components/alert/tests/actions/input-field.test.ts +180 -0
  140. package/src/components/alert/tests/alert.basic.test.ts +126 -0
  141. package/src/components/alert/tests/alert.config.test.ts +75 -0
  142. package/src/components/alert/tests/alert.templates.test.ts +17 -0
  143. package/src/components/alert/tests/config/attribute-config.test.ts +94 -0
  144. package/src/components/alert/tests/config/json-config.test.ts +119 -0
  145. package/src/components/alert/tests/config/merging.test.ts +89 -0
  146. package/src/components/alert/tests/dismissal/auto-dismiss.test.ts +96 -0
  147. package/src/components/alert/tests/dismissal/escape-key-dismiss.test.ts +105 -0
  148. package/src/components/alert/tests/dismissal/manual-dismiss.test.ts +90 -0
  149. package/src/components/alert/tests/dismissal/outside-click-dismiss.test.ts +91 -0
  150. package/src/components/alert/tests/edge-cases/invalid-config.test.ts +19 -0
  151. package/src/components/alert/tests/edge-cases/multiple-alerts.test.ts +19 -0
  152. package/src/components/alert/tests/rendering/custom-content.test.ts +81 -0
  153. package/src/components/alert/tests/rendering/info-alert.test.ts +84 -0
  154. package/src/components/alert/tests/rendering/success-alert.test.ts +100 -0
  155. package/src/components/alert/tests/templates/default-templates.test.ts +16 -0
  156. package/src/components/alert/tests/templates/user-templates.test.ts +16 -0
  157. package/src/components/alert/types.ts +145 -0
  158. package/src/components/datepicker/__tests__/datepicker-events.test.ts +356 -0
  159. package/src/components/datepicker/__tests__/datepicker-init.test.ts +343 -0
  160. package/src/components/datepicker/__tests__/datepicker-integration.test.ts +435 -0
  161. package/src/components/datepicker/__tests__/datepicker-timezone.test.ts +220 -0
  162. package/src/components/datepicker/__tests__/segmented-input-focus.test.ts +380 -0
  163. package/src/components/datepicker/__tests__/selective-state-updates.test.ts +400 -0
  164. package/src/components/datepicker/__tests__/state-manager.test.ts +421 -0
  165. package/src/components/datepicker/__tests__/time-preservation.test.ts +387 -0
  166. package/src/components/datepicker/config/config.ts +40 -0
  167. package/src/components/datepicker/config/index.ts +8 -0
  168. package/src/components/datepicker/config/interfaces.ts +82 -0
  169. package/src/components/datepicker/config/types.ts +188 -0
  170. package/src/components/datepicker/core/event-manager.ts +159 -0
  171. package/src/components/datepicker/core/focus-manager.ts +201 -0
  172. package/src/components/datepicker/core/helpers.ts +231 -0
  173. package/src/components/datepicker/core/index.ts +9 -0
  174. package/src/components/datepicker/core/unified-state-manager.ts +459 -0
  175. package/src/components/datepicker/datepicker.css +429 -1
  176. package/src/components/datepicker/datepicker.ts +2538 -1277
  177. package/src/components/datepicker/index.ts +6 -8
  178. package/src/components/datepicker/ui/index.ts +7 -0
  179. package/src/components/datepicker/ui/input/dropdown.ts +552 -0
  180. package/src/components/datepicker/ui/input/index.ts +7 -0
  181. package/src/components/datepicker/ui/input/segmented-input.ts +638 -0
  182. package/src/components/datepicker/ui/renderers/__tests__/calendar-optimizations.test.ts +611 -0
  183. package/src/components/datepicker/ui/renderers/calendar.ts +530 -0
  184. package/src/components/datepicker/ui/renderers/footer.ts +43 -0
  185. package/src/components/datepicker/ui/renderers/header.ts +33 -0
  186. package/src/components/datepicker/ui/renderers/index.ts +9 -0
  187. package/src/components/datepicker/ui/renderers/time-picker.ts +438 -0
  188. package/src/components/datepicker/ui/templates/index.ts +6 -0
  189. package/src/components/datepicker/ui/templates/templates.ts +306 -0
  190. package/src/components/datepicker/utils/__tests__/date-formatters.test.ts +160 -0
  191. package/src/components/datepicker/utils/__tests__/date-utils-keys.test.ts +86 -0
  192. package/src/components/datepicker/utils/__tests__/date-utils-timezone.test.ts +215 -0
  193. package/src/components/datepicker/utils/date-formatters.ts +85 -0
  194. package/src/components/datepicker/utils/date-utils.ts +172 -0
  195. package/src/components/datepicker/utils/index.ts +8 -0
  196. package/src/components/datepicker/utils/time-utils.ts +221 -0
  197. package/src/index.ts +7 -1
  198. package/CONTRIBUTING.md +0 -101
  199. package/examples/datatable/checkbox-events-test.html +0 -400
  200. package/examples/datatable/credentials-test.html +0 -423
  201. package/examples/datatable/remote-checkbox-test.html +0 -365
  202. package/examples/datatable/sorting-test.html +0 -258
  203. package/examples/image-input/file-upload-example.html +0 -189
  204. package/examples/modal/persistent.html +0 -205
  205. package/examples/modal/remote-select-dropdown.html +0 -166
  206. package/examples/modal/select-dropdown-container.html +0 -129
  207. package/examples/select/avatar.html +0 -47
  208. package/examples/select/basic-usage.html +0 -39
  209. package/examples/select/country.html +0 -43
  210. package/examples/select/dark-mode.html +0 -93
  211. package/examples/select/description.html +0 -53
  212. package/examples/select/disable-option.html +0 -37
  213. package/examples/select/disable-select.html +0 -35
  214. package/examples/select/dropdowncontainer.html +0 -111
  215. package/examples/select/dynamic-methods.html +0 -273
  216. package/examples/select/formdata-remote.html +0 -161
  217. package/examples/select/global-config.html +0 -81
  218. package/examples/select/icon-multiple.html +0 -50
  219. package/examples/select/icon.html +0 -48
  220. package/examples/select/max-selection.html +0 -38
  221. package/examples/select/modal-container.html +0 -128
  222. package/examples/select/modal-positioning-test.html +0 -338
  223. package/examples/select/modal.html +0 -80
  224. package/examples/select/multiple.html +0 -40
  225. package/examples/select/native-selected.html +0 -64
  226. package/examples/select/placeholder.html +0 -40
  227. package/examples/select/remote-data-preselected.html +0 -283
  228. package/examples/select/remote-data.html +0 -38
  229. package/examples/select/search.html +0 -57
  230. package/examples/select/sizes.html +0 -94
  231. package/examples/select/tags-enhanced.html +0 -86
  232. package/examples/select/tags-icons.html +0 -57
  233. package/examples/select/template-customization.html +0 -61
  234. package/examples/sticky/README.md +0 -158
  235. package/examples/sticky/debug-sticky.html +0 -144
  236. package/examples/sticky/test-runner.html +0 -175
  237. package/examples/sticky/test-sticky-logic.js +0 -369
  238. package/examples/sticky/test-sticky-positioning.html +0 -386
  239. package/examples/toast/example.html +0 -479
  240. package/lib/cjs/components/datepicker/calendar.js +0 -1061
  241. package/lib/cjs/components/datepicker/calendar.js.map +0 -1
  242. package/lib/cjs/components/datepicker/config.js +0 -332
  243. package/lib/cjs/components/datepicker/config.js.map +0 -1
  244. package/lib/cjs/components/datepicker/dropdown.js +0 -635
  245. package/lib/cjs/components/datepicker/dropdown.js.map +0 -1
  246. package/lib/cjs/components/datepicker/events.js +0 -129
  247. package/lib/cjs/components/datepicker/events.js.map +0 -1
  248. package/lib/cjs/components/datepicker/keyboard.js +0 -536
  249. package/lib/cjs/components/datepicker/keyboard.js.map +0 -1
  250. package/lib/cjs/components/datepicker/locales.js +0 -78
  251. package/lib/cjs/components/datepicker/locales.js.map +0 -1
  252. package/lib/cjs/components/datepicker/templates.js +0 -403
  253. package/lib/cjs/components/datepicker/templates.js.map +0 -1
  254. package/lib/cjs/components/datepicker/types.js +0 -23
  255. package/lib/cjs/components/datepicker/types.js.map +0 -1
  256. package/lib/cjs/components/datepicker/utils.js +0 -524
  257. package/lib/cjs/components/datepicker/utils.js.map +0 -1
  258. package/lib/esm/components/datepicker/calendar.js +0 -1058
  259. package/lib/esm/components/datepicker/calendar.js.map +0 -1
  260. package/lib/esm/components/datepicker/config.js +0 -329
  261. package/lib/esm/components/datepicker/config.js.map +0 -1
  262. package/lib/esm/components/datepicker/dropdown.js +0 -632
  263. package/lib/esm/components/datepicker/dropdown.js.map +0 -1
  264. package/lib/esm/components/datepicker/events.js +0 -126
  265. package/lib/esm/components/datepicker/events.js.map +0 -1
  266. package/lib/esm/components/datepicker/keyboard.js +0 -533
  267. package/lib/esm/components/datepicker/keyboard.js.map +0 -1
  268. package/lib/esm/components/datepicker/locales.js +0 -74
  269. package/lib/esm/components/datepicker/locales.js.map +0 -1
  270. package/lib/esm/components/datepicker/templates.js +0 -390
  271. package/lib/esm/components/datepicker/templates.js.map +0 -1
  272. package/lib/esm/components/datepicker/types.js +0 -20
  273. package/lib/esm/components/datepicker/types.js.map +0 -1
  274. package/lib/esm/components/datepicker/utils.js +0 -508
  275. package/lib/esm/components/datepicker/utils.js.map +0 -1
  276. package/prettier.config.js +0 -9
  277. package/src/components/datepicker/calendar.ts +0 -1397
  278. package/src/components/datepicker/config.ts +0 -368
  279. package/src/components/datepicker/dropdown.ts +0 -757
  280. package/src/components/datepicker/events.ts +0 -149
  281. package/src/components/datepicker/keyboard.ts +0 -646
  282. package/src/components/datepicker/locales.ts +0 -80
  283. package/src/components/datepicker/templates.ts +0 -792
  284. package/src/components/datepicker/types.ts +0 -154
  285. package/src/components/datepicker/utils.ts +0 -631
  286. package/src/components/select/variants.css +0 -4
  287. package/tsconfig.json +0 -17
  288. package/webpack.config.js +0 -118
@@ -0,0 +1,90 @@
1
+ /**
2
+ * TEST SUITE: Manual Dismissal
3
+ * PURPOSE: Test dismissing via close button and confirm/cancel
4
+ * SCOPE: KTAlert manual dismissal logic
5
+ * DEPENDENCIES: vitest, jsdom
6
+ * LAST UPDATED: 2024-06-08
7
+ */
8
+
9
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
10
+ import { KTAlert } from '../../alert';
11
+
12
+ describe('KTAlert manual dismissal', () => {
13
+ beforeEach(() => {
14
+ document.body.innerHTML = '';
15
+ });
16
+ afterEach(() => {
17
+ document.body.innerHTML = '';
18
+ });
19
+
20
+ it('should dismiss alert via close button', () => {
21
+ // ARRANGE
22
+ const element = document.createElement('div');
23
+ document.body.appendChild(element);
24
+ const alert = new KTAlert(element, { showCloseButton: true });
25
+ const fireEventSpy = vi.spyOn(alert as any, '_fireEvent');
26
+ // ACT
27
+ const closeButton = element.querySelector('[data-kt-alert-close]') as HTMLElement;
28
+ closeButton?.click();
29
+ // ASSERT
30
+ expect(fireEventSpy).toHaveBeenCalledWith('dismiss', {});
31
+ expect((alert as any)._state.isDismissed).toBe(true);
32
+ expect(element.innerHTML).toBe('');
33
+ });
34
+
35
+ it('should dismiss alert via confirm button', () => {
36
+ // ARRANGE
37
+ const element = document.createElement('div');
38
+ document.body.appendChild(element);
39
+ const alert = new KTAlert(element, { showConfirmButton: true });
40
+ const fireEventSpy = vi.spyOn(alert as any, '_fireEvent');
41
+ // ACT
42
+ const confirmButton = element.querySelector('[data-kt-alert-confirm]') as HTMLElement;
43
+ confirmButton?.click();
44
+ // ASSERT
45
+ expect(fireEventSpy).toHaveBeenCalledWith('confirm', { inputValue: undefined });
46
+ expect((alert as any)._state.isDismissed).toBe(true);
47
+ expect(element.innerHTML).toBe('');
48
+ });
49
+
50
+ it('should dismiss alert via cancel button', () => {
51
+ // ARRANGE
52
+ const element = document.createElement('div');
53
+ document.body.appendChild(element);
54
+ const alert = new KTAlert(element, { showCancelButton: true });
55
+ const fireEventSpy = vi.spyOn(alert as any, '_fireEvent');
56
+ // ACT
57
+ const cancelButton = element.querySelector('[data-kt-alert-cancel]') as HTMLElement;
58
+ cancelButton?.click();
59
+ // ASSERT
60
+ expect(fireEventSpy).toHaveBeenCalledWith('cancel', {});
61
+ expect((alert as any)._state.isDismissed).toBe(true);
62
+ expect(element.innerHTML).toBe('');
63
+ });
64
+
65
+ it('should not dismiss if close button is disabled', () => {
66
+ // ARRANGE
67
+ const element = document.createElement('div');
68
+ document.body.appendChild(element);
69
+ const alert = new KTAlert(element, { showCloseButton: false });
70
+ const fireEventSpy = vi.spyOn(alert as any, '_fireEvent');
71
+ // ACT
72
+ const closeButton = element.querySelector('[data-kt-alert-close]');
73
+ // ASSERT
74
+ expect(closeButton).toBeNull();
75
+ expect(fireEventSpy).not.toHaveBeenCalled();
76
+ });
77
+
78
+ it('should clear timer when manually dismissed', () => {
79
+ // ARRANGE
80
+ const element = document.createElement('div');
81
+ document.body.appendChild(element);
82
+ const alert = new KTAlert(element, { timer: 5000, showCloseButton: true });
83
+ const clearTimerSpy = vi.spyOn(alert as any, '_clearTimer');
84
+ // ACT
85
+ const closeButton = element.querySelector('[data-kt-alert-close]') as HTMLElement;
86
+ closeButton?.click();
87
+ // ASSERT
88
+ expect(clearTimerSpy).toHaveBeenCalled();
89
+ });
90
+ });
@@ -0,0 +1,91 @@
1
+ /**
2
+ * TEST SUITE: Outside Click Dismissal
3
+ * PURPOSE: Test dismissal by clicking outside modal (if allowed)
4
+ * SCOPE: KTAlert outside click dismissal logic
5
+ * DEPENDENCIES: vitest, jsdom
6
+ * LAST UPDATED: 2024-06-08
7
+ */
8
+
9
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
10
+ import { KTAlert } from '../../alert';
11
+
12
+ describe('KTAlert outside click dismissal', () => {
13
+ beforeEach(() => {
14
+ document.body.innerHTML = '';
15
+ });
16
+ afterEach(() => {
17
+ document.body.innerHTML = '';
18
+ });
19
+
20
+ it('should dismiss alert by clicking outside modal if allowed', () => {
21
+ // ARRANGE
22
+ const config = { modal: true, allowOutsideClick: true, title: 'Test' };
23
+ // ACT
24
+ KTAlert.fire(config);
25
+ const overlay = document.querySelector('[data-kt-alert-overlay]');
26
+ const fireEventSpy = vi.spyOn(overlay as any, 'dispatchEvent');
27
+ // Simulate click on overlay (outside the alert)
28
+ const outsideClick = new MouseEvent('click', { bubbles: true });
29
+ overlay?.dispatchEvent(outsideClick);
30
+ // ASSERT
31
+ // The event should be handled by the overlay click listener
32
+ expect(overlay).toBeTruthy();
33
+ });
34
+
35
+ it('should not dismiss if allowOutsideClick is false', () => {
36
+ // ARRANGE
37
+ const config = { modal: true, allowOutsideClick: false, title: 'Test' };
38
+ // ACT
39
+ KTAlert.fire(config);
40
+ const overlay = document.querySelector('[data-kt-alert-overlay]');
41
+ const alert = overlay?.querySelector('[data-kt-alert]');
42
+ // Simulate click on overlay
43
+ const outsideClick = new MouseEvent('click', { bubbles: true });
44
+ overlay?.dispatchEvent(outsideClick);
45
+ // ASSERT
46
+ // Alert should still be present
47
+ expect(alert).toBeTruthy();
48
+ });
49
+
50
+ it('should not dismiss if clicking inside the alert', () => {
51
+ // ARRANGE
52
+ const config = { modal: true, allowOutsideClick: true, title: 'Test' };
53
+ // ACT
54
+ KTAlert.fire(config);
55
+ const alert = document.querySelector('[data-kt-alert]');
56
+ // Simulate click inside the alert
57
+ const insideClick = new MouseEvent('click', { bubbles: true });
58
+ alert?.dispatchEvent(insideClick);
59
+ // ASSERT
60
+ // Alert should still be present
61
+ expect(alert).toBeTruthy();
62
+ });
63
+
64
+ it('should not dismiss if not modal', () => {
65
+ // ARRANGE
66
+ const config = { modal: false, allowOutsideClick: true, title: 'Test' };
67
+ // ACT
68
+ KTAlert.fire(config);
69
+ const alert = document.querySelector('[data-kt-alert]');
70
+ // Simulate click outside
71
+ const outsideClick = new MouseEvent('click', { bubbles: true });
72
+ document.body.dispatchEvent(outsideClick);
73
+ // ASSERT
74
+ // Alert should still be present
75
+ expect(alert).toBeTruthy();
76
+ });
77
+
78
+ it('should clear timer when dismissed by outside click', () => {
79
+ // ARRANGE
80
+ const config = { modal: true, allowOutsideClick: true, timer: 5000, title: 'Test' };
81
+ // ACT
82
+ KTAlert.fire(config);
83
+ const overlay = document.querySelector('[data-kt-alert-overlay]');
84
+ // Simulate click on overlay
85
+ const outsideClick = new MouseEvent('click', { bubbles: true });
86
+ overlay?.dispatchEvent(outsideClick);
87
+ // ASSERT
88
+ // The overlay should be removed
89
+ expect(document.querySelector('[data-kt-alert-overlay]')).toBeNull();
90
+ });
91
+ });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * TEST SUITE: Invalid Config Handling
3
+ * PURPOSE: Test handling of invalid/missing config, fallback to defaults, error handling
4
+ * SCOPE: KTAlert invalid config and error handling
5
+ * DEPENDENCIES: vitest, jsdom
6
+ * LAST UPDATED: 2024-06-08
7
+ */
8
+
9
+ import { describe, it, expect } from 'vitest';
10
+ import { KTAlert } from '../../alert';
11
+
12
+ describe('KTAlert invalid config handling', () => {
13
+ it('should fallback to defaults on missing config', () => {
14
+ // TODO: Implement test
15
+ });
16
+ it('should handle invalid config gracefully', () => {
17
+ // TODO: Implement test
18
+ });
19
+ });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * TEST SUITE: Multiple Alerts
3
+ * PURPOSE: Test stacking/multiple alerts, overlay handling, and cleanup
4
+ * SCOPE: KTAlert multiple/stacked alerts
5
+ * DEPENDENCIES: vitest, jsdom
6
+ * LAST UPDATED: 2024-06-08
7
+ */
8
+
9
+ import { describe, it, expect } from 'vitest';
10
+ import { KTAlert } from '../../alert';
11
+
12
+ describe('KTAlert multiple/stacked alerts', () => {
13
+ it('should handle multiple alerts and overlays correctly', () => {
14
+ // TODO: Implement test
15
+ });
16
+ it('should clean up overlays and DOM after dismissal', () => {
17
+ // TODO: Implement test
18
+ });
19
+ });
@@ -0,0 +1,81 @@
1
+ /**
2
+ * TEST SUITE: Custom Content Alert Rendering
3
+ * PURPOSE: Test rendering of alerts with custom HTML/content
4
+ * SCOPE: KTAlert rendering with customContent config
5
+ * DEPENDENCIES: vitest, jsdom
6
+ * LAST UPDATED: 2024-06-08
7
+ */
8
+
9
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
10
+ import { KTAlert } from '../../alert';
11
+
12
+ function getAlertElements() {
13
+ // KTAlert.fire() creates an overlay structure
14
+ const overlay = document.querySelector('[data-kt-alert-overlay]');
15
+ const alert = overlay?.querySelector('[data-kt-alert]') || document.querySelector('[data-kt-alert]');
16
+ return {
17
+ alert,
18
+ overlay,
19
+ custom: alert?.querySelector('[data-kt-alert-custom-content]'),
20
+ icon: alert?.querySelector('[data-kt-alert-icon]'),
21
+ title: alert?.querySelector('[data-kt-alert-title]'),
22
+ message: alert?.querySelector('[data-kt-alert-message]'),
23
+ };
24
+ }
25
+
26
+ describe('KTAlert custom content rendering', () => {
27
+ beforeEach(() => {
28
+ document.body.innerHTML = '';
29
+ });
30
+ afterEach(() => {
31
+ document.body.innerHTML = '';
32
+ });
33
+
34
+ it('should render alert with custom HTML content', () => {
35
+ // ARRANGE
36
+ const config = {
37
+ type: 'info',
38
+ title: 'Custom',
39
+ customContent: '<div id="my-custom">Hello <b>World</b></div>'
40
+ };
41
+ // ACT
42
+ KTAlert.fire(config);
43
+ const { alert, custom } = getAlertElements();
44
+ // ASSERT
45
+ expect(alert).toBeTruthy();
46
+ expect(custom?.innerHTML).toContain('Hello <b>World</b>');
47
+ expect(custom?.querySelector('#my-custom')).toBeTruthy();
48
+ });
49
+
50
+ it('should render custom content alongside title and message', () => {
51
+ // ARRANGE
52
+ const config = {
53
+ type: 'info',
54
+ title: 'Custom',
55
+ text: 'This is a message',
56
+ customContent: '<span id="extra">Extra</span>'
57
+ };
58
+ // ACT
59
+ KTAlert.fire(config);
60
+ const { title, message, custom } = getAlertElements();
61
+ // ASSERT
62
+ expect(title?.textContent).toBe('Custom');
63
+ expect(message?.textContent).toBe('This is a message');
64
+ expect(custom?.innerHTML).toContain('Extra');
65
+ expect(custom?.querySelector('#extra')).toBeTruthy();
66
+ });
67
+
68
+ it('should not render custom content if not provided', () => {
69
+ // ARRANGE
70
+ const config = {
71
+ type: 'info',
72
+ title: 'No Custom'
73
+ };
74
+ // ACT
75
+ KTAlert.fire(config);
76
+ const { custom } = getAlertElements();
77
+ // ASSERT
78
+ // custom-content fragment may be present but empty
79
+ expect(custom?.innerHTML === '' || custom == null).toBeTruthy();
80
+ });
81
+ });
@@ -0,0 +1,84 @@
1
+ /**
2
+ * TEST SUITE: Info Alert Rendering
3
+ * PURPOSE: Test rendering of info alerts (icon, title, message, ARIA, default config)
4
+ * SCOPE: KTAlert rendering for info type
5
+ * DEPENDENCIES: vitest, jsdom
6
+ * LAST UPDATED: 2024-06-08
7
+ */
8
+
9
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
10
+ import { KTAlert } from '../../alert';
11
+
12
+ function getAlertElements() {
13
+ // KTAlert.fire() creates an overlay structure
14
+ const overlay = document.querySelector('[data-kt-alert-overlay]');
15
+ const alert = overlay?.querySelector('[data-kt-alert]') || document.querySelector('[data-kt-alert]');
16
+ return {
17
+ alert,
18
+ overlay,
19
+ icon: alert?.querySelector('[data-kt-alert-icon]'),
20
+ title: alert?.querySelector('[data-kt-alert-title]'),
21
+ message: alert?.querySelector('[data-kt-alert-message]'),
22
+ };
23
+ }
24
+
25
+ describe('KTAlert info alert rendering', () => {
26
+ beforeEach(() => {
27
+ document.body.innerHTML = '';
28
+ });
29
+ afterEach(() => {
30
+ document.body.innerHTML = '';
31
+ });
32
+
33
+ it('should render info alert with correct icon, title, and message', () => {
34
+ // ARRANGE
35
+ const config = {
36
+ type: 'info',
37
+ title: 'Information',
38
+ text: 'This is an info alert.',
39
+ };
40
+ // ACT
41
+ KTAlert.fire(config);
42
+ const { alert, icon, title, message } = getAlertElements();
43
+ // ASSERT
44
+ expect(alert).toBeTruthy();
45
+ expect(alert?.getAttribute('data-kt-alert-type')).toBe('info');
46
+ expect(title?.textContent).toBe('Information');
47
+ expect(message?.textContent).toBe('This is an info alert.');
48
+ expect(icon).toBeTruthy();
49
+ // Check ARIA
50
+ expect(alert?.getAttribute('role')).toBe('alertdialog');
51
+ expect(alert?.getAttribute('aria-modal')).toBe('true');
52
+ });
53
+
54
+ it('should fallback to default title/message if not provided', () => {
55
+ // ARRANGE
56
+ const config = { type: 'info' };
57
+ // ACT
58
+ KTAlert.fire(config);
59
+ const { title, message } = getAlertElements();
60
+ // ASSERT
61
+ expect(title?.textContent).toBeDefined();
62
+ expect(message?.textContent).toBeDefined();
63
+ });
64
+
65
+ it('should render with custom id if provided', () => {
66
+ // ARRANGE
67
+ const config = { type: 'info', title: 'Info', text: 'Msg', id: 'custom-id' };
68
+ // ACT
69
+ KTAlert.fire(config);
70
+ const { alert } = getAlertElements();
71
+ // ASSERT
72
+ expect(alert?.id).toBe('custom-id');
73
+ });
74
+
75
+ it('should not render icon if icon: false is set', () => {
76
+ // ARRANGE
77
+ const config = { type: 'info', title: 'Info', text: 'Msg', icon: false };
78
+ // ACT
79
+ KTAlert.fire(config);
80
+ const { icon } = getAlertElements();
81
+ // ASSERT
82
+ expect(icon).toBeNull();
83
+ });
84
+ });
@@ -0,0 +1,100 @@
1
+ /**
2
+ * TEST SUITE: Success Alert Rendering
3
+ * PURPOSE: Test rendering of success alerts (icon, color, confirm button)
4
+ * SCOPE: KTAlert rendering for success type
5
+ * DEPENDENCIES: vitest, jsdom
6
+ * LAST UPDATED: 2024-06-08
7
+ */
8
+
9
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
10
+ import { KTAlert } from '../../alert';
11
+
12
+ function getAlertElements() {
13
+ // KTAlert.fire() creates an overlay structure
14
+ const overlay = document.querySelector('[data-kt-alert-overlay]');
15
+ const alert = overlay?.querySelector('[data-kt-alert]') || document.querySelector('[data-kt-alert]');
16
+ return {
17
+ alert,
18
+ overlay,
19
+ icon: alert?.querySelector('[data-kt-alert-icon]'),
20
+ title: alert?.querySelector('[data-kt-alert-title]'),
21
+ message: alert?.querySelector('[data-kt-alert-message]'),
22
+ confirm: alert?.querySelector('[data-kt-alert-confirm]'),
23
+ };
24
+ }
25
+
26
+ describe('KTAlert success alert rendering', () => {
27
+ beforeEach(() => {
28
+ document.body.innerHTML = '';
29
+ });
30
+ afterEach(() => {
31
+ document.body.innerHTML = '';
32
+ });
33
+
34
+ it('should render success alert with correct icon, color, and confirm button', () => {
35
+ // ARRANGE
36
+ const config = {
37
+ type: 'success',
38
+ title: 'Success!',
39
+ text: 'Operation completed successfully.',
40
+ };
41
+ // ACT
42
+ KTAlert.fire(config);
43
+ const { alert, icon, title, message, confirm } = getAlertElements();
44
+ // ASSERT
45
+ expect(alert).toBeTruthy();
46
+ expect(alert?.getAttribute('data-kt-alert-type')).toBe('success');
47
+ expect(title?.textContent).toBe('Success!');
48
+ expect(message?.textContent).toBe('Operation completed successfully.');
49
+ expect(icon).toBeTruthy();
50
+ expect(confirm).toBeTruthy();
51
+ // Check ARIA
52
+ expect(alert?.getAttribute('role')).toBe('alertdialog');
53
+ expect(alert?.getAttribute('aria-modal')).toBe('true');
54
+ });
55
+
56
+ it('should use custom confirm button text if provided', () => {
57
+ // ARRANGE
58
+ const config = {
59
+ type: 'success',
60
+ title: 'Success!',
61
+ text: 'Done!',
62
+ confirmText: 'Great!'
63
+ };
64
+ // ACT
65
+ KTAlert.fire(config);
66
+ const { confirm } = getAlertElements();
67
+ // ASSERT
68
+ expect(confirm?.textContent).toBe('Great!');
69
+ });
70
+
71
+ it('should not render confirm button if showConfirmButton is false', () => {
72
+ // ARRANGE
73
+ const config = {
74
+ type: 'success',
75
+ title: 'Success!',
76
+ text: 'Done!',
77
+ showConfirmButton: false
78
+ };
79
+ // ACT
80
+ KTAlert.fire(config);
81
+ const { confirm } = getAlertElements();
82
+ // ASSERT
83
+ expect(confirm).toBeNull();
84
+ });
85
+
86
+ it('should apply correct color class for success type', () => {
87
+ // ARRANGE
88
+ const config = {
89
+ type: 'success',
90
+ title: 'Success!',
91
+ text: 'Done!'
92
+ };
93
+ // ACT
94
+ KTAlert.fire(config);
95
+ const { alert } = getAlertElements();
96
+ // ASSERT
97
+ // The class is applied via Tailwind, but we can check the attribute for type
98
+ expect(alert?.getAttribute('data-kt-alert-type')).toBe('success');
99
+ });
100
+ });
@@ -0,0 +1,16 @@
1
+ /**
2
+ * TEST SUITE: Default Templates
3
+ * PURPOSE: Test rendering with default templates
4
+ * SCOPE: KTAlert default template rendering
5
+ * DEPENDENCIES: vitest, jsdom
6
+ * LAST UPDATED: 2024-06-08
7
+ */
8
+
9
+ import { describe, it, expect } from 'vitest';
10
+ import { KTAlert } from '../../alert';
11
+
12
+ describe('KTAlert default templates', () => {
13
+ it('should render alert using default templates', () => {
14
+ // TODO: Implement test
15
+ });
16
+ });
@@ -0,0 +1,16 @@
1
+ /**
2
+ * TEST SUITE: User Templates
3
+ * PURPOSE: Test rendering with user-provided template overrides
4
+ * SCOPE: KTAlert user template rendering
5
+ * DEPENDENCIES: vitest, jsdom
6
+ * LAST UPDATED: 2024-06-08
7
+ */
8
+
9
+ import { describe, it, expect } from 'vitest';
10
+ import { KTAlert } from '../../alert';
11
+
12
+ describe('KTAlert user templates', () => {
13
+ it('should render alert using user-provided template overrides', () => {
14
+ // TODO: Implement test
15
+ });
16
+ });
@@ -0,0 +1,145 @@
1
+ /*
2
+ * types.ts - Type definitions for KTAlert (modular alert/dialog component)
3
+ * Defines config, template, and state interfaces for extensible template customization.
4
+ */
5
+
6
+ // Template keys for all customizable UI fragments
7
+ export type KTAlertTemplateKey =
8
+ | 'container'
9
+ | 'overlay'
10
+ | 'modal'
11
+ | 'icon'
12
+ | 'title'
13
+ | 'message'
14
+ | 'actions'
15
+ | 'confirmButton'
16
+ | 'cancelButton'
17
+ | 'confirmButtonCustomClass'
18
+ | 'cancelButtonCustomClass'
19
+ | 'input'
20
+ | 'inputText'
21
+ | 'inputTextarea'
22
+ | 'inputSelect'
23
+ | 'inputRadio'
24
+ | 'inputCheckbox'
25
+ | 'inputError'
26
+ | 'closeButton'
27
+ | 'customContent'
28
+ | 'loaderHtml'
29
+ | 'option'
30
+ | 'radioOption'
31
+ | 'checkboxOption';
32
+
33
+ // Template string map
34
+ export type KTAlertTemplateStrings = {
35
+ [K in KTAlertTemplateKey]?: string | ((data: any) => string);
36
+ };
37
+
38
+ /**
39
+ * Configuration options for KTAlert
40
+ */
41
+ export interface KTAlertConfig {
42
+ /** Custom templates for UI fragments */
43
+ templates?: KTAlertTemplateStrings;
44
+ /** Alert type (success, error, warning, info, question, custom) */
45
+ type?: string;
46
+ /** Title text or HTML */
47
+ title?: string;
48
+ /** Message text or HTML */
49
+ message?: string;
50
+ /** Icon name or HTML (success, error, warning, info, question, or custom HTML) */
51
+ icon?: string;
52
+ /** Position of the alert (top, center, bottom, etc.) */
53
+ position?: string;
54
+ /** Whether the alert is dismissible */
55
+ dismissible?: boolean;
56
+ /** Whether the alert is modal (blocks background) */
57
+ modal?: boolean;
58
+ /** Whether to show an input field */
59
+ input?: boolean;
60
+ /** Input placeholder text */
61
+ inputPlaceholder?: string;
62
+ /** Input default value */
63
+ inputValue?: string;
64
+ /** Input type (text, password, email, textarea, select, radio, checkbox, etc.) */
65
+ inputType?: string;
66
+ /** Input label */
67
+ inputLabel?: string;
68
+ /** Input attributes (object of key-value pairs) */
69
+ inputAttributes?: Record<string, string>;
70
+ /** Input options (for select, radio, checkbox, etc.) */
71
+ inputOptions?: Array<{ value: string; label: string; checked?: boolean; disabled?: boolean }>;
72
+ /** Custom content HTML */
73
+ customContent?: string;
74
+ /** Confirm button text */
75
+ confirmText?: string;
76
+ /** Cancel button text */
77
+ cancelText?: string;
78
+ /** Show confirm button */
79
+ showConfirmButton?: boolean;
80
+ /** Show cancel button */
81
+ showCancelButton?: boolean;
82
+ /** Show close (X) button */
83
+ showCloseButton?: boolean;
84
+ /** Auto-dismiss timer (ms) */
85
+ timer?: number;
86
+ /** Allow dismiss by clicking outside the alert */
87
+ allowOutsideClick?: boolean;
88
+ /** Allow dismiss by pressing Escape key */
89
+ allowEscapeKey?: boolean;
90
+ /** Focus confirm button on open */
91
+ focusConfirm?: boolean;
92
+ /** Show loader on confirm */
93
+ showLoaderOnConfirm?: boolean;
94
+ /** Custom class for alert container */
95
+ customClass?: string;
96
+ /** Loader HTML or template */
97
+ loaderHtml?: string;
98
+
99
+ // Validation and processing callbacks
100
+ /** Input validation function - return string for error, null/undefined for success */
101
+ inputValidator?: (value: string) => string | null | undefined | Promise<string | null | undefined>;
102
+ /** Pre-confirmation processing function - can return Promise for async processing */
103
+ preConfirm?: (value: string) => string | Promise<string>;
104
+ /** Auto-focus the input field when alert opens */
105
+ inputAutoFocus?: boolean;
106
+
107
+ // Granular class overrides for individual UI elements
108
+ overlayClass?: string;
109
+ modalClass?: string;
110
+ containerClass?: string;
111
+ iconClass?: string;
112
+ titleClass?: string;
113
+ messageClass?: string;
114
+ actionsClass?: string;
115
+ inputClass?: string;
116
+ inputLabelClass?: string;
117
+ closeButtonClass?: string;
118
+ customContentClass?: string;
119
+ loaderClass?: string;
120
+ /**
121
+ * Per-type theming overrides (e.g., { success: { customClass, icon, confirmText, ... }, ... })
122
+ */
123
+ theme?: {
124
+ [type: string]: {
125
+ customClass?: string;
126
+ icon?: string;
127
+ confirmText?: string;
128
+ cancelText?: string;
129
+ confirmButtonClass?: string;
130
+ cancelButtonClass?: string;
131
+ // Add more per-type overrides as needed
132
+ }
133
+ };
134
+ /** Additional config options */
135
+ [key: string]: any;
136
+ }
137
+
138
+ // State interface for KTAlert
139
+ export interface KTAlertState {
140
+ isOpen: boolean;
141
+ isModal: boolean;
142
+ isDismissed: boolean;
143
+ inputValue?: string;
144
+ // Add more state fields as needed
145
+ }