@keenthemes/ktui 1.2.1 → 1.2.3

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 (304) hide show
  1. package/dist/ktui.js +2216 -845
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +24 -197
  5. package/lib/cjs/components/carousel/carousel.d.ts +102 -0
  6. package/lib/cjs/components/carousel/carousel.d.ts.map +1 -0
  7. package/lib/cjs/components/carousel/carousel.js +769 -0
  8. package/lib/cjs/components/carousel/carousel.js.map +1 -0
  9. package/lib/cjs/components/carousel/index.d.ts +7 -0
  10. package/lib/cjs/components/carousel/index.d.ts.map +1 -0
  11. package/lib/cjs/components/carousel/index.js +10 -0
  12. package/lib/cjs/components/carousel/index.js.map +1 -0
  13. package/lib/cjs/components/carousel/types.d.ts +36 -0
  14. package/lib/cjs/components/carousel/types.d.ts.map +1 -0
  15. package/lib/cjs/components/carousel/types.js +7 -0
  16. package/lib/cjs/components/carousel/types.js.map +1 -0
  17. package/lib/cjs/components/component.d.ts +3 -3
  18. package/lib/cjs/components/component.d.ts.map +1 -1
  19. package/lib/cjs/components/component.js +9 -1
  20. package/lib/cjs/components/component.js.map +1 -1
  21. package/lib/cjs/components/datatable/datatable-checkbox.d.ts +1 -1
  22. package/lib/cjs/components/datatable/datatable-checkbox.d.ts.map +1 -1
  23. package/lib/cjs/components/datatable/datatable-checkbox.js +1 -1
  24. package/lib/cjs/components/datatable/datatable-checkbox.js.map +1 -1
  25. package/lib/cjs/components/datatable/datatable-sort.d.ts +1 -1
  26. package/lib/cjs/components/datatable/datatable-sort.d.ts.map +1 -1
  27. package/lib/cjs/components/datatable/datatable-sort.js.map +1 -1
  28. package/lib/cjs/components/datatable/datatable.d.ts +2 -0
  29. package/lib/cjs/components/datatable/datatable.d.ts.map +1 -1
  30. package/lib/cjs/components/datatable/datatable.js +30 -17
  31. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  32. package/lib/cjs/components/datatable/types.d.ts +2 -1
  33. package/lib/cjs/components/datatable/types.d.ts.map +1 -1
  34. package/lib/cjs/components/drawer/drawer.d.ts.map +1 -1
  35. package/lib/cjs/components/drawer/drawer.js +3 -16
  36. package/lib/cjs/components/drawer/drawer.js.map +1 -1
  37. package/lib/cjs/components/dropdown/dropdown.d.ts +1 -1
  38. package/lib/cjs/components/dropdown/dropdown.d.ts.map +1 -1
  39. package/lib/cjs/components/dropdown/dropdown.js +2 -3
  40. package/lib/cjs/components/dropdown/dropdown.js.map +1 -1
  41. package/lib/cjs/components/modal/modal.d.ts.map +1 -1
  42. package/lib/cjs/components/modal/modal.js +19 -13
  43. package/lib/cjs/components/modal/modal.js.map +1 -1
  44. package/lib/cjs/components/pin-input/index.d.ts +3 -0
  45. package/lib/cjs/components/pin-input/index.d.ts.map +1 -0
  46. package/lib/cjs/components/pin-input/index.js +6 -0
  47. package/lib/cjs/components/pin-input/index.js.map +1 -0
  48. package/lib/cjs/components/pin-input/pin-input.d.ts +56 -0
  49. package/lib/cjs/components/pin-input/pin-input.d.ts.map +1 -0
  50. package/lib/cjs/components/pin-input/pin-input.js +455 -0
  51. package/lib/cjs/components/pin-input/pin-input.js.map +1 -0
  52. package/lib/cjs/components/pin-input/types.d.ts +41 -0
  53. package/lib/cjs/components/pin-input/types.d.ts.map +1 -0
  54. package/lib/cjs/components/pin-input/types.js +6 -0
  55. package/lib/cjs/components/pin-input/types.js.map +1 -0
  56. package/lib/cjs/components/rating/rating.d.ts.map +1 -1
  57. package/lib/cjs/components/rating/rating.js.map +1 -1
  58. package/lib/cjs/components/select/combobox.d.ts.map +1 -1
  59. package/lib/cjs/components/select/combobox.js +25 -15
  60. package/lib/cjs/components/select/combobox.js.map +1 -1
  61. package/lib/cjs/components/select/config.d.ts +2 -2
  62. package/lib/cjs/components/select/config.d.ts.map +1 -1
  63. package/lib/cjs/components/select/config.js +10 -9
  64. package/lib/cjs/components/select/config.js.map +1 -1
  65. package/lib/cjs/components/select/dropdown.js.map +1 -1
  66. package/lib/cjs/components/select/option.d.ts +2 -1
  67. package/lib/cjs/components/select/option.d.ts.map +1 -1
  68. package/lib/cjs/components/select/option.js +9 -3
  69. package/lib/cjs/components/select/option.js.map +1 -1
  70. package/lib/cjs/components/select/remote.d.ts +1 -0
  71. package/lib/cjs/components/select/remote.d.ts.map +1 -1
  72. package/lib/cjs/components/select/remote.js +21 -14
  73. package/lib/cjs/components/select/remote.js.map +1 -1
  74. package/lib/cjs/components/select/search.d.ts +1 -1
  75. package/lib/cjs/components/select/search.d.ts.map +1 -1
  76. package/lib/cjs/components/select/search.js +34 -25
  77. package/lib/cjs/components/select/search.js.map +1 -1
  78. package/lib/cjs/components/select/select.d.ts +5 -3
  79. package/lib/cjs/components/select/select.d.ts.map +1 -1
  80. package/lib/cjs/components/select/select.js +31 -31
  81. package/lib/cjs/components/select/select.js.map +1 -1
  82. package/lib/cjs/components/select/tags.d.ts.map +1 -1
  83. package/lib/cjs/components/select/tags.js +22 -13
  84. package/lib/cjs/components/select/tags.js.map +1 -1
  85. package/lib/cjs/components/select/templates.d.ts.map +1 -1
  86. package/lib/cjs/components/select/templates.js +4 -4
  87. package/lib/cjs/components/select/templates.js.map +1 -1
  88. package/lib/cjs/components/select/types.d.ts +1 -1
  89. package/lib/cjs/components/select/types.d.ts.map +1 -1
  90. package/lib/cjs/components/select/utils.d.ts +4 -4
  91. package/lib/cjs/components/select/utils.d.ts.map +1 -1
  92. package/lib/cjs/components/select/utils.js +2 -3
  93. package/lib/cjs/components/select/utils.js.map +1 -1
  94. package/lib/cjs/components/sticky/sticky.d.ts +1 -1
  95. package/lib/cjs/components/sticky/sticky.d.ts.map +1 -1
  96. package/lib/cjs/components/sticky/sticky.js +13 -13
  97. package/lib/cjs/components/sticky/sticky.js.map +1 -1
  98. package/lib/cjs/components/theme-switch/theme-switch.d.ts +3 -0
  99. package/lib/cjs/components/theme-switch/theme-switch.d.ts.map +1 -1
  100. package/lib/cjs/components/theme-switch/theme-switch.js +17 -4
  101. package/lib/cjs/components/theme-switch/theme-switch.js.map +1 -1
  102. package/lib/cjs/components/toast/toast.d.ts.map +1 -1
  103. package/lib/cjs/components/toast/toast.js +17 -9
  104. package/lib/cjs/components/toast/toast.js.map +1 -1
  105. package/lib/cjs/components/toast/types.d.ts +3 -0
  106. package/lib/cjs/components/toast/types.d.ts.map +1 -1
  107. package/lib/cjs/components/toggle/toggle.d.ts +2 -0
  108. package/lib/cjs/components/toggle/toggle.d.ts.map +1 -1
  109. package/lib/cjs/components/toggle/toggle.js +11 -2
  110. package/lib/cjs/components/toggle/toggle.js.map +1 -1
  111. package/lib/cjs/components/toggle-password/toggle-password.d.ts.map +1 -1
  112. package/lib/cjs/components/toggle-password/toggle-password.js.map +1 -1
  113. package/lib/cjs/helpers/dom.d.ts +4 -4
  114. package/lib/cjs/helpers/dom.d.ts.map +1 -1
  115. package/lib/cjs/helpers/dom.js +8 -10
  116. package/lib/cjs/helpers/dom.js.map +1 -1
  117. package/lib/cjs/helpers/event-handler.d.ts +1 -1
  118. package/lib/cjs/helpers/event-handler.d.ts.map +1 -1
  119. package/lib/cjs/helpers/event-handler.js +3 -1
  120. package/lib/cjs/helpers/event-handler.js.map +1 -1
  121. package/lib/cjs/helpers/utils.d.ts +1 -1
  122. package/lib/cjs/helpers/utils.d.ts.map +1 -1
  123. package/lib/cjs/helpers/utils.js +4 -1
  124. package/lib/cjs/helpers/utils.js.map +1 -1
  125. package/lib/cjs/index.d.ts +8 -0
  126. package/lib/cjs/index.d.ts.map +1 -1
  127. package/lib/cjs/index.js +9 -1
  128. package/lib/cjs/index.js.map +1 -1
  129. package/lib/cjs/types.d.ts +1 -1
  130. package/lib/cjs/types.d.ts.map +1 -1
  131. package/lib/esm/components/carousel/carousel.d.ts +102 -0
  132. package/lib/esm/components/carousel/carousel.d.ts.map +1 -0
  133. package/lib/esm/components/carousel/carousel.js +766 -0
  134. package/lib/esm/components/carousel/carousel.js.map +1 -0
  135. package/lib/esm/components/carousel/index.d.ts +7 -0
  136. package/lib/esm/components/carousel/index.d.ts.map +1 -0
  137. package/lib/esm/components/carousel/index.js +6 -0
  138. package/lib/esm/components/carousel/index.js.map +1 -0
  139. package/lib/esm/components/carousel/types.d.ts +36 -0
  140. package/lib/esm/components/carousel/types.d.ts.map +1 -0
  141. package/lib/esm/components/carousel/types.js +6 -0
  142. package/lib/esm/components/carousel/types.js.map +1 -0
  143. package/lib/esm/components/component.d.ts +3 -3
  144. package/lib/esm/components/component.d.ts.map +1 -1
  145. package/lib/esm/components/component.js +9 -1
  146. package/lib/esm/components/component.js.map +1 -1
  147. package/lib/esm/components/datatable/datatable-checkbox.d.ts +1 -1
  148. package/lib/esm/components/datatable/datatable-checkbox.d.ts.map +1 -1
  149. package/lib/esm/components/datatable/datatable-checkbox.js +1 -1
  150. package/lib/esm/components/datatable/datatable-checkbox.js.map +1 -1
  151. package/lib/esm/components/datatable/datatable-sort.d.ts +1 -1
  152. package/lib/esm/components/datatable/datatable-sort.d.ts.map +1 -1
  153. package/lib/esm/components/datatable/datatable-sort.js.map +1 -1
  154. package/lib/esm/components/datatable/datatable.d.ts +2 -0
  155. package/lib/esm/components/datatable/datatable.d.ts.map +1 -1
  156. package/lib/esm/components/datatable/datatable.js +30 -17
  157. package/lib/esm/components/datatable/datatable.js.map +1 -1
  158. package/lib/esm/components/datatable/types.d.ts +2 -1
  159. package/lib/esm/components/datatable/types.d.ts.map +1 -1
  160. package/lib/esm/components/drawer/drawer.d.ts.map +1 -1
  161. package/lib/esm/components/drawer/drawer.js +3 -16
  162. package/lib/esm/components/drawer/drawer.js.map +1 -1
  163. package/lib/esm/components/dropdown/dropdown.d.ts +1 -1
  164. package/lib/esm/components/dropdown/dropdown.d.ts.map +1 -1
  165. package/lib/esm/components/dropdown/dropdown.js +2 -3
  166. package/lib/esm/components/dropdown/dropdown.js.map +1 -1
  167. package/lib/esm/components/modal/modal.d.ts.map +1 -1
  168. package/lib/esm/components/modal/modal.js +19 -13
  169. package/lib/esm/components/modal/modal.js.map +1 -1
  170. package/lib/esm/components/pin-input/index.d.ts +3 -0
  171. package/lib/esm/components/pin-input/index.d.ts.map +1 -0
  172. package/lib/esm/components/pin-input/index.js +2 -0
  173. package/lib/esm/components/pin-input/index.js.map +1 -0
  174. package/lib/esm/components/pin-input/pin-input.d.ts +56 -0
  175. package/lib/esm/components/pin-input/pin-input.d.ts.map +1 -0
  176. package/lib/esm/components/pin-input/pin-input.js +452 -0
  177. package/lib/esm/components/pin-input/pin-input.js.map +1 -0
  178. package/lib/esm/components/pin-input/types.d.ts +41 -0
  179. package/lib/esm/components/pin-input/types.d.ts.map +1 -0
  180. package/lib/esm/components/pin-input/types.js +5 -0
  181. package/lib/esm/components/pin-input/types.js.map +1 -0
  182. package/lib/esm/components/rating/rating.d.ts.map +1 -1
  183. package/lib/esm/components/rating/rating.js.map +1 -1
  184. package/lib/esm/components/select/combobox.d.ts.map +1 -1
  185. package/lib/esm/components/select/combobox.js +25 -15
  186. package/lib/esm/components/select/combobox.js.map +1 -1
  187. package/lib/esm/components/select/config.d.ts +2 -2
  188. package/lib/esm/components/select/config.d.ts.map +1 -1
  189. package/lib/esm/components/select/config.js +10 -9
  190. package/lib/esm/components/select/config.js.map +1 -1
  191. package/lib/esm/components/select/dropdown.js.map +1 -1
  192. package/lib/esm/components/select/option.d.ts +2 -1
  193. package/lib/esm/components/select/option.d.ts.map +1 -1
  194. package/lib/esm/components/select/option.js +9 -3
  195. package/lib/esm/components/select/option.js.map +1 -1
  196. package/lib/esm/components/select/remote.d.ts +1 -0
  197. package/lib/esm/components/select/remote.d.ts.map +1 -1
  198. package/lib/esm/components/select/remote.js +21 -14
  199. package/lib/esm/components/select/remote.js.map +1 -1
  200. package/lib/esm/components/select/search.d.ts +1 -1
  201. package/lib/esm/components/select/search.d.ts.map +1 -1
  202. package/lib/esm/components/select/search.js +34 -25
  203. package/lib/esm/components/select/search.js.map +1 -1
  204. package/lib/esm/components/select/select.d.ts +5 -3
  205. package/lib/esm/components/select/select.d.ts.map +1 -1
  206. package/lib/esm/components/select/select.js +31 -31
  207. package/lib/esm/components/select/select.js.map +1 -1
  208. package/lib/esm/components/select/tags.d.ts.map +1 -1
  209. package/lib/esm/components/select/tags.js +22 -13
  210. package/lib/esm/components/select/tags.js.map +1 -1
  211. package/lib/esm/components/select/templates.d.ts.map +1 -1
  212. package/lib/esm/components/select/templates.js +4 -4
  213. package/lib/esm/components/select/templates.js.map +1 -1
  214. package/lib/esm/components/select/types.d.ts +1 -1
  215. package/lib/esm/components/select/types.d.ts.map +1 -1
  216. package/lib/esm/components/select/utils.d.ts +4 -4
  217. package/lib/esm/components/select/utils.d.ts.map +1 -1
  218. package/lib/esm/components/select/utils.js +2 -3
  219. package/lib/esm/components/select/utils.js.map +1 -1
  220. package/lib/esm/components/sticky/sticky.d.ts +1 -1
  221. package/lib/esm/components/sticky/sticky.d.ts.map +1 -1
  222. package/lib/esm/components/sticky/sticky.js +13 -13
  223. package/lib/esm/components/sticky/sticky.js.map +1 -1
  224. package/lib/esm/components/theme-switch/theme-switch.d.ts +3 -0
  225. package/lib/esm/components/theme-switch/theme-switch.d.ts.map +1 -1
  226. package/lib/esm/components/theme-switch/theme-switch.js +17 -4
  227. package/lib/esm/components/theme-switch/theme-switch.js.map +1 -1
  228. package/lib/esm/components/toast/toast.d.ts.map +1 -1
  229. package/lib/esm/components/toast/toast.js +17 -9
  230. package/lib/esm/components/toast/toast.js.map +1 -1
  231. package/lib/esm/components/toast/types.d.ts +3 -0
  232. package/lib/esm/components/toast/types.d.ts.map +1 -1
  233. package/lib/esm/components/toggle/toggle.d.ts +2 -0
  234. package/lib/esm/components/toggle/toggle.d.ts.map +1 -1
  235. package/lib/esm/components/toggle/toggle.js +11 -2
  236. package/lib/esm/components/toggle/toggle.js.map +1 -1
  237. package/lib/esm/components/toggle-password/toggle-password.d.ts.map +1 -1
  238. package/lib/esm/components/toggle-password/toggle-password.js.map +1 -1
  239. package/lib/esm/helpers/dom.d.ts +4 -4
  240. package/lib/esm/helpers/dom.d.ts.map +1 -1
  241. package/lib/esm/helpers/dom.js +8 -10
  242. package/lib/esm/helpers/dom.js.map +1 -1
  243. package/lib/esm/helpers/event-handler.d.ts +1 -1
  244. package/lib/esm/helpers/event-handler.d.ts.map +1 -1
  245. package/lib/esm/helpers/event-handler.js +3 -1
  246. package/lib/esm/helpers/event-handler.js.map +1 -1
  247. package/lib/esm/helpers/utils.d.ts +1 -1
  248. package/lib/esm/helpers/utils.d.ts.map +1 -1
  249. package/lib/esm/helpers/utils.js +4 -1
  250. package/lib/esm/helpers/utils.js.map +1 -1
  251. package/lib/esm/index.d.ts +8 -0
  252. package/lib/esm/index.d.ts.map +1 -1
  253. package/lib/esm/index.js +6 -0
  254. package/lib/esm/index.js.map +1 -1
  255. package/lib/esm/types.d.ts +1 -1
  256. package/lib/esm/types.d.ts.map +1 -1
  257. package/package.json +5 -2
  258. package/src/components/carousel/__tests__/carousel.test.ts +326 -0
  259. package/src/components/carousel/carousel.css +42 -0
  260. package/src/components/carousel/carousel.ts +847 -0
  261. package/src/components/carousel/index.ts +11 -0
  262. package/src/components/carousel/types.ts +38 -0
  263. package/src/components/clipboard/__tests__/clipboard.test.ts +4 -4
  264. package/src/components/component.ts +15 -5
  265. package/src/components/datatable/__tests__/currency-sort.test.ts +4 -3
  266. package/src/components/datatable/__tests__/pagination-reset.test.ts +7 -4
  267. package/src/components/datatable/__tests__/setup.ts +1 -1
  268. package/src/components/datatable/datatable-checkbox.ts +6 -4
  269. package/src/components/datatable/datatable-sort.ts +27 -7
  270. package/src/components/datatable/datatable.ts +64 -37
  271. package/src/components/datatable/types.ts +3 -1
  272. package/src/components/drawer/drawer.ts +3 -18
  273. package/src/components/dropdown/dropdown.ts +2 -3
  274. package/src/components/modal/modal.ts +22 -14
  275. package/src/components/pin-input/__tests__/pin-input.test.ts +928 -0
  276. package/src/components/pin-input/index.ts +6 -0
  277. package/src/components/pin-input/pin-input.ts +499 -0
  278. package/src/components/pin-input/types.ts +45 -0
  279. package/src/components/rating/rating.ts +0 -1
  280. package/src/components/repeater/__tests__/repeater.test.ts +5 -5
  281. package/src/components/select/__tests__/ux-behaviors.test.ts +4 -3
  282. package/src/components/select/combobox.ts +23 -16
  283. package/src/components/select/config.ts +15 -14
  284. package/src/components/select/dropdown.ts +1 -1
  285. package/src/components/select/option.ts +14 -4
  286. package/src/components/select/remote.ts +68 -56
  287. package/src/components/select/search.ts +30 -27
  288. package/src/components/select/select.ts +41 -37
  289. package/src/components/select/tags.ts +14 -8
  290. package/src/components/select/templates.ts +11 -6
  291. package/src/components/select/types.ts +1 -1
  292. package/src/components/select/utils.ts +7 -9
  293. package/src/components/sticky/sticky.ts +2 -2
  294. package/src/components/theme-switch/theme-switch.ts +22 -4
  295. package/src/components/toast/toast.ts +34 -21
  296. package/src/components/toast/types.ts +5 -1
  297. package/src/components/toggle/toggle.ts +12 -2
  298. package/src/components/toggle-password/toggle-password.ts +0 -1
  299. package/src/helpers/dom.ts +14 -17
  300. package/src/helpers/event-handler.ts +5 -6
  301. package/src/helpers/utils.ts +5 -2
  302. package/src/index.ts +18 -0
  303. package/src/types.ts +1 -1
  304. package/styles.css +1 -0
@@ -0,0 +1,847 @@
1
+ /**
2
+ * KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
3
+ * Copyright 2025 by Keenthemes Inc
4
+ */
5
+
6
+ import KTData from '../../helpers/data';
7
+ import KTComponent from '../component';
8
+ import {
9
+ KTCarouselChangePayloadInterface,
10
+ KTCarouselConfigInterface,
11
+ KTCarouselInterface,
12
+ } from './types';
13
+
14
+ declare global {
15
+ interface Window {
16
+ KTCarousel: typeof KTCarousel;
17
+ }
18
+ }
19
+
20
+ const SELECTOR_VIEWPORT = '[data-kt-carousel-viewport]';
21
+ const SELECTOR_ITEM = '[data-kt-carousel-item]';
22
+ const SELECTOR_PREV = '[data-kt-carousel-prev]';
23
+ const SELECTOR_NEXT = '[data-kt-carousel-next]';
24
+ const SELECTOR_PAGINATION = '[data-kt-carousel-pagination]';
25
+ const SELECTOR_PAGINATION_ITEM = '[data-kt-carousel-pagination-item]';
26
+ const SELECTOR_THUMBS = '[data-kt-carousel-thumbnails]';
27
+ const SELECTOR_THUMB = '[data-kt-carousel-thumbnail]';
28
+ const SELECTOR_CURRENT = '[data-kt-carousel-current]';
29
+ const SELECTOR_TOTAL = '[data-kt-carousel-total]';
30
+
31
+ export class KTCarousel extends KTComponent implements KTCarouselInterface {
32
+ protected override _name: string = 'carousel';
33
+ protected override _defaultConfig: KTCarouselConfigInterface = {
34
+ autoplay: false,
35
+ autoplayInterval: 4000,
36
+ infiniteLoop: false,
37
+ rtl: false,
38
+ perView: 1,
39
+ centered: false,
40
+ draggable: false,
41
+ snap: false,
42
+ autoHeight: false,
43
+ showScrollbar: false,
44
+ lazy: false,
45
+ pauseOnHover: true,
46
+ changeEvent: 'kt.carousel.change',
47
+ };
48
+
49
+ protected override _config: KTCarouselConfigInterface = this
50
+ ._defaultConfig as KTCarouselConfigInterface;
51
+
52
+ private _viewport: HTMLElement | null = null;
53
+ private _slides: HTMLElement[] = [];
54
+ private _index = 0;
55
+ private _autoplayTimer: ReturnType<typeof setInterval> | null = null;
56
+ private _programmaticScroll = false;
57
+ private _resizeObserver: ResizeObserver | null = null;
58
+ private _prefersReducedMotion = false;
59
+
60
+ private _onPrevClick: ((e: Event) => void) | null = null;
61
+ private _onNextClick: ((e: Event) => void) | null = null;
62
+ private _onScroll: (() => void) | null = null;
63
+ private _onScrollEnd: (() => void) | null = null;
64
+ private _onKeyDown: ((e: KeyboardEvent) => void) | null = null;
65
+ private _onPointerDown: ((e: PointerEvent) => void) | null = null;
66
+ private _onPointerMove: ((e: PointerEvent) => void) | null = null;
67
+ private _onPointerUp: ((e: PointerEvent) => void) | null = null;
68
+ private _paginationHandlers: Array<{
69
+ el: HTMLElement;
70
+ fn: (e: Event) => void;
71
+ }> = [];
72
+ private _thumbHandlers: Array<{ el: HTMLElement; fn: (e: Event) => void }> =
73
+ [];
74
+ private _programmaticScrollPrevIndex: number | null = null;
75
+ private _programmaticScrollTargetIndex: number | null = null;
76
+ private _programmaticScrollUserInitiated = false;
77
+ private _programmaticScrollFallbackTimer: ReturnType<
78
+ typeof setTimeout
79
+ > | null = null;
80
+ private _scrollSyncRaf = 0;
81
+ private _pauseAutoplay: (() => void) | null = null;
82
+ private _resumeAutoplay: (() => void) | null = null;
83
+ private _dragStartX = 0;
84
+ private _dragStartScroll = 0;
85
+ private _dragging = false;
86
+ private _dragMoved = false;
87
+ private _pointerId: number | null = null;
88
+ private _prevButtons: HTMLElement[] = [];
89
+ private _nextButtons: HTMLElement[] = [];
90
+ private _currentLabels: HTMLElement[] = [];
91
+ private _totalLabels: HTMLElement[] = [];
92
+
93
+ constructor(
94
+ element: HTMLElement,
95
+ config: Partial<KTCarouselConfigInterface> | null = null,
96
+ ) {
97
+ super();
98
+
99
+ if (this._shouldSkipInit(element)) {
100
+ return;
101
+ }
102
+
103
+ const viewport = KTCarousel._resolveViewportStatic(element);
104
+ const slides = KTCarousel._collectSlidesStatic(viewport);
105
+ if (!viewport || slides.length === 0) {
106
+ return;
107
+ }
108
+
109
+ this._init(element);
110
+ this._buildConfig(config);
111
+ this._syncShowScrollbarAttribute();
112
+
113
+ this._viewport = viewport;
114
+ this._slides = slides;
115
+
116
+ this._prefersReducedMotion = this._readPrefersReducedMotion();
117
+ this._bindControls();
118
+ this._bindScrollSync();
119
+ this._bindKeyboard();
120
+ this._bindAutoplayHoverPause();
121
+ this._bindDraggable();
122
+ this._bindAutoHeight();
123
+
124
+ this._syncIndexFromScroll();
125
+ this._updateInfo();
126
+ this._updatePaginationState();
127
+ this._updateThumbState(false);
128
+ this._startAutoplay();
129
+ }
130
+
131
+ private _readPrefersReducedMotion(): boolean {
132
+ if (typeof window === 'undefined' || !window.matchMedia) {
133
+ return false;
134
+ }
135
+ return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
136
+ }
137
+
138
+ private _syncShowScrollbarAttribute(): void {
139
+ if (!this._element) return;
140
+ const show = this._getOption('showScrollbar') === true;
141
+ if (show) {
142
+ this._element.setAttribute('data-kt-carousel-show-scrollbar', 'true');
143
+ } else {
144
+ this._element.removeAttribute('data-kt-carousel-show-scrollbar');
145
+ }
146
+ }
147
+
148
+ private static _resolveViewportStatic(root: HTMLElement): HTMLElement | null {
149
+ const explicit = root.querySelector<HTMLElement>(SELECTOR_VIEWPORT);
150
+ if (explicit) return explicit;
151
+ return root;
152
+ }
153
+
154
+ private static _collectSlidesStatic(
155
+ viewport: HTMLElement | null,
156
+ ): HTMLElement[] {
157
+ if (!viewport) return [];
158
+ return Array.from(viewport.querySelectorAll<HTMLElement>(SELECTOR_ITEM));
159
+ }
160
+
161
+ private _isRtl(): boolean {
162
+ if (this._getOption('rtl') === true) return true;
163
+ if (this._element?.getAttribute('dir') === 'rtl') return true;
164
+ if (
165
+ this._viewport &&
166
+ getComputedStyle(this._viewport).direction === 'rtl'
167
+ ) {
168
+ return true;
169
+ }
170
+ return false;
171
+ }
172
+
173
+ private _scrollBehavior(): ScrollBehavior {
174
+ return this._prefersReducedMotion ? 'auto' : 'smooth';
175
+ }
176
+
177
+ private _effectiveDraggable(): boolean {
178
+ if (this._getOption('snap') === true) return false;
179
+ return this._getOption('draggable') === true;
180
+ }
181
+
182
+ private _bindControls(): void {
183
+ if (!this._element) return;
184
+ const root = this._element;
185
+
186
+ this._prevButtons = Array.from(
187
+ root.querySelectorAll<HTMLElement>(SELECTOR_PREV),
188
+ );
189
+ this._nextButtons = Array.from(
190
+ root.querySelectorAll<HTMLElement>(SELECTOR_NEXT),
191
+ );
192
+ this._currentLabels = Array.from(
193
+ root.querySelectorAll<HTMLElement>(SELECTOR_CURRENT),
194
+ );
195
+ this._totalLabels = Array.from(
196
+ root.querySelectorAll<HTMLElement>(SELECTOR_TOTAL),
197
+ );
198
+
199
+ this._onPrevClick = (e: Event) => {
200
+ e.preventDefault();
201
+ this.prev(true);
202
+ };
203
+ this._onNextClick = (e: Event) => {
204
+ e.preventDefault();
205
+ this.next(true);
206
+ };
207
+
208
+ this._prevButtons.forEach((btn) => {
209
+ btn.addEventListener('click', this._onPrevClick!);
210
+ });
211
+ this._nextButtons.forEach((btn) => {
212
+ btn.addEventListener('click', this._onNextClick!);
213
+ });
214
+
215
+ this._bindIndexedClickStrips(
216
+ SELECTOR_PAGINATION,
217
+ SELECTOR_PAGINATION_ITEM,
218
+ this._paginationHandlers,
219
+ );
220
+ this._bindIndexedClickStrips(
221
+ SELECTOR_THUMBS,
222
+ SELECTOR_THUMB,
223
+ this._thumbHandlers,
224
+ );
225
+ }
226
+
227
+ private _bindIndexedClickStrips(
228
+ stripSelector: string,
229
+ itemSelector: string,
230
+ handlers: Array<{ el: HTMLElement; fn: (e: Event) => void }>,
231
+ ): void {
232
+ if (!this._element) return;
233
+ this._element
234
+ .querySelectorAll<HTMLElement>(stripSelector)
235
+ .forEach((strip) => {
236
+ strip.querySelectorAll<HTMLElement>(itemSelector).forEach((item, i) => {
237
+ const fn = (e: Event) => {
238
+ e.preventDefault();
239
+ this.goTo(i, true);
240
+ };
241
+ item.addEventListener('click', fn);
242
+ handlers.push({ el: item, fn });
243
+ });
244
+ });
245
+ }
246
+
247
+ private _bindScrollSync(): void {
248
+ if (!this._viewport) return;
249
+
250
+ this._onScroll = () => {
251
+ if (this._scrollSyncRaf) cancelAnimationFrame(this._scrollSyncRaf);
252
+ this._scrollSyncRaf = requestAnimationFrame(() => {
253
+ this._scrollSyncRaf = 0;
254
+ const prev = this._index;
255
+ this._applyScrollDerivedIndexChange(prev, {
256
+ dispatch: !this._programmaticScroll,
257
+ userInitiated: true,
258
+ });
259
+ });
260
+ };
261
+
262
+ this._viewport.addEventListener('scroll', this._onScroll, {
263
+ passive: true,
264
+ });
265
+
266
+ this._onScrollEnd = () => {
267
+ if (this._programmaticScroll) {
268
+ const t = this._programmaticScrollTargetIndex;
269
+ if (t !== null && this._nearestIndex() === t) {
270
+ queueMicrotask(() => this._completeProgrammaticScroll());
271
+ }
272
+ return;
273
+ }
274
+ const prev = this._index;
275
+ this._applyScrollDerivedIndexChange(prev, {
276
+ dispatch: true,
277
+ userInitiated: true,
278
+ });
279
+ };
280
+
281
+ this._viewport.addEventListener(
282
+ 'scrollend',
283
+ this._onScrollEnd as EventListener,
284
+ );
285
+ }
286
+
287
+ private _bindKeyboard(): void {
288
+ if (!this._element) return;
289
+ this._onKeyDown = (e: KeyboardEvent) => {
290
+ if (!this._element?.contains(e.target as Node)) return;
291
+ const t = e.target as HTMLElement | null;
292
+ if (
293
+ t &&
294
+ (t.tagName === 'INPUT' ||
295
+ t.tagName === 'TEXTAREA' ||
296
+ t.isContentEditable)
297
+ ) {
298
+ return;
299
+ }
300
+
301
+ if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;
302
+
303
+ const rtl = this._isRtl();
304
+ const nextKey = rtl ? 'ArrowLeft' : 'ArrowRight';
305
+ const prevKey = rtl ? 'ArrowRight' : 'ArrowLeft';
306
+
307
+ if (e.key === nextKey) {
308
+ e.preventDefault();
309
+ this.next(true);
310
+ } else if (e.key === prevKey) {
311
+ e.preventDefault();
312
+ this.prev(true);
313
+ }
314
+ };
315
+ this._element.addEventListener('keydown', this._onKeyDown);
316
+ }
317
+
318
+ private _bindAutoplayHoverPause(): void {
319
+ if (!this._element || !this._viewport) return;
320
+ if (this._getOption('pauseOnHover') !== true) return;
321
+
322
+ this._pauseAutoplay = () => this._stopAutoplay();
323
+ this._resumeAutoplay = () => this._startAutoplay();
324
+
325
+ this._element.addEventListener('mouseenter', this._pauseAutoplay);
326
+ this._element.addEventListener('mouseleave', this._resumeAutoplay);
327
+ this._element.addEventListener('focusin', this._pauseAutoplay);
328
+ this._element.addEventListener('focusout', this._resumeAutoplay);
329
+ }
330
+
331
+ private _bindDraggable(): void {
332
+ if (!this._viewport || !this._effectiveDraggable()) return;
333
+
334
+ this._onPointerDown = (e: PointerEvent) => {
335
+ if (e.pointerType === 'mouse' && e.button !== 0) return;
336
+ const t = e.target as HTMLElement | null;
337
+ if (t && t.closest('button,a,input,textarea,select')) return;
338
+
339
+ this._pointerId = e.pointerId;
340
+ this._dragStartX = e.clientX;
341
+ this._dragStartScroll = this._viewport!.scrollLeft;
342
+ this._dragging = true;
343
+ this._dragMoved = false;
344
+ this._viewport!.setPointerCapture(e.pointerId);
345
+ };
346
+
347
+ this._onPointerMove = (e: PointerEvent) => {
348
+ if (!this._dragging || e.pointerId !== this._pointerId) return;
349
+ const dx = e.clientX - this._dragStartX;
350
+ if (Math.abs(dx) > 5) this._dragMoved = true;
351
+ this._viewport!.scrollLeft = this._dragStartScroll - dx;
352
+ };
353
+
354
+ this._onPointerUp = (e: PointerEvent) => {
355
+ if (e.pointerId !== this._pointerId) return;
356
+ this._dragging = false;
357
+ this._pointerId = null;
358
+ try {
359
+ this._viewport!.releasePointerCapture(e.pointerId);
360
+ } catch {
361
+ /* ignore */
362
+ }
363
+ };
364
+
365
+ this._viewport.addEventListener('pointerdown', this._onPointerDown);
366
+ this._viewport.addEventListener('pointermove', this._onPointerMove);
367
+ this._viewport.addEventListener('pointerup', this._onPointerUp);
368
+ this._viewport.addEventListener('pointercancel', this._onPointerUp);
369
+ }
370
+
371
+ private _bindAutoHeight(): void {
372
+ if (!this._viewport || this._getOption('autoHeight') !== true) return;
373
+
374
+ this._applyAutoHeight();
375
+ this._observeActiveSlideForHeight();
376
+ }
377
+
378
+ private _observeActiveSlideForHeight(): void {
379
+ if (this._getOption('autoHeight') !== true) return;
380
+ const active = this._slides[this._index];
381
+ if (!active || typeof ResizeObserver === 'undefined') return;
382
+
383
+ if (!this._resizeObserver) {
384
+ this._resizeObserver = new ResizeObserver(() => {
385
+ this._applyAutoHeight();
386
+ });
387
+ } else {
388
+ this._resizeObserver.disconnect();
389
+ }
390
+ this._resizeObserver.observe(active);
391
+ }
392
+
393
+ private _applyAutoHeight(): void {
394
+ if (!this._viewport || this._getOption('autoHeight') !== true) return;
395
+ const slide = this._slides[this._index];
396
+ if (!slide) return;
397
+ const h = slide.offsetHeight;
398
+ if (h > 0) {
399
+ this._viewport.style.height = `${h}px`;
400
+ }
401
+ }
402
+
403
+ private _nearestIndex(): number {
404
+ if (!this._viewport || this._slides.length === 0) return 0;
405
+ const vp = this._viewport;
406
+ const origin = vp.scrollLeft;
407
+ let best = 0;
408
+ let bestDist = Infinity;
409
+ for (let i = 0; i < this._slides.length; i++) {
410
+ const slide = this._slides[i];
411
+ const dist = Math.abs(slide.offsetLeft - origin);
412
+ if (dist < bestDist) {
413
+ bestDist = dist;
414
+ best = i;
415
+ }
416
+ }
417
+ return best;
418
+ }
419
+
420
+ private _syncIndexFromScroll(): void {
421
+ if (this._slides.length === 0) return;
422
+ this._index = this._nearestIndex();
423
+ }
424
+
425
+ private _applyScrollDerivedIndexChange(
426
+ prevIndex: number,
427
+ options: { dispatch: boolean; userInitiated: boolean },
428
+ ): void {
429
+ this._syncIndexFromScroll();
430
+ if (prevIndex === this._index) return;
431
+ this._updateInfo();
432
+ this._updatePaginationState();
433
+ this._updateThumbState(false);
434
+ this._applyAutoHeight();
435
+ this._observeActiveSlideForHeight();
436
+ if (options.dispatch) {
437
+ this._dispatchChange(this._index, prevIndex, options.userInitiated);
438
+ }
439
+ }
440
+
441
+ private _setStripItemsActiveState(
442
+ handlers: Array<{ el: HTMLElement; fn: (e: Event) => void }>,
443
+ activeDataAttr: string,
444
+ ): void {
445
+ handlers.forEach(({ el }, i) => {
446
+ const active = i === this._index;
447
+ if (active) {
448
+ el.setAttribute('aria-current', 'true');
449
+ } else {
450
+ el.removeAttribute('aria-current');
451
+ }
452
+ el.toggleAttribute(activeDataAttr, active);
453
+ });
454
+ }
455
+
456
+ /**
457
+ * Scroll the viewport only. Avoid `Element.scrollIntoView`, which walks
458
+ * ancestor scroll containers and can pull the whole docs page to an embedded
459
+ * carousel (e.g. autoplay ticking on `/docs/carousel`).
460
+ */
461
+ private _scrollToIndex(index: number, behavior: ScrollBehavior): void {
462
+ if (!this._viewport) return;
463
+ const slide = this._slides[index];
464
+ if (!slide) return;
465
+
466
+ this._programmaticScroll = true;
467
+ const vp = this._viewport;
468
+ const centered = this._getOption('centered') === true;
469
+ const slideRect = slide.getBoundingClientRect();
470
+ const vpRect = vp.getBoundingClientRect();
471
+ let left = vp.scrollLeft + slideRect.left - vpRect.left;
472
+ if (centered) {
473
+ left -= (vp.clientWidth - slideRect.width) / 2;
474
+ }
475
+ const maxScroll = Math.max(0, vp.scrollWidth - vp.clientWidth);
476
+ left = Math.max(0, Math.min(left, maxScroll));
477
+
478
+ try {
479
+ vp.scrollTo({ left, top: vp.scrollTop, behavior });
480
+ } catch {
481
+ vp.scrollLeft = left;
482
+ }
483
+
484
+ queueMicrotask(() => {
485
+ if (
486
+ this._programmaticScroll &&
487
+ this._programmaticScrollTargetIndex !== null &&
488
+ this._nearestIndex() === this._programmaticScrollTargetIndex
489
+ ) {
490
+ this._completeProgrammaticScroll();
491
+ }
492
+ });
493
+
494
+ this._clearProgrammaticScrollFallbackTimer();
495
+ const fallbackMs = behavior === 'smooth' ? 550 : 50;
496
+ this._programmaticScrollFallbackTimer = setTimeout(() => {
497
+ this._programmaticScrollFallbackTimer = null;
498
+ this._completeProgrammaticScroll();
499
+ }, fallbackMs);
500
+ }
501
+
502
+ private _clearProgrammaticScrollFallbackTimer(): void {
503
+ if (this._programmaticScrollFallbackTimer !== null) {
504
+ clearTimeout(this._programmaticScrollFallbackTimer);
505
+ this._programmaticScrollFallbackTimer = null;
506
+ }
507
+ }
508
+
509
+ private _completeProgrammaticScroll(): void {
510
+ if (!this._programmaticScroll) return;
511
+ const prev = this._programmaticScrollPrevIndex;
512
+ const targetIdx = this._programmaticScrollTargetIndex;
513
+ const userInitiated = this._programmaticScrollUserInitiated;
514
+ if (prev === null || targetIdx === null) {
515
+ this._programmaticScroll = false;
516
+ this._programmaticScrollPrevIndex = null;
517
+ this._programmaticScrollTargetIndex = null;
518
+ return;
519
+ }
520
+
521
+ if (this._scrollSyncRaf) {
522
+ cancelAnimationFrame(this._scrollSyncRaf);
523
+ this._scrollSyncRaf = 0;
524
+ }
525
+ this._clearProgrammaticScrollFallbackTimer();
526
+
527
+ this._programmaticScroll = false;
528
+ this._programmaticScrollPrevIndex = null;
529
+ this._programmaticScrollTargetIndex = null;
530
+ this._programmaticScrollUserInitiated = false;
531
+
532
+ this._index = targetIdx;
533
+ this._updateInfo();
534
+ this._updatePaginationState();
535
+ this._updateThumbState(true);
536
+ this._applyAutoHeight();
537
+ this._observeActiveSlideForHeight();
538
+ this._dispatchChange(targetIdx, prev, userInitiated);
539
+ }
540
+
541
+ public goTo(index: number, userInitiated = false): void {
542
+ if (this._slides.length === 0) return;
543
+ const n = this._slides.length;
544
+ let target = index;
545
+ if (target < 0) target = 0;
546
+ if (target >= n) target = n - 1;
547
+
548
+ const prev = this._index;
549
+ if (target === prev) return;
550
+
551
+ this._clearProgrammaticScrollFallbackTimer();
552
+ this._programmaticScrollPrevIndex = prev;
553
+ this._programmaticScrollTargetIndex = target;
554
+ this._programmaticScrollUserInitiated = userInitiated;
555
+ this._scrollToIndex(target, this._scrollBehavior());
556
+ }
557
+
558
+ public next(userInitiated = false): void {
559
+ if (this._slides.length === 0) return;
560
+ const n = this._slides.length;
561
+ const last = n - 1;
562
+ const infinite = this._getOption('infiniteLoop') === true;
563
+
564
+ if (this._index >= last) {
565
+ if (infinite) {
566
+ this.goTo(0, userInitiated);
567
+ return;
568
+ }
569
+ return;
570
+ }
571
+ this.goTo(this._index + 1, userInitiated);
572
+ }
573
+
574
+ public prev(userInitiated = false): void {
575
+ if (this._slides.length === 0) return;
576
+ const infinite = this._getOption('infiniteLoop') === true;
577
+
578
+ if (this._index <= 0) {
579
+ if (infinite) {
580
+ this.goTo(this._slides.length - 1, userInitiated);
581
+ return;
582
+ }
583
+ return;
584
+ }
585
+ this.goTo(this._index - 1, userInitiated);
586
+ }
587
+
588
+ public getIndex(): number {
589
+ return this._index;
590
+ }
591
+
592
+ public getSlideCount(): number {
593
+ return this._slides.length;
594
+ }
595
+
596
+ private _getChangeEventName(): string {
597
+ const name = this._getOption('changeEvent');
598
+ return typeof name === 'string' && name.length > 0
599
+ ? name
600
+ : 'kt.carousel.change';
601
+ }
602
+
603
+ private _dispatchChange(
604
+ index: number,
605
+ prevIndex: number,
606
+ userInitiated: boolean,
607
+ ): void {
608
+ if (!this._element) return;
609
+ const payload: KTCarouselChangePayloadInterface = {
610
+ index,
611
+ prevIndex,
612
+ userInitiated,
613
+ };
614
+ const eventName = this._getChangeEventName();
615
+ this._fireEvent(eventName, payload);
616
+ this._dispatchEvent(eventName, payload);
617
+ }
618
+
619
+ private _updateInfo(): void {
620
+ if (!this._element) return;
621
+ const total = this._slides.length;
622
+ const cur = total === 0 ? 0 : this._index + 1;
623
+ const curStr = String(cur);
624
+ const totalStr = String(total);
625
+
626
+ this._currentLabels.forEach((label) => {
627
+ label.textContent = curStr;
628
+ });
629
+ this._totalLabels.forEach((label) => {
630
+ label.textContent = totalStr;
631
+ });
632
+ }
633
+
634
+ private _updatePaginationState(): void {
635
+ this._setStripItemsActiveState(
636
+ this._paginationHandlers,
637
+ 'data-kt-carousel-pagination-active',
638
+ );
639
+ }
640
+
641
+ private _updateThumbState(alignStripSmooth: boolean): void {
642
+ this._setStripItemsActiveState(
643
+ this._thumbHandlers,
644
+ 'data-kt-carousel-thumbnail-active',
645
+ );
646
+ this._scrollActiveThumbnailsIntoView(
647
+ alignStripSmooth ? this._scrollBehavior() : 'auto',
648
+ );
649
+ }
650
+
651
+ /**
652
+ * Keep the active thumb visible inside each thumbnail strip by scrolling
653
+ * that container only (no `scrollIntoView`, which can scroll ancestor pages).
654
+ */
655
+ private _scrollActiveThumbnailsIntoView(behavior: ScrollBehavior): void {
656
+ if (!this._element) return;
657
+ const pad = 6;
658
+ this._element
659
+ .querySelectorAll<HTMLElement>(SELECTOR_THUMBS)
660
+ .forEach((strip) => {
661
+ const items = strip.querySelectorAll<HTMLElement>(SELECTOR_THUMB);
662
+ const thumb = items[this._index];
663
+ if (!thumb) return;
664
+ this._alignElementInScrollContainer(thumb, strip, pad, behavior);
665
+ });
666
+ }
667
+
668
+ private _alignElementInScrollContainer(
669
+ el: HTMLElement,
670
+ container: HTMLElement,
671
+ pad: number,
672
+ behavior: ScrollBehavior,
673
+ ): void {
674
+ const c = container.getBoundingClientRect();
675
+ const r = el.getBoundingClientRect();
676
+ let left = container.scrollLeft;
677
+ let top = container.scrollTop;
678
+
679
+ if (container.scrollWidth > container.clientWidth + 1) {
680
+ if (r.left < c.left + pad) {
681
+ left += r.left - c.left - pad;
682
+ } else if (r.right > c.right - pad) {
683
+ left += r.right - c.right + pad;
684
+ }
685
+ const maxL = Math.max(0, container.scrollWidth - container.clientWidth);
686
+ left = Math.max(0, Math.min(left, maxL));
687
+ }
688
+
689
+ if (container.scrollHeight > container.clientHeight + 1) {
690
+ if (r.top < c.top + pad) {
691
+ top += r.top - c.top - pad;
692
+ } else if (r.bottom > c.bottom - pad) {
693
+ top += r.bottom - c.bottom + pad;
694
+ }
695
+ const maxT = Math.max(0, container.scrollHeight - container.clientHeight);
696
+ top = Math.max(0, Math.min(top, maxT));
697
+ }
698
+
699
+ try {
700
+ container.scrollTo({ left, top, behavior });
701
+ } catch {
702
+ container.scrollLeft = left;
703
+ container.scrollTop = top;
704
+ }
705
+ }
706
+
707
+ private _startAutoplay(): void {
708
+ this._stopAutoplay();
709
+ if (this._getOption('autoplay') !== true) return;
710
+ if (this._prefersReducedMotion) return;
711
+ if (this._slides.length <= 1) return;
712
+
713
+ const raw = this._getOption('autoplayInterval');
714
+ const interval = typeof raw === 'number' && raw >= 200 ? raw : 4000;
715
+
716
+ this._autoplayTimer = setInterval(() => {
717
+ this.next(false);
718
+ }, interval);
719
+ }
720
+
721
+ private _stopAutoplay(): void {
722
+ if (this._autoplayTimer !== null) {
723
+ clearInterval(this._autoplayTimer);
724
+ this._autoplayTimer = null;
725
+ }
726
+ }
727
+
728
+ public override dispose(): void {
729
+ this._stopAutoplay();
730
+ this._clearProgrammaticScrollFallbackTimer();
731
+ if (this._scrollSyncRaf) {
732
+ cancelAnimationFrame(this._scrollSyncRaf);
733
+ this._scrollSyncRaf = 0;
734
+ }
735
+ this._programmaticScroll = false;
736
+ this._programmaticScrollPrevIndex = null;
737
+ this._programmaticScrollTargetIndex = null;
738
+
739
+ if (this._resizeObserver) {
740
+ this._resizeObserver.disconnect();
741
+ this._resizeObserver = null;
742
+ }
743
+
744
+ if (this._element) {
745
+ if (this._onPrevClick) {
746
+ this._prevButtons.forEach((btn) =>
747
+ btn.removeEventListener('click', this._onPrevClick!),
748
+ );
749
+ }
750
+ if (this._onNextClick) {
751
+ this._nextButtons.forEach((btn) =>
752
+ btn.removeEventListener('click', this._onNextClick!),
753
+ );
754
+ }
755
+ this._paginationHandlers.forEach(({ el, fn }) => {
756
+ el.removeEventListener('click', fn);
757
+ });
758
+ this._paginationHandlers = [];
759
+ this._thumbHandlers.forEach(({ el, fn }) => {
760
+ el.removeEventListener('click', fn);
761
+ });
762
+ this._thumbHandlers = [];
763
+
764
+ if (this._onKeyDown) {
765
+ this._element.removeEventListener('keydown', this._onKeyDown);
766
+ }
767
+ if (this._pauseAutoplay && this._resumeAutoplay) {
768
+ this._element.removeEventListener('mouseenter', this._pauseAutoplay);
769
+ this._element.removeEventListener('mouseleave', this._resumeAutoplay);
770
+ this._element.removeEventListener('focusin', this._pauseAutoplay);
771
+ this._element.removeEventListener('focusout', this._resumeAutoplay);
772
+ }
773
+ this._pauseAutoplay = null;
774
+ this._resumeAutoplay = null;
775
+ }
776
+
777
+ if (this._viewport && this._onScroll) {
778
+ this._viewport.removeEventListener('scroll', this._onScroll);
779
+ }
780
+ if (this._viewport && this._onScrollEnd) {
781
+ this._viewport.removeEventListener('scrollend', this._onScrollEnd);
782
+ }
783
+ if (this._viewport && this._onPointerDown) {
784
+ this._viewport.removeEventListener('pointerdown', this._onPointerDown);
785
+ this._viewport.removeEventListener('pointermove', this._onPointerMove!);
786
+ this._viewport.removeEventListener('pointerup', this._onPointerUp!);
787
+ this._viewport.removeEventListener('pointercancel', this._onPointerUp!);
788
+ }
789
+
790
+ if (this._viewport && this._getOption('autoHeight') === true) {
791
+ this._viewport.style.height = '';
792
+ }
793
+
794
+ this._onPrevClick = null;
795
+ this._onNextClick = null;
796
+ this._onScroll = null;
797
+ this._onScrollEnd = null;
798
+ this._onKeyDown = null;
799
+ this._onPointerDown = null;
800
+ this._onPointerMove = null;
801
+ this._onPointerUp = null;
802
+
803
+ this._prevButtons = [];
804
+ this._nextButtons = [];
805
+ this._currentLabels = [];
806
+ this._totalLabels = [];
807
+
808
+ super.dispose();
809
+ }
810
+
811
+ public static getInstance(element: HTMLElement): KTCarousel | null {
812
+ if (!element) return null;
813
+ if (KTData.has(element, 'carousel')) {
814
+ return KTData.get(element, 'carousel') as KTCarousel;
815
+ }
816
+ return null;
817
+ }
818
+
819
+ public static getOrCreateInstance(
820
+ element: HTMLElement,
821
+ config?: Partial<KTCarouselConfigInterface>,
822
+ ): KTCarousel | null {
823
+ const existing = this.getInstance(element);
824
+ if (existing) return existing;
825
+ new KTCarousel(element, config ?? undefined);
826
+ return this.getInstance(element);
827
+ }
828
+
829
+ public static createInstances(): void {
830
+ document
831
+ .querySelectorAll<HTMLElement>('[data-kt-carousel]')
832
+ .forEach((el) => {
833
+ if (el.getAttribute('data-kt-carousel-lazy') === 'true') {
834
+ return;
835
+ }
836
+ new KTCarousel(el);
837
+ });
838
+ }
839
+
840
+ public static init(): void {
841
+ KTCarousel.createInstances();
842
+ }
843
+ }
844
+
845
+ if (typeof window !== 'undefined') {
846
+ window.KTCarousel = KTCarousel;
847
+ }