@keenthemes/ktui 1.0.29 → 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 (243) 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 +12 -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/lib/cjs/components/datepicker/calendar.js +0 -1061
  199. package/lib/cjs/components/datepicker/calendar.js.map +0 -1
  200. package/lib/cjs/components/datepicker/config.js +0 -332
  201. package/lib/cjs/components/datepicker/config.js.map +0 -1
  202. package/lib/cjs/components/datepicker/dropdown.js +0 -635
  203. package/lib/cjs/components/datepicker/dropdown.js.map +0 -1
  204. package/lib/cjs/components/datepicker/events.js +0 -129
  205. package/lib/cjs/components/datepicker/events.js.map +0 -1
  206. package/lib/cjs/components/datepicker/keyboard.js +0 -536
  207. package/lib/cjs/components/datepicker/keyboard.js.map +0 -1
  208. package/lib/cjs/components/datepicker/locales.js +0 -78
  209. package/lib/cjs/components/datepicker/locales.js.map +0 -1
  210. package/lib/cjs/components/datepicker/templates.js +0 -403
  211. package/lib/cjs/components/datepicker/templates.js.map +0 -1
  212. package/lib/cjs/components/datepicker/types.js +0 -23
  213. package/lib/cjs/components/datepicker/types.js.map +0 -1
  214. package/lib/cjs/components/datepicker/utils.js +0 -524
  215. package/lib/cjs/components/datepicker/utils.js.map +0 -1
  216. package/lib/esm/components/datepicker/calendar.js +0 -1058
  217. package/lib/esm/components/datepicker/calendar.js.map +0 -1
  218. package/lib/esm/components/datepicker/config.js +0 -329
  219. package/lib/esm/components/datepicker/config.js.map +0 -1
  220. package/lib/esm/components/datepicker/dropdown.js +0 -632
  221. package/lib/esm/components/datepicker/dropdown.js.map +0 -1
  222. package/lib/esm/components/datepicker/events.js +0 -126
  223. package/lib/esm/components/datepicker/events.js.map +0 -1
  224. package/lib/esm/components/datepicker/keyboard.js +0 -533
  225. package/lib/esm/components/datepicker/keyboard.js.map +0 -1
  226. package/lib/esm/components/datepicker/locales.js +0 -74
  227. package/lib/esm/components/datepicker/locales.js.map +0 -1
  228. package/lib/esm/components/datepicker/templates.js +0 -390
  229. package/lib/esm/components/datepicker/templates.js.map +0 -1
  230. package/lib/esm/components/datepicker/types.js +0 -20
  231. package/lib/esm/components/datepicker/types.js.map +0 -1
  232. package/lib/esm/components/datepicker/utils.js +0 -508
  233. package/lib/esm/components/datepicker/utils.js.map +0 -1
  234. package/src/components/datepicker/calendar.ts +0 -1397
  235. package/src/components/datepicker/config.ts +0 -368
  236. package/src/components/datepicker/dropdown.ts +0 -757
  237. package/src/components/datepicker/events.ts +0 -149
  238. package/src/components/datepicker/keyboard.ts +0 -646
  239. package/src/components/datepicker/locales.ts +0 -80
  240. package/src/components/datepicker/templates.ts +0 -792
  241. package/src/components/datepicker/types.ts +0 -154
  242. package/src/components/datepicker/utils.ts +0 -631
  243. package/src/components/select/variants.css +0 -4
@@ -0,0 +1,1022 @@
1
+ /*
2
+ * alert.ts - Main entry point for KTAlert (modular alert/dialog component)
3
+ *
4
+ * Provides a modular, extensible alert/dialog system for notifications, confirmations, and custom content.
5
+ * Follows the KTDatepicker pattern: extends KTComponent, uses a template system, and supports full customization.
6
+ *
7
+ * All UI fragments are rendered via dedicated methods and customizable via a one-level config/template system.
8
+ *
9
+ * Copyright 2025 by Keenthemes Inc
10
+ */
11
+ var __extends = (this && this.__extends) || (function () {
12
+ var extendStatics = function (d, b) {
13
+ extendStatics = Object.setPrototypeOf ||
14
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
15
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
16
+ return extendStatics(d, b);
17
+ };
18
+ return function (d, b) {
19
+ if (typeof b !== "function" && b !== null)
20
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
21
+ extendStatics(d, b);
22
+ function __() { this.constructor = d; }
23
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
24
+ };
25
+ })();
26
+ var __assign = (this && this.__assign) || function () {
27
+ __assign = Object.assign || function(t) {
28
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
29
+ s = arguments[i];
30
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
31
+ t[p] = s[p];
32
+ }
33
+ return t;
34
+ };
35
+ return __assign.apply(this, arguments);
36
+ };
37
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
38
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
39
+ return new (P || (P = Promise))(function (resolve, reject) {
40
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
41
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
42
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
43
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
44
+ });
45
+ };
46
+ var __generator = (this && this.__generator) || function (thisArg, body) {
47
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
48
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
49
+ function verb(n) { return function (v) { return step([n, v]); }; }
50
+ function step(op) {
51
+ if (f) throw new TypeError("Generator is already executing.");
52
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
53
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
54
+ if (y = 0, t) op = [op[0] & 2, t.value];
55
+ switch (op[0]) {
56
+ case 0: case 1: t = op; break;
57
+ case 4: _.label++; return { value: op[1], done: false };
58
+ case 5: _.label++; y = op[1]; op = [0]; continue;
59
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
60
+ default:
61
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
62
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
63
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
64
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
65
+ if (t[2]) _.ops.pop();
66
+ _.trys.pop(); continue;
67
+ }
68
+ op = body.call(thisArg, _);
69
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
70
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
71
+ }
72
+ };
73
+ import KTComponent from '../component';
74
+ import { getTemplateStrings, coreTemplateStrings, renderTemplateString, isTemplateFunction, renderOptions } from './templates';
75
+ /**
76
+ * Default configuration for KTAlert
77
+ */
78
+ var defaultConfig = {
79
+ type: 'info',
80
+ title: '',
81
+ message: '',
82
+ icon: undefined, // success, error, warning, info, question, or custom HTML
83
+ position: 'center',
84
+ dismissible: false,
85
+ modal: false,
86
+ input: false,
87
+ inputPlaceholder: '',
88
+ inputValue: '',
89
+ inputType: 'text',
90
+ inputLabel: '',
91
+ inputAttributes: {},
92
+ customContent: '',
93
+ confirmText: 'OK',
94
+ cancelText: 'Cancel',
95
+ showConfirmButton: true,
96
+ showCancelButton: false,
97
+ showCloseButton: true,
98
+ timer: undefined,
99
+ allowOutsideClick: true,
100
+ allowEscapeKey: true,
101
+ focusConfirm: true,
102
+ showLoaderOnConfirm: false,
103
+ customClass: '',
104
+ loaderHtml: '',
105
+ };
106
+ /**
107
+ * KTAlert
108
+ *
109
+ * Modular alert/dialog component for notifications, confirmations, and custom content.
110
+ *
111
+ * @class
112
+ * @extends KTComponent
113
+ */
114
+ var KTAlert = /** @class */ (function (_super) {
115
+ __extends(KTAlert, _super);
116
+ /**
117
+ * Constructor: Initializes the alert component (matches KTDatepicker pattern)
118
+ * @param element - The root element for the alert
119
+ * @param config - Optional user config
120
+ */
121
+ function KTAlert(element, config) {
122
+ var _this = _super.call(this) || this;
123
+ /**
124
+ * Component name for data attributes and config
125
+ * @protected
126
+ * @type {string}
127
+ */
128
+ _this._name = 'alert';
129
+ /**
130
+ * User-provided template overrides
131
+ * @private
132
+ * @type {Record<string, string | ((data: any) => string)>}
133
+ */
134
+ _this._userTemplates = {};
135
+ /**
136
+ * Timer ID for auto-dismiss
137
+ * @private
138
+ * @type {ReturnType<typeof setTimeout> | null}
139
+ */
140
+ _this._timerId = null;
141
+ _this._init(element);
142
+ _this._buildConfig(config);
143
+ _this._templateSet = getTemplateStrings(_this._config);
144
+ _this._state = {
145
+ isOpen: true,
146
+ isModal: !!_this._config.modal,
147
+ isDismissed: false,
148
+ inputValue: _this._config.inputValue || ''
149
+ };
150
+ _this._render();
151
+ // Auto-dismiss logic: start timer if timer is set in config
152
+ if (typeof _this._config.timer === 'number' && _this._config.timer > 0) {
153
+ _this._timerId = setTimeout(function () {
154
+ if (!_this._state.isDismissed) {
155
+ _this._state.isDismissed = true;
156
+ _this._fireEvent('dismiss', { reason: 'timer' });
157
+ _this._element.innerHTML = '';
158
+ }
159
+ }, _this._config.timer);
160
+ }
161
+ return _this;
162
+ }
163
+ /**
164
+ * Initialize the component (placeholder)
165
+ * @param {HTMLElement} element - The root element for the alert
166
+ * @protected
167
+ */
168
+ KTAlert.prototype._init = function (element) {
169
+ _super.prototype._init.call(this, element);
170
+ // To be implemented: config merging, template setup, event binding
171
+ };
172
+ /**
173
+ * Build the component config by merging defaults, global, data attributes, and user config
174
+ * @param {KTAlertConfig} [config] - Optional user config
175
+ * @protected
176
+ */
177
+ KTAlert.prototype._buildConfig = function (config) {
178
+ if (!this._element)
179
+ return;
180
+ // Merge order: defaultConfig < globalConfig < data attributes < JSON config < user config
181
+ var globalConfig = this._getGlobalConfig();
182
+ // Parse data-kt-alert-* attributes
183
+ var dataAttrs = {};
184
+ Array.from(this._element.attributes).forEach(function (attr) {
185
+ if (attr.name.startsWith('data-kt-alert-') && attr.name !== 'data-kt-alert-config') {
186
+ // Convert kebab-case to camelCase
187
+ var key = attr.name
188
+ .replace('data-kt-alert-', '')
189
+ .replace(/-([a-z])/g, function (_, c) { return c.toUpperCase(); });
190
+ var value = attr.value;
191
+ // Parse booleans and numbers for known config keys
192
+ if ([
193
+ 'dismissible', 'modal', 'input', 'showConfirmButton', 'showCancelButton', 'showCloseButton',
194
+ 'allowOutsideClick', 'allowEscapeKey', 'focusConfirm', 'showLoaderOnConfirm'
195
+ ].includes(key)) {
196
+ value = value === 'true';
197
+ }
198
+ else if (['timer'].includes(key)) {
199
+ value = Number(value);
200
+ }
201
+ else if (['inputAttributes'].includes(key)) {
202
+ try {
203
+ value = JSON.parse(value);
204
+ }
205
+ catch (_a) {
206
+ value = {};
207
+ }
208
+ }
209
+ dataAttrs[key] = value;
210
+ }
211
+ });
212
+ // JSON config (data-kt-alert-config)
213
+ var jsonConfig = {};
214
+ var jsonAttr = this._element.getAttribute('data-kt-alert-config');
215
+ if (jsonAttr) {
216
+ try {
217
+ jsonConfig = JSON.parse(jsonAttr);
218
+ }
219
+ catch (e) {
220
+ // Invalid JSON, ignore
221
+ }
222
+ }
223
+ // Merge all config sources
224
+ var mergedConfig = __assign(__assign(__assign(__assign(__assign({}, defaultConfig), globalConfig), dataAttrs), jsonConfig), (config || {}));
225
+ // Apply per-type theming if present
226
+ if (mergedConfig.theme && mergedConfig.type && mergedConfig.theme[mergedConfig.type]) {
227
+ var themeOverrides = mergedConfig.theme[mergedConfig.type];
228
+ mergedConfig = __assign(__assign(__assign({}, mergedConfig), themeOverrides), {
229
+ // Use custom class templates if provided
230
+ templates: __assign(__assign({}, (mergedConfig.templates || {})), { confirmButton: themeOverrides.confirmButtonClass ? coreTemplateStrings.confirmButtonCustomClass : undefined, cancelButton: themeOverrides.cancelButtonClass ? coreTemplateStrings.cancelButtonCustomClass : undefined }) });
231
+ }
232
+ this._config = mergedConfig;
233
+ };
234
+ /**
235
+ * Render the alert UI by composing all fragments using templates and config
236
+ * Adds ARIA roles and keyboard navigation for accessibility
237
+ * @private
238
+ */
239
+ KTAlert.prototype._render = function () {
240
+ if (!this._element)
241
+ return;
242
+ this._templateSet = getTemplateStrings(this._config);
243
+ // Render fragments
244
+ var icon = this._renderIcon();
245
+ var title = this._renderTitle();
246
+ var message = this._renderMessage();
247
+ var input = this._renderInput();
248
+ var customContent = this._renderCustomContent();
249
+ var confirmButton = this._renderConfirmButton();
250
+ var cancelButton = this._renderCancelButton();
251
+ var actions = this._renderActions(confirmButton, cancelButton);
252
+ var closeButton = this._renderCloseButton();
253
+ // Compose content
254
+ var content = [icon, title, message, input, customContent, actions, closeButton].join('');
255
+ // Render container
256
+ var containerTpl = this._templateSet.container;
257
+ var containerHtml;
258
+ if (isTemplateFunction(containerTpl)) {
259
+ containerHtml = containerTpl(__assign(__assign({}, this._config), { content: content }));
260
+ }
261
+ else if (typeof containerTpl === 'string') {
262
+ containerHtml = renderTemplateString(containerTpl, __assign(__assign({}, this._config), { content: content }));
263
+ }
264
+ else {
265
+ // Use default container template
266
+ var defaultContainer = coreTemplateStrings.container;
267
+ if (isTemplateFunction(defaultContainer)) {
268
+ containerHtml = defaultContainer(__assign(__assign({}, this._config), { content: content }));
269
+ }
270
+ else if (typeof defaultContainer === 'string') {
271
+ containerHtml = renderTemplateString(defaultContainer, __assign(__assign({}, this._config), { content: content }));
272
+ }
273
+ else {
274
+ containerHtml = "<div>".concat(content, "</div>");
275
+ }
276
+ }
277
+ // Create DOM node
278
+ var temp = document.createElement('div');
279
+ temp.innerHTML = containerHtml;
280
+ this._container = temp.firstElementChild;
281
+ // Add custom class if set
282
+ if (this._config.customClass) {
283
+ this._container.classList.add(this._config.customClass);
284
+ }
285
+ // Set ARIA attributes for accessibility
286
+ this._container.setAttribute('role', this._config.modal ? 'alertdialog' : 'alert');
287
+ this._container.setAttribute('aria-modal', this._config.modal ? 'true' : 'false');
288
+ this._container.setAttribute('aria-labelledby', 'kt-alert-title');
289
+ this._container.setAttribute('aria-describedby', 'kt-alert-message');
290
+ // Replace or append to element
291
+ this._element.innerHTML = '';
292
+ this._element.appendChild(this._container);
293
+ // Focus first interactive element
294
+ this._focusFirstInteractive();
295
+ // Bind event listeners
296
+ this._bindEvents();
297
+ // Bind keyboard navigation
298
+ this._bindKeyboardNav();
299
+ };
300
+ /**
301
+ * Focus the first interactive element (input, confirm, cancel, close)
302
+ * @private
303
+ */
304
+ KTAlert.prototype._focusFirstInteractive = function () {
305
+ if (!this._container)
306
+ return;
307
+ // Auto-focus input if configured and input exists
308
+ if (this._config.inputAutoFocus && this._config.input) {
309
+ var inputElement = this._container.querySelector('[data-kt-alert-input]');
310
+ if (inputElement) {
311
+ inputElement.focus();
312
+ return;
313
+ }
314
+ }
315
+ // Fallback to first interactive element
316
+ var first = this._container.querySelector('[data-kt-alert-input], [data-kt-alert-confirm], [data-kt-alert-cancel], [data-kt-alert-close]');
317
+ if (first)
318
+ first.focus();
319
+ };
320
+ /**
321
+ * Keyboard navigation: focus trap, Escape closes, Enter triggers confirm
322
+ * @private
323
+ */
324
+ KTAlert.prototype._bindKeyboardNav = function () {
325
+ var _this = this;
326
+ if (!this._container)
327
+ return;
328
+ var focusable = Array.from(this._container.querySelectorAll('[tabindex="0"]'));
329
+ if (focusable.length === 0)
330
+ return;
331
+ var current = 0;
332
+ // Focus trap for modal
333
+ if (this._config.modal) {
334
+ this._container.addEventListener('keydown', function (e) {
335
+ if (e.key === 'Tab') {
336
+ e.preventDefault();
337
+ if (e.shiftKey) {
338
+ current = (current - 1 + focusable.length) % focusable.length;
339
+ }
340
+ else {
341
+ current = (current + 1) % focusable.length;
342
+ }
343
+ focusable[current].focus();
344
+ }
345
+ });
346
+ }
347
+ // Escape closes alert if dismissible or modal
348
+ this._container.addEventListener('keydown', function (e) {
349
+ if (e.key === 'Escape' && (_this._config.dismissible || _this._config.modal)) {
350
+ _this._clearTimer();
351
+ _this._state.isDismissed = true;
352
+ _this._fireEvent('dismiss', {});
353
+ _this._element.innerHTML = '';
354
+ }
355
+ // Enter triggers confirm if present
356
+ if (e.key === 'Enter') {
357
+ var confirmBtn = _this._container.querySelector('[data-kt-alert-confirm]');
358
+ if (confirmBtn) {
359
+ confirmBtn.click();
360
+ }
361
+ }
362
+ });
363
+ };
364
+ /** Render icon fragment */
365
+ KTAlert.prototype._renderIcon = function () {
366
+ if (!this._config.icon || !this._templateSet.icon)
367
+ return '';
368
+ var iconVal = this._config.icon;
369
+ var tpl = this._templateSet.icon;
370
+ if (isTemplateFunction(tpl)) {
371
+ return tpl(__assign(__assign({}, this._config), { icon: iconVal }));
372
+ }
373
+ else if (typeof tpl === 'string') {
374
+ return renderTemplateString(tpl, __assign(__assign({}, this._config), { icon: iconVal }));
375
+ }
376
+ return '';
377
+ };
378
+ /** Render title fragment */
379
+ KTAlert.prototype._renderTitle = function () {
380
+ if (!this._templateSet.title)
381
+ return '';
382
+ var titleVal = this._config.title || '';
383
+ var tpl = this._templateSet.title;
384
+ if (isTemplateFunction(tpl)) {
385
+ return tpl(__assign(__assign({}, this._config), { title: titleVal }));
386
+ }
387
+ else if (typeof tpl === 'string') {
388
+ return renderTemplateString(tpl, __assign(__assign({}, this._config), { title: titleVal }));
389
+ }
390
+ return '';
391
+ };
392
+ /** Render message fragment */
393
+ KTAlert.prototype._renderMessage = function () {
394
+ if (!this._templateSet.message)
395
+ return '';
396
+ var messageVal = this._config.message || '';
397
+ var tpl = this._templateSet.message;
398
+ if (isTemplateFunction(tpl)) {
399
+ return tpl(__assign(__assign({}, this._config), { message: messageVal }));
400
+ }
401
+ else if (typeof tpl === 'string') {
402
+ return renderTemplateString(tpl, __assign(__assign({}, this._config), { message: messageVal }));
403
+ }
404
+ return '';
405
+ };
406
+ /** Render input fragment */
407
+ KTAlert.prototype._renderInput = function () {
408
+ if (!this._config.input)
409
+ return '';
410
+ var inputType = this._config.inputType || 'text';
411
+ var inputPlaceholder = this._config.inputPlaceholder || '';
412
+ var inputValue = this._config.inputValue || '';
413
+ var inputLabel = this._config.inputLabel || '';
414
+ var attrs = this._config.inputAttributes
415
+ ? Object.entries(this._config.inputAttributes).map(function (_a) {
416
+ var k = _a[0], v = _a[1];
417
+ return "".concat(k, "=\"").concat(v, "\"");
418
+ }).join(' ')
419
+ : '';
420
+ var options = this._config.inputOptions || [];
421
+ var tplKey = 'inputText';
422
+ var optionsHtml = '';
423
+ // Set template key and render options if needed
424
+ switch (inputType) {
425
+ case 'textarea':
426
+ tplKey = 'inputTextarea';
427
+ break;
428
+ case 'select':
429
+ tplKey = 'inputSelect';
430
+ if (options.length > 0) {
431
+ optionsHtml = renderOptions(options.map(function (opt) { return (__assign(__assign({}, opt), { inputValue: inputValue })); }), 'option', this._templateSet);
432
+ }
433
+ break;
434
+ case 'radio':
435
+ tplKey = 'inputRadio';
436
+ if (options.length > 0) {
437
+ optionsHtml = renderOptions(options.map(function (opt) { return (__assign(__assign({}, opt), { inputValue: inputValue })); }), 'radioOption', this._templateSet);
438
+ }
439
+ break;
440
+ case 'checkbox':
441
+ tplKey = 'inputCheckbox';
442
+ if (options.length > 0) {
443
+ optionsHtml = renderOptions(options, 'checkboxOption', this._templateSet);
444
+ }
445
+ break;
446
+ default:
447
+ tplKey = 'inputText';
448
+ break;
449
+ }
450
+ // Use type assertion to satisfy TS for dynamic template keys
451
+ var tpl = this._templateSet[tplKey];
452
+ var data = __assign(__assign({}, this._config), { inputType: inputType, inputPlaceholder: inputPlaceholder, inputValue: inputValue, inputLabel: inputLabel, attrs: attrs, optionsHtml: optionsHtml });
453
+ if (isTemplateFunction(tpl)) {
454
+ return tpl(data);
455
+ }
456
+ else if (typeof tpl === 'string') {
457
+ return renderTemplateString(tpl, data);
458
+ }
459
+ return '';
460
+ };
461
+ /** Render custom content fragment */
462
+ KTAlert.prototype._renderCustomContent = function () {
463
+ if (!this._templateSet.customContent)
464
+ return '';
465
+ var customVal = this._config.customContent || '';
466
+ var tpl = this._templateSet.customContent;
467
+ if (isTemplateFunction(tpl)) {
468
+ return tpl(__assign(__assign({}, this._config), { customContent: customVal }));
469
+ }
470
+ else if (typeof tpl === 'string') {
471
+ return renderTemplateString(tpl, __assign(__assign({}, this._config), { customContent: customVal }));
472
+ }
473
+ return '';
474
+ };
475
+ /** Render confirm button fragment */
476
+ KTAlert.prototype._renderConfirmButton = function () {
477
+ if (!this._config.showConfirmButton)
478
+ return '';
479
+ var confirmText = this._config.confirmText || 'OK';
480
+ var tpl = this._templateSet.confirmButton;
481
+ // Use custom class template if present
482
+ if (this._config.confirmButtonClass && this._templateSet.confirmButtonCustomClass) {
483
+ tpl = this._templateSet.confirmButtonCustomClass;
484
+ }
485
+ if (isTemplateFunction(tpl)) {
486
+ return tpl(__assign(__assign({}, this._config), { confirmText: confirmText, confirmButtonClass: this._config.confirmButtonClass }));
487
+ }
488
+ else if (typeof tpl === 'string') {
489
+ return renderTemplateString(tpl, __assign(__assign({}, this._config), { confirmText: confirmText, confirmButtonClass: this._config.confirmButtonClass }));
490
+ }
491
+ return '';
492
+ };
493
+ /** Render cancel button fragment */
494
+ KTAlert.prototype._renderCancelButton = function () {
495
+ if (!this._config.showCancelButton)
496
+ return '';
497
+ var cancelText = this._config.cancelText || 'Cancel';
498
+ var tpl = this._templateSet.cancelButton;
499
+ // Use custom class template if present
500
+ if (this._config.cancelButtonClass && this._templateSet.cancelButtonCustomClass) {
501
+ tpl = this._templateSet.cancelButtonCustomClass;
502
+ }
503
+ if (isTemplateFunction(tpl)) {
504
+ return tpl(__assign(__assign({}, this._config), { cancelText: cancelText, cancelButtonClass: this._config.cancelButtonClass }));
505
+ }
506
+ else if (typeof tpl === 'string') {
507
+ return renderTemplateString(tpl, __assign(__assign({}, this._config), { cancelText: cancelText, cancelButtonClass: this._config.cancelButtonClass }));
508
+ }
509
+ return '';
510
+ };
511
+ /** Render actions fragment (wraps confirm/cancel buttons) */
512
+ KTAlert.prototype._renderActions = function (confirmButton, cancelButton) {
513
+ if (!this._templateSet.actions)
514
+ return '';
515
+ var tpl = this._templateSet.actions;
516
+ if (isTemplateFunction(tpl)) {
517
+ return tpl(__assign(__assign({}, this._config), { confirmButton: confirmButton, cancelButton: cancelButton }));
518
+ }
519
+ else if (typeof tpl === 'string') {
520
+ return renderTemplateString(tpl, __assign(__assign({}, this._config), { confirmButton: confirmButton, cancelButton: cancelButton }));
521
+ }
522
+ return '';
523
+ };
524
+ /** Render close button fragment */
525
+ KTAlert.prototype._renderCloseButton = function () {
526
+ if (!this._config.showCloseButton || !this._templateSet.closeButton)
527
+ return '';
528
+ var tpl = this._templateSet.closeButton;
529
+ if (isTemplateFunction(tpl)) {
530
+ return tpl(__assign({}, this._config));
531
+ }
532
+ else if (typeof tpl === 'string') {
533
+ return renderTemplateString(tpl, __assign({}, this._config));
534
+ }
535
+ else {
536
+ return '';
537
+ }
538
+ };
539
+ /**
540
+ * Attach event listeners for dismiss, confirm, cancel, and input actions
541
+ * @private
542
+ */
543
+ KTAlert.prototype._bindEvents = function () {
544
+ var _this = this;
545
+ if (!this._container)
546
+ return;
547
+ // Dismiss (close) button
548
+ var closeBtn = this._container.querySelector('[data-kt-alert-close]');
549
+ if (closeBtn) {
550
+ closeBtn.addEventListener('click', function () {
551
+ _this._clearTimer();
552
+ _this._state.isDismissed = true;
553
+ _this._fireEvent('dismiss', {});
554
+ _this._element.innerHTML = '';
555
+ });
556
+ }
557
+ // Confirm button
558
+ var confirmBtn = this._container.querySelector('[data-kt-alert-confirm]');
559
+ if (confirmBtn) {
560
+ confirmBtn.addEventListener('click', function () { return __awaiter(_this, void 0, void 0, function () {
561
+ var inputValue, inputType, checkboxes, radio, inputEl, validationResult, error_1, error_2;
562
+ return __generator(this, function (_a) {
563
+ switch (_a.label) {
564
+ case 0:
565
+ this._clearTimer();
566
+ inputValue = undefined;
567
+ inputType = this._config.inputType || 'text';
568
+ if (inputType === 'checkbox') {
569
+ checkboxes = this._container.querySelectorAll('input[type="checkbox"][data-kt-alert-input]');
570
+ // Return as comma-separated string for type safety
571
+ inputValue = Array.from(checkboxes).filter(function (el) { return el.checked; }).map(function (el) { return el.value; }).join(',');
572
+ }
573
+ else if (inputType === 'radio') {
574
+ radio = this._container.querySelector('input[type="radio"][data-kt-alert-input]:checked');
575
+ inputValue = radio ? radio.value : undefined;
576
+ }
577
+ else {
578
+ inputEl = this._container.querySelector('[data-kt-alert-input]');
579
+ inputValue = inputEl ? inputEl.value : undefined;
580
+ }
581
+ if (!this._config.inputValidator) return [3 /*break*/, 4];
582
+ _a.label = 1;
583
+ case 1:
584
+ _a.trys.push([1, 3, , 4]);
585
+ return [4 /*yield*/, this._config.inputValidator(inputValue || '')];
586
+ case 2:
587
+ validationResult = _a.sent();
588
+ if (validationResult) {
589
+ // Show validation error
590
+ this._showValidationError(validationResult);
591
+ return [2 /*return*/]; // Don't proceed with confirmation
592
+ }
593
+ return [3 /*break*/, 4];
594
+ case 3:
595
+ error_1 = _a.sent();
596
+ // Show validation error for exceptions
597
+ this._showValidationError('Validation failed. Please try again.');
598
+ return [2 /*return*/];
599
+ case 4:
600
+ // Clear any existing validation errors
601
+ this._clearValidationError();
602
+ if (!this._config.preConfirm) return [3 /*break*/, 8];
603
+ _a.label = 5;
604
+ case 5:
605
+ _a.trys.push([5, 7, , 8]);
606
+ return [4 /*yield*/, this._config.preConfirm(inputValue || '')];
607
+ case 6:
608
+ inputValue = _a.sent();
609
+ return [3 /*break*/, 8];
610
+ case 7:
611
+ error_2 = _a.sent();
612
+ // Show error for pre-confirmation failures
613
+ this._showValidationError('Processing failed. Please try again.');
614
+ return [2 /*return*/];
615
+ case 8:
616
+ this._fireEvent('confirm', { inputValue: inputValue });
617
+ this._state.isDismissed = true;
618
+ this._element.innerHTML = '';
619
+ return [2 /*return*/];
620
+ }
621
+ });
622
+ }); });
623
+ }
624
+ // Cancel button
625
+ var cancelBtn = this._container.querySelector('[data-kt-alert-cancel]');
626
+ if (cancelBtn) {
627
+ cancelBtn.addEventListener('click', function () {
628
+ _this._clearTimer();
629
+ _this._fireEvent('cancel', {});
630
+ _this._state.isDismissed = true;
631
+ _this._element.innerHTML = '';
632
+ });
633
+ }
634
+ // Outside click dismissal (for modal alerts)
635
+ if (this._config.modal && this._config.allowOutsideClick) {
636
+ var overlay_1 = this._element.closest('[data-kt-alert-overlay]');
637
+ if (overlay_1) {
638
+ overlay_1.addEventListener('click', function (e) {
639
+ if (e.target === overlay_1) {
640
+ _this._clearTimer();
641
+ _this._state.isDismissed = true;
642
+ _this._fireEvent('dismiss', {});
643
+ _this._element.innerHTML = '';
644
+ }
645
+ });
646
+ }
647
+ }
648
+ // Input field (update state on input/change)
649
+ var inputType = this._config.inputType || 'text';
650
+ if (inputType === 'checkbox' || inputType === 'radio' || inputType === 'select') {
651
+ var inputs = this._container.querySelectorAll('[data-kt-alert-input]');
652
+ inputs.forEach(function (input) {
653
+ input.addEventListener('change', function (e) {
654
+ if (inputType === 'checkbox') {
655
+ var checkboxes = _this._container.querySelectorAll('input[type="checkbox"][data-kt-alert-input]');
656
+ // Store as comma-separated string for type safety
657
+ _this._state.inputValue = Array.from(checkboxes).filter(function (el) { return el.checked; }).map(function (el) { return el.value; }).join(',');
658
+ }
659
+ else if (inputType === 'radio') {
660
+ var radio = _this._container.querySelector('input[type="radio"][data-kt-alert-input]:checked');
661
+ _this._state.inputValue = radio ? radio.value : undefined;
662
+ }
663
+ else if (inputType === 'select') {
664
+ var select = _this._container.querySelector('select[data-kt-alert-input]');
665
+ _this._state.inputValue = select ? select.value : undefined;
666
+ }
667
+ _this._fireEvent('input', { value: _this._state.inputValue });
668
+ });
669
+ });
670
+ }
671
+ else {
672
+ var inputEl = this._container.querySelector('[data-kt-alert-input]');
673
+ if (inputEl) {
674
+ inputEl.addEventListener('input', function (e) {
675
+ _this._state.inputValue = e.target.value;
676
+ _this._fireEvent('input', { value: _this._state.inputValue });
677
+ });
678
+ }
679
+ }
680
+ };
681
+ /**
682
+ * Clear the current timer if it exists.
683
+ * @private
684
+ */
685
+ KTAlert.prototype._clearTimer = function () {
686
+ if (this._timerId) {
687
+ clearTimeout(this._timerId);
688
+ this._timerId = null;
689
+ }
690
+ };
691
+ /**
692
+ * Show validation error message below input field.
693
+ * @private
694
+ */
695
+ KTAlert.prototype._showValidationError = function (message) {
696
+ var _a;
697
+ if (!this._container)
698
+ return;
699
+ // Clear any existing error
700
+ this._clearValidationError();
701
+ // Create error element
702
+ var errorElement = document.createElement('div');
703
+ errorElement.setAttribute('data-kt-alert-input-error', '');
704
+ errorElement.className = 'kt-alert-input-error';
705
+ errorElement.setAttribute('role', 'alert');
706
+ errorElement.setAttribute('aria-live', 'polite');
707
+ errorElement.textContent = message;
708
+ // Find input label and insert error after it
709
+ var inputLabel = this._container.querySelector('[data-kt-alert-input-label]');
710
+ if (inputLabel) {
711
+ (_a = inputLabel.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(errorElement, inputLabel.nextSibling);
712
+ }
713
+ // Mark input as invalid
714
+ var inputElement = this._container.querySelector('[data-kt-alert-input]');
715
+ if (inputElement) {
716
+ inputElement.setAttribute('aria-invalid', 'true');
717
+ }
718
+ };
719
+ /**
720
+ * Clear validation error message.
721
+ * @private
722
+ */
723
+ KTAlert.prototype._clearValidationError = function () {
724
+ if (!this._container)
725
+ return;
726
+ // Remove error element
727
+ var errorElement = this._container.querySelector('[data-kt-alert-input-error]');
728
+ if (errorElement) {
729
+ errorElement.remove();
730
+ }
731
+ // Remove invalid state from input
732
+ var inputElement = this._container.querySelector('[data-kt-alert-input]');
733
+ if (inputElement) {
734
+ inputElement.removeAttribute('aria-invalid');
735
+ }
736
+ };
737
+ /**
738
+ * Show validation error message below input field (static method helper).
739
+ * @private
740
+ */
741
+ KTAlert.showValidationError = function (alert, message) {
742
+ var _a;
743
+ // Clear any existing error
744
+ this.clearValidationError(alert);
745
+ // Create error element
746
+ var errorElement = document.createElement('div');
747
+ errorElement.setAttribute('data-kt-alert-input-error', '');
748
+ errorElement.className = 'kt-alert-input-error';
749
+ errorElement.setAttribute('role', 'alert');
750
+ errorElement.setAttribute('aria-live', 'polite');
751
+ errorElement.textContent = message;
752
+ // Find input label and insert error after it
753
+ var inputLabel = alert.querySelector('[data-kt-alert-input-label]');
754
+ if (inputLabel) {
755
+ (_a = inputLabel.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(errorElement, inputLabel.nextSibling);
756
+ }
757
+ // Mark input as invalid
758
+ var inputElement = alert.querySelector('[data-kt-alert-input]');
759
+ if (inputElement) {
760
+ inputElement.setAttribute('aria-invalid', 'true');
761
+ }
762
+ };
763
+ /**
764
+ * Clear validation error message (static method helper).
765
+ * @private
766
+ */
767
+ KTAlert.clearValidationError = function (alert) {
768
+ // Remove error element
769
+ var errorElement = alert.querySelector('[data-kt-alert-input-error]');
770
+ if (errorElement) {
771
+ errorElement.remove();
772
+ }
773
+ // Remove invalid state from input
774
+ var inputElement = alert.querySelector('[data-kt-alert-input]');
775
+ if (inputElement) {
776
+ inputElement.removeAttribute('aria-invalid');
777
+ }
778
+ };
779
+ /**
780
+ * KTAlert.fire(options)
781
+ * Accepts a config object and returns a Promise that resolves with the user's action and input value.
782
+ */
783
+ KTAlert.fire = function (options) {
784
+ var _this = this;
785
+ var _a;
786
+ // Remove any existing overlay
787
+ var existing = document.querySelector('[data-kt-alert-overlay]');
788
+ if (existing)
789
+ (_a = existing.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(existing);
790
+ // Prepare templates
791
+ var templates = getTemplateStrings(options);
792
+ // Helper to resolve template (string or function)
793
+ function resolveTemplate(tpl, data) {
794
+ if (typeof tpl === 'function')
795
+ return tpl(data);
796
+ return tpl ? renderTemplateString(tpl, data) : '';
797
+ }
798
+ // Set default icon based on type if no explicit icon is provided
799
+ var iconToUse = options.icon === false ? '' : (options.icon || (function () {
800
+ switch (options.type) {
801
+ case 'success': return '✓';
802
+ case 'error': return '✕';
803
+ case 'warning': return '⚠';
804
+ case 'info': return 'ℹ';
805
+ case 'question': return '?';
806
+ default: return '';
807
+ }
808
+ })());
809
+ // Render modal content (all fragments)
810
+ var icon = iconToUse ? resolveTemplate(templates.icon, __assign(__assign({}, options), { icon: iconToUse })) : '';
811
+ var title = resolveTemplate(templates.title, options);
812
+ var message = resolveTemplate(templates.message, __assign(__assign({}, options), { message: options.text || options.message || '' }));
813
+ // Render input based on type
814
+ var input = '';
815
+ if (options.input) {
816
+ var inputType = options.inputType || 'text';
817
+ var inputPlaceholder = options.inputPlaceholder || '';
818
+ var inputValue_1 = options.inputValue || '';
819
+ var inputLabel = options.inputLabel || '';
820
+ var attrs = options.inputAttributes ? Object.entries(options.inputAttributes).map(function (_a) {
821
+ var k = _a[0], v = _a[1];
822
+ return "".concat(k, "=\"").concat(v, "\"");
823
+ }).join(' ') : '';
824
+ var inputOptions = options.inputOptions || [];
825
+ var tplKey = 'inputText';
826
+ var optionsHtml = '';
827
+ // Set template key and render options if needed
828
+ switch (inputType) {
829
+ case 'textarea':
830
+ tplKey = 'inputTextarea';
831
+ break;
832
+ case 'select':
833
+ tplKey = 'inputSelect';
834
+ if (inputOptions.length > 0) {
835
+ optionsHtml = renderOptions(inputOptions.map(function (opt) { return (__assign(__assign({}, opt), { inputValue: inputValue_1 })); }), 'option', templates);
836
+ }
837
+ break;
838
+ case 'radio':
839
+ tplKey = 'inputRadio';
840
+ if (inputOptions.length > 0) {
841
+ optionsHtml = renderOptions(inputOptions.map(function (opt) { return (__assign(__assign({}, opt), { inputValue: inputValue_1 })); }), 'radioOption', templates);
842
+ }
843
+ break;
844
+ case 'checkbox':
845
+ tplKey = 'inputCheckbox';
846
+ if (inputOptions.length > 0) {
847
+ optionsHtml = renderOptions(inputOptions, 'checkboxOption', templates);
848
+ }
849
+ break;
850
+ default:
851
+ tplKey = 'inputText';
852
+ break;
853
+ }
854
+ var inputTemplate = templates[tplKey];
855
+ var inputData = __assign(__assign({}, options), { inputType: inputType, inputPlaceholder: inputPlaceholder, inputValue: inputValue_1, inputLabel: inputLabel, attrs: attrs, optionsHtml: optionsHtml });
856
+ if (typeof inputTemplate === 'string') {
857
+ input = renderTemplateString(inputTemplate, inputData);
858
+ }
859
+ else if (typeof inputTemplate === 'function') {
860
+ input = inputTemplate(inputData);
861
+ }
862
+ }
863
+ var customContent = options.customContent ? resolveTemplate(templates.customContent, options) : '';
864
+ var confirmButton = options.showConfirmButton !== false ? resolveTemplate(templates.confirmButton, __assign(__assign({}, options), { confirmText: options.confirmText || 'OK' })) : '';
865
+ var cancelButton = options.showCancelButton ? resolveTemplate(templates.cancelButton, __assign(__assign({}, options), { cancelText: options.cancelText || 'Cancel' })) : '';
866
+ var actions = resolveTemplate(templates.actions, __assign(__assign({}, options), { confirmButton: confirmButton, cancelButton: cancelButton }));
867
+ var closeButton = options.showCloseButton !== false ? resolveTemplate(templates.closeButton, options) : '';
868
+ // Loader support
869
+ var loaderHtml = options.showLoaderOnConfirm && options.loaderHtml ? resolveTemplate(templates.loaderHtml, options) : '';
870
+ // Compose content
871
+ var content = [icon, title, message, input, customContent, actions, closeButton, loaderHtml].join('');
872
+ // Render modal container
873
+ var modalHtml = resolveTemplate(templates.modal, __assign(__assign({}, options), { type: options.type || 'info', variant: options.variant || '', ariaModal: options.modal !== false ? 'true' : 'false', role: options.modal !== false ? 'alertdialog' : 'alert', content: content, customClass: options.customClass || '', position: options.position || 'center' }));
874
+ // Render overlay (if modal)
875
+ var overlayHtml = options.modal !== false
876
+ ? resolveTemplate(templates.overlay, __assign(__assign({}, options), { modal: modalHtml }))
877
+ : modalHtml;
878
+ // Create DOM node from template
879
+ var temp = document.createElement('div');
880
+ temp.innerHTML = overlayHtml;
881
+ var overlay = options.modal !== false
882
+ ? temp.querySelector('[data-kt-alert-overlay]')
883
+ : temp.firstElementChild;
884
+ document.body.appendChild(overlay);
885
+ // Set custom ID if provided
886
+ var alert = overlay.querySelector('[data-kt-alert]') || overlay;
887
+ if (options.id) {
888
+ alert.id = options.id;
889
+ }
890
+ // Timer support (auto-dismiss)
891
+ var timerId = null;
892
+ // Promise for result
893
+ return new Promise(function (resolve) {
894
+ // Helper to clean up overlay
895
+ var cleanup = function () {
896
+ if (timerId)
897
+ clearTimeout(timerId);
898
+ if (overlay.parentNode)
899
+ overlay.parentNode.removeChild(overlay);
900
+ };
901
+ // Timer support (auto-dismiss) - moved inside Promise to access cleanup and resolve
902
+ if (options.timer && typeof options.timer === 'number' && options.timer > 0) {
903
+ timerId = setTimeout(function () {
904
+ cleanup();
905
+ resolve({ isConfirmed: false, isDismissed: true, isCanceled: false });
906
+ }, options.timer);
907
+ }
908
+ // Bind events manually
909
+ var alert = overlay.querySelector('[data-kt-alert]') || overlay;
910
+ // Dismiss (close) button
911
+ var closeBtn = alert.querySelector('[data-kt-alert-close]');
912
+ if (closeBtn) {
913
+ closeBtn.addEventListener('click', function () {
914
+ cleanup();
915
+ resolve({ isConfirmed: false, isDismissed: true, isCanceled: false });
916
+ });
917
+ }
918
+ // Confirm button
919
+ var confirmBtn = alert.querySelector('[data-kt-alert-confirm]');
920
+ if (confirmBtn) {
921
+ confirmBtn.addEventListener('click', function () { return __awaiter(_this, void 0, void 0, function () {
922
+ var inputValue, inputType, checkboxes, radio, inputEl, validationResult, error_3, error_4;
923
+ return __generator(this, function (_a) {
924
+ switch (_a.label) {
925
+ case 0:
926
+ inputValue = undefined;
927
+ inputType = options.inputType || 'text';
928
+ if (inputType === 'checkbox') {
929
+ checkboxes = alert.querySelectorAll('input[type="checkbox"][data-kt-alert-input]');
930
+ inputValue = Array.from(checkboxes).filter(function (el) { return el.checked; }).map(function (el) { return el.value; }).join(',');
931
+ }
932
+ else if (inputType === 'radio') {
933
+ radio = alert.querySelector('input[type="radio"][data-kt-alert-input]:checked');
934
+ inputValue = radio ? radio.value : undefined;
935
+ }
936
+ else {
937
+ inputEl = alert.querySelector('[data-kt-alert-input]');
938
+ inputValue = inputEl ? inputEl.value : undefined;
939
+ }
940
+ if (!options.inputValidator) return [3 /*break*/, 4];
941
+ _a.label = 1;
942
+ case 1:
943
+ _a.trys.push([1, 3, , 4]);
944
+ return [4 /*yield*/, options.inputValidator(inputValue || '')];
945
+ case 2:
946
+ validationResult = _a.sent();
947
+ if (validationResult) {
948
+ // Show validation error
949
+ KTAlert.showValidationError(alert, validationResult);
950
+ return [2 /*return*/]; // Don't proceed with confirmation
951
+ }
952
+ return [3 /*break*/, 4];
953
+ case 3:
954
+ error_3 = _a.sent();
955
+ // Show validation error for exceptions
956
+ KTAlert.showValidationError(alert, 'Validation failed. Please try again.');
957
+ return [2 /*return*/];
958
+ case 4:
959
+ // Clear any existing validation errors
960
+ KTAlert.clearValidationError(alert);
961
+ if (!options.preConfirm) return [3 /*break*/, 8];
962
+ _a.label = 5;
963
+ case 5:
964
+ _a.trys.push([5, 7, , 8]);
965
+ return [4 /*yield*/, options.preConfirm(inputValue || '')];
966
+ case 6:
967
+ inputValue = _a.sent();
968
+ return [3 /*break*/, 8];
969
+ case 7:
970
+ error_4 = _a.sent();
971
+ // Show error for pre-confirmation failures
972
+ KTAlert.showValidationError(alert, 'Processing failed. Please try again.');
973
+ return [2 /*return*/];
974
+ case 8:
975
+ cleanup();
976
+ resolve({ isConfirmed: true, isDismissed: false, isCanceled: false, value: inputValue });
977
+ return [2 /*return*/];
978
+ }
979
+ });
980
+ }); });
981
+ }
982
+ // Cancel button
983
+ var cancelBtn = alert.querySelector('[data-kt-alert-cancel]');
984
+ if (cancelBtn) {
985
+ cancelBtn.addEventListener('click', function () {
986
+ cleanup();
987
+ resolve({ isConfirmed: false, isDismissed: false, isCanceled: true });
988
+ });
989
+ }
990
+ // Outside click dismissal (for modal alerts)
991
+ if (options.modal && options.allowOutsideClick) {
992
+ overlay.addEventListener('click', function (e) {
993
+ if (e.target === overlay) {
994
+ cleanup();
995
+ resolve({ isConfirmed: false, isDismissed: true, isCanceled: false });
996
+ }
997
+ });
998
+ }
999
+ // Keyboard events
1000
+ alert.addEventListener('keydown', function (e) {
1001
+ if (e.key === 'Escape' && (options.allowEscapeKey !== false || options.dismissible || options.modal)) {
1002
+ cleanup();
1003
+ resolve({ isConfirmed: false, isDismissed: true, isCanceled: false });
1004
+ }
1005
+ if (e.key === 'Enter' && confirmBtn) {
1006
+ confirmBtn.click();
1007
+ }
1008
+ });
1009
+ // Auto-focus input if configured
1010
+ if (options.inputAutoFocus && options.input) {
1011
+ var inputElement_1 = alert.querySelector('[data-kt-alert-input]');
1012
+ if (inputElement_1) {
1013
+ // Use setTimeout to ensure DOM is ready
1014
+ setTimeout(function () { return inputElement_1.focus(); }, 0);
1015
+ }
1016
+ }
1017
+ });
1018
+ };
1019
+ return KTAlert;
1020
+ }(KTComponent));
1021
+ export { KTAlert };
1022
+ //# sourceMappingURL=alert.js.map