cats-data-grid 0.0.2 → 0.0.5

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 (354) hide show
  1. package/README.md +63 -63
  2. package/ng-package.json +20 -0
  3. package/package.json +5 -16
  4. package/src/lib/assets/images/check-white.svg +3 -0
  5. package/src/lib/assets/images/filter-icon.svg +1 -0
  6. package/src/lib/assets/images/gripper.svg +8 -0
  7. package/src/lib/assets/images/minus-blue.svg +3 -0
  8. package/src/lib/assets/images/pin.svg +4 -0
  9. package/src/lib/assets/images/t-arrow-down.svg +4 -0
  10. package/src/lib/assets/images/t-arrow-up.svg +4 -0
  11. package/src/lib/assets/images/t-choose-column.svg +3 -0
  12. package/src/lib/assets/images/t-data-pipeline.svg +13 -0
  13. package/src/lib/assets/images/t-filter-applied.svg +4 -0
  14. package/src/lib/assets/images/t-filter.svg +3 -0
  15. package/src/lib/assets/images/t-gripper.svg +8 -0
  16. package/src/lib/assets/images/t-group-by-name.svg +3 -0
  17. package/src/lib/assets/images/t-more-vertical.svg +5 -0
  18. package/src/lib/assets/images/t-move.svg +15 -0
  19. package/src/lib/assets/images/t-x.svg +4 -0
  20. package/src/lib/cats-data-grid.component.html +1389 -0
  21. package/src/lib/cats-data-grid.component.scss +736 -0
  22. package/src/lib/cats-data-grid.component.ts +1756 -0
  23. package/src/lib/common-components/common-calendar/common-calendar.component.html +228 -0
  24. package/src/lib/common-components/common-calendar/common-calendar.component.scss +279 -0
  25. package/src/lib/common-components/common-calendar/common-calendar.component.spec.ts +23 -0
  26. package/src/lib/common-components/common-calendar/common-calendar.component.ts +606 -0
  27. package/src/lib/common-components/common-input/common-input.component.html +36 -0
  28. package/src/lib/common-components/common-input/common-input.component.scss +3 -0
  29. package/src/lib/common-components/common-input/common-input.component.spec.ts +23 -0
  30. package/src/lib/common-components/common-input/common-input.component.ts +51 -0
  31. package/src/lib/directives/adaptive-position.directive.ts +192 -0
  32. package/src/lib/directives/outside-click.directive.ts +32 -0
  33. package/src/lib/directives/renderer-parser.directive.ts +51 -0
  34. package/src/lib/pipes/add-class.pipe.ts +18 -0
  35. package/src/lib/renderers/common-renderer/common-renderer.component.html +129 -0
  36. package/src/lib/renderers/common-renderer/common-renderer.component.scss +256 -0
  37. package/src/lib/renderers/common-renderer/common-renderer.component.spec.ts +23 -0
  38. package/src/lib/renderers/common-renderer/common-renderer.component.ts +302 -0
  39. package/src/lib/services/cats-data-grid.service.spec.ts +16 -0
  40. package/src/lib/services/cats-data-grid.service.ts +9 -0
  41. package/{styles → src/lib/styles}/_index.scss +3 -3
  42. package/{styles → src/lib/styles}/base/_fonts.scss +74 -74
  43. package/{styles → src/lib/styles}/base/_index.scss +1 -1
  44. package/{styles → src/lib/styles}/base/_reset.scss +60 -60
  45. package/src/lib/styles/component/_form.scss +371 -0
  46. package/{styles → src/lib/styles}/component/_index.scss +1 -1
  47. package/{styles → src/lib/styles}/sass-utils/_function.scss +14 -14
  48. package/{styles → src/lib/styles}/sass-utils/_index.scss +3 -3
  49. package/{styles → src/lib/styles}/sass-utils/_mixin.scss +87 -56
  50. package/src/lib/styles/sass-utils/_variable.scss +77 -0
  51. package/src/public-api.ts +7 -0
  52. package/tsconfig.lib.json +15 -0
  53. package/tsconfig.lib.prod.json +11 -0
  54. package/tsconfig.spec.json +15 -0
  55. package/fesm2022/cats-data-grid.mjs +0 -530
  56. package/fesm2022/cats-data-grid.mjs.map +0 -1
  57. package/index.d.ts +0 -5
  58. package/lib/cats-data-grid.component.d.ts +0 -148
  59. package/lib/directives/outside-click.directive.d.ts +0 -10
  60. package/lib/directives/renderer-parser.directive.d.ts +0 -15
  61. package/lib/pipes/add-class.pipe.d.ts +0 -7
  62. package/lib/services/cats-data-grid.service.d.ts +0 -6
  63. package/public-api.d.ts +0 -2
  64. package/styles/component/_form.scss +0 -246
  65. package/styles/sass-utils/_variable.scss +0 -66
  66. /package/{assets → src/lib/assets}/images/activity.svg +0 -0
  67. /package/{assets → src/lib/assets}/images/airplay.svg +0 -0
  68. /package/{assets → src/lib/assets}/images/alert-circle.svg +0 -0
  69. /package/{assets → src/lib/assets}/images/alert-octagon.svg +0 -0
  70. /package/{assets → src/lib/assets}/images/alert-triangle.svg +0 -0
  71. /package/{assets → src/lib/assets}/images/align-center.svg +0 -0
  72. /package/{assets → src/lib/assets}/images/align-justify.svg +0 -0
  73. /package/{assets → src/lib/assets}/images/align-left.svg +0 -0
  74. /package/{assets → src/lib/assets}/images/align-right.svg +0 -0
  75. /package/{assets → src/lib/assets}/images/anchor.svg +0 -0
  76. /package/{assets → src/lib/assets}/images/aperture.svg +0 -0
  77. /package/{assets → src/lib/assets}/images/archive.svg +0 -0
  78. /package/{assets → src/lib/assets}/images/arrow-down-circle.svg +0 -0
  79. /package/{assets → src/lib/assets}/images/arrow-down-left.svg +0 -0
  80. /package/{assets → src/lib/assets}/images/arrow-down-right.svg +0 -0
  81. /package/{assets → src/lib/assets}/images/arrow-down.svg +0 -0
  82. /package/{assets → src/lib/assets}/images/arrow-left-circle.svg +0 -0
  83. /package/{assets → src/lib/assets}/images/arrow-left.svg +0 -0
  84. /package/{assets → src/lib/assets}/images/arrow-right-circle.svg +0 -0
  85. /package/{assets → src/lib/assets}/images/arrow-right.svg +0 -0
  86. /package/{assets → src/lib/assets}/images/arrow-up-circle.svg +0 -0
  87. /package/{assets → src/lib/assets}/images/arrow-up-left.svg +0 -0
  88. /package/{assets → src/lib/assets}/images/arrow-up-right.svg +0 -0
  89. /package/{assets → src/lib/assets}/images/arrow-up.svg +0 -0
  90. /package/{assets → src/lib/assets}/images/at-sign.svg +0 -0
  91. /package/{assets → src/lib/assets}/images/award.svg +0 -0
  92. /package/{assets → src/lib/assets}/images/bar-chart-2.svg +0 -0
  93. /package/{assets → src/lib/assets}/images/bar-chart.svg +0 -0
  94. /package/{assets → src/lib/assets}/images/battery-charging.svg +0 -0
  95. /package/{assets → src/lib/assets}/images/battery.svg +0 -0
  96. /package/{assets → src/lib/assets}/images/bell-off.svg +0 -0
  97. /package/{assets → src/lib/assets}/images/bell.svg +0 -0
  98. /package/{assets → src/lib/assets}/images/bluetooth.svg +0 -0
  99. /package/{assets → src/lib/assets}/images/bold.svg +0 -0
  100. /package/{assets → src/lib/assets}/images/book-open.svg +0 -0
  101. /package/{assets → src/lib/assets}/images/book.svg +0 -0
  102. /package/{assets → src/lib/assets}/images/bookmark.svg +0 -0
  103. /package/{assets → src/lib/assets}/images/box.svg +0 -0
  104. /package/{assets → src/lib/assets}/images/briefcase.svg +0 -0
  105. /package/{assets → src/lib/assets}/images/calendar.svg +0 -0
  106. /package/{assets → src/lib/assets}/images/camera-off.svg +0 -0
  107. /package/{assets → src/lib/assets}/images/camera.svg +0 -0
  108. /package/{assets → src/lib/assets}/images/cast.svg +0 -0
  109. /package/{assets → src/lib/assets}/images/check-circle.svg +0 -0
  110. /package/{assets → src/lib/assets}/images/check-square.svg +0 -0
  111. /package/{assets → src/lib/assets}/images/check.svg +0 -0
  112. /package/{assets → src/lib/assets}/images/chevron-down.svg +0 -0
  113. /package/{assets → src/lib/assets}/images/chevron-left.svg +0 -0
  114. /package/{assets → src/lib/assets}/images/chevron-right.svg +0 -0
  115. /package/{assets → src/lib/assets}/images/chevron-up.svg +0 -0
  116. /package/{assets → src/lib/assets}/images/chevrons-down.svg +0 -0
  117. /package/{assets → src/lib/assets}/images/chevrons-left.svg +0 -0
  118. /package/{assets → src/lib/assets}/images/chevrons-right.svg +0 -0
  119. /package/{assets → src/lib/assets}/images/chevrons-up.svg +0 -0
  120. /package/{assets → src/lib/assets}/images/chrome.svg +0 -0
  121. /package/{assets → src/lib/assets}/images/circle.svg +0 -0
  122. /package/{assets → src/lib/assets}/images/clipboard.svg +0 -0
  123. /package/{assets → src/lib/assets}/images/clock.svg +0 -0
  124. /package/{assets → src/lib/assets}/images/cloud-drizzle.svg +0 -0
  125. /package/{assets → src/lib/assets}/images/cloud-lightning.svg +0 -0
  126. /package/{assets → src/lib/assets}/images/cloud-off.svg +0 -0
  127. /package/{assets → src/lib/assets}/images/cloud-rain.svg +0 -0
  128. /package/{assets → src/lib/assets}/images/cloud-snow.svg +0 -0
  129. /package/{assets → src/lib/assets}/images/cloud.svg +0 -0
  130. /package/{assets → src/lib/assets}/images/code.svg +0 -0
  131. /package/{assets → src/lib/assets}/images/codepen.svg +0 -0
  132. /package/{assets → src/lib/assets}/images/codesandbox.svg +0 -0
  133. /package/{assets → src/lib/assets}/images/coffee.svg +0 -0
  134. /package/{assets → src/lib/assets}/images/columns.svg +0 -0
  135. /package/{assets → src/lib/assets}/images/command.svg +0 -0
  136. /package/{assets → src/lib/assets}/images/compass.svg +0 -0
  137. /package/{assets → src/lib/assets}/images/copy.svg +0 -0
  138. /package/{assets → src/lib/assets}/images/corner-down-left.svg +0 -0
  139. /package/{assets → src/lib/assets}/images/corner-down-right.svg +0 -0
  140. /package/{assets → src/lib/assets}/images/corner-left-down.svg +0 -0
  141. /package/{assets → src/lib/assets}/images/corner-left-up.svg +0 -0
  142. /package/{assets → src/lib/assets}/images/corner-right-down.svg +0 -0
  143. /package/{assets → src/lib/assets}/images/corner-right-up.svg +0 -0
  144. /package/{assets → src/lib/assets}/images/corner-up-left.svg +0 -0
  145. /package/{assets → src/lib/assets}/images/corner-up-right.svg +0 -0
  146. /package/{assets → src/lib/assets}/images/cpu.svg +0 -0
  147. /package/{assets → src/lib/assets}/images/credit-card.svg +0 -0
  148. /package/{assets → src/lib/assets}/images/crop.svg +0 -0
  149. /package/{assets → src/lib/assets}/images/crosshair.svg +0 -0
  150. /package/{assets → src/lib/assets}/images/database.svg +0 -0
  151. /package/{assets → src/lib/assets}/images/delete.svg +0 -0
  152. /package/{assets → src/lib/assets}/images/disc.svg +0 -0
  153. /package/{assets → src/lib/assets}/images/divide-circle.svg +0 -0
  154. /package/{assets → src/lib/assets}/images/divide-square.svg +0 -0
  155. /package/{assets → src/lib/assets}/images/divide.svg +0 -0
  156. /package/{assets → src/lib/assets}/images/dollar-sign.svg +0 -0
  157. /package/{assets → src/lib/assets}/images/download-cloud.svg +0 -0
  158. /package/{assets → src/lib/assets}/images/download.svg +0 -0
  159. /package/{assets → src/lib/assets}/images/dribbble.svg +0 -0
  160. /package/{assets → src/lib/assets}/images/droplet.svg +0 -0
  161. /package/{assets → src/lib/assets}/images/edit-2.svg +0 -0
  162. /package/{assets → src/lib/assets}/images/edit-3.svg +0 -0
  163. /package/{assets → src/lib/assets}/images/edit.svg +0 -0
  164. /package/{assets → src/lib/assets}/images/external-link.svg +0 -0
  165. /package/{assets → src/lib/assets}/images/eye-off.svg +0 -0
  166. /package/{assets → src/lib/assets}/images/eye.svg +0 -0
  167. /package/{assets → src/lib/assets}/images/facebook.svg +0 -0
  168. /package/{assets → src/lib/assets}/images/fast-forward.svg +0 -0
  169. /package/{assets → src/lib/assets}/images/feather.svg +0 -0
  170. /package/{assets → src/lib/assets}/images/figma.svg +0 -0
  171. /package/{assets → src/lib/assets}/images/file-minus.svg +0 -0
  172. /package/{assets → src/lib/assets}/images/file-plus.svg +0 -0
  173. /package/{assets → src/lib/assets}/images/file-text.svg +0 -0
  174. /package/{assets → src/lib/assets}/images/file.svg +0 -0
  175. /package/{assets → src/lib/assets}/images/film.svg +0 -0
  176. /package/{assets → src/lib/assets}/images/filter.svg +0 -0
  177. /package/{assets → src/lib/assets}/images/flag.svg +0 -0
  178. /package/{assets → src/lib/assets}/images/folder-minus.svg +0 -0
  179. /package/{assets → src/lib/assets}/images/folder-plus.svg +0 -0
  180. /package/{assets → src/lib/assets}/images/folder.svg +0 -0
  181. /package/{assets → src/lib/assets}/images/framer.svg +0 -0
  182. /package/{assets → src/lib/assets}/images/frown.svg +0 -0
  183. /package/{assets → src/lib/assets}/images/gift.svg +0 -0
  184. /package/{assets → src/lib/assets}/images/git-branch.svg +0 -0
  185. /package/{assets → src/lib/assets}/images/git-commit.svg +0 -0
  186. /package/{assets → src/lib/assets}/images/git-merge.svg +0 -0
  187. /package/{assets → src/lib/assets}/images/git-pull-request.svg +0 -0
  188. /package/{assets → src/lib/assets}/images/github.svg +0 -0
  189. /package/{assets → src/lib/assets}/images/gitlab.svg +0 -0
  190. /package/{assets → src/lib/assets}/images/globe.svg +0 -0
  191. /package/{assets → src/lib/assets}/images/grid.svg +0 -0
  192. /package/{assets → src/lib/assets}/images/hard-drive.svg +0 -0
  193. /package/{assets → src/lib/assets}/images/hash.svg +0 -0
  194. /package/{assets → src/lib/assets}/images/headphones.svg +0 -0
  195. /package/{assets → src/lib/assets}/images/heart.svg +0 -0
  196. /package/{assets → src/lib/assets}/images/help-circle.svg +0 -0
  197. /package/{assets → src/lib/assets}/images/hexagon.svg +0 -0
  198. /package/{assets → src/lib/assets}/images/home.svg +0 -0
  199. /package/{assets → src/lib/assets}/images/image.svg +0 -0
  200. /package/{assets → src/lib/assets}/images/inbox.svg +0 -0
  201. /package/{assets → src/lib/assets}/images/info.svg +0 -0
  202. /package/{assets → src/lib/assets}/images/instagram.svg +0 -0
  203. /package/{assets → src/lib/assets}/images/italic.svg +0 -0
  204. /package/{assets → src/lib/assets}/images/key.svg +0 -0
  205. /package/{assets → src/lib/assets}/images/layers.svg +0 -0
  206. /package/{assets → src/lib/assets}/images/layout.svg +0 -0
  207. /package/{assets → src/lib/assets}/images/life-buoy.svg +0 -0
  208. /package/{assets → src/lib/assets}/images/link-2.svg +0 -0
  209. /package/{assets → src/lib/assets}/images/link.svg +0 -0
  210. /package/{assets → src/lib/assets}/images/linkedin.svg +0 -0
  211. /package/{assets → src/lib/assets}/images/list.svg +0 -0
  212. /package/{assets → src/lib/assets}/images/loader.svg +0 -0
  213. /package/{assets → src/lib/assets}/images/lock.svg +0 -0
  214. /package/{assets → src/lib/assets}/images/log-in.svg +0 -0
  215. /package/{assets → src/lib/assets}/images/log-out.svg +0 -0
  216. /package/{assets → src/lib/assets}/images/mail.svg +0 -0
  217. /package/{assets → src/lib/assets}/images/map-pin.svg +0 -0
  218. /package/{assets → src/lib/assets}/images/map.svg +0 -0
  219. /package/{assets → src/lib/assets}/images/maximize-2.svg +0 -0
  220. /package/{assets → src/lib/assets}/images/maximize.svg +0 -0
  221. /package/{assets → src/lib/assets}/images/meh.svg +0 -0
  222. /package/{assets → src/lib/assets}/images/menu.svg +0 -0
  223. /package/{assets → src/lib/assets}/images/message-circle.svg +0 -0
  224. /package/{assets → src/lib/assets}/images/message-square.svg +0 -0
  225. /package/{assets → src/lib/assets}/images/mic-off.svg +0 -0
  226. /package/{assets → src/lib/assets}/images/mic.svg +0 -0
  227. /package/{assets → src/lib/assets}/images/minimize-2.svg +0 -0
  228. /package/{assets → src/lib/assets}/images/minimize.svg +0 -0
  229. /package/{assets → src/lib/assets}/images/minus-circle.svg +0 -0
  230. /package/{assets → src/lib/assets}/images/minus-square.svg +0 -0
  231. /package/{assets → src/lib/assets}/images/minus.svg +0 -0
  232. /package/{assets → src/lib/assets}/images/monitor.svg +0 -0
  233. /package/{assets → src/lib/assets}/images/moon.svg +0 -0
  234. /package/{assets → src/lib/assets}/images/more-horizontal.svg +0 -0
  235. /package/{assets → src/lib/assets}/images/more-vertical.svg +0 -0
  236. /package/{assets → src/lib/assets}/images/mouse-pointer.svg +0 -0
  237. /package/{assets → src/lib/assets}/images/move.svg +0 -0
  238. /package/{assets → src/lib/assets}/images/music.svg +0 -0
  239. /package/{assets → src/lib/assets}/images/navigation-2.svg +0 -0
  240. /package/{assets → src/lib/assets}/images/navigation.svg +0 -0
  241. /package/{assets → src/lib/assets}/images/octagon.svg +0 -0
  242. /package/{assets → src/lib/assets}/images/package.svg +0 -0
  243. /package/{assets → src/lib/assets}/images/paperclip.svg +0 -0
  244. /package/{assets → src/lib/assets}/images/pause-circle.svg +0 -0
  245. /package/{assets → src/lib/assets}/images/pause.svg +0 -0
  246. /package/{assets → src/lib/assets}/images/pen-tool.svg +0 -0
  247. /package/{assets → src/lib/assets}/images/percent.svg +0 -0
  248. /package/{assets → src/lib/assets}/images/phone-call.svg +0 -0
  249. /package/{assets → src/lib/assets}/images/phone-forwarded.svg +0 -0
  250. /package/{assets → src/lib/assets}/images/phone-incoming.svg +0 -0
  251. /package/{assets → src/lib/assets}/images/phone-missed.svg +0 -0
  252. /package/{assets → src/lib/assets}/images/phone-off.svg +0 -0
  253. /package/{assets → src/lib/assets}/images/phone-outgoing.svg +0 -0
  254. /package/{assets → src/lib/assets}/images/phone.svg +0 -0
  255. /package/{assets → src/lib/assets}/images/pie-chart.svg +0 -0
  256. /package/{assets → src/lib/assets}/images/play-circle.svg +0 -0
  257. /package/{assets → src/lib/assets}/images/play.svg +0 -0
  258. /package/{assets → src/lib/assets}/images/plus-circle.svg +0 -0
  259. /package/{assets → src/lib/assets}/images/plus-square.svg +0 -0
  260. /package/{assets → src/lib/assets}/images/plus.svg +0 -0
  261. /package/{assets → src/lib/assets}/images/pocket.svg +0 -0
  262. /package/{assets → src/lib/assets}/images/power.svg +0 -0
  263. /package/{assets → src/lib/assets}/images/printer.svg +0 -0
  264. /package/{assets → src/lib/assets}/images/radio.svg +0 -0
  265. /package/{assets → src/lib/assets}/images/refresh-ccw.svg +0 -0
  266. /package/{assets → src/lib/assets}/images/refresh-cw.svg +0 -0
  267. /package/{assets → src/lib/assets}/images/repeat.svg +0 -0
  268. /package/{assets → src/lib/assets}/images/rewind.svg +0 -0
  269. /package/{assets → src/lib/assets}/images/rotate-ccw.svg +0 -0
  270. /package/{assets → src/lib/assets}/images/rotate-cw.svg +0 -0
  271. /package/{assets → src/lib/assets}/images/rss.svg +0 -0
  272. /package/{assets → src/lib/assets}/images/save.svg +0 -0
  273. /package/{assets → src/lib/assets}/images/scissors.svg +0 -0
  274. /package/{assets → src/lib/assets}/images/search.svg +0 -0
  275. /package/{assets → src/lib/assets}/images/send.svg +0 -0
  276. /package/{assets → src/lib/assets}/images/server.svg +0 -0
  277. /package/{assets → src/lib/assets}/images/settings.svg +0 -0
  278. /package/{assets → src/lib/assets}/images/share-2.svg +0 -0
  279. /package/{assets → src/lib/assets}/images/share.svg +0 -0
  280. /package/{assets → src/lib/assets}/images/shield-off.svg +0 -0
  281. /package/{assets → src/lib/assets}/images/shield.svg +0 -0
  282. /package/{assets → src/lib/assets}/images/shopping-bag.svg +0 -0
  283. /package/{assets → src/lib/assets}/images/shopping-cart.svg +0 -0
  284. /package/{assets → src/lib/assets}/images/shuffle.svg +0 -0
  285. /package/{assets → src/lib/assets}/images/sidebar.svg +0 -0
  286. /package/{assets → src/lib/assets}/images/skip-back.svg +0 -0
  287. /package/{assets → src/lib/assets}/images/skip-forward.svg +0 -0
  288. /package/{assets → src/lib/assets}/images/slack.svg +0 -0
  289. /package/{assets → src/lib/assets}/images/slash.svg +0 -0
  290. /package/{assets → src/lib/assets}/images/sliders.svg +0 -0
  291. /package/{assets → src/lib/assets}/images/smartphone.svg +0 -0
  292. /package/{assets → src/lib/assets}/images/smile.svg +0 -0
  293. /package/{assets → src/lib/assets}/images/sort_down.svg +0 -0
  294. /package/{assets → src/lib/assets}/images/sort_up.svg +0 -0
  295. /package/{assets → src/lib/assets}/images/speaker.svg +0 -0
  296. /package/{assets → src/lib/assets}/images/square.svg +0 -0
  297. /package/{assets → src/lib/assets}/images/star.svg +0 -0
  298. /package/{assets → src/lib/assets}/images/stop-circle.svg +0 -0
  299. /package/{assets → src/lib/assets}/images/sun.svg +0 -0
  300. /package/{assets → src/lib/assets}/images/sunrise.svg +0 -0
  301. /package/{assets → src/lib/assets}/images/sunset.svg +0 -0
  302. /package/{assets → src/lib/assets}/images/table.svg +0 -0
  303. /package/{assets → src/lib/assets}/images/tablet.svg +0 -0
  304. /package/{assets → src/lib/assets}/images/tag.svg +0 -0
  305. /package/{assets → src/lib/assets}/images/target.svg +0 -0
  306. /package/{assets → src/lib/assets}/images/terminal.svg +0 -0
  307. /package/{assets → src/lib/assets}/images/thermometer.svg +0 -0
  308. /package/{assets → src/lib/assets}/images/thumbs-down.svg +0 -0
  309. /package/{assets → src/lib/assets}/images/thumbs-up.svg +0 -0
  310. /package/{assets → src/lib/assets}/images/toggle-left.svg +0 -0
  311. /package/{assets → src/lib/assets}/images/toggle-right.svg +0 -0
  312. /package/{assets → src/lib/assets}/images/tool.svg +0 -0
  313. /package/{assets → src/lib/assets}/images/trash-2.svg +0 -0
  314. /package/{assets → src/lib/assets}/images/trash.svg +0 -0
  315. /package/{assets → src/lib/assets}/images/trello.svg +0 -0
  316. /package/{assets → src/lib/assets}/images/trending-down.svg +0 -0
  317. /package/{assets → src/lib/assets}/images/trending-up.svg +0 -0
  318. /package/{assets → src/lib/assets}/images/triangle.svg +0 -0
  319. /package/{assets → src/lib/assets}/images/truck.svg +0 -0
  320. /package/{assets → src/lib/assets}/images/tv.svg +0 -0
  321. /package/{assets → src/lib/assets}/images/twitch.svg +0 -0
  322. /package/{assets → src/lib/assets}/images/twitter.svg +0 -0
  323. /package/{assets → src/lib/assets}/images/type.svg +0 -0
  324. /package/{assets → src/lib/assets}/images/umbrella.svg +0 -0
  325. /package/{assets → src/lib/assets}/images/underline.svg +0 -0
  326. /package/{assets → src/lib/assets}/images/unlock.svg +0 -0
  327. /package/{assets → src/lib/assets}/images/upload-cloud.svg +0 -0
  328. /package/{assets → src/lib/assets}/images/upload.svg +0 -0
  329. /package/{assets → src/lib/assets}/images/user-check.svg +0 -0
  330. /package/{assets → src/lib/assets}/images/user-minus.svg +0 -0
  331. /package/{assets → src/lib/assets}/images/user-plus.svg +0 -0
  332. /package/{assets → src/lib/assets}/images/user-x.svg +0 -0
  333. /package/{assets → src/lib/assets}/images/user.svg +0 -0
  334. /package/{assets → src/lib/assets}/images/users.svg +0 -0
  335. /package/{assets → src/lib/assets}/images/video-off.svg +0 -0
  336. /package/{assets → src/lib/assets}/images/video.svg +0 -0
  337. /package/{assets → src/lib/assets}/images/voicemail.svg +0 -0
  338. /package/{assets → src/lib/assets}/images/volume-1.svg +0 -0
  339. /package/{assets → src/lib/assets}/images/volume-2.svg +0 -0
  340. /package/{assets → src/lib/assets}/images/volume-x.svg +0 -0
  341. /package/{assets → src/lib/assets}/images/volume.svg +0 -0
  342. /package/{assets → src/lib/assets}/images/watch.svg +0 -0
  343. /package/{assets → src/lib/assets}/images/wifi-off.svg +0 -0
  344. /package/{assets → src/lib/assets}/images/wifi.svg +0 -0
  345. /package/{assets → src/lib/assets}/images/wind.svg +0 -0
  346. /package/{assets → src/lib/assets}/images/x-circle.svg +0 -0
  347. /package/{assets → src/lib/assets}/images/x-octagon.svg +0 -0
  348. /package/{assets → src/lib/assets}/images/x-square.svg +0 -0
  349. /package/{assets → src/lib/assets}/images/x.svg +0 -0
  350. /package/{assets → src/lib/assets}/images/youtube.svg +0 -0
  351. /package/{assets → src/lib/assets}/images/zap-off.svg +0 -0
  352. /package/{assets → src/lib/assets}/images/zap.svg +0 -0
  353. /package/{assets → src/lib/assets}/images/zoom-in.svg +0 -0
  354. /package/{assets → src/lib/assets}/images/zoom-out.svg +0 -0
@@ -0,0 +1,1756 @@
1
+ import { AddClassPipe } from './pipes/add-class.pipe';
2
+ import { CommonModule } from '@angular/common';
3
+ import {
4
+ ChangeDetectorRef,
5
+ Component,
6
+ ElementRef,
7
+ EventEmitter,
8
+ Input,
9
+ NgZone,
10
+ OnChanges,
11
+ OnInit,
12
+ Output,
13
+ Renderer2,
14
+ SimpleChanges,
15
+ ViewChild,
16
+ } from '@angular/core';
17
+ import { FormsModule } from '@angular/forms';
18
+ import { OutsideClickDirective } from './directives/outside-click.directive';
19
+ import { RendererParserDirective } from './directives/renderer-parser.directive';
20
+ import { CommonInputComponent } from './common-components/common-input/common-input.component';
21
+ import { AdaptivePositionDirective } from './directives/adaptive-position.directive';
22
+ import {
23
+ CommonCalendarComponent,
24
+ DateConfig,
25
+ } from './common-components/common-calendar/common-calendar.component';
26
+
27
+ export class ColDefs {
28
+ fieldName!: string;
29
+ headerName!: string;
30
+ width!: number;
31
+ minWidth!: number;
32
+ sortable: boolean = true;
33
+ filterable: boolean = true;
34
+ cellRenderer: any;
35
+ }
36
+
37
+ export interface ColumnFilter {
38
+ fieldName: string;
39
+ filterLogic: string;
40
+ filters: FilterCondition[];
41
+ }
42
+ export interface FilterCondition {
43
+ filterOperation: string;
44
+ filterValue: any;
45
+ }
46
+ @Component({
47
+ selector: 'cats-data-grid',
48
+ imports: [
49
+ CommonModule,
50
+ FormsModule,
51
+ CommonCalendarComponent,
52
+ OutsideClickDirective,
53
+ AdaptivePositionDirective,
54
+ RendererParserDirective,
55
+ AddClassPipe,
56
+ CommonInputComponent,
57
+ ],
58
+ templateUrl: './cats-data-grid.component.html',
59
+ styleUrls: ['./cats-data-grid.component.scss'],
60
+ })
61
+ export class CatsDataGridComponent implements OnChanges, OnInit {
62
+ @ViewChild('pinMenu') pinMenu!: ElementRef;
63
+ @ViewChild('colActionMenu') colActionMenu!: ElementRef;
64
+ @ViewChild('table') table!: ElementRef;
65
+ @Input() tableOptions: any;
66
+ @Input() totalRecords: number = 0;
67
+ @Input() sortingRequired = true;
68
+ @Input() checkBoxSelection = false;
69
+ @Input() checkboxSelectionType = 'multiple';
70
+ @Input() rowData: any[] = [];
71
+ @Input() colDefs: any[] = [];
72
+ @Input() paginationRequired = true;
73
+ @Input() selectedRowEmpty: boolean = false;
74
+ @Input() filterRequired: boolean = true;
75
+ @Input() threeDotsMenuRequired: boolean = true;
76
+ @Input() settingsRequired: boolean = false;
77
+ @Input() settingsClicked: boolean = false;
78
+ @Input() resetPage = true;
79
+ @Input() rowId: any = null;
80
+ showDropdown: boolean = false;
81
+
82
+ @Input() height: number = 400;
83
+ @Input() groupByRequired: boolean = false;
84
+ @Output() onPaginationChange = new EventEmitter();
85
+ @Output() onCheckboxSelection = new EventEmitter();
86
+ @Output() onScrollEmitter = new EventEmitter();
87
+ @Output() filter = new EventEmitter();
88
+ @Output() onHideSettings = new EventEmitter();
89
+
90
+ activeFilterIndex: number | null = null;
91
+ originalRowData: any[] = [];
92
+ activeAll = true;
93
+
94
+ pageDetails: any = {
95
+ pageSize: 20,
96
+ totalPages: 1,
97
+ currentPage: 1,
98
+ };
99
+ recordsToShow: any = {
100
+ min: 0,
101
+ max: 20,
102
+ };
103
+ sortingColumnIndex!: number;
104
+ sortingType: any = {};
105
+ selectedRow: any[] = [];
106
+
107
+ @Input() pageSizeList: number[] = [20, 50, 75, 100];
108
+ showPageSizeList: boolean = false;
109
+ dragOverIndex: null | number = null;
110
+ draggedIndex: null | number = null;
111
+ originalColDefs: any[] = [];
112
+ filteredRowData: any[] = [];
113
+ filteredData: any[] = [];
114
+ currentColumn: any;
115
+ currentIndex!: number;
116
+ menuVisible: boolean[] = [];
117
+ menuPosition: any[] = [];
118
+ activeFilters: Set<any> = new Set<any>();
119
+ resizingColumnIndex: number | null = null;
120
+ startX: number = 0;
121
+ startWidth: number = 0;
122
+ isResizing: boolean = false;
123
+ groupedResult: any[] = [];
124
+ showMoveIcon: any = {};
125
+ columnDraggable: any[] = [];
126
+ activeGroups: any[] = [];
127
+ groupBy: string[] = [];
128
+ @Input() groupByField: string = '';
129
+ dragGroupIndex: number | null = null;
130
+
131
+ dateConfig: DateConfig = {
132
+ selectionMode: 'single',
133
+ enableTime: false,
134
+ };
135
+
136
+ filterOptions = [
137
+ { label: 'Contains', value: 'contains' },
138
+ { label: 'Does Not Contain', value: 'doesNotContain' },
139
+ { label: 'Equals', value: 'equals' },
140
+ { label: 'Does Not Equal', value: 'doesNotEqual' },
141
+ { label: 'Starts With', value: 'startsWith' },
142
+ { label: 'Ends With', value: 'endsWith' },
143
+ ];
144
+
145
+ numberFilterOptions = [
146
+ { label: 'Equals', value: '=' },
147
+ { label: 'Greater Than', value: '>' },
148
+ { label: 'Less Than', value: '<' },
149
+ { label: 'Greater Than or Equal', value: '>=' },
150
+ { label: 'Less Than or Equal', value: '<=' },
151
+ ];
152
+ showPin: boolean = false;
153
+ pinActionClicked: any = {};
154
+ private removeMouseMove!: () => void;
155
+ private removeMouseUp!: () => void;
156
+ private rafId: number | null = null;
157
+ @Input() appliedFilters: ColumnFilter[] = [];
158
+ @Output() appliedFiltersEvent = new EventEmitter<ColumnFilter[]>();
159
+ @Output() activeGroupsEvent = new EventEmitter<any[]>();
160
+ @Input() dynamicGroupingFiltering: boolean = false;
161
+ atLeastOneColumnChecked: boolean = true;
162
+ draggedRowData: any = {};
163
+ firstCol: any;
164
+ isRowSelected: boolean = false;
165
+ constructor(
166
+ private renderer: Renderer2,
167
+ private zone: NgZone,
168
+ private cd: ChangeDetectorRef,
169
+ ) {}
170
+
171
+ ngOnInit(): void {
172
+ if (this.colDefs && this.colDefs.length > 0) {
173
+ this.firstCol = this.colDefs[0];
174
+ }
175
+ }
176
+
177
+ ngOnChanges(changes: SimpleChanges): void {
178
+ if (changes['colDefs']?.currentValue) {
179
+ this.resetPagination();
180
+ this.colDefs = this.getUpdatedColDefs(changes['colDefs']?.currentValue);
181
+ setTimeout(() => {
182
+ this.applyAllFilters();
183
+ });
184
+ setTimeout(() => {
185
+ this.applyAllFilters();
186
+ });
187
+ this.originalColDefs = [...this.colDefs];
188
+ }
189
+
190
+ if (changes['totalRecords']?.currentValue && this.resetPage) {
191
+ this.resetPagination();
192
+ } else {
193
+ this.setPageCount();
194
+ }
195
+ if (changes['rowData']?.currentValue) {
196
+ if (this.selectedRowEmpty) this.selectedRow = [];
197
+ this.rowData = changes['rowData']?.currentValue.map(
198
+ (row: any, i: number) => {
199
+ if (row[this.rowId]) {
200
+ row.rowId = row[this.rowId];
201
+ } else {
202
+ row.rowId = `${Date.now()}_${i}`;
203
+ }
204
+ if (row?.isSelected) [...this.selectedRow, row];
205
+ return row;
206
+ },
207
+ );
208
+
209
+ if (this.dynamicGroupingFiltering && this.groupBy.length > 0) {
210
+ this.groupedResult = structuredClone(this.rowData);
211
+ }
212
+ if (!this.activeFilters.size) {
213
+ this.originalRowData = structuredClone(this.rowData);
214
+ }
215
+
216
+ this.getGroupedData();
217
+ }
218
+
219
+ if (changes['groupByField']?.currentValue) {
220
+ this.activeGroups = [];
221
+ this.groupBy = [];
222
+ const groupByField = changes['groupByField'].currentValue;
223
+ const col = this.getColumnDetail(this.colDefs, groupByField);
224
+ this.activeGroups.push(...col);
225
+ this.groupBy.push(groupByField);
226
+ this.getGroupedData();
227
+ }
228
+ }
229
+
230
+ getColumnDetail(colDefs: any, groupByField: any) {
231
+ return colDefs.filter((col: any) => col.fieldName === groupByField);
232
+ }
233
+
234
+ activeAllSelection(event: Event) {
235
+ let checked = (event.target as HTMLInputElement).checked;
236
+ if (checked) {
237
+ this.colDefs = this.originalColDefs.map((dt) => {
238
+ if (!dt.active && !dt.headerLocked) {
239
+ dt.active = true;
240
+ }
241
+ this.atLeastOneColumnChecked = true;
242
+ return dt;
243
+ });
244
+ } else {
245
+ this.colDefs = this.originalColDefs.map((dt) => {
246
+ if (dt.active && !dt.headerLocked) {
247
+ dt.active = false;
248
+ }
249
+ this.atLeastOneColumnChecked = false;
250
+ return dt;
251
+ });
252
+ }
253
+ }
254
+
255
+ changeActiveColSelection(event: Event, col: any) {
256
+ col.active = !col.active;
257
+ const isAllNotChecked = this.originalColDefs.some((dt: any) => !dt.active);
258
+ this.atLeastOneColumnChecked = this.originalColDefs.some(
259
+ (dt: any) => dt.active,
260
+ );
261
+ if (isAllNotChecked) {
262
+ this.activeAll = false;
263
+ } else {
264
+ this.activeAll = true;
265
+ }
266
+ }
267
+
268
+ /**
269
+ * @description Prepares and normalizes column definitions for filtering and menu behavior
270
+ * @author Anand Pandey
271
+ * @param {any[]} colDefs - Raw column definitions received from the parent.
272
+ * @returns {any[]} - Updated column definitions with filter/menu
273
+ */
274
+ getUpdatedColDefs(colDefs: any[]) {
275
+ return colDefs.map((col, index) => {
276
+ this.sortingType[index] = '';
277
+ col.colId = `${Date.now()}_${index}`;
278
+ // if (col.fieldName === 'action') {
279
+ // col.isAction = true;
280
+ // }
281
+
282
+ if (!col.filterType && !col.isAction) {
283
+ col.filterType = 'text';
284
+ }
285
+
286
+ if (!col.filterLogic) {
287
+ col.filterLogic = 'OR';
288
+ }
289
+
290
+ let updatedCol = {
291
+ ...col,
292
+ active: col.active ?? true,
293
+ locked: col.locked ?? false,
294
+ filterable: col.filterable ?? true,
295
+ columnAction: col.columnAction ?? true,
296
+ sortable: col.sortable ?? true,
297
+ };
298
+
299
+ if (!updatedCol.filterable) {
300
+ return updatedCol;
301
+ }
302
+
303
+ switch (col.filterType) {
304
+ case 'text':
305
+ updatedCol = {
306
+ ...updatedCol,
307
+ filters: [
308
+ {
309
+ filterOperation: 'contains',
310
+ filterValue: '',
311
+ },
312
+ {
313
+ filterOperation: 'startsWith',
314
+ filterValue: '',
315
+ },
316
+ ],
317
+ };
318
+ break;
319
+
320
+ case 'number':
321
+ case 'date':
322
+ updatedCol = {
323
+ ...updatedCol,
324
+ filterValue: '',
325
+ filters: [
326
+ {
327
+ filterOperation: '=',
328
+ filterValue: '',
329
+ },
330
+ {
331
+ filterOperation: '=',
332
+ filterValue: '',
333
+ },
334
+ ],
335
+ };
336
+ break;
337
+
338
+ case 'set':
339
+ const options = [
340
+ ...new Set(
341
+ this.rowData.flatMap((r) => {
342
+ return this.normalizeSetFilterType(
343
+ r[col.fieldName],
344
+ col?.cellRendererParams?.tagKey,
345
+ )?.filter(Boolean);
346
+ }),
347
+ ),
348
+ ];
349
+ updatedCol = {
350
+ ...updatedCol,
351
+ options,
352
+ filteredOptions: options,
353
+ selectedValues: new Set(options),
354
+ };
355
+ break;
356
+ }
357
+
358
+ if (this.appliedFilters.length > 0) {
359
+ const appliedFilter = this.appliedFilters.find(
360
+ (f) => f.fieldName === col.fieldName,
361
+ );
362
+ if (appliedFilter) {
363
+ switch (col.filterType) {
364
+ case 'text':
365
+ case 'number':
366
+ case 'date':
367
+ updatedCol = {
368
+ ...updatedCol,
369
+ filters: appliedFilter.filters,
370
+ filterLogic: appliedFilter.filterLogic,
371
+ };
372
+ break;
373
+ case 'set':
374
+ const options = [
375
+ ...new Set(
376
+ this.rowData.flatMap((r) => {
377
+ return this.normalizeSetFilterType(
378
+ r[col.fieldName],
379
+ col?.cellRendererParams?.tagKey,
380
+ )?.filter(Boolean);
381
+ }),
382
+ ),
383
+ ];
384
+ const selectedValues = new Set(
385
+ appliedFilter.filters.map((f) => f.filterValue),
386
+ );
387
+ updatedCol = {
388
+ ...updatedCol,
389
+ options,
390
+ filteredOptions: options,
391
+ selectedValues,
392
+ };
393
+ break;
394
+ }
395
+ }
396
+ }
397
+ return updatedCol;
398
+ });
399
+ }
400
+ normalizeSetFilterType(value: any, key: string) {
401
+ if (!value) return;
402
+
403
+ if (Array.isArray(value) && typeof value[0] === 'string') {
404
+ return value;
405
+ }
406
+ if (Array.isArray(value) && typeof value[0] === 'object') {
407
+ return (value = value.map((val) => val[key]));
408
+ }
409
+
410
+ if (typeof value === 'string') {
411
+ return [value];
412
+ }
413
+
414
+ if (typeof value === 'object') {
415
+ return [value[key]];
416
+ }
417
+
418
+ return [];
419
+ }
420
+
421
+ /**
422
+ * @description - Evaluates a text-based filter condition on a given field value.
423
+ * @author Anand Pandey
424
+ * @param {string} type - The type of text filter to apply ('contains' | 'doesNotContain' | 'equals' etc).
425
+ * @param {string} fieldValue - The actual value from the data row being evaluated.
426
+ * @param {string} value - The user-entered filter value to compare against.
427
+ * @returns {boolean} `true` if the fieldValue satisfies the specified filter condition,
428
+ * otherwise `false`.
429
+ */
430
+ evaluateTextFilterCondition(
431
+ type: string,
432
+ fieldValue: string,
433
+ value: string,
434
+ ): boolean {
435
+ switch (type) {
436
+ case 'contains':
437
+ return fieldValue.includes(value);
438
+ case 'doesNotContain':
439
+ return !fieldValue.includes(value);
440
+ case 'equals':
441
+ return fieldValue === value;
442
+ case 'doesNotEqual':
443
+ return fieldValue !== value;
444
+ case 'startsWith':
445
+ return fieldValue.startsWith(value);
446
+ case 'endsWith':
447
+ return fieldValue.endsWith(value);
448
+ default:
449
+ return true;
450
+ }
451
+ }
452
+
453
+ /**
454
+ * @description - Evaluates number/date filter conditions.
455
+ * @author Anand
456
+ * @param {string} type - Comparison operator ('=' | '>' | '<' | '>=' | '<=').
457
+ * @param {number|string} fieldValue - Actual value from the row (number or timestamp).
458
+ * @param {number|string} value - User-entered value for comparison.
459
+ * @returns {boolean} True if the condition matches, otherwise false.
460
+ */
461
+ evaluateNumDateFilterCondition(
462
+ type: string,
463
+ fieldValue: number | string,
464
+ value: number | string,
465
+ ): boolean {
466
+ switch (type) {
467
+ case '=':
468
+ return fieldValue === value;
469
+ case '>':
470
+ return fieldValue > value;
471
+ case '<':
472
+ return fieldValue < value;
473
+ case '>=':
474
+ return fieldValue >= value;
475
+ case '<=':
476
+ return fieldValue <= value;
477
+ default:
478
+ return true;
479
+ }
480
+ }
481
+
482
+ /**
483
+ * @description Method to filter data according to filterOperation and comparator selection
484
+ * @author Anand Pandey
485
+ * @param {}
486
+ * @returns void
487
+ */
488
+ applyAllFilters() {
489
+ let result: any[] = structuredClone(this.originalRowData);
490
+
491
+ this.colDefs.forEach((col) => {
492
+ const field = col.fieldName;
493
+ if (col?.filterable) {
494
+ if (col.filterType === 'text') {
495
+ // *********** TEXT FILTER ***********
496
+ const [c1, c2] = col.filters;
497
+
498
+ const textVal1 = c1.filterValue?.toLowerCase().trim();
499
+ const textVal2 = c2.filterValue?.toLowerCase().trim();
500
+ if (!textVal1 && !textVal2) {
501
+ this.activeFilters.delete(col.fieldName);
502
+ return;
503
+ }
504
+ this.activeFilters.add(col.fieldName);
505
+
506
+ result = result.filter((r) => {
507
+ const fieldVal = String(r[field]).toLowerCase();
508
+ const cond1 = textVal1
509
+ ? this.evaluateTextFilterCondition(
510
+ c1.filterOperation,
511
+ fieldVal,
512
+ textVal1,
513
+ )
514
+ : false;
515
+ const cond2 = textVal2
516
+ ? this.evaluateTextFilterCondition(
517
+ c2.filterOperation,
518
+ fieldVal,
519
+ textVal2,
520
+ )
521
+ : false;
522
+
523
+ return col.filterLogic === 'AND' ? cond1 && cond2 : cond1 || cond2;
524
+ });
525
+ }
526
+
527
+ // *********** NUMBER FILTER ***********
528
+ if (col.filterType === 'number') {
529
+ const [c1, c2] = col.filters;
530
+ const numValue1 = Number(c1.filterValue);
531
+ const numValue2 = Number(c2.filterValue);
532
+
533
+ if (!numValue1 && !numValue2) {
534
+ this.activeFilters.delete(col.fieldName);
535
+ return;
536
+ }
537
+ this.activeFilters.add(col.fieldName);
538
+
539
+ result = result.filter((r) => {
540
+ const fieldVal = Number(r[field]);
541
+ const cond1 = numValue1
542
+ ? this.evaluateNumDateFilterCondition(
543
+ c1.filterOperation,
544
+ fieldVal,
545
+ numValue1,
546
+ )
547
+ : false;
548
+ const cond2 = numValue2
549
+ ? this.evaluateNumDateFilterCondition(
550
+ c2.filterOperation,
551
+ fieldVal,
552
+ numValue2,
553
+ )
554
+ : false;
555
+
556
+ return col.filterLogic === 'AND' ? cond1 && cond2 : cond1 || cond2;
557
+ });
558
+ }
559
+
560
+ // *********** DATE FILTER ***********
561
+ if (col.filterType === 'date') {
562
+ const [c1, c2] = col.filters;
563
+ const selected1 = this.normalizeDate(c1.filterValue);
564
+ const selected2 = this.normalizeDate(c2.filterValue);
565
+ if (!selected1 && !selected2) {
566
+ this.activeFilters.delete(col.fieldName);
567
+ return;
568
+ }
569
+ this.activeFilters.add(col.fieldName);
570
+ result = result.filter((r) => {
571
+ const fieldVal = this.normalizeDate(r[field]);
572
+ const cond1 = selected1
573
+ ? this.evaluateNumDateFilterCondition(
574
+ c1.filterOperation,
575
+ fieldVal ?? r[field],
576
+ selected1,
577
+ )
578
+ : false;
579
+ const cond2 = selected2
580
+ ? this.evaluateNumDateFilterCondition(
581
+ c2.filterOperation,
582
+ fieldVal ?? r[field],
583
+ selected2,
584
+ )
585
+ : false;
586
+
587
+ return col.filterLogic === 'AND' ? cond1 && cond2 : cond1 || cond2;
588
+ });
589
+ }
590
+
591
+ // *********** SET FILTER ***********
592
+ if (col.filterType === 'set') {
593
+ if (
594
+ col.selectedValues?.size >= 0 &&
595
+ col.selectedValues?.size !== col.options.length
596
+ ) {
597
+ result = result.filter((r) => {
598
+ const value: any = r[field];
599
+
600
+ if (
601
+ Array.isArray(value) &&
602
+ value.every((val) => typeof val !== 'object')
603
+ ) {
604
+ return value.some((m) => col.selectedValues.has(m));
605
+ }
606
+
607
+ if (
608
+ Array.isArray(value) &&
609
+ value.every((val) => typeof val === 'object')
610
+ ) {
611
+ return value.some((m) =>
612
+ col.selectedValues.has(m[col?.cellRendererParams?.tagKey]),
613
+ );
614
+ }
615
+
616
+ return col.selectedValues.has(r[field]);
617
+ });
618
+ this.activeFilters.add(col.fieldName);
619
+ } else {
620
+ this.activeFilters.delete(col.fieldName);
621
+ }
622
+ }
623
+
624
+ if (this.activeFilters.has(col.fieldName)) {
625
+ let filterObj: ColumnFilter = {
626
+ fieldName: col.fieldName,
627
+ filterLogic: col.filterLogic,
628
+ filters: col.filters,
629
+ };
630
+ if (col.filterType === 'set') {
631
+ filterObj.filters = Array(...col.selectedValues).map(
632
+ (f: string) => ({
633
+ filterOperation: 'equals',
634
+ filterValue: f,
635
+ }),
636
+ );
637
+ filterObj.filterLogic = 'OR';
638
+ }
639
+ const existingIndex = this.appliedFilters.findIndex(
640
+ (f) => f.fieldName === col.fieldName,
641
+ );
642
+ if (existingIndex === -1) {
643
+ this.appliedFilters.push(filterObj);
644
+ } else {
645
+ this.appliedFilters[existingIndex] = filterObj;
646
+ }
647
+ } else {
648
+ this.appliedFilters = this.appliedFilters.filter(
649
+ (f) => f.fieldName !== col.fieldName,
650
+ );
651
+ }
652
+ }
653
+ });
654
+
655
+ if (this.dynamicGroupingFiltering) {
656
+ this.appliedFiltersEvent.emit(this.appliedFilters);
657
+ return;
658
+ }
659
+ this.filteredData = result;
660
+ this.rowData = this.filteredData;
661
+ this.getGroupedData();
662
+ this.filter.emit(this.filteredData);
663
+ }
664
+
665
+ resetFilter(col: any) {
666
+ switch (col.filterType) {
667
+ case 'text':
668
+ case 'number':
669
+ case 'date': {
670
+ col.filters.forEach((f: any) => (f.filterValue = ''));
671
+ col.filterLogic = 'OR';
672
+ break;
673
+ }
674
+
675
+ case 'set': {
676
+ // Select all values again
677
+ col.selectedValues = new Set(col.options);
678
+ break;
679
+ }
680
+ }
681
+ this.appliedFilters = this.appliedFilters.filter(
682
+ (f) => f.fieldName !== col.fieldName,
683
+ );
684
+ // Remove active flag
685
+ this.activeFilters.delete(col.fieldName);
686
+
687
+ // Re-apply all filters
688
+ if (this.dynamicGroupingFiltering) {
689
+ this.appliedFiltersEvent.emit(this.appliedFilters);
690
+ return;
691
+ }
692
+ this.applyAllFilters();
693
+ }
694
+
695
+ removeActiveFilter(col: any) {
696
+ this.activeFilters.delete(col.fieldName);
697
+ this.colDefs
698
+ .find((c) => c.fieldName === col.fieldName)
699
+ .filters.forEach((f: any) => (f.filterValue = ''));
700
+ this.appliedFilters = this.appliedFilters.filter(
701
+ (f) => f.fieldName !== col.fieldName,
702
+ );
703
+
704
+ if (this.dynamicGroupingFiltering) {
705
+ this.appliedFiltersEvent.emit(this.appliedFilters);
706
+ return;
707
+ }
708
+ this.applyAllFilters();
709
+ }
710
+
711
+ /**
712
+ * @description Method to change the data format to utc
713
+ * @author Anand Pandey
714
+ * @param {date} - date value to be changed
715
+ * @returns date in milliseconds
716
+ */
717
+ normalizeDate(dateStr: string) {
718
+ const d = new Date(dateStr);
719
+ if (isNaN(d.getTime())) return null;
720
+ return new Date(
721
+ Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()),
722
+ ).getTime();
723
+ }
724
+
725
+ /**
726
+ * @description
727
+ * Filters the available set options inside a Set Filter (checkbox filter)
728
+ * based on the user's search text. This updates only the list shown in
729
+ * the dropdown
730
+ * @author Anand Pandey
731
+ * @param col - Column definition object containing filter config
732
+ * @param event - Input event from the search textbox
733
+ * @returns void
734
+ */
735
+ filterSetOptions(col: any, event: any) {
736
+ const text = event.target.value.toLowerCase();
737
+ col.filteredOptions = col.options.filter((option: any) =>
738
+ String(option).toLowerCase().includes(text),
739
+ );
740
+ }
741
+
742
+ /**
743
+ * @description
744
+ * Toggles an individual checkbox option inside a Set Filter. *
745
+ * @author Anand Pandey
746
+ * @param col - Column definition object
747
+ * @param opt - Selected option value
748
+ * @param event - Checkbox change event
749
+ * @returns void
750
+ */
751
+ toggleSetOption(col: any, opt: any, event: any) {
752
+ if (event.target.checked) col.selectedValues.add(opt);
753
+ else col.selectedValues.delete(opt);
754
+
755
+ this.applyAllFilters();
756
+ }
757
+
758
+ /**
759
+ * @description * Selects or deselects all checkbox options in the Set Filter.
760
+ * @author Anand Pandey
761
+ * @param col - Column definition object
762
+ * @param event - Checkbox change event
763
+ * @returns void
764
+ */
765
+ toggleSelectAll(col: any, event: any) {
766
+ if (event.target.checked) {
767
+ col.options.forEach((option: any) => col.selectedValues.add(option));
768
+ } else {
769
+ col.selectedValues.clear();
770
+ }
771
+ this.applyAllFilters();
772
+ }
773
+
774
+ /**
775
+ * @description
776
+ * Checks whether all options inside a Set Filter are currently selected.
777
+ * @author Anand Pandey
778
+ * @param col - Column definition object
779
+ * @returns boolean - TRUE if all options are selected, otherwise FALSE.
780
+ */
781
+ isAllSelected(col: any) {
782
+ return (
783
+ col.options?.length > 0 && col.options?.length === col.selectedValues.size
784
+ );
785
+ }
786
+
787
+ /**
788
+ * @description
789
+ * Opens the three-dots column menu for the selected column.
790
+ * Opens only the menu belonging to the clicked column index
791
+ * @author Anand Pandey
792
+ * @param {MouseEvent} event - The click event triggered on the three-dots icon.
793
+ * @param {any} col - The column definition object for which menu is opened.
794
+ * @param {number} index - Index of the column whose menu has been requested.
795
+ * @returns {void}
796
+ */
797
+ openMenu(event: MouseEvent, col: any, index: number) {
798
+ event.stopPropagation();
799
+ this.showPin = false;
800
+ this.activeFilterIndex = null;
801
+ this.menuVisible = this.menuVisible.map(() => false);
802
+
803
+ if (!this.menuVisible[index]) this.menuVisible[index] = false;
804
+
805
+ this.menuVisible[index] = true;
806
+
807
+ // setTimeout(() => {
808
+ // const rect = (event.target as HTMLElement).getBoundingClientRect();
809
+ // const el = this.colActionMenu?.nativeElement;
810
+ // const leftAvailableSpace = rect.left;
811
+ // const elWidth = el.offsetWidth;
812
+ // if (leftAvailableSpace < elWidth) {
813
+ // el.style.right = 'unset';
814
+ // el.style.left = '0px';
815
+ // }
816
+ // });
817
+ setTimeout(() => {
818
+ const table = this.table?.nativeElement;
819
+ const tableRect = table.getBoundingClientRect();
820
+ const rect = (event.target as HTMLElement).getBoundingClientRect();
821
+ const el = this.colActionMenu?.nativeElement;
822
+ const elWidth = el.offsetWidth;
823
+ const popUpLeftWidth = rect.left - elWidth;
824
+ if (popUpLeftWidth < tableRect.left) {
825
+ el.style.right = 'unset';
826
+ el.style.left = '0px';
827
+ }
828
+ });
829
+ }
830
+
831
+ /**
832
+ * @description Sort from three dots menu pop up.
833
+ * @author Anand Pandey
834
+ * @param {fieldName} string - fieldname.
835
+ * @param {string} type - Type defines the sorting type whether this is ascending, descending.
836
+ * @returns {void}
837
+ */
838
+ onSort(col: any, type: string, sortingColumIndex: number) {
839
+ this.sortingType[sortingColumIndex] = type;
840
+ this.sortingColumnIndex = sortingColumIndex;
841
+ Object.keys(this.sortingType).forEach((k) => {
842
+ if (k !== String(sortingColumIndex)) this.sortingType[k] = '';
843
+ });
844
+ if (this.sortingType[sortingColumIndex] == 'asc') {
845
+ this.ascendingOrder(col);
846
+ } else if (this.sortingType[sortingColumIndex] == 'dsc') {
847
+ this.descendingOrder(col);
848
+ } else {
849
+ this.rowData = structuredClone(this.originalRowData);
850
+ }
851
+ // if (this.sortingType[sortingColumIndex] == '') {
852
+ // this.rowData = this.originalRowData;
853
+ // }
854
+ this.getGroupedData();
855
+ this.menuVisible[this.currentIndex] = false;
856
+ }
857
+
858
+ /**
859
+ * @description Generates grouped data based on the selected `groupBy` columns..
860
+ * @author Anand Pandey
861
+ * @returns void
862
+ */
863
+ getGroupedData() {
864
+ if (this.groupBy && this.groupBy.length > 0) {
865
+ if (this.dynamicGroupingFiltering) {
866
+ return;
867
+ }
868
+ this.groupedResult = this.groupData(this.rowData, this.groupBy) || [];
869
+ }
870
+ }
871
+
872
+ /**
873
+ * @description Initializes column resize operation when the user presses the mouse on the resize handle.
874
+ * @author Anand Pandey
875
+ * @param {MouseEvent} event - The mousedown event triggered on the resize handle.
876
+ * @param {number} index - Index of the column being resized.
877
+ * @returns {void}
878
+ */
879
+ startResize(event: MouseEvent, index: number) {
880
+ event.preventDefault();
881
+ event.stopPropagation();
882
+
883
+ this.isResizing = true;
884
+ this.resizingColumnIndex = index;
885
+ this.startX = event.clientX;
886
+ this.startWidth = this.colDefs[index].width ?? 150;
887
+
888
+ this.zone.runOutsideAngular(() => {
889
+ this.removeMouseMove = this.renderer.listen(
890
+ 'document',
891
+ 'mousemove',
892
+ (e: MouseEvent) => this.onMouseMove(e),
893
+ );
894
+
895
+ this.removeMouseUp = this.renderer.listen(
896
+ 'document',
897
+ 'mouseup',
898
+ (e: MouseEvent) => this.stopResize(e),
899
+ );
900
+ });
901
+ }
902
+
903
+ /**
904
+ * @description Handles column resizing as the mouse moves.
905
+ * @author Anand Pandey
906
+ * @param {MouseEvent} event - Mouse movement event during resizing.
907
+ * @returns {void}
908
+ */
909
+ onMouseMove = (event: MouseEvent) => {
910
+ if (this.resizingColumnIndex == null || this.rafId) return;
911
+
912
+ this.rafId = requestAnimationFrame(() => {
913
+ const movement = event.clientX - this.startX;
914
+ const newWidth = this.startWidth + movement;
915
+
916
+ if (newWidth > 50) {
917
+ this.zone.run(() => {
918
+ this.colDefs[this.resizingColumnIndex!].width = newWidth;
919
+ this.cd.markForCheck();
920
+ });
921
+ }
922
+
923
+ this.rafId = null;
924
+ });
925
+ };
926
+
927
+ /**
928
+ * @description Stops the column resizing operation.
929
+ * Clears resizing state and removes mouse event listeners.
930
+ * @author Anand Pandey
931
+ * @param {MouseEvent} event - Mouse up event ending the resize action.
932
+ * @returns {void}
933
+ */
934
+ stopResize = (event: MouseEvent) => {
935
+ event.stopPropagation();
936
+
937
+ this.isResizing = false;
938
+ this.resizingColumnIndex = null;
939
+
940
+ this.removeMouseMove?.();
941
+ this.removeMouseUp?.();
942
+
943
+ if (this.rafId) {
944
+ cancelAnimationFrame(this.rafId);
945
+ this.rafId = null;
946
+ }
947
+ };
948
+
949
+ /**
950
+ * @description Recursively groups row data into a hierarchical structure based on the provided group keys.
951
+ * @author Anand Pandey
952
+ * @param {any[]} data - The row data to be grouped.
953
+ * @param {string[]} groupKeys - Ordered list of column keys to group by.
954
+ * @returns {any[]} A hierarchical grouped structure containing nested group nodes.
955
+ */
956
+ groupData(data: any[], groupKeys: string[]): any {
957
+ if (groupKeys.length === 0) return data;
958
+ const [currentKey, ...restKeys] = groupKeys;
959
+
960
+ const groups: any = {};
961
+ for (const row of data) {
962
+ const key = row[currentKey] ?? '';
963
+ if (!groups[key]) groups[key] = [];
964
+ groups[key].push(row);
965
+ }
966
+
967
+ // recursively group child arrays
968
+
969
+ let result = [];
970
+
971
+ for (const key of Object.keys(groups)) {
972
+ result.push({
973
+ key,
974
+ field: currentKey,
975
+ expanded: false,
976
+ children: this.groupData(groups[key], restKeys),
977
+ });
978
+ }
979
+
980
+ return result;
981
+ }
982
+
983
+ /**
984
+ * @description Toggles the expand/collapse state of a group node.
985
+ * @author Anand Pandey
986
+ * @param {any} node - The group node whose expanded state needs to be toggled.
987
+ * @returns {void}
988
+ */
989
+
990
+ toggleGroup(node: any) {
991
+ node.expanded = !node.expanded;
992
+ }
993
+
994
+ /**
995
+ * @description Pin column on the left side.
996
+ * @author Anand Pandey
997
+ * @param {any} col - The selected column details from table on clicking pin or unpin from three dots menu.
998
+ * @param {number} index - The index of column from table on clicking pin or unpin from three dots menu.
999
+ * @returns {void}
1000
+ */
1001
+
1002
+ pinColumn(col: any, index: number, direction: string) {
1003
+ this.pinActionClicked[col.colId] = direction;
1004
+ col.leftPinned = direction === 'left';
1005
+ col.rightPinned = direction === 'right';
1006
+
1007
+ if (col.leftPinned) {
1008
+ this.colDefs.splice(index, 1);
1009
+ this.colDefs = [col, ...this.colDefs];
1010
+ } else if (col.rightPinned) {
1011
+ this.colDefs.splice(index, 1);
1012
+ this.colDefs.splice(this.colDefs.length - 1, 0, col);
1013
+ } else {
1014
+ const indx = this.originalColDefs.findIndex(
1015
+ (dt) => dt.fieldName === col.fieldName,
1016
+ );
1017
+ if (index >= 0) {
1018
+ this.colDefs.splice(index, 1);
1019
+ this.colDefs.splice(indx, 0, col);
1020
+ }
1021
+ }
1022
+
1023
+ this.updatePinnedOffsets();
1024
+ this.onClickOutside();
1025
+ }
1026
+
1027
+ showPinActions(event: MouseEvent) {
1028
+ event.stopPropagation();
1029
+ const parentEl = event.currentTarget as HTMLElement;
1030
+
1031
+ this.showPin = true;
1032
+ setTimeout(() => {
1033
+ const menuEl = this.pinMenu?.nativeElement;
1034
+ if (!menuEl || !parentEl) return;
1035
+ const parentRect = parentEl.getBoundingClientRect();
1036
+ const menuWidth = menuEl.offsetWidth;
1037
+
1038
+ const viewPortWidth = window.innerWidth;
1039
+ let x = parentRect.right;
1040
+
1041
+ if (x + menuWidth > viewPortWidth) {
1042
+ menuEl.style.right = `${parentRect.width}px`;
1043
+ }
1044
+ });
1045
+ }
1046
+
1047
+ hidePinActions() {
1048
+ this.showPin = false;
1049
+ }
1050
+
1051
+ /**
1052
+ * @description Updates the horizontal left and right offsets of pinned columns by assigning cumulative widths to each pinned column and resetting non-pinned columns.
1053
+ * @author Anand Pandey
1054
+ * @returns void
1055
+ */
1056
+
1057
+ updatePinnedOffsets() {
1058
+ let leftOffset = 0;
1059
+ let rightOffset = 0;
1060
+
1061
+ // LEFT pinned (normal order)
1062
+ this.colDefs.forEach((col) => {
1063
+ if (col.leftPinned) {
1064
+ col.left = leftOffset;
1065
+ col.right = null;
1066
+ leftOffset += col.width || 120;
1067
+ }
1068
+ });
1069
+
1070
+ // RIGHT pinned (REVERSE order)
1071
+ [...this.colDefs].reverse().forEach((col) => {
1072
+ if (col.rightPinned) {
1073
+ col.right = rightOffset;
1074
+ col.left = null;
1075
+ rightOffset += col.width || 120;
1076
+ }
1077
+ });
1078
+ }
1079
+
1080
+ /**
1081
+ * @description Method to parse column value from rowdata object
1082
+ * according to given field value in column Defination
1083
+ * @author Tarun Kumar
1084
+ * @param row - current row object
1085
+ * @param toParse - field value
1086
+ * @returns string
1087
+ */
1088
+ parseColValue(row: any, col: any): any {
1089
+ if (!col?.fieldName?.includes('.')) {
1090
+ if (Array.isArray(row[col.fieldName])) {
1091
+ if (row[col.fieldName].every((dt: string) => typeof dt === 'string')) {
1092
+ return row[col.fieldName][0];
1093
+ }
1094
+ if (row[col.fieldName].every((dt: any) => typeof dt === 'object')) {
1095
+ return row[col.fieldName][0]?.[col.cellRendererParams?.tagKey];
1096
+ }
1097
+ }
1098
+ return row[col.fieldName] || 'N/A';
1099
+ } else {
1100
+ let toParseArr = col?.fieldName.split('.');
1101
+ let val = row;
1102
+ for (const key of toParseArr) {
1103
+ val = val[key];
1104
+ }
1105
+ return val || 'N/A';
1106
+ }
1107
+ }
1108
+
1109
+ /**
1110
+ * @description method to reset table configuration
1111
+ * @author Tarun Kumar
1112
+ * @param none
1113
+ * @returns void
1114
+ */
1115
+ resetPagination(): void {
1116
+ //this.pageDetails.pageSize = 20;
1117
+ this.pageDetails.currentPage = 1;
1118
+ this.pageDetails.totalPages = 1;
1119
+ this.recordsToShow.min = 0;
1120
+ this.recordsToShow.max = this.pageDetails.pageSize;
1121
+ this.setPageCount();
1122
+ }
1123
+
1124
+ /**
1125
+ * @description method to set total pages count
1126
+ * @author Tarun Kumar
1127
+ * @param none
1128
+ * @returns void
1129
+ */
1130
+ setPageCount(): void {
1131
+ this.pageDetails.totalPages = Math.ceil(
1132
+ this.totalRecords / this.pageDetails.pageSize,
1133
+ );
1134
+ }
1135
+
1136
+ /**
1137
+ * @description method to update table on page size change
1138
+ * @author Tarun Kumar
1139
+ * @param event
1140
+ * @returns void
1141
+ */
1142
+ onPageSizeChanged(event: any): void {
1143
+ this.recordsToShow.min = 0;
1144
+ this.recordsToShow.max = parseInt(event);
1145
+ this.pageDetails.currentPage = 1;
1146
+ this.pageDetails.pageSize = parseInt(event);
1147
+ this.setPageCount();
1148
+ this.onPaginationChange.emit({
1149
+ page: this.pageDetails.currentPage - 1,
1150
+ pageSize: this.pageDetails.pageSize,
1151
+ });
1152
+ }
1153
+
1154
+ /**
1155
+ * @description method to update table on previous button click
1156
+ * @author Tarun Kumar
1157
+ */
1158
+ onBtPrevClick(): void {
1159
+ this.recordsToShow.min = this.recordsToShow.min - this.pageDetails.pageSize;
1160
+ this.recordsToShow.max = this.recordsToShow.max - this.pageDetails.pageSize;
1161
+ if (this.pageDetails.currentPage > 1)
1162
+ this.pageDetails.currentPage = this.pageDetails.currentPage - 1;
1163
+
1164
+ this.onPaginationChange.emit({
1165
+ page: this.pageDetails.currentPage - 1,
1166
+ pageSize: this.pageDetails.pageSize,
1167
+ });
1168
+ }
1169
+
1170
+ /**
1171
+ * @description method to update table on next button click
1172
+ * @author Tarun Kumar
1173
+ */
1174
+ onBtNextClick(): void {
1175
+ this.recordsToShow.min = this.recordsToShow.min + this.pageDetails.pageSize;
1176
+ this.recordsToShow.max = this.recordsToShow.max + this.pageDetails.pageSize;
1177
+
1178
+ if (this.pageDetails.currentPage < this.pageDetails.totalPages)
1179
+ this.pageDetails.currentPage = this.pageDetails.currentPage + 1;
1180
+
1181
+ this.onPaginationChange.emit({
1182
+ page: this.pageDetails.currentPage - 1,
1183
+ pageSize: this.pageDetails.pageSize,
1184
+ });
1185
+ }
1186
+
1187
+ /**
1188
+ * @description method to update table on selecting any page randomly
1189
+ * @author Tarun Kumar
1190
+ * @param event
1191
+ */
1192
+ goToSelectedPage(event: any): void {
1193
+ let pageNo = event.target.value;
1194
+ if (pageNo < 1) {
1195
+ this.pageDetails.currentPage = 1;
1196
+ } else if (pageNo > this.pageDetails.totalPages) {
1197
+ this.pageDetails.currentPage = this.pageDetails.totalPages;
1198
+ }
1199
+ this.recordsToShow.max =
1200
+ this.pageDetails.currentPage * this.pageDetails.pageSize;
1201
+ this.recordsToShow.min =
1202
+ this.pageDetails.currentPage * this.pageDetails.pageSize -
1203
+ this.pageDetails.pageSize;
1204
+
1205
+ this.onPaginationChange.emit({
1206
+ page: this.pageDetails.currentPage - 1,
1207
+ pageSize: this.pageDetails.pageSize,
1208
+ });
1209
+ }
1210
+
1211
+ /**
1212
+ * @description method to sort data according to type and column
1213
+ * @author Tarun Kumar
1214
+ * @param sortingColumIndex
1215
+ * @param col
1216
+ * @param sortingType
1217
+ */
1218
+ onSortingRowData(sortingColumIndex: number, col: any): void {
1219
+ if (!col.sortable) return;
1220
+ this.sortingColumnIndex = sortingColumIndex;
1221
+ Object.keys(this.sortingType).forEach((k) => {
1222
+ if (k !== String(sortingColumIndex)) this.sortingType[k] = '';
1223
+ });
1224
+
1225
+ if (!this.sortingType[sortingColumIndex]) {
1226
+ this.sortingType[sortingColumIndex] = 'asc';
1227
+ } else {
1228
+ this.sortingType[sortingColumIndex] =
1229
+ this.sortingType[sortingColumIndex] === 'asc' ? 'dsc' : '';
1230
+ }
1231
+
1232
+ if (this.sortingType[sortingColumIndex] == 'asc') {
1233
+ this.ascendingOrder(col);
1234
+ } else if (this.sortingType[sortingColumIndex] == 'dsc') {
1235
+ this.descendingOrder(col);
1236
+ } else {
1237
+ this.rowData = structuredClone(this.originalRowData);
1238
+ }
1239
+
1240
+ this.getGroupedData();
1241
+ }
1242
+
1243
+ /**
1244
+ * @description method to sort table in ascending order according to given field
1245
+ * @param fieldName
1246
+ */
1247
+ ascendingOrder(col: any): void {
1248
+ this.rowData = this.rowData.sort((a, b) => {
1249
+ const valA = this.parseColValue(a, col);
1250
+ const valB = this.parseColValue(b, col);
1251
+ if (typeof valA === 'string' && typeof valB === 'string') {
1252
+ return valA.localeCompare(valB);
1253
+ } else {
1254
+ if (valA > valB) {
1255
+ return 1;
1256
+ } else {
1257
+ return -1;
1258
+ }
1259
+ }
1260
+ });
1261
+ }
1262
+
1263
+ /**
1264
+ * @description method to sort table in descending order according to given field
1265
+ * @param fieldName
1266
+ */
1267
+ descendingOrder(col: any): void {
1268
+ this.rowData = this.rowData.sort((a, b) => {
1269
+ const valA = this.parseColValue(a, col);
1270
+ const valB = this.parseColValue(b, col);
1271
+ if (typeof valA === 'string' && typeof valB === 'string') {
1272
+ return valA.localeCompare(valB) * -1;
1273
+ } else {
1274
+ if (valA > valB) {
1275
+ return -1;
1276
+ } else {
1277
+ return 1;
1278
+ }
1279
+ }
1280
+ });
1281
+ }
1282
+
1283
+ /**
1284
+ * @description method to check/uncheck all rows on header checkbox selection/deselection
1285
+ * @author Tarun Kumar
1286
+ * @param event
1287
+ */
1288
+ onHeaderCheckboxChange(event: any): void {
1289
+ if (event.target.checked) {
1290
+ this.rowData = this.rowData.map((data) => {
1291
+ data.isSelected = true;
1292
+ return data;
1293
+ });
1294
+ this.selectedRow = JSON.parse(JSON.stringify(this.rowData));
1295
+ this.onCheckboxSelection.emit(this.rowData);
1296
+ } else {
1297
+ this.rowData = this.rowData.map((data) => {
1298
+ if (!data.isLocked) data.isSelected = false;
1299
+ return data;
1300
+ });
1301
+ this.selectedRow = [];
1302
+ this.onCheckboxSelection.emit([]);
1303
+ }
1304
+ }
1305
+
1306
+ /**
1307
+ * @description method to check/uncheck row on row checkbox selection/deselection
1308
+ * @author Tarun Kumar
1309
+ * @param event
1310
+ */
1311
+ onRowCheckboxSelection(event: any): void {
1312
+ if (event.target.checked) {
1313
+ let ind = this.rowData.findIndex(
1314
+ (item: any) => item.rowId == event.target.id,
1315
+ );
1316
+ this.rowData[ind].isSelected = true;
1317
+ if (
1318
+ this.checkboxSelectionType != 'multiple' &&
1319
+ this.selectedRow.length > 0
1320
+ ) {
1321
+ (
1322
+ document.getElementById(this.selectedRow[0].rowId) as HTMLInputElement
1323
+ ).checked = false;
1324
+ this.selectedRow = [];
1325
+ }
1326
+ this.selectedRow.push(this.rowData[ind]);
1327
+
1328
+ this.onCheckboxSelection.emit(this.selectedRow);
1329
+ } else {
1330
+ let ind = this.rowData.findIndex(
1331
+ (item: any) => item.rowId == event.target.id,
1332
+ );
1333
+ this.rowData[ind].isSelected = false;
1334
+ let i = this.selectedRow.findIndex(
1335
+ (item: any) => item.rowId == event.target.id,
1336
+ );
1337
+ this.selectedRow.splice(i, 1);
1338
+ this.onCheckboxSelection.emit(this.selectedRow);
1339
+ }
1340
+ this.cd.detectChanges();
1341
+ }
1342
+ /**
1343
+ * @description method to check/uncheck all rows on header checkbox selection/deselection
1344
+ * @author Tarun Kumar
1345
+ * @param col
1346
+ * @returns {object}
1347
+ */
1348
+ getStyle(col: any, type?: string): object {
1349
+ const style: any = {
1350
+ width: `${col.width ?? 150}px`,
1351
+ minWidth: `${col.minWidth ?? 50}px`,
1352
+ };
1353
+ if (col.isAction) {
1354
+ style.position = 'sticky';
1355
+ style.right = '0px';
1356
+ style.zIndex = 14;
1357
+ style.background = '#fff';
1358
+ style.width = '60px';
1359
+ style.minWidth = '60px';
1360
+ } else if (col.leftPinned) {
1361
+ style.position = 'sticky';
1362
+ style.left = col.left + 'px';
1363
+ style.zIndex = 12;
1364
+ style.background = '#fff';
1365
+ } else if (col.rightPinned) {
1366
+ style.position = 'sticky';
1367
+ style.right = col.right + 'px';
1368
+ style.zIndex = 12;
1369
+ style.background = '#fff';
1370
+ } else {
1371
+ style.position = '';
1372
+ }
1373
+ if (type === 'action') {
1374
+ style.background = '#f0f0f0';
1375
+ }
1376
+ return style;
1377
+ }
1378
+ onClickOutside() {
1379
+ this.showPageSizeList = false;
1380
+ this.activeFilterIndex = null;
1381
+ this.menuVisible = this.menuVisible.map(() => false);
1382
+ }
1383
+
1384
+ infinityScroll(event: any) {
1385
+ if (
1386
+ event.target.offsetHeight + event.target.scrollTop >=
1387
+ event.target.scrollHeight - 1 &&
1388
+ this.rowData.length
1389
+ ) {
1390
+ this.onScrollEmitter.emit();
1391
+ }
1392
+ }
1393
+
1394
+ checkAllSelected(): boolean {
1395
+ if (!this.rowData.length) return false;
1396
+ return this.selectedRow.length == this.rowData.length;
1397
+ }
1398
+ checkInterminate(): boolean {
1399
+ if (!this.rowData.length) return false;
1400
+ return (
1401
+ this.selectedRow.length > 0 &&
1402
+ this.selectedRow.length < this.rowData.length
1403
+ );
1404
+ }
1405
+
1406
+ /**
1407
+ * @author Tarun Kumar
1408
+ * @description function triggered when the drag starts
1409
+ * @param {event object, index}
1410
+ * @returns {void}
1411
+ */
1412
+ onDragStart(event: DragEvent, index: number) {
1413
+ this.dragGroupIndex = null;
1414
+ const target = event.target as HTMLElement;
1415
+ if (this.isResizing) {
1416
+ event.preventDefault();
1417
+ return;
1418
+ }
1419
+ this.draggedIndex = index;
1420
+
1421
+ // For column reorder.
1422
+ event.dataTransfer?.setData('text/plain', index.toString());
1423
+
1424
+ // For group panel
1425
+ event.dataTransfer?.setData('columnIndex', index.toString());
1426
+
1427
+ const th = target.closest('th') as HTMLElement;
1428
+ if (!th) return;
1429
+ const clone = th.cloneNode(true) as HTMLElement;
1430
+
1431
+ this.copyComputedStyles(th, clone);
1432
+
1433
+ clone.style.position = 'absolute';
1434
+ clone.style.top = '-9999px';
1435
+ clone.style.left = '-9999px';
1436
+ clone.style.pointerEvents = 'none';
1437
+
1438
+ document.body.appendChild(clone);
1439
+ event.dataTransfer?.setDragImage(clone, 0, 0);
1440
+ setTimeout(() => clone.remove(), 0);
1441
+ }
1442
+
1443
+ onGroupDragStart(event: DragEvent, index: number) {
1444
+ event.dataTransfer?.setData('groupIndex', index.toString());
1445
+ this.dragGroupIndex = index;
1446
+ }
1447
+
1448
+ /**
1449
+ * @author Anand Pandey
1450
+ * @description Copies computed CSS styles from the source element to the target element, including all child elements recursively.
1451
+ * @param {HTMLElement} source - Original element.
1452
+ * @param {HTMLElement} target - Cloned element.
1453
+ * @returns {void}
1454
+ */
1455
+ copyComputedStyles(source: HTMLElement, target: HTMLElement) {
1456
+ const computed = window.getComputedStyle(source);
1457
+ for (const prop of computed) {
1458
+ target.style.setProperty(prop, computed.getPropertyValue(prop));
1459
+ }
1460
+
1461
+ // Copy children styles recursively
1462
+ const sourceChildren = Array.from(source.children) as HTMLElement[];
1463
+ const targetChildren = Array.from(target.children) as HTMLElement[];
1464
+
1465
+ sourceChildren.forEach((srcChild, i) => {
1466
+ const tgtChild = targetChildren[i] as HTMLElement;
1467
+ if (srcChild && tgtChild) {
1468
+ this.copyComputedStyles(srcChild, tgtChild);
1469
+ }
1470
+ });
1471
+ }
1472
+
1473
+ /**
1474
+ * @author Tarun Kumar
1475
+ * @description function to track the index of the element being dragged over and allow dropping
1476
+ * @param {event object, index}
1477
+ * @returns {void}
1478
+ */
1479
+ onDragOver(event: DragEvent, index: number) {
1480
+ event.preventDefault();
1481
+ this.isResizing = false;
1482
+ if (this.dragOverIndex !== index) {
1483
+ this.dragOverIndex = index;
1484
+ }
1485
+ }
1486
+
1487
+ /**
1488
+ * @author Tarun Kumar
1489
+ * @description function to Reorder the items on drop
1490
+ * @param {event object, index}
1491
+ * @returns {void}
1492
+ */
1493
+ onDrop(event: DragEvent, index: number) {
1494
+ event.preventDefault();
1495
+ if (this.draggedIndex === null) return;
1496
+ const draggedItem = this.colDefs[this.draggedIndex];
1497
+ this.colDefs.splice(this.draggedIndex, 1);
1498
+ this.colDefs.splice(index, 0, draggedItem);
1499
+ this.draggedIndex = null;
1500
+ this.dragOverIndex = null;
1501
+ }
1502
+
1503
+ /**
1504
+ * @author Tarun Kumar
1505
+ * @description function to reset dragOverIndex when the drag ends
1506
+ * @param {none}
1507
+ * @returns {void}
1508
+ */
1509
+ onDragEnd() {
1510
+ this.draggedIndex = null;
1511
+ this.dragOverIndex = null;
1512
+ }
1513
+
1514
+ /**
1515
+ * @description Handles drag over on group panel to allow dropping.
1516
+ * @author Anand Pandey
1517
+ * @param {DragEvent} event
1518
+ * @returns {void}
1519
+ */
1520
+ onGroupDragOver(event: DragEvent) {
1521
+ event.preventDefault();
1522
+ }
1523
+
1524
+ /**
1525
+ * @description Handles drag over on a group tag and updates the target index for reordering.
1526
+ * @author Anand Pandey
1527
+ * @param {DragEvent} event
1528
+ * @param {number} index
1529
+ * @returns {void}
1530
+ */
1531
+ onActiveDragOver(event: DragEvent, index: number) {
1532
+ event.preventDefault();
1533
+ event.stopPropagation();
1534
+ this.dragGroupIndex = index;
1535
+ }
1536
+
1537
+ /**
1538
+ * @description Handles drop on group panel and routes the drop to group reordering or column grouping logic.
1539
+ * @author Anand Pandey
1540
+ * @param {DragEvent} event
1541
+ * @returns {void}
1542
+ */
1543
+ onGroupDrop(event: DragEvent) {
1544
+ const colIndex = Number(event.dataTransfer?.getData('columnIndex'));
1545
+ const groupIndex = Number(event.dataTransfer?.getData('groupIndex'));
1546
+ const target = event.target as HTMLElement;
1547
+ const isOverGroupPanel = target.closest('.group-tag');
1548
+ if (
1549
+ this.dragGroupIndex !== null &&
1550
+ this.dragGroupIndex >= 0 &&
1551
+ groupIndex >= 0
1552
+ ) {
1553
+ if (!isOverGroupPanel) {
1554
+ this.dragGroupIndex = this.activeGroups.length - 1;
1555
+ }
1556
+ this.onActiveGroupDrop(event, this.dragGroupIndex);
1557
+ } else {
1558
+ if (isNaN(colIndex)) return;
1559
+ if (colIndex) this.dragGroupIndex = null;
1560
+
1561
+ const col = this.colDefs[colIndex];
1562
+
1563
+ const el = this.activeGroups.find((c) => c.fieldName === col.fieldName);
1564
+ if (!el) {
1565
+ this.activeGroups.push(col);
1566
+ this.groupBy.push(col.fieldName);
1567
+ }
1568
+ this.colDefs.splice(colIndex, 1);
1569
+ if (this.dynamicGroupingFiltering) {
1570
+ this.activeGroupsEvent.emit(this.groupBy);
1571
+ return;
1572
+ }
1573
+ // this.applyGrouping();
1574
+ this.getGroupedData();
1575
+ }
1576
+ }
1577
+
1578
+ /**
1579
+ * @description Handles column grouping triggered from the column action menu by adding the column to the active group list,
1580
+ * removing it from visible columns, and recalculating grouped row data.
1581
+ *
1582
+ * @param {any} col - The column definition selected for grouping.
1583
+ * @param {number} index - Index of the column in the current column definitions array.
1584
+ * @returns {void}
1585
+ */
1586
+
1587
+ groupByColumnAction(col: any, index: number) {
1588
+ this.activeGroups.push(col);
1589
+ this.groupBy.push(col.fieldName);
1590
+ this.colDefs.splice(index, 1);
1591
+ if (this.dynamicGroupingFiltering) {
1592
+ this.activeGroupsEvent.emit(this.groupBy);
1593
+ return;
1594
+ }
1595
+ this.getGroupedData();
1596
+ this.onClickOutside();
1597
+ }
1598
+
1599
+ /**
1600
+ * @description Handles drop on a group tag and reorders the active groups accordingly.
1601
+ * @author Anand Pandey
1602
+ * @param {DragEvent} event
1603
+ * @param {number} index
1604
+ * @returns {void}
1605
+ */
1606
+ onActiveGroupDrop(event: DragEvent, index: number) {
1607
+ event.stopPropagation();
1608
+ const groupIndex = Number(event.dataTransfer?.getData('groupIndex'));
1609
+ if (isNaN(groupIndex)) return;
1610
+ if (groupIndex === index) return;
1611
+ const item = this.groupBy.splice(groupIndex, 1)[0];
1612
+ this.groupBy.splice(index, 0, item);
1613
+
1614
+ const col = this.activeGroups.splice(groupIndex, 1)[0];
1615
+ this.activeGroups.splice(index, 0, col);
1616
+ if (this.dynamicGroupingFiltering) {
1617
+ this.activeGroupsEvent.emit(this.groupBy);
1618
+ return;
1619
+ }
1620
+ this.getGroupedData();
1621
+ }
1622
+
1623
+ /**
1624
+ * @description Removes a group tag and restores the column to available columns list.
1625
+ * @author Anand Pandey
1626
+ * @param {any} col
1627
+ * @param {number} id
1628
+ * @returns {void}
1629
+ */
1630
+ removeGroup(col: any, id: number) {
1631
+ this.activeGroups.splice(id, 1);
1632
+ const colIndex = this.originalColDefs.findIndex(
1633
+ (dt) => dt.fieldName === col.fieldName,
1634
+ );
1635
+ this.colDefs.splice(colIndex, 0, col);
1636
+ this.groupBy.splice(id, 1);
1637
+ if (this.groupBy.length === 0) {
1638
+ this.groupedResult = [];
1639
+ if (this.dynamicGroupingFiltering) {
1640
+ this.activeGroupsEvent.emit(this.groupBy);
1641
+ return;
1642
+ }
1643
+ } else {
1644
+ if (this.dynamicGroupingFiltering) {
1645
+ this.activeGroupsEvent.emit(this.groupBy);
1646
+ return;
1647
+ }
1648
+ this.getGroupedData();
1649
+ }
1650
+ }
1651
+
1652
+ toggleDropdown(): void {
1653
+ this.showDropdown = !this.showDropdown;
1654
+ }
1655
+
1656
+ selectFilter(option: any, col: any): void {
1657
+ col.filters[0].filterOperation = option.value;
1658
+ this.showDropdown = false;
1659
+ }
1660
+
1661
+ getSelectedFilterLabel(value: string): string {
1662
+ return this.filterOptions.find((o) => o.value === value)?.label || '';
1663
+ }
1664
+
1665
+ toggleFilter(col: any, index: number, event: MouseEvent) {
1666
+ event.stopPropagation();
1667
+ this.activeFilterIndex = this.activeFilterIndex === index ? null : index;
1668
+ this.menuVisible = this.menuVisible.map(() => false);
1669
+ }
1670
+
1671
+ onMouseEnterHeader(index: number) {
1672
+ this.showMoveIcon[index] = true;
1673
+ }
1674
+
1675
+ onMouseLeaveHeader(index: number) {
1676
+ this.showMoveIcon[index] = false;
1677
+ }
1678
+
1679
+ enableColumnDrag(event: MouseEvent, index: number) {
1680
+ event.stopPropagation();
1681
+ this.columnDraggable[index] = true;
1682
+ }
1683
+
1684
+ disableColumnDrag(event: MouseEvent, index: number) {
1685
+ event.stopPropagation();
1686
+ this.columnDraggable[index] = false;
1687
+ }
1688
+
1689
+ dateTimeSelected(date: any) {
1690
+ this.applyAllFilters();
1691
+ }
1692
+
1693
+ convertToNumber(value: number | string): number {
1694
+ return Number(value);
1695
+ }
1696
+
1697
+ hideSettings(): void {
1698
+ this.onHideSettings.emit(false);
1699
+ }
1700
+
1701
+ dragRow(e: Event, row: any) {
1702
+ this.draggedRowData = row;
1703
+ this.isRowSelected = this.selectedRow.some((s) => s.rowId === row.rowId);
1704
+ }
1705
+
1706
+ allowRowDrop(e: Event) {
1707
+ e.preventDefault();
1708
+ }
1709
+ dropRow(targetRow: any) {
1710
+ let sourceIndex = null;
1711
+ let targetIndex = this.rowData.findIndex(
1712
+ (dt: any) => dt.rowId === targetRow.rowId,
1713
+ );
1714
+
1715
+ if (this.selectedRow.length > 0 && this.isRowSelected) {
1716
+ sourceIndex = this.rowData.findIndex(
1717
+ (dt: any) => dt.rowId === this.selectedRow[0].rowId,
1718
+ );
1719
+
1720
+ const selectedIds = new Set(this.selectedRow.map((r) => r.rowId));
1721
+ this.rowData = this.rowData.filter((dt) => !selectedIds.has(dt.rowId));
1722
+ if (sourceIndex > this.rowData.length) {
1723
+ sourceIndex = sourceIndex - this.selectedRow.length + 1;
1724
+ }
1725
+
1726
+ if (targetIndex >= this.rowData.length) {
1727
+ targetIndex = targetIndex - this.selectedRow.length + 1;
1728
+ }
1729
+ this.rowData.splice(sourceIndex, 0, ...this.selectedRow);
1730
+ } else {
1731
+ sourceIndex = this.rowData.findIndex(
1732
+ (dt: any) => dt.rowId === this.draggedRowData.rowId,
1733
+ );
1734
+ }
1735
+ if (sourceIndex < 0 || targetIndex < 0) return;
1736
+ this.moveRow(sourceIndex, targetIndex);
1737
+ }
1738
+
1739
+ moveRow(from: number, to: number) {
1740
+ let rowMoved = [];
1741
+ if (this.selectedRow.length > 0 && this.isRowSelected) {
1742
+ rowMoved = this.rowData.splice(from, this.selectedRow.length);
1743
+ } else {
1744
+ rowMoved = this.rowData.splice(from, 1);
1745
+ }
1746
+
1747
+ this.rowData.splice(to, 0, ...rowMoved);
1748
+ this.isRowSelected = false;
1749
+ }
1750
+
1751
+ clearAllFilter() {
1752
+ this.colDefs.forEach((col) => {
1753
+ this.resetFilter(col);
1754
+ });
1755
+ }
1756
+ }