@dynect/base 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (871) hide show
  1. package/package.json +1 -1
  2. package/src/runtime/assets/svg/app/asset.svg +8 -0
  3. package/src/runtime/assets/svg/app/crm.svg +8 -0
  4. package/src/runtime/assets/svg/app/dark/asset.svg +6 -0
  5. package/src/runtime/assets/svg/app/dark/crm.svg +6 -0
  6. package/src/runtime/assets/svg/app/dark/erp.svg +5 -0
  7. package/src/runtime/assets/svg/app/dark/hrms.svg +8 -0
  8. package/src/runtime/assets/svg/app/dark/investment.svg +10 -0
  9. package/src/runtime/assets/svg/app/dark/pos.svg +5 -0
  10. package/src/runtime/assets/svg/app/dark/project.svg +8 -0
  11. package/src/runtime/assets/svg/app/dark/retail.svg +9 -0
  12. package/src/runtime/assets/svg/app/erp.svg +5 -0
  13. package/src/runtime/assets/svg/app/hrms.svg +10 -0
  14. package/src/runtime/assets/svg/app/investment.svg +12 -0
  15. package/src/runtime/assets/svg/app/outline/asset.svg +5 -0
  16. package/src/runtime/assets/svg/app/outline/crm.svg +6 -0
  17. package/src/runtime/assets/svg/app/outline/erp.svg +5 -0
  18. package/src/runtime/assets/svg/app/outline/hrms.svg +7 -0
  19. package/src/runtime/assets/svg/app/outline/investment.svg +9 -0
  20. package/src/runtime/assets/svg/app/outline/pos.svg +5 -0
  21. package/src/runtime/assets/svg/app/outline/project.svg +8 -0
  22. package/src/runtime/assets/svg/app/outline/retail.svg +9 -0
  23. package/src/runtime/assets/svg/app/pos.svg +7 -0
  24. package/src/runtime/assets/svg/app/project.svg +10 -0
  25. package/src/runtime/assets/svg/app/retail.svg +11 -0
  26. package/src/runtime/assets/svg/flags/ad.svg +150 -0
  27. package/src/runtime/assets/svg/flags/ae.svg +6 -0
  28. package/src/runtime/assets/svg/flags/af.svg +81 -0
  29. package/src/runtime/assets/svg/flags/ag.svg +14 -0
  30. package/src/runtime/assets/svg/flags/ai.svg +29 -0
  31. package/src/runtime/assets/svg/flags/al.svg +5 -0
  32. package/src/runtime/assets/svg/flags/am.svg +5 -0
  33. package/src/runtime/assets/svg/flags/ao.svg +13 -0
  34. package/src/runtime/assets/svg/flags/aq.svg +5 -0
  35. package/src/runtime/assets/svg/flags/ar.svg +32 -0
  36. package/src/runtime/assets/svg/flags/arab.svg +109 -0
  37. package/src/runtime/assets/svg/flags/as.svg +72 -0
  38. package/src/runtime/assets/svg/flags/asean.svg +13 -0
  39. package/src/runtime/assets/svg/flags/at.svg +4 -0
  40. package/src/runtime/assets/svg/flags/au.svg +8 -0
  41. package/src/runtime/assets/svg/flags/aw.svg +186 -0
  42. package/src/runtime/assets/svg/flags/ax.svg +18 -0
  43. package/src/runtime/assets/svg/flags/az.svg +8 -0
  44. package/src/runtime/assets/svg/flags/ba.svg +12 -0
  45. package/src/runtime/assets/svg/flags/bb.svg +6 -0
  46. package/src/runtime/assets/svg/flags/bd.svg +4 -0
  47. package/src/runtime/assets/svg/flags/be.svg +7 -0
  48. package/src/runtime/assets/svg/flags/bf.svg +7 -0
  49. package/src/runtime/assets/svg/flags/bg.svg +5 -0
  50. package/src/runtime/assets/svg/flags/bh.svg +4 -0
  51. package/src/runtime/assets/svg/flags/bi.svg +15 -0
  52. package/src/runtime/assets/svg/flags/bj.svg +14 -0
  53. package/src/runtime/assets/svg/flags/bl.svg +5 -0
  54. package/src/runtime/assets/svg/flags/bm.svg +97 -0
  55. package/src/runtime/assets/svg/flags/bn.svg +36 -0
  56. package/src/runtime/assets/svg/flags/bo.svg +673 -0
  57. package/src/runtime/assets/svg/flags/bq.svg +5 -0
  58. package/src/runtime/assets/svg/flags/br.svg +45 -0
  59. package/src/runtime/assets/svg/flags/bs.svg +13 -0
  60. package/src/runtime/assets/svg/flags/bt.svg +89 -0
  61. package/src/runtime/assets/svg/flags/bv.svg +13 -0
  62. package/src/runtime/assets/svg/flags/bw.svg +7 -0
  63. package/src/runtime/assets/svg/flags/by.svg +18 -0
  64. package/src/runtime/assets/svg/flags/bz.svg +145 -0
  65. package/src/runtime/assets/svg/flags/ca.svg +4 -0
  66. package/src/runtime/assets/svg/flags/cc.svg +19 -0
  67. package/src/runtime/assets/svg/flags/cd.svg +5 -0
  68. package/src/runtime/assets/svg/flags/cefta.svg +13 -0
  69. package/src/runtime/assets/svg/flags/cf.svg +15 -0
  70. package/src/runtime/assets/svg/flags/cg.svg +12 -0
  71. package/src/runtime/assets/svg/flags/ch.svg +9 -0
  72. package/src/runtime/assets/svg/flags/ci.svg +7 -0
  73. package/src/runtime/assets/svg/flags/ck.svg +9 -0
  74. package/src/runtime/assets/svg/flags/cl.svg +13 -0
  75. package/src/runtime/assets/svg/flags/cm.svg +15 -0
  76. package/src/runtime/assets/svg/flags/cn.svg +11 -0
  77. package/src/runtime/assets/svg/flags/co.svg +7 -0
  78. package/src/runtime/assets/svg/flags/cp.svg +7 -0
  79. package/src/runtime/assets/svg/flags/cr.svg +7 -0
  80. package/src/runtime/assets/svg/flags/cu.svg +13 -0
  81. package/src/runtime/assets/svg/flags/cv.svg +13 -0
  82. package/src/runtime/assets/svg/flags/cw.svg +14 -0
  83. package/src/runtime/assets/svg/flags/cx.svg +15 -0
  84. package/src/runtime/assets/svg/flags/cy.svg +6 -0
  85. package/src/runtime/assets/svg/flags/cz.svg +5 -0
  86. package/src/runtime/assets/svg/flags/de.svg +5 -0
  87. package/src/runtime/assets/svg/flags/dg.svg +130 -0
  88. package/src/runtime/assets/svg/flags/dj.svg +13 -0
  89. package/src/runtime/assets/svg/flags/dk.svg +5 -0
  90. package/src/runtime/assets/svg/flags/dm.svg +152 -0
  91. package/src/runtime/assets/svg/flags/do.svg +121 -0
  92. package/src/runtime/assets/svg/flags/dz.svg +5 -0
  93. package/src/runtime/assets/svg/flags/eac.svg +48 -0
  94. package/src/runtime/assets/svg/flags/ec.svg +138 -0
  95. package/src/runtime/assets/svg/flags/ee.svg +5 -0
  96. package/src/runtime/assets/svg/flags/eg.svg +38 -0
  97. package/src/runtime/assets/svg/flags/eh.svg +16 -0
  98. package/src/runtime/assets/svg/flags/er.svg +8 -0
  99. package/src/runtime/assets/svg/flags/es-ct.svg +4 -0
  100. package/src/runtime/assets/svg/flags/es-ga.svg +187 -0
  101. package/src/runtime/assets/svg/flags/es-pv.svg +5 -0
  102. package/src/runtime/assets/svg/flags/es.svg +544 -0
  103. package/src/runtime/assets/svg/flags/et.svg +14 -0
  104. package/src/runtime/assets/svg/flags/eu.svg +28 -0
  105. package/src/runtime/assets/svg/flags/fi.svg +5 -0
  106. package/src/runtime/assets/svg/flags/fj.svg +120 -0
  107. package/src/runtime/assets/svg/flags/fk.svg +90 -0
  108. package/src/runtime/assets/svg/flags/fm.svg +11 -0
  109. package/src/runtime/assets/svg/flags/fo.svg +12 -0
  110. package/src/runtime/assets/svg/flags/fr.svg +5 -0
  111. package/src/runtime/assets/svg/flags/ga.svg +7 -0
  112. package/src/runtime/assets/svg/flags/gb-eng.svg +5 -0
  113. package/src/runtime/assets/svg/flags/gb-nir.svg +132 -0
  114. package/src/runtime/assets/svg/flags/gb-sct.svg +4 -0
  115. package/src/runtime/assets/svg/flags/gb-wls.svg +9 -0
  116. package/src/runtime/assets/svg/flags/gb.svg +7 -0
  117. package/src/runtime/assets/svg/flags/gd.svg +27 -0
  118. package/src/runtime/assets/svg/flags/ge.svg +6 -0
  119. package/src/runtime/assets/svg/flags/gf.svg +5 -0
  120. package/src/runtime/assets/svg/flags/gg.svg +9 -0
  121. package/src/runtime/assets/svg/flags/gh.svg +6 -0
  122. package/src/runtime/assets/svg/flags/gi.svg +32 -0
  123. package/src/runtime/assets/svg/flags/gl.svg +4 -0
  124. package/src/runtime/assets/svg/flags/gm.svg +14 -0
  125. package/src/runtime/assets/svg/flags/gn.svg +7 -0
  126. package/src/runtime/assets/svg/flags/gp.svg +5 -0
  127. package/src/runtime/assets/svg/flags/gq.svg +23 -0
  128. package/src/runtime/assets/svg/flags/gr.svg +16 -0
  129. package/src/runtime/assets/svg/flags/gs.svg +133 -0
  130. package/src/runtime/assets/svg/flags/gt.svg +204 -0
  131. package/src/runtime/assets/svg/flags/gu.svg +19 -0
  132. package/src/runtime/assets/svg/flags/gw.svg +13 -0
  133. package/src/runtime/assets/svg/flags/gy.svg +9 -0
  134. package/src/runtime/assets/svg/flags/hk.svg +8 -0
  135. package/src/runtime/assets/svg/flags/hm.svg +8 -0
  136. package/src/runtime/assets/svg/flags/hn.svg +18 -0
  137. package/src/runtime/assets/svg/flags/hr.svg +58 -0
  138. package/src/runtime/assets/svg/flags/ht.svg +116 -0
  139. package/src/runtime/assets/svg/flags/hu.svg +7 -0
  140. package/src/runtime/assets/svg/flags/ic.svg +7 -0
  141. package/src/runtime/assets/svg/flags/id.svg +4 -0
  142. package/src/runtime/assets/svg/flags/ie.svg +7 -0
  143. package/src/runtime/assets/svg/flags/il.svg +14 -0
  144. package/src/runtime/assets/svg/flags/im.svg +36 -0
  145. package/src/runtime/assets/svg/flags/in.svg +25 -0
  146. package/src/runtime/assets/svg/flags/io.svg +130 -0
  147. package/src/runtime/assets/svg/flags/iq.svg +10 -0
  148. package/src/runtime/assets/svg/flags/ir.svg +219 -0
  149. package/src/runtime/assets/svg/flags/is.svg +12 -0
  150. package/src/runtime/assets/svg/flags/it.svg +7 -0
  151. package/src/runtime/assets/svg/flags/je.svg +62 -0
  152. package/src/runtime/assets/svg/flags/jm.svg +8 -0
  153. package/src/runtime/assets/svg/flags/jo.svg +16 -0
  154. package/src/runtime/assets/svg/flags/jp.svg +11 -0
  155. package/src/runtime/assets/svg/flags/ke.svg +23 -0
  156. package/src/runtime/assets/svg/flags/kg.svg +4 -0
  157. package/src/runtime/assets/svg/flags/kh.svg +61 -0
  158. package/src/runtime/assets/svg/flags/ki.svg +36 -0
  159. package/src/runtime/assets/svg/flags/km.svg +16 -0
  160. package/src/runtime/assets/svg/flags/kn.svg +14 -0
  161. package/src/runtime/assets/svg/flags/kp.svg +15 -0
  162. package/src/runtime/assets/svg/flags/kr.svg +24 -0
  163. package/src/runtime/assets/svg/flags/kw.svg +13 -0
  164. package/src/runtime/assets/svg/flags/ky.svg +103 -0
  165. package/src/runtime/assets/svg/flags/kz.svg +36 -0
  166. package/src/runtime/assets/svg/flags/la.svg +12 -0
  167. package/src/runtime/assets/svg/flags/lb.svg +15 -0
  168. package/src/runtime/assets/svg/flags/lc.svg +8 -0
  169. package/src/runtime/assets/svg/flags/li.svg +43 -0
  170. package/src/runtime/assets/svg/flags/lk.svg +22 -0
  171. package/src/runtime/assets/svg/flags/lr.svg +14 -0
  172. package/src/runtime/assets/svg/flags/ls.svg +8 -0
  173. package/src/runtime/assets/svg/flags/lt.svg +7 -0
  174. package/src/runtime/assets/svg/flags/lu.svg +5 -0
  175. package/src/runtime/assets/svg/flags/lv.svg +6 -0
  176. package/src/runtime/assets/svg/flags/ly.svg +13 -0
  177. package/src/runtime/assets/svg/flags/ma.svg +4 -0
  178. package/src/runtime/assets/svg/flags/mc.svg +6 -0
  179. package/src/runtime/assets/svg/flags/md.svg +70 -0
  180. package/src/runtime/assets/svg/flags/me.svg +116 -0
  181. package/src/runtime/assets/svg/flags/mf.svg +5 -0
  182. package/src/runtime/assets/svg/flags/mg.svg +7 -0
  183. package/src/runtime/assets/svg/flags/mh.svg +7 -0
  184. package/src/runtime/assets/svg/flags/mk.svg +5 -0
  185. package/src/runtime/assets/svg/flags/ml.svg +7 -0
  186. package/src/runtime/assets/svg/flags/mm.svg +12 -0
  187. package/src/runtime/assets/svg/flags/mn.svg +14 -0
  188. package/src/runtime/assets/svg/flags/mo.svg +9 -0
  189. package/src/runtime/assets/svg/flags/mp.svg +86 -0
  190. package/src/runtime/assets/svg/flags/mq.svg +5 -0
  191. package/src/runtime/assets/svg/flags/mr.svg +6 -0
  192. package/src/runtime/assets/svg/flags/ms.svg +29 -0
  193. package/src/runtime/assets/svg/flags/mt.svg +58 -0
  194. package/src/runtime/assets/svg/flags/mu.svg +8 -0
  195. package/src/runtime/assets/svg/flags/mv.svg +6 -0
  196. package/src/runtime/assets/svg/flags/mw.svg +10 -0
  197. package/src/runtime/assets/svg/flags/mx.svg +382 -0
  198. package/src/runtime/assets/svg/flags/my.svg +26 -0
  199. package/src/runtime/assets/svg/flags/mz.svg +21 -0
  200. package/src/runtime/assets/svg/flags/na.svg +16 -0
  201. package/src/runtime/assets/svg/flags/nc.svg +13 -0
  202. package/src/runtime/assets/svg/flags/ne.svg +6 -0
  203. package/src/runtime/assets/svg/flags/nf.svg +9 -0
  204. package/src/runtime/assets/svg/flags/ng.svg +6 -0
  205. package/src/runtime/assets/svg/flags/ni.svg +129 -0
  206. package/src/runtime/assets/svg/flags/nl.svg +5 -0
  207. package/src/runtime/assets/svg/flags/no.svg +7 -0
  208. package/src/runtime/assets/svg/flags/np.svg +13 -0
  209. package/src/runtime/assets/svg/flags/nr.svg +12 -0
  210. package/src/runtime/assets/svg/flags/nu.svg +10 -0
  211. package/src/runtime/assets/svg/flags/nz.svg +36 -0
  212. package/src/runtime/assets/svg/flags/om.svg +115 -0
  213. package/src/runtime/assets/svg/flags/pa.svg +14 -0
  214. package/src/runtime/assets/svg/flags/pc.svg +33 -0
  215. package/src/runtime/assets/svg/flags/pe.svg +4 -0
  216. package/src/runtime/assets/svg/flags/pf.svg +19 -0
  217. package/src/runtime/assets/svg/flags/pg.svg +9 -0
  218. package/src/runtime/assets/svg/flags/ph.svg +6 -0
  219. package/src/runtime/assets/svg/flags/pk.svg +15 -0
  220. package/src/runtime/assets/svg/flags/pl.svg +6 -0
  221. package/src/runtime/assets/svg/flags/pm.svg +5 -0
  222. package/src/runtime/assets/svg/flags/pn.svg +53 -0
  223. package/src/runtime/assets/svg/flags/pr.svg +13 -0
  224. package/src/runtime/assets/svg/flags/ps.svg +15 -0
  225. package/src/runtime/assets/svg/flags/pt.svg +57 -0
  226. package/src/runtime/assets/svg/flags/pw.svg +11 -0
  227. package/src/runtime/assets/svg/flags/py.svg +157 -0
  228. package/src/runtime/assets/svg/flags/qa.svg +4 -0
  229. package/src/runtime/assets/svg/flags/re.svg +5 -0
  230. package/src/runtime/assets/svg/flags/ro.svg +7 -0
  231. package/src/runtime/assets/svg/flags/rs.svg +292 -0
  232. package/src/runtime/assets/svg/flags/ru.svg +5 -0
  233. package/src/runtime/assets/svg/flags/rw.svg +13 -0
  234. package/src/runtime/assets/svg/flags/sa.svg +25 -0
  235. package/src/runtime/assets/svg/flags/sb.svg +13 -0
  236. package/src/runtime/assets/svg/flags/sc.svg +7 -0
  237. package/src/runtime/assets/svg/flags/sd.svg +13 -0
  238. package/src/runtime/assets/svg/flags/se.svg +4 -0
  239. package/src/runtime/assets/svg/flags/sg.svg +13 -0
  240. package/src/runtime/assets/svg/flags/sh-ac.svg +689 -0
  241. package/src/runtime/assets/svg/flags/sh-hl.svg +164 -0
  242. package/src/runtime/assets/svg/flags/sh-ta.svg +76 -0
  243. package/src/runtime/assets/svg/flags/sh.svg +7 -0
  244. package/src/runtime/assets/svg/flags/si.svg +18 -0
  245. package/src/runtime/assets/svg/flags/sj.svg +7 -0
  246. package/src/runtime/assets/svg/flags/sk.svg +9 -0
  247. package/src/runtime/assets/svg/flags/sl.svg +7 -0
  248. package/src/runtime/assets/svg/flags/sm.svg +75 -0
  249. package/src/runtime/assets/svg/flags/sn.svg +8 -0
  250. package/src/runtime/assets/svg/flags/so.svg +11 -0
  251. package/src/runtime/assets/svg/flags/sr.svg +6 -0
  252. package/src/runtime/assets/svg/flags/ss.svg +8 -0
  253. package/src/runtime/assets/svg/flags/st.svg +16 -0
  254. package/src/runtime/assets/svg/flags/state/ft.svg +5503 -0
  255. package/src/runtime/assets/svg/flags/state/johor.svg +59 -0
  256. package/src/runtime/assets/svg/flags/state/kedah.svg +246 -0
  257. package/src/runtime/assets/svg/flags/state/kelantan.svg +84 -0
  258. package/src/runtime/assets/svg/flags/state/kuala_lumpur.svg +9 -0
  259. package/src/runtime/assets/svg/flags/state/labuan.svg +10 -0
  260. package/src/runtime/assets/svg/flags/state/melaka.svg +56 -0
  261. package/src/runtime/assets/svg/flags/state/negeri_sembilan.svg +5 -0
  262. package/src/runtime/assets/svg/flags/state/pahang.svg +5 -0
  263. package/src/runtime/assets/svg/flags/state/penang.svg +514 -0
  264. package/src/runtime/assets/svg/flags/state/perak.svg +5 -0
  265. package/src/runtime/assets/svg/flags/state/perlis.svg +5 -0
  266. package/src/runtime/assets/svg/flags/state/putrajaya.svg +2631 -0
  267. package/src/runtime/assets/svg/flags/state/sabah.svg +8 -0
  268. package/src/runtime/assets/svg/flags/state/sarawak.svg +18 -0
  269. package/src/runtime/assets/svg/flags/state/selangor.svg +20 -0
  270. package/src/runtime/assets/svg/flags/state/terengganu.svg +6 -0
  271. package/src/runtime/assets/svg/flags/sv.svg +593 -0
  272. package/src/runtime/assets/svg/flags/sx.svg +56 -0
  273. package/src/runtime/assets/svg/flags/sy.svg +6 -0
  274. package/src/runtime/assets/svg/flags/sz.svg +34 -0
  275. package/src/runtime/assets/svg/flags/tc.svg +50 -0
  276. package/src/runtime/assets/svg/flags/td.svg +7 -0
  277. package/src/runtime/assets/svg/flags/tf.svg +15 -0
  278. package/src/runtime/assets/svg/flags/tg.svg +14 -0
  279. package/src/runtime/assets/svg/flags/th.svg +7 -0
  280. package/src/runtime/assets/svg/flags/tj.svg +22 -0
  281. package/src/runtime/assets/svg/flags/tk.svg +5 -0
  282. package/src/runtime/assets/svg/flags/tl.svg +13 -0
  283. package/src/runtime/assets/svg/flags/tm.svg +204 -0
  284. package/src/runtime/assets/svg/flags/tn.svg +4 -0
  285. package/src/runtime/assets/svg/flags/to.svg +10 -0
  286. package/src/runtime/assets/svg/flags/tr.svg +8 -0
  287. package/src/runtime/assets/svg/flags/tt.svg +5 -0
  288. package/src/runtime/assets/svg/flags/tv.svg +9 -0
  289. package/src/runtime/assets/svg/flags/tw.svg +34 -0
  290. package/src/runtime/assets/svg/flags/tz.svg +13 -0
  291. package/src/runtime/assets/svg/flags/ua.svg +6 -0
  292. package/src/runtime/assets/svg/flags/ug.svg +30 -0
  293. package/src/runtime/assets/svg/flags/um.svg +9 -0
  294. package/src/runtime/assets/svg/flags/un.svg +16 -0
  295. package/src/runtime/assets/svg/flags/us.svg +9 -0
  296. package/src/runtime/assets/svg/flags/uy.svg +28 -0
  297. package/src/runtime/assets/svg/flags/uz.svg +30 -0
  298. package/src/runtime/assets/svg/flags/va.svg +190 -0
  299. package/src/runtime/assets/svg/flags/vc.svg +8 -0
  300. package/src/runtime/assets/svg/flags/ve.svg +26 -0
  301. package/src/runtime/assets/svg/flags/vg.svg +59 -0
  302. package/src/runtime/assets/svg/flags/vi.svg +28 -0
  303. package/src/runtime/assets/svg/flags/vn.svg +11 -0
  304. package/src/runtime/assets/svg/flags/vu.svg +21 -0
  305. package/src/runtime/assets/svg/flags/wf.svg +5 -0
  306. package/src/runtime/assets/svg/flags/ws.svg +7 -0
  307. package/src/runtime/assets/svg/flags/xk.svg +5 -0
  308. package/src/runtime/assets/svg/flags/xx.svg +4 -0
  309. package/src/runtime/assets/svg/flags/ye.svg +7 -0
  310. package/src/runtime/assets/svg/flags/yt.svg +5 -0
  311. package/src/runtime/assets/svg/flags/za.svg +17 -0
  312. package/src/runtime/assets/svg/flags/zm.svg +27 -0
  313. package/src/runtime/assets/svg/flags/zw.svg +21 -0
  314. package/src/runtime/assets/svg/icon/activity.svg +4 -0
  315. package/src/runtime/assets/svg/icon/arrow-left.svg +3 -0
  316. package/src/runtime/assets/svg/icon/arrow-right.svg +3 -0
  317. package/src/runtime/assets/svg/icon/building-07.svg +4 -0
  318. package/src/runtime/assets/svg/icon/car-01.svg +4 -0
  319. package/src/runtime/assets/svg/icon/cash.svg +3 -0
  320. package/src/runtime/assets/svg/icon/clipboard-check.svg +3 -0
  321. package/src/runtime/assets/svg/icon/cog.svg +3 -0
  322. package/src/runtime/assets/svg/icon/colapse-sidebar.svg +3 -0
  323. package/src/runtime/assets/svg/icon/file-chart-bar.svg +3 -0
  324. package/src/runtime/assets/svg/icon/frame.svg +3 -0
  325. package/src/runtime/assets/svg/icon/gift-09.svg +7 -0
  326. package/src/runtime/assets/svg/icon/grid.svg +227 -0
  327. package/src/runtime/assets/svg/icon/layers.svg +3 -0
  328. package/src/runtime/assets/svg/icon/medical-cross.svg +3 -0
  329. package/src/runtime/assets/svg/icon/minimise-sidebar.svg +3 -0
  330. package/src/runtime/assets/svg/icon/rocket.svg +3 -0
  331. package/src/runtime/assets/svg/icon/speedometer-04.svg +5 -0
  332. package/src/runtime/assets/svg/icon/user-headset.svg +3 -0
  333. package/src/runtime/assets/svg/icon/users-group.svg +3 -0
  334. package/src/runtime/assets/svg/icon/users.svg +3 -0
  335. package/src/runtime/assets/svg/images/document-folders.svg +86 -0
  336. package/src/runtime/assets/svg/images/error-404.svg +56 -0
  337. package/src/runtime/assets/svg/images/error-500.svg +243 -0
  338. package/src/runtime/assets/svg/images/login-right-content.svg +272 -0
  339. package/src/runtime/assets/svg/images/man-question-mark.svg +130 -0
  340. package/src/runtime/assets/svg/logo/logomark.svg +4 -0
  341. package/src/runtime/assets/svg/logo/logotext.svg +10 -0
  342. package/src/runtime/components/base/event-calendar/AgendaView.vue +92 -0
  343. package/src/runtime/components/base/event-calendar/ColorManager.vue +149 -0
  344. package/src/runtime/components/base/event-calendar/DayEventsOverflowPopup.vue +41 -0
  345. package/src/runtime/components/base/event-calendar/DayView.vue +254 -0
  346. package/src/runtime/components/base/event-calendar/DragDropVisualFeedback.vue +97 -0
  347. package/src/runtime/components/base/event-calendar/EventCalendar.md +203 -0
  348. package/src/runtime/components/base/event-calendar/EventCalendar.vue +414 -0
  349. package/src/runtime/components/base/event-calendar/EventModal.vue +573 -0
  350. package/src/runtime/components/base/event-calendar/EventResizeHandle.vue +284 -0
  351. package/src/runtime/components/base/event-calendar/ExternalCalendarSettings.vue +138 -0
  352. package/src/runtime/components/base/event-calendar/LocationDisplay.vue +62 -0
  353. package/src/runtime/components/base/event-calendar/MonthView.vue +272 -0
  354. package/src/runtime/components/base/event-calendar/WeekView.vue +329 -0
  355. package/src/runtime/components/base/event-calendar/composables/useAdvancedValidation.ts +557 -0
  356. package/src/runtime/components/base/event-calendar/composables/useCalendarUtils.ts +70 -0
  357. package/src/runtime/components/base/event-calendar/composables/useColorManager.ts +244 -0
  358. package/src/runtime/components/base/event-calendar/composables/useCompatibility.ts +318 -0
  359. package/src/runtime/components/base/event-calendar/composables/useDragAndDrop.ts +481 -0
  360. package/src/runtime/components/base/event-calendar/composables/useEventFiltering.ts +116 -0
  361. package/src/runtime/components/base/event-calendar/composables/useEventStatus.ts +108 -0
  362. package/src/runtime/components/base/event-calendar/composables/useEventStore.ts +325 -0
  363. package/src/runtime/components/base/event-calendar/composables/useExternalCalendar.ts +340 -0
  364. package/src/runtime/components/base/event-calendar/composables/useKeyboardNavigation.ts +95 -0
  365. package/src/runtime/components/base/event-calendar/composables/useMonitoring.ts +433 -0
  366. package/src/runtime/components/base/event-calendar/composables/useMultiDayLayout.ts +131 -0
  367. package/src/runtime/components/base/event-calendar/composables/usePerformanceCache.ts +134 -0
  368. package/src/runtime/components/base/event-calendar/composables/useRecurringEvents.ts +291 -0
  369. package/src/runtime/components/base/event-calendar/composables/useResilientErrorHandling.ts +480 -0
  370. package/src/runtime/components/base/event-calendar/composables/useSecurity.ts +425 -0
  371. package/src/runtime/components/base/event-calendar/composables/useTimezone.ts +256 -0
  372. package/src/runtime/components/base/event-calendar/constants.ts +18 -0
  373. package/src/runtime/components/base/event-calendar/eventModal.schema.ts +32 -0
  374. package/src/runtime/components/base/event-calendar/types.ts +96 -0
  375. package/src/runtime/components/base/org-chart/index.vue +359 -0
  376. package/src/runtime/components/base/org-chart/main.ts +2372 -0
  377. package/src/runtime/components/base/org-chart/svg-icons.ts +58 -0
  378. package/src/runtime/components/base/org-chart/types.ts +492 -0
  379. package/src/runtime/components/base/signature/index.vue +218 -0
  380. package/src/runtime/components/base/toast/Toast.vue +396 -0
  381. package/src/runtime/components/base/toast/Toaster.vue +1241 -0
  382. package/src/runtime/components/base/toast/assets/CloseIcon.vue +3 -0
  383. package/src/runtime/components/base/toast/assets/ErrorIcon.vue +7 -0
  384. package/src/runtime/components/base/toast/assets/IconWrapper.vue +13 -0
  385. package/src/runtime/components/base/toast/assets/InfoIcon.vue +7 -0
  386. package/src/runtime/components/base/toast/assets/Loader.vue +18 -0
  387. package/src/runtime/components/base/toast/assets/SuccessIcon.vue +7 -0
  388. package/src/runtime/components/base/toast/assets/WarningIcon.vue +7 -0
  389. package/src/runtime/components/base/toast/constant.ts +30 -0
  390. package/src/runtime/components/base/toast/hooks.ts +114 -0
  391. package/src/runtime/components/base/toast/state.ts +317 -0
  392. package/src/runtime/components/base/toast/types.ts +201 -0
  393. package/src/runtime/components/chart/Bar.vue +175 -0
  394. package/src/runtime/components/chart/Line.vue +149 -0
  395. package/src/runtime/components/chart/Pie.vue +115 -0
  396. package/src/runtime/components/chart/Radar.vue +167 -0
  397. package/src/runtime/components/dynect/Accordion.vue +152 -0
  398. package/src/runtime/components/dynect/Alert.vue +194 -0
  399. package/src/runtime/components/dynect/Autocomplete.vue +404 -0
  400. package/src/runtime/components/dynect/Avatar.vue +132 -0
  401. package/src/runtime/components/dynect/AvatarGroup.vue +56 -0
  402. package/src/runtime/components/dynect/AvatarLabel.vue +82 -0
  403. package/src/runtime/components/dynect/Badge.vue +101 -0
  404. package/src/runtime/components/dynect/Button.vue +36 -0
  405. package/src/runtime/components/dynect/Checkbox.vue +80 -0
  406. package/src/runtime/components/dynect/DatePicker.vue +180 -0
  407. package/src/runtime/components/dynect/DateRange.vue +217 -0
  408. package/src/runtime/components/dynect/Dropzone.vue +355 -0
  409. package/src/runtime/components/dynect/EventCalendar.vue +66 -0
  410. package/src/runtime/components/dynect/Filters.vue +162 -0
  411. package/src/runtime/components/dynect/FormDescription.vue +20 -0
  412. package/src/runtime/components/dynect/FormError.vue +20 -0
  413. package/src/runtime/components/dynect/FormField.vue +45 -0
  414. package/src/runtime/components/dynect/FormLabel.vue +40 -0
  415. package/src/runtime/components/dynect/Gantt.vue +231 -0
  416. package/src/runtime/components/dynect/Input.vue +234 -0
  417. package/src/runtime/components/dynect/Kanban.vue +128 -0
  418. package/src/runtime/components/dynect/Modal.vue +118 -0
  419. package/src/runtime/components/dynect/OtpInput.vue +148 -0
  420. package/src/runtime/components/dynect/Pagination.vue +57 -0
  421. package/src/runtime/components/dynect/PermissionGuard.vue +50 -0
  422. package/src/runtime/components/dynect/Progress.vue +102 -0
  423. package/src/runtime/components/dynect/Radio.vue +90 -0
  424. package/src/runtime/components/dynect/Select.vue +190 -0
  425. package/src/runtime/components/dynect/SelectMultiple.vue +259 -0
  426. package/src/runtime/components/dynect/Sheet.vue +80 -0
  427. package/src/runtime/components/dynect/Signature.vue +135 -0
  428. package/src/runtime/components/dynect/SwitchColor.vue +14 -0
  429. package/src/runtime/components/dynect/SwitchLanguage.vue +39 -0
  430. package/src/runtime/components/dynect/Table.vue +488 -0
  431. package/src/runtime/components/dynect/TagsInput.vue +388 -0
  432. package/src/runtime/components/dynect/Telephone.vue +651 -0
  433. package/src/runtime/components/dynect/TextEditor.vue +94 -0
  434. package/src/runtime/components/dynect/Textarea.vue +108 -0
  435. package/src/runtime/components/dynect/TimePicker.vue +275 -0
  436. package/src/runtime/components/dynect/Timeline.vue +301 -0
  437. package/src/runtime/components/dynect/Toggle.vue +100 -0
  438. package/src/runtime/components/ui/accordion/Accordion.vue +15 -0
  439. package/src/runtime/components/ui/accordion/AccordionContent.vue +19 -0
  440. package/src/runtime/components/ui/accordion/AccordionItem.vue +19 -0
  441. package/src/runtime/components/ui/accordion/AccordionTrigger.vue +32 -0
  442. package/src/runtime/components/ui/accordion/index.ts +4 -0
  443. package/src/runtime/components/ui/alert/Alert.vue +17 -0
  444. package/src/runtime/components/ui/alert/AlertDescription.vue +14 -0
  445. package/src/runtime/components/ui/alert/AlertTitle.vue +14 -0
  446. package/src/runtime/components/ui/alert/index.ts +20 -0
  447. package/src/runtime/components/ui/alert-dialog/AlertDialog.vue +15 -0
  448. package/src/runtime/components/ui/alert-dialog/AlertDialogAction.vue +18 -0
  449. package/src/runtime/components/ui/alert-dialog/AlertDialogCancel.vue +18 -0
  450. package/src/runtime/components/ui/alert-dialog/AlertDialogContent.vue +36 -0
  451. package/src/runtime/components/ui/alert-dialog/AlertDialogDescription.vue +17 -0
  452. package/src/runtime/components/ui/alert-dialog/AlertDialogFooter.vue +14 -0
  453. package/src/runtime/components/ui/alert-dialog/AlertDialogHeader.vue +14 -0
  454. package/src/runtime/components/ui/alert-dialog/AlertDialogTitle.vue +17 -0
  455. package/src/runtime/components/ui/alert-dialog/AlertDialogTrigger.vue +12 -0
  456. package/src/runtime/components/ui/alert-dialog/index.ts +9 -0
  457. package/src/runtime/components/ui/aspect-ratio/AspectRatio.vue +12 -0
  458. package/src/runtime/components/ui/aspect-ratio/index.ts +1 -0
  459. package/src/runtime/components/ui/avatar/Avatar.vue +15 -0
  460. package/src/runtime/components/ui/avatar/AvatarFallback.vue +17 -0
  461. package/src/runtime/components/ui/avatar/AvatarImage.vue +12 -0
  462. package/src/runtime/components/ui/avatar/index.ts +3 -0
  463. package/src/runtime/components/ui/badge/Badge.vue +24 -0
  464. package/src/runtime/components/ui/badge/index.ts +22 -0
  465. package/src/runtime/components/ui/breadcrumb/Breadcrumb.vue +13 -0
  466. package/src/runtime/components/ui/breadcrumb/BreadcrumbEllipsis.vue +18 -0
  467. package/src/runtime/components/ui/breadcrumb/BreadcrumbItem.vue +14 -0
  468. package/src/runtime/components/ui/breadcrumb/BreadcrumbLink.vue +16 -0
  469. package/src/runtime/components/ui/breadcrumb/BreadcrumbList.vue +14 -0
  470. package/src/runtime/components/ui/breadcrumb/BreadcrumbPage.vue +14 -0
  471. package/src/runtime/components/ui/breadcrumb/BreadcrumbSeparator.vue +17 -0
  472. package/src/runtime/components/ui/breadcrumb/index.ts +7 -0
  473. package/src/runtime/components/ui/button/Button.vue +38 -0
  474. package/src/runtime/components/ui/button/index.ts +51 -0
  475. package/src/runtime/components/ui/button-group/ButtonGroup.vue +17 -0
  476. package/src/runtime/components/ui/button-group/ButtonGroupSeparator.vue +16 -0
  477. package/src/runtime/components/ui/button-group/ButtonGroupText.vue +22 -0
  478. package/src/runtime/components/ui/button-group/index.ts +23 -0
  479. package/src/runtime/components/ui/calendar/Calendar.vue +163 -0
  480. package/src/runtime/components/ui/calendar/CalendarCell.vue +19 -0
  481. package/src/runtime/components/ui/calendar/CalendarCellTrigger.vue +47 -0
  482. package/src/runtime/components/ui/calendar/CalendarGrid.vue +19 -0
  483. package/src/runtime/components/ui/calendar/CalendarGridBody.vue +12 -0
  484. package/src/runtime/components/ui/calendar/CalendarGridHead.vue +13 -0
  485. package/src/runtime/components/ui/calendar/CalendarGridRow.vue +19 -0
  486. package/src/runtime/components/ui/calendar/CalendarHeadCell.vue +19 -0
  487. package/src/runtime/components/ui/calendar/CalendarHeader.vue +19 -0
  488. package/src/runtime/components/ui/calendar/CalendarHeading.vue +25 -0
  489. package/src/runtime/components/ui/calendar/CalendarNextButton.vue +22 -0
  490. package/src/runtime/components/ui/calendar/CalendarPrevButton.vue +22 -0
  491. package/src/runtime/components/ui/calendar/index.ts +14 -0
  492. package/src/runtime/components/ui/card/Card.vue +14 -0
  493. package/src/runtime/components/ui/card/CardAction.vue +14 -0
  494. package/src/runtime/components/ui/card/CardContent.vue +14 -0
  495. package/src/runtime/components/ui/card/CardDescription.vue +14 -0
  496. package/src/runtime/components/ui/card/CardFooter.vue +14 -0
  497. package/src/runtime/components/ui/card/CardHeader.vue +14 -0
  498. package/src/runtime/components/ui/card/CardTitle.vue +14 -0
  499. package/src/runtime/components/ui/card/index.ts +7 -0
  500. package/src/runtime/components/ui/carousel/Carousel.vue +46 -0
  501. package/src/runtime/components/ui/carousel/CarouselContent.vue +21 -0
  502. package/src/runtime/components/ui/carousel/CarouselItem.vue +15 -0
  503. package/src/runtime/components/ui/carousel/CarouselNext.vue +32 -0
  504. package/src/runtime/components/ui/carousel/CarouselPrevious.vue +32 -0
  505. package/src/runtime/components/ui/carousel/index.ts +8 -0
  506. package/src/runtime/components/ui/carousel/interface.ts +22 -0
  507. package/src/runtime/components/ui/carousel/useCarousel.ts +51 -0
  508. package/src/runtime/components/ui/chart/ChartContainer.vue +61 -0
  509. package/src/runtime/components/ui/chart/ChartLegendContent.vue +52 -0
  510. package/src/runtime/components/ui/chart/ChartStyle.vue +37 -0
  511. package/src/runtime/components/ui/chart/ChartTooltipContent.vue +92 -0
  512. package/src/runtime/components/ui/chart/index.ts +26 -0
  513. package/src/runtime/components/ui/chart/utils.ts +45 -0
  514. package/src/runtime/components/ui/checkbox/Checkbox.vue +34 -0
  515. package/src/runtime/components/ui/checkbox/index.ts +1 -0
  516. package/src/runtime/components/ui/collapsible/Collapsible.vue +15 -0
  517. package/src/runtime/components/ui/collapsible/CollapsibleContent.vue +12 -0
  518. package/src/runtime/components/ui/collapsible/CollapsibleTrigger.vue +12 -0
  519. package/src/runtime/components/ui/collapsible/index.ts +3 -0
  520. package/src/runtime/components/ui/combobox/Combobox.vue +15 -0
  521. package/src/runtime/components/ui/combobox/ComboboxAnchor.vue +19 -0
  522. package/src/runtime/components/ui/combobox/ComboboxEmpty.vue +17 -0
  523. package/src/runtime/components/ui/combobox/ComboboxGroup.vue +25 -0
  524. package/src/runtime/components/ui/combobox/ComboboxInput.vue +33 -0
  525. package/src/runtime/components/ui/combobox/ComboboxItem.vue +29 -0
  526. package/src/runtime/components/ui/combobox/ComboboxItemIndicator.vue +19 -0
  527. package/src/runtime/components/ui/combobox/ComboboxList.vue +38 -0
  528. package/src/runtime/components/ui/combobox/ComboboxSeparator.vue +17 -0
  529. package/src/runtime/components/ui/combobox/ComboboxTrigger.vue +19 -0
  530. package/src/runtime/components/ui/combobox/ComboboxViewport.vue +19 -0
  531. package/src/runtime/components/ui/combobox/index.ts +12 -0
  532. package/src/runtime/components/ui/command/Command.vue +85 -0
  533. package/src/runtime/components/ui/command/CommandDialog.vue +36 -0
  534. package/src/runtime/components/ui/command/CommandEmpty.vue +22 -0
  535. package/src/runtime/components/ui/command/CommandGroup.vue +40 -0
  536. package/src/runtime/components/ui/command/CommandInput.vue +38 -0
  537. package/src/runtime/components/ui/command/CommandItem.vue +80 -0
  538. package/src/runtime/components/ui/command/CommandList.vue +21 -0
  539. package/src/runtime/components/ui/command/CommandSeparator.vue +17 -0
  540. package/src/runtime/components/ui/command/CommandShortcut.vue +14 -0
  541. package/src/runtime/components/ui/command/index.ts +25 -0
  542. package/src/runtime/components/ui/context-menu/ContextMenu.vue +15 -0
  543. package/src/runtime/components/ui/context-menu/ContextMenuCheckboxItem.vue +37 -0
  544. package/src/runtime/components/ui/context-menu/ContextMenuContent.vue +35 -0
  545. package/src/runtime/components/ui/context-menu/ContextMenuGroup.vue +12 -0
  546. package/src/runtime/components/ui/context-menu/ContextMenuItem.vue +42 -0
  547. package/src/runtime/components/ui/context-menu/ContextMenuLabel.vue +17 -0
  548. package/src/runtime/components/ui/context-menu/ContextMenuPortal.vue +12 -0
  549. package/src/runtime/components/ui/context-menu/ContextMenuRadioGroup.vue +15 -0
  550. package/src/runtime/components/ui/context-menu/ContextMenuRadioItem.vue +37 -0
  551. package/src/runtime/components/ui/context-menu/ContextMenuSeparator.vue +15 -0
  552. package/src/runtime/components/ui/context-menu/ContextMenuShortcut.vue +14 -0
  553. package/src/runtime/components/ui/context-menu/ContextMenuSub.vue +15 -0
  554. package/src/runtime/components/ui/context-menu/ContextMenuSubContent.vue +29 -0
  555. package/src/runtime/components/ui/context-menu/ContextMenuSubTrigger.vue +31 -0
  556. package/src/runtime/components/ui/context-menu/ContextMenuTrigger.vue +14 -0
  557. package/src/runtime/components/ui/context-menu/index.ts +14 -0
  558. package/src/runtime/components/ui/dialog/Dialog.vue +15 -0
  559. package/src/runtime/components/ui/dialog/DialogClose.vue +12 -0
  560. package/src/runtime/components/ui/dialog/DialogContent.vue +49 -0
  561. package/src/runtime/components/ui/dialog/DialogDescription.vue +19 -0
  562. package/src/runtime/components/ui/dialog/DialogFooter.vue +25 -0
  563. package/src/runtime/components/ui/dialog/DialogHeader.vue +14 -0
  564. package/src/runtime/components/ui/dialog/DialogOverlay.vue +17 -0
  565. package/src/runtime/components/ui/dialog/DialogScrollContent.vue +46 -0
  566. package/src/runtime/components/ui/dialog/DialogTitle.vue +19 -0
  567. package/src/runtime/components/ui/dialog/DialogTrigger.vue +12 -0
  568. package/src/runtime/components/ui/dialog/index.ts +10 -0
  569. package/src/runtime/components/ui/drawer/Drawer.vue +19 -0
  570. package/src/runtime/components/ui/drawer/DrawerClose.vue +12 -0
  571. package/src/runtime/components/ui/drawer/DrawerContent.vue +40 -0
  572. package/src/runtime/components/ui/drawer/DrawerDescription.vue +17 -0
  573. package/src/runtime/components/ui/drawer/DrawerFooter.vue +14 -0
  574. package/src/runtime/components/ui/drawer/DrawerHeader.vue +14 -0
  575. package/src/runtime/components/ui/drawer/DrawerOverlay.vue +15 -0
  576. package/src/runtime/components/ui/drawer/DrawerTitle.vue +17 -0
  577. package/src/runtime/components/ui/drawer/DrawerTrigger.vue +12 -0
  578. package/src/runtime/components/ui/drawer/index.ts +9 -0
  579. package/src/runtime/components/ui/dropdown-menu/DropdownMenu.vue +15 -0
  580. package/src/runtime/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +37 -0
  581. package/src/runtime/components/ui/dropdown-menu/DropdownMenuContent.vue +37 -0
  582. package/src/runtime/components/ui/dropdown-menu/DropdownMenuGroup.vue +12 -0
  583. package/src/runtime/components/ui/dropdown-menu/DropdownMenuItem.vue +41 -0
  584. package/src/runtime/components/ui/dropdown-menu/DropdownMenuLabel.vue +18 -0
  585. package/src/runtime/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +15 -0
  586. package/src/runtime/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +38 -0
  587. package/src/runtime/components/ui/dropdown-menu/DropdownMenuSeparator.vue +19 -0
  588. package/src/runtime/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
  589. package/src/runtime/components/ui/dropdown-menu/DropdownMenuSub.vue +15 -0
  590. package/src/runtime/components/ui/dropdown-menu/DropdownMenuSubContent.vue +29 -0
  591. package/src/runtime/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +30 -0
  592. package/src/runtime/components/ui/dropdown-menu/DropdownMenuTrigger.vue +14 -0
  593. package/src/runtime/components/ui/dropdown-menu/index.ts +16 -0
  594. package/src/runtime/components/ui/empty/Empty.vue +14 -0
  595. package/src/runtime/components/ui/empty/EmptyContent.vue +14 -0
  596. package/src/runtime/components/ui/empty/EmptyDescription.vue +14 -0
  597. package/src/runtime/components/ui/empty/EmptyHeader.vue +14 -0
  598. package/src/runtime/components/ui/empty/EmptyMedia.vue +17 -0
  599. package/src/runtime/components/ui/empty/EmptyTitle.vue +14 -0
  600. package/src/runtime/components/ui/empty/index.ts +23 -0
  601. package/src/runtime/components/ui/field/Field.vue +17 -0
  602. package/src/runtime/components/ui/field/FieldContent.vue +14 -0
  603. package/src/runtime/components/ui/field/FieldDescription.vue +17 -0
  604. package/src/runtime/components/ui/field/FieldError.vue +45 -0
  605. package/src/runtime/components/ui/field/FieldGroup.vue +14 -0
  606. package/src/runtime/components/ui/field/FieldLabel.vue +31 -0
  607. package/src/runtime/components/ui/field/FieldLegend.vue +15 -0
  608. package/src/runtime/components/ui/field/FieldSeparator.vue +18 -0
  609. package/src/runtime/components/ui/field/FieldSet.vue +14 -0
  610. package/src/runtime/components/ui/field/FieldTitle.vue +14 -0
  611. package/src/runtime/components/ui/field/index.ts +32 -0
  612. package/src/runtime/components/ui/form/FormControl.vue +12 -0
  613. package/src/runtime/components/ui/form/FormDescription.vue +17 -0
  614. package/src/runtime/components/ui/form/FormItem.vue +20 -0
  615. package/src/runtime/components/ui/form/FormLabel.vue +17 -0
  616. package/src/runtime/components/ui/form/FormMessage.vue +17 -0
  617. package/src/runtime/components/ui/form/index.ts +7 -0
  618. package/src/runtime/components/ui/form/injectionKeys.ts +3 -0
  619. package/src/runtime/components/ui/form/useFormField.ts +29 -0
  620. package/src/runtime/components/ui/gantt/Gantt.vue +108 -0
  621. package/src/runtime/components/ui/gantt/GanttCreateMarkerTrigger.vue +44 -0
  622. package/src/runtime/components/ui/gantt/GanttFeatureItem.vue +303 -0
  623. package/src/runtime/components/ui/gantt/GanttFeatureList.vue +16 -0
  624. package/src/runtime/components/ui/gantt/GanttFeatureListGroup.vue +20 -0
  625. package/src/runtime/components/ui/gantt/GanttHeader.vue +197 -0
  626. package/src/runtime/components/ui/gantt/GanttMarker.vue +133 -0
  627. package/src/runtime/components/ui/gantt/GanttSidebar.vue +65 -0
  628. package/src/runtime/components/ui/gantt/GanttSidebarGroup.vue +25 -0
  629. package/src/runtime/components/ui/gantt/GanttSidebarItem.vue +32 -0
  630. package/src/runtime/components/ui/gantt/GanttTimeline.vue +179 -0
  631. package/src/runtime/components/ui/gantt/GanttToday.vue +52 -0
  632. package/src/runtime/components/ui/gantt/GanttZoomControls.vue +49 -0
  633. package/src/runtime/components/ui/gantt/README.md +356 -0
  634. package/src/runtime/components/ui/gantt/index.ts +18 -0
  635. package/src/runtime/components/ui/gantt/meta.json +96 -0
  636. package/src/runtime/components/ui/hover-card/HoverCard.vue +15 -0
  637. package/src/runtime/components/ui/hover-card/HoverCardContent.vue +36 -0
  638. package/src/runtime/components/ui/hover-card/HoverCardTrigger.vue +12 -0
  639. package/src/runtime/components/ui/hover-card/index.ts +3 -0
  640. package/src/runtime/components/ui/inline-editable-input/InlineEditableInput.vue +126 -0
  641. package/src/runtime/components/ui/inline-editable-input/index.ts +1 -0
  642. package/src/runtime/components/ui/input/Input.vue +35 -0
  643. package/src/runtime/components/ui/input/index.ts +1 -0
  644. package/src/runtime/components/ui/input-group/InputGroup.vue +37 -0
  645. package/src/runtime/components/ui/input-group/InputGroupAddon.vue +33 -0
  646. package/src/runtime/components/ui/input-group/InputGroupButton.vue +25 -0
  647. package/src/runtime/components/ui/input-group/InputGroupInput.vue +13 -0
  648. package/src/runtime/components/ui/input-group/InputGroupText.vue +14 -0
  649. package/src/runtime/components/ui/input-group/InputGroupTextarea.vue +13 -0
  650. package/src/runtime/components/ui/input-group/index.ts +41 -0
  651. package/src/runtime/components/ui/input-otp/InputOTP.vue +22 -0
  652. package/src/runtime/components/ui/input-otp/InputOTPGroup.vue +18 -0
  653. package/src/runtime/components/ui/input-otp/InputOTPSeparator.vue +17 -0
  654. package/src/runtime/components/ui/input-otp/InputOTPSlot.vue +37 -0
  655. package/src/runtime/components/ui/input-otp/index.ts +4 -0
  656. package/src/runtime/components/ui/item/Item.vue +27 -0
  657. package/src/runtime/components/ui/item/ItemActions.vue +14 -0
  658. package/src/runtime/components/ui/item/ItemContent.vue +14 -0
  659. package/src/runtime/components/ui/item/ItemDescription.vue +14 -0
  660. package/src/runtime/components/ui/item/ItemFooter.vue +14 -0
  661. package/src/runtime/components/ui/item/ItemGroup.vue +14 -0
  662. package/src/runtime/components/ui/item/ItemHeader.vue +14 -0
  663. package/src/runtime/components/ui/item/ItemMedia.vue +17 -0
  664. package/src/runtime/components/ui/item/ItemSeparator.vue +12 -0
  665. package/src/runtime/components/ui/item/ItemTitle.vue +14 -0
  666. package/src/runtime/components/ui/item/index.ts +47 -0
  667. package/src/runtime/components/ui/kanban/Kanban.vue +42 -0
  668. package/src/runtime/components/ui/kanban/KanbanBoard.vue +75 -0
  669. package/src/runtime/components/ui/kanban/KanbanCard.vue +59 -0
  670. package/src/runtime/components/ui/kanban/KanbanCards.vue +27 -0
  671. package/src/runtime/components/ui/kanban/KanbanHeader.vue +15 -0
  672. package/src/runtime/components/ui/kanban/README.md +184 -0
  673. package/src/runtime/components/ui/kanban/index.ts +8 -0
  674. package/src/runtime/components/ui/kbd/Kbd.vue +23 -0
  675. package/src/runtime/components/ui/kbd/KbdGroup.vue +14 -0
  676. package/src/runtime/components/ui/kbd/index.ts +2 -0
  677. package/src/runtime/components/ui/label/Label.vue +30 -0
  678. package/src/runtime/components/ui/label/index.ts +1 -0
  679. package/src/runtime/components/ui/menubar/Menubar.vue +20 -0
  680. package/src/runtime/components/ui/menubar/MenubarCheckboxItem.vue +37 -0
  681. package/src/runtime/components/ui/menubar/MenubarContent.vue +38 -0
  682. package/src/runtime/components/ui/menubar/MenubarGroup.vue +12 -0
  683. package/src/runtime/components/ui/menubar/MenubarItem.vue +37 -0
  684. package/src/runtime/components/ui/menubar/MenubarLabel.vue +16 -0
  685. package/src/runtime/components/ui/menubar/MenubarMenu.vue +12 -0
  686. package/src/runtime/components/ui/menubar/MenubarRadioGroup.vue +15 -0
  687. package/src/runtime/components/ui/menubar/MenubarRadioItem.vue +37 -0
  688. package/src/runtime/components/ui/menubar/MenubarSeparator.vue +17 -0
  689. package/src/runtime/components/ui/menubar/MenubarShortcut.vue +14 -0
  690. package/src/runtime/components/ui/menubar/MenubarSub.vue +20 -0
  691. package/src/runtime/components/ui/menubar/MenubarSubContent.vue +35 -0
  692. package/src/runtime/components/ui/menubar/MenubarSubTrigger.vue +25 -0
  693. package/src/runtime/components/ui/menubar/MenubarTrigger.vue +19 -0
  694. package/src/runtime/components/ui/menubar/index.ts +15 -0
  695. package/src/runtime/components/ui/native-select/NativeSelect.vue +45 -0
  696. package/src/runtime/components/ui/native-select/NativeSelectOptGroup.vue +15 -0
  697. package/src/runtime/components/ui/native-select/NativeSelectOption.vue +15 -0
  698. package/src/runtime/components/ui/native-select/index.ts +3 -0
  699. package/src/runtime/components/ui/navigation-menu/NavigationMenu.vue +31 -0
  700. package/src/runtime/components/ui/navigation-menu/NavigationMenuContent.vue +30 -0
  701. package/src/runtime/components/ui/navigation-menu/NavigationMenuIndicator.vue +23 -0
  702. package/src/runtime/components/ui/navigation-menu/NavigationMenuItem.vue +17 -0
  703. package/src/runtime/components/ui/navigation-menu/NavigationMenuLink.vue +28 -0
  704. package/src/runtime/components/ui/navigation-menu/NavigationMenuList.vue +19 -0
  705. package/src/runtime/components/ui/navigation-menu/NavigationMenuTrigger.vue +22 -0
  706. package/src/runtime/components/ui/navigation-menu/NavigationMenuViewport.vue +28 -0
  707. package/src/runtime/components/ui/navigation-menu/index.ts +14 -0
  708. package/src/runtime/components/ui/number-field/NumberField.vue +20 -0
  709. package/src/runtime/components/ui/number-field/NumberFieldContent.vue +14 -0
  710. package/src/runtime/components/ui/number-field/NumberFieldDecrement.vue +22 -0
  711. package/src/runtime/components/ui/number-field/NumberFieldIncrement.vue +22 -0
  712. package/src/runtime/components/ui/number-field/NumberFieldInput.vue +16 -0
  713. package/src/runtime/components/ui/number-field/index.ts +5 -0
  714. package/src/runtime/components/ui/pagination/Pagination.vue +23 -0
  715. package/src/runtime/components/ui/pagination/PaginationContent.vue +17 -0
  716. package/src/runtime/components/ui/pagination/PaginationEllipsis.vue +21 -0
  717. package/src/runtime/components/ui/pagination/PaginationFirst.vue +34 -0
  718. package/src/runtime/components/ui/pagination/PaginationItem.vue +44 -0
  719. package/src/runtime/components/ui/pagination/PaginationLast.vue +33 -0
  720. package/src/runtime/components/ui/pagination/PaginationNext.vue +33 -0
  721. package/src/runtime/components/ui/pagination/PaginationPrevious.vue +33 -0
  722. package/src/runtime/components/ui/pagination/index.ts +8 -0
  723. package/src/runtime/components/ui/pin-input/PinInput.vue +22 -0
  724. package/src/runtime/components/ui/pin-input/PinInputGroup.vue +17 -0
  725. package/src/runtime/components/ui/pin-input/PinInputSeparator.vue +16 -0
  726. package/src/runtime/components/ui/pin-input/PinInputSlot.vue +26 -0
  727. package/src/runtime/components/ui/pin-input/index.ts +4 -0
  728. package/src/runtime/components/ui/popover/Popover.vue +15 -0
  729. package/src/runtime/components/ui/popover/PopoverAnchor.vue +12 -0
  730. package/src/runtime/components/ui/popover/PopoverContent.vue +38 -0
  731. package/src/runtime/components/ui/popover/PopoverTrigger.vue +12 -0
  732. package/src/runtime/components/ui/popover/index.ts +4 -0
  733. package/src/runtime/components/ui/progress/Progress.vue +19 -0
  734. package/src/runtime/components/ui/progress/index.ts +1 -0
  735. package/src/runtime/components/ui/radio-group/RadioGroup.vue +20 -0
  736. package/src/runtime/components/ui/radio-group/RadioGroupItem.vue +33 -0
  737. package/src/runtime/components/ui/radio-group/index.ts +2 -0
  738. package/src/runtime/components/ui/range-calendar/RangeCalendar.vue +61 -0
  739. package/src/runtime/components/ui/range-calendar/RangeCalendarCell.vue +32 -0
  740. package/src/runtime/components/ui/range-calendar/RangeCalendarCellTrigger.vue +46 -0
  741. package/src/runtime/components/ui/range-calendar/RangeCalendarGrid.vue +19 -0
  742. package/src/runtime/components/ui/range-calendar/RangeCalendarGridBody.vue +12 -0
  743. package/src/runtime/components/ui/range-calendar/RangeCalendarGridHead.vue +12 -0
  744. package/src/runtime/components/ui/range-calendar/RangeCalendarGridRow.vue +19 -0
  745. package/src/runtime/components/ui/range-calendar/RangeCalendarHeadCell.vue +19 -0
  746. package/src/runtime/components/ui/range-calendar/RangeCalendarHeader.vue +19 -0
  747. package/src/runtime/components/ui/range-calendar/RangeCalendarHeading.vue +25 -0
  748. package/src/runtime/components/ui/range-calendar/RangeCalendarNextButton.vue +22 -0
  749. package/src/runtime/components/ui/range-calendar/RangeCalendarPrevButton.vue +22 -0
  750. package/src/runtime/components/ui/range-calendar/index.ts +12 -0
  751. package/src/runtime/components/ui/resizable/ResizableHandle.vue +35 -0
  752. package/src/runtime/components/ui/resizable/ResizablePanel.vue +16 -0
  753. package/src/runtime/components/ui/resizable/ResizablePanelGroup.vue +20 -0
  754. package/src/runtime/components/ui/resizable/index.ts +3 -0
  755. package/src/runtime/components/ui/scroll-area/ScrollArea.vue +22 -0
  756. package/src/runtime/components/ui/scroll-area/ScrollBar.vue +19 -0
  757. package/src/runtime/components/ui/scroll-area/index.ts +2 -0
  758. package/src/runtime/components/ui/select/Select.vue +15 -0
  759. package/src/runtime/components/ui/select/SelectContent.vue +43 -0
  760. package/src/runtime/components/ui/select/SelectGroup.vue +12 -0
  761. package/src/runtime/components/ui/select/SelectItem.vue +39 -0
  762. package/src/runtime/components/ui/select/SelectItemText.vue +12 -0
  763. package/src/runtime/components/ui/select/SelectLabel.vue +14 -0
  764. package/src/runtime/components/ui/select/SelectScrollDownButton.vue +22 -0
  765. package/src/runtime/components/ui/select/SelectScrollUpButton.vue +22 -0
  766. package/src/runtime/components/ui/select/SelectSeparator.vue +15 -0
  767. package/src/runtime/components/ui/select/SelectTrigger.vue +32 -0
  768. package/src/runtime/components/ui/select/SelectValue.vue +12 -0
  769. package/src/runtime/components/ui/select/index.ts +11 -0
  770. package/src/runtime/components/ui/separator/Separator.vue +18 -0
  771. package/src/runtime/components/ui/separator/index.ts +1 -0
  772. package/src/runtime/components/ui/sheet/Sheet.vue +15 -0
  773. package/src/runtime/components/ui/sheet/SheetClose.vue +12 -0
  774. package/src/runtime/components/ui/sheet/SheetContent.vue +54 -0
  775. package/src/runtime/components/ui/sheet/SheetDescription.vue +17 -0
  776. package/src/runtime/components/ui/sheet/SheetFooter.vue +12 -0
  777. package/src/runtime/components/ui/sheet/SheetHeader.vue +12 -0
  778. package/src/runtime/components/ui/sheet/SheetOverlay.vue +17 -0
  779. package/src/runtime/components/ui/sheet/SheetTitle.vue +17 -0
  780. package/src/runtime/components/ui/sheet/SheetTrigger.vue +12 -0
  781. package/src/runtime/components/ui/sheet/index.ts +8 -0
  782. package/src/runtime/components/ui/sidebar/Sidebar.vue +78 -0
  783. package/src/runtime/components/ui/sidebar/SidebarContent.vue +14 -0
  784. package/src/runtime/components/ui/sidebar/SidebarFooter.vue +14 -0
  785. package/src/runtime/components/ui/sidebar/SidebarGroup.vue +14 -0
  786. package/src/runtime/components/ui/sidebar/SidebarGroupAction.vue +31 -0
  787. package/src/runtime/components/ui/sidebar/SidebarGroupContent.vue +14 -0
  788. package/src/runtime/components/ui/sidebar/SidebarGroupLabel.vue +30 -0
  789. package/src/runtime/components/ui/sidebar/SidebarHeader.vue +14 -0
  790. package/src/runtime/components/ui/sidebar/SidebarInput.vue +15 -0
  791. package/src/runtime/components/ui/sidebar/SidebarInset.vue +24 -0
  792. package/src/runtime/components/ui/sidebar/SidebarMenu.vue +14 -0
  793. package/src/runtime/components/ui/sidebar/SidebarMenuAction.vue +41 -0
  794. package/src/runtime/components/ui/sidebar/SidebarMenuBadge.vue +28 -0
  795. package/src/runtime/components/ui/sidebar/SidebarMenuButton.vue +49 -0
  796. package/src/runtime/components/ui/sidebar/SidebarMenuButtonChild.vue +27 -0
  797. package/src/runtime/components/ui/sidebar/SidebarMenuItem.vue +14 -0
  798. package/src/runtime/components/ui/sidebar/SidebarMenuSkeleton.vue +23 -0
  799. package/src/runtime/components/ui/sidebar/SidebarMenuSub.vue +14 -0
  800. package/src/runtime/components/ui/sidebar/SidebarMenuSubButton.vue +43 -0
  801. package/src/runtime/components/ui/sidebar/SidebarMenuSubItem.vue +14 -0
  802. package/src/runtime/components/ui/sidebar/SidebarProvider.vue +89 -0
  803. package/src/runtime/components/ui/sidebar/SidebarRail.vue +35 -0
  804. package/src/runtime/components/ui/sidebar/SidebarSeparator.vue +15 -0
  805. package/src/runtime/components/ui/sidebar/SidebarTrigger.vue +19 -0
  806. package/src/runtime/components/ui/sidebar/index.ts +59 -0
  807. package/src/runtime/components/ui/sidebar/utils.ts +19 -0
  808. package/src/runtime/components/ui/skeleton/Skeleton.vue +14 -0
  809. package/src/runtime/components/ui/skeleton/index.ts +1 -0
  810. package/src/runtime/components/ui/slider/Slider.vue +34 -0
  811. package/src/runtime/components/ui/slider/index.ts +1 -0
  812. package/src/runtime/components/ui/spinner/Spinner.vue +13 -0
  813. package/src/runtime/components/ui/spinner/index.ts +1 -0
  814. package/src/runtime/components/ui/stepper/Stepper.vue +20 -0
  815. package/src/runtime/components/ui/stepper/StepperDescription.vue +19 -0
  816. package/src/runtime/components/ui/stepper/StepperIndicator.vue +34 -0
  817. package/src/runtime/components/ui/stepper/StepperItem.vue +19 -0
  818. package/src/runtime/components/ui/stepper/StepperSeparator.vue +29 -0
  819. package/src/runtime/components/ui/stepper/StepperTitle.vue +19 -0
  820. package/src/runtime/components/ui/stepper/StepperTrigger.vue +19 -0
  821. package/src/runtime/components/ui/stepper/index.ts +7 -0
  822. package/src/runtime/components/ui/switch/Switch.vue +36 -0
  823. package/src/runtime/components/ui/switch/index.ts +1 -0
  824. package/src/runtime/components/ui/table/Table.vue +16 -0
  825. package/src/runtime/components/ui/table/TableBody.vue +14 -0
  826. package/src/runtime/components/ui/table/TableCaption.vue +14 -0
  827. package/src/runtime/components/ui/table/TableCell.vue +14 -0
  828. package/src/runtime/components/ui/table/TableEmpty.vue +29 -0
  829. package/src/runtime/components/ui/table/TableFooter.vue +14 -0
  830. package/src/runtime/components/ui/table/TableHead.vue +14 -0
  831. package/src/runtime/components/ui/table/TableHeader.vue +14 -0
  832. package/src/runtime/components/ui/table/TableRow.vue +14 -0
  833. package/src/runtime/components/ui/table/index.ts +9 -0
  834. package/src/runtime/components/ui/table/utils.ts +8 -0
  835. package/src/runtime/components/ui/tabs/Tabs.vue +23 -0
  836. package/src/runtime/components/ui/tabs/TabsContent.vue +17 -0
  837. package/src/runtime/components/ui/tabs/TabsList.vue +17 -0
  838. package/src/runtime/components/ui/tabs/TabsTrigger.vue +28 -0
  839. package/src/runtime/components/ui/tabs/index.ts +4 -0
  840. package/src/runtime/components/ui/tags-input/TagsInput.vue +20 -0
  841. package/src/runtime/components/ui/tags-input/TagsInputInput.vue +17 -0
  842. package/src/runtime/components/ui/tags-input/TagsInputItem.vue +20 -0
  843. package/src/runtime/components/ui/tags-input/TagsInputItemDelete.vue +22 -0
  844. package/src/runtime/components/ui/tags-input/TagsInputItemText.vue +19 -0
  845. package/src/runtime/components/ui/tags-input/index.ts +5 -0
  846. package/src/runtime/components/ui/textarea/Textarea.vue +31 -0
  847. package/src/runtime/components/ui/textarea/index.ts +1 -0
  848. package/src/runtime/components/ui/tiptap/TiptapContent.vue +154 -0
  849. package/src/runtime/components/ui/tiptap/TiptapEditor.vue +37 -0
  850. package/src/runtime/components/ui/tiptap/TiptapIcon.vue +141 -0
  851. package/src/runtime/components/ui/tiptap/TiptapKeyboardShortcuts.vue +25 -0
  852. package/src/runtime/components/ui/tiptap/TiptapMobileToolbar.vue +148 -0
  853. package/src/runtime/components/ui/tiptap/TiptapProvider.vue +407 -0
  854. package/src/runtime/components/ui/tiptap/TiptapSlotPanel.vue +112 -0
  855. package/src/runtime/components/ui/tiptap/TiptapStatusBar.vue +83 -0
  856. package/src/runtime/components/ui/tiptap/TiptapTableToolbar.vue +176 -0
  857. package/src/runtime/components/ui/tiptap/TiptapToolbar.vue +223 -0
  858. package/src/runtime/components/ui/tiptap/TiptapTreeItem.vue +210 -0
  859. package/src/runtime/components/ui/tiptap/TiptapTreeStructure.vue +133 -0
  860. package/src/runtime/components/ui/tiptap/index.ts +49 -0
  861. package/src/runtime/components/ui/tiptap/tiptapTreeUtils.ts +137 -0
  862. package/src/runtime/components/ui/toggle/Toggle.vue +35 -0
  863. package/src/runtime/components/ui/toggle/index.ts +27 -0
  864. package/src/runtime/components/ui/toggle-group/ToggleGroup.vue +54 -0
  865. package/src/runtime/components/ui/toggle-group/ToggleGroupItem.vue +51 -0
  866. package/src/runtime/components/ui/toggle-group/index.ts +2 -0
  867. package/src/runtime/components/ui/tooltip/Tooltip.vue +15 -0
  868. package/src/runtime/components/ui/tooltip/TooltipContent.vue +39 -0
  869. package/src/runtime/components/ui/tooltip/TooltipProvider.vue +14 -0
  870. package/src/runtime/components/ui/tooltip/TooltipTrigger.vue +12 -0
  871. package/src/runtime/components/ui/tooltip/index.ts +4 -0
@@ -0,0 +1,2372 @@
1
+ /**
2
+ * @description Org Chart component — contains the OrgChart class and all rendering/configuration
3
+ * logic for visualising hierarchical data. Built on top of D3.js with support for
4
+ * compact layouts, zoom/pan, custom node content, Vue h() render functions, and
5
+ * multiple layout directions (top / right / bottom / left).
6
+ * @author Amirul Apex
7
+ * @created Jan 2026
8
+ * @project Dynect
9
+ */
10
+
11
+ import { flextree } from 'd3-flextree';
12
+ import 'd3-transition';
13
+ import { selection, select, max, min, sum, cumsum, tree, stratify, linkHorizontal, zoom, zoomIdentity, zoomTransform, type D3ZoomEvent } from 'd3';
14
+ import { createApp } from 'vue';
15
+ import { createIconSVG, getLayoutIcon } from './svg-icons';
16
+ import type {
17
+ OrgChartAttrs,
18
+ OrgChartNode,
19
+ OrgChartNodeData,
20
+ Connection,
21
+ LayoutType,
22
+ Point,
23
+ UpdateParams,
24
+ ExportImageParams,
25
+ DownloadImageParams,
26
+ FitParams,
27
+ ZoomToBoundsParams,
28
+ TextMeasurementParams,
29
+ CalcProperties,
30
+ NodeAccessor,
31
+ DataAccessor,
32
+ NodeContentCallback,
33
+ ButtonContentCallback,
34
+ PagingButtonCallback,
35
+ NodeClickCallback,
36
+ NodeExpandCollapseCallback,
37
+ ZoomCallback,
38
+ NodeUpdateCallback,
39
+ NodeEnterCallback,
40
+ NodeExitCallback,
41
+ LinkUpdateCallback,
42
+ DefsCallback,
43
+ ConnectionsUpdateCallback,
44
+ } from './types';
45
+
46
+ function vnodeToHTML(result: unknown): string {
47
+ if (result !== null && typeof result === 'object' && (result as any).__v_isVNode) {
48
+ const container = document.createElement('div');
49
+ const app = createApp({ render: () => result as any });
50
+ app.mount(container);
51
+ const html = container.innerHTML;
52
+ app.unmount();
53
+ return html;
54
+ }
55
+ return result as string;
56
+ }
57
+
58
+ const d3 = {
59
+ selection,
60
+ select,
61
+ max,
62
+ min,
63
+ sum,
64
+ cumsum,
65
+ tree,
66
+ stratify,
67
+ zoom,
68
+ zoomIdentity,
69
+ zoomTransform,
70
+ linkHorizontal,
71
+ flextree,
72
+ };
73
+
74
+ // Interface untuk method overloading (untuk IDE autocomplete)
75
+ export interface IOrgChart<Datum = any> {
76
+ // Configuration Methods
77
+ container(): string | HTMLElement;
78
+ container(value: string | HTMLElement): this;
79
+ data(): Datum[] | null;
80
+ data(value: Datum[]): this;
81
+ svgWidth(): number;
82
+ svgWidth(value: number): this;
83
+ svgHeight(): number;
84
+ svgHeight(value: number): this;
85
+ compact(): boolean;
86
+ compact(value: boolean): this;
87
+ layout(): LayoutType;
88
+ layout(value: LayoutType): this;
89
+ duration(): number;
90
+ duration(value: number): this;
91
+ connections(): Connection<Datum>[];
92
+ connections(value: Connection<Datum>[]): this;
93
+ rootMargin(): number;
94
+ rootMargin(value: number): this;
95
+ setActiveNodeCentered(): boolean;
96
+ setActiveNodeCentered(value: boolean): this;
97
+ scaleExtent(): [number, number];
98
+ scaleExtent(value: [number, number]): this;
99
+ defaultFont(): string;
100
+ defaultFont(value: string): this;
101
+ imageName(): string;
102
+ imageName(value: string): this;
103
+ linkYOffset(): number;
104
+ linkYOffset(value: number): this;
105
+
106
+ // Accessor Methods
107
+ nodeId(): DataAccessor<string | number, Datum>;
108
+ nodeId(value: DataAccessor<string | number, Datum>): this;
109
+ parentNodeId(): DataAccessor<string | number, Datum>;
110
+ parentNodeId(value: DataAccessor<string | number, Datum>): this;
111
+ nodeWidth(): NodeAccessor<number, Datum>;
112
+ nodeWidth(value: NodeAccessor<number, Datum>): this;
113
+ nodeHeight(): NodeAccessor<number, Datum>;
114
+ nodeHeight(value: NodeAccessor<number, Datum>): this;
115
+ siblingsMargin(): NodeAccessor<number, Datum>;
116
+ siblingsMargin(value: NodeAccessor<number, Datum>): this;
117
+ childrenMargin(): NodeAccessor<number, Datum>;
118
+ childrenMargin(value: NodeAccessor<number, Datum>): this;
119
+ neighbourMargin(): (node1: OrgChartNode<Datum>, node2: OrgChartNode<Datum>) => number;
120
+ neighbourMargin(value: (node1: OrgChartNode<Datum>, node2: OrgChartNode<Datum>) => number): this;
121
+ compactMarginPair(): NodeAccessor<number, Datum>;
122
+ compactMarginPair(value: NodeAccessor<number, Datum>): this;
123
+ compactMarginBetween(): NodeAccessor<number, Datum>;
124
+ compactMarginBetween(value: NodeAccessor<number, Datum>): this;
125
+ initialExpandLevel(): number;
126
+ initialExpandLevel(value: number): this;
127
+ nodeButtonWidth(): NodeAccessor<number, Datum>;
128
+ nodeButtonWidth(value: NodeAccessor<number, Datum>): this;
129
+ nodeButtonHeight(): NodeAccessor<number, Datum>;
130
+ nodeButtonHeight(value: NodeAccessor<number, Datum>): this;
131
+ nodeButtonX(): NodeAccessor<number, Datum>;
132
+ nodeButtonX(value: NodeAccessor<number, Datum>): this;
133
+ nodeButtonY(): NodeAccessor<number, Datum>;
134
+ nodeButtonY(value: NodeAccessor<number, Datum>): this;
135
+ pagingStep(): NodeAccessor<number, Datum>;
136
+ pagingStep(value: NodeAccessor<number, Datum>): this;
137
+ minPagingVisibleNodes(): NodeAccessor<number, Datum>;
138
+ minPagingVisibleNodes(value: NodeAccessor<number, Datum>): this;
139
+
140
+ // Callback Methods
141
+ nodeContent(): NodeContentCallback<Datum>;
142
+ nodeContent(value: NodeContentCallback<Datum>): this;
143
+ buttonContent(): ButtonContentCallback<Datum>;
144
+ buttonContent(value: ButtonContentCallback<Datum>): this;
145
+ pagingButton(): PagingButtonCallback<Datum>;
146
+ pagingButton(value: PagingButtonCallback<Datum>): this;
147
+ onNodeClick(): NodeClickCallback<Datum>;
148
+ onNodeClick(value: NodeClickCallback<Datum>): this;
149
+ onExpandOrCollapse(): NodeExpandCollapseCallback<Datum>;
150
+ onExpandOrCollapse(value: NodeExpandCollapseCallback<Datum>): this;
151
+ onZoomStart(): ZoomCallback<Datum>;
152
+ onZoomStart(value: ZoomCallback<Datum>): this;
153
+ onZoom(): ZoomCallback<Datum>;
154
+ onZoom(value: ZoomCallback<Datum>): this;
155
+ onZoomEnd(): ZoomCallback<Datum>;
156
+ onZoomEnd(value: ZoomCallback<Datum>): this;
157
+ nodeUpdate(): NodeUpdateCallback<Datum>;
158
+ nodeUpdate(value: NodeUpdateCallback<Datum>): this;
159
+ nodeEnter(): NodeEnterCallback<Datum>;
160
+ nodeEnter(value: NodeEnterCallback<Datum>): this;
161
+ nodeExit(): NodeExitCallback<Datum>;
162
+ nodeExit(value: NodeExitCallback<Datum>): this;
163
+ linkUpdate(): LinkUpdateCallback<Datum>;
164
+ linkUpdate(value: LinkUpdateCallback<Datum>): this;
165
+ connectionsUpdate(): ConnectionsUpdateCallback<Datum>;
166
+ connectionsUpdate(value: ConnectionsUpdateCallback<Datum>): this;
167
+ defs(): DefsCallback<Datum>;
168
+ defs(value: DefsCallback<Datum>): this;
169
+ lastTransform(): { x: number; y: number; k: number };
170
+ lastTransform(value: { x: number; y: number; k: number }): this;
171
+
172
+ // Utility Methods
173
+ groupBy<T, K extends string | number>(array: T[], accessor: (item: T) => K, aggregator: (group: T[]) => any): [string, any][];
174
+ calculateCompactFlexDimensions(root: OrgChartNode<Datum>): void;
175
+ calculateCompactFlexPositions(root: OrgChartNode<Datum>): void;
176
+ }
177
+
178
+ export class OrgChart<Datum = any> implements IOrgChart<Datum> {
179
+ private readonly attrs: OrgChartAttrs<Datum>;
180
+
181
+ // Public getter for accessing chart state
182
+ getChartState: () => OrgChartAttrs<Datum>;
183
+
184
+ // Dynamic properties (added via getter/setter pattern)
185
+ [key: string]: any;
186
+
187
+ constructor() {
188
+ // Exposed variables test test
189
+ const attrs: OrgChartAttrs<Datum> = {
190
+ /* NOT INTENDED FOR PUBLIC OVERRIDE */
191
+
192
+ id: `ID${crypto.randomUUID()}`, // Id for event handlings
193
+ firstDraw: true, // Whether chart is drawn for the first time
194
+ ctx: document.createElement('canvas').getContext('2d'),
195
+ initialExpandLevel: 1,
196
+ nodeDefaultBackground: 'none',
197
+ lastTransform: { x: 0, y: 0, k: 1 }, // Panning and zooming values
198
+ allowedNodesCount: {},
199
+ zoomBehavior: null,
200
+ generateRoot: null,
201
+
202
+ /* INTENDED FOR PUBLIC OVERRIDE */
203
+
204
+ svgWidth: 800, // Configure svg width
205
+ svgHeight: window.innerHeight - 100, // Configure svg height
206
+ container: 'body', // Set parent container, either CSS style selector or DOM element
207
+ data: null, // Set data, it must be an array of objects, where hierarchy is clearly defined via id and parent ID (property names are configurable)
208
+ connections: [], // Sets connection data, array of objects, SAMPLE: [{from:"145",to:"201",label:"Conflicts of interest"}]
209
+ defaultFont: 'Helvetica', // Set default font
210
+ nodeId: (d: Datum) => (d as any).nodeId || (d as any).id, // Configure accessor for node id, default is either odeId or id
211
+ parentNodeId: (d: Datum) => (d as any).parentNodeId || (d as any).parentId, // Configure accessor for parent node id, default is either parentNodeId or parentId
212
+ rootMargin: 40, // Configure how much root node is offset from top
213
+ nodeWidth: (_) => 250, // Configure each node width, use with caution, it is better to have the same value set for all nodes
214
+ nodeHeight: (_) => 150, // Configure each node height, use with caution, it is better to have the same value set for all nodes
215
+ neighbourMargin: (_, __) => 80, // Configure margin between two nodes, use with caution, it is better to have the same value set for all nodes
216
+ siblingsMargin: (_) => 40, // Configure margin between two siblings, use with caution, it is better to have the same value set for all nodes
217
+ childrenMargin: (_) => 60, // Configure margin between parent and children, use with caution, it is better to have the same value set for all nodes
218
+ compactMarginPair: (_) => 100, // Configure margin between two nodes in compact mode, use with caution, it is better to have the same value set for all nodes
219
+ compactMarginBetween: (_) => 40, // Configure margin between two nodes in compact mode, use with caution, it is better to have the same value set for all nodes
220
+ nodeButtonWidth: (_) => 40, // Configure expand & collapse button width
221
+ nodeButtonHeight: (_) => 40, // Configure expand & collapse button height
222
+ nodeButtonX: (_) => -20, // Configure expand & collapse button x position
223
+ nodeButtonY: (_) => -20, // Configure expand & collapse button y position
224
+ linkYOffset: 10, // When correcting links which is not working for safari
225
+ pagingStep: (_) => 5, // Configure how many nodes to show when making new nodes appear
226
+ minPagingVisibleNodes: (_) => 2000, // Configure minimum number of visible nodes , after which paging button appears
227
+ scaleExtent: [0.001, 20], // Configure zoom scale extent , if you don't want any kind of zooming, set it to [1,1]
228
+ duration: 400, // Configure duration of transitions
229
+ imageName: 'Chart', // Configure exported PNG and SVG image name
230
+ setActiveNodeCentered: true, // Configure if active node should be centered when expanded and collapsed
231
+ layout: 'top', // Configure layout direction , possible values are "top", "left", "right", "bottom"
232
+ compact: true, // Configure if compact mode is enabled , when enabled, nodes are shown in compact positions, instead of horizontal spread
233
+ createZoom: (_) => d3.zoom(),
234
+ onZoomStart: (_) => {}, // Callback for zoom & panning start
235
+ onZoom: (_) => {}, // Callback for zoom & panning
236
+ onZoomEnd: (_) => {}, // Callback for zoom & panning end
237
+ onNodeClick: (d) => d, // Callback for node click
238
+ onExpandOrCollapse: (d) => d, // Callback for node expand or collapse
239
+
240
+ /*
241
+ * Node HTML content generation , remember that you can access some helper methods:
242
+
243
+ * node=> node.data - to access node's original data
244
+ * node=> node.leaves() - to access node's leaves
245
+ * node=> node.descendants() - to access node's descendants
246
+ * node=> node.children - to access node's children
247
+ * node=> node.parent - to access node's parent
248
+ * node=> node.depth - to access node's depth
249
+ * node=> node.hierarchyHeight - to access node's hierarchy height ( Height, which d3 assigns to hierarchy nodes)
250
+ * node=> node.height - to access node's height
251
+ * node=> node.width - to access node's width
252
+ *
253
+ * You can also access additional properties to style your node:
254
+ *
255
+ * d=>d.data._centeredWithDescendants - when node is centered with descendants
256
+ * d=>d.data._directSubordinatesPaging - subordinates count in paging mode
257
+ * d=>d.data._directSubordinates - subordinates count
258
+ * d=>d.data._totalSubordinates - total subordinates count
259
+ * d=>d._highlighted - when node is highlighted
260
+ * d=>d._upToTheRootHighlighted - when node is highlighted up to the root
261
+ * d=>d._expanded - when node is expanded
262
+ * d=>d.data._centered - when node is centered
263
+ */
264
+ nodeContent: (d: OrgChartNode<Datum>) => `<div style="padding:5px;font-size:10px;">Sample Node(id=${(d.data as any).id}), override using <br/>
265
+ <code>chart.nodeContent({data}=>{ <br/>
266
+ &nbsp;&nbsp;&nbsp;&nbsp;return '' // Custom HTML <br/>
267
+ })</code>
268
+ </div>`,
269
+
270
+ /* Node expand & collapse button content and styling. You can access same helper methods as above */
271
+ buttonContent: ({ node, state }: { node: OrgChartNode<Datum>; state: OrgChartAttrs<Datum> }) => {
272
+ const iconPath = getLayoutIcon(state.layout, !!node.children);
273
+ const marginLeft = state.layout === 'bottom' || state.layout === 'top' ? '1px' : '0';
274
+ const iconHTML = createIconSVG(iconPath, node.data._directSubordinatesPaging || 0, marginLeft);
275
+ return `<div style="border:1px solid #E4E2E9;border-radius:3px;padding:3px;font-size:9px;margin:auto auto;background-color:white"> ${iconHTML} </div>`;
276
+ },
277
+ /* Node paging button content and styling. You can access same helper methods as above. */
278
+ pagingButton: (d: OrgChartNode<Datum>, _i: number, _arr: OrgChartNode<Datum>[], state: OrgChartAttrs<Datum>) => {
279
+ const step = state.pagingStep(d.parent!);
280
+ const currentIndex = d.parent!.data._pagingStep;
281
+ const diff = d.parent!.data._directSubordinatesPaging! - currentIndex!;
282
+ const min = Math.min(diff, step);
283
+ return `
284
+ <div style="margin-top:90px;">
285
+ <div style="display:flex;width:170px;border-radius:20px;padding:5px 15px; padding-bottom:4px;;background-color:#E5E9F2">
286
+ <div><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
287
+ <path d="M5.59 7.41L10.18 12L5.59 16.59L7 18L13 12L7 6L5.59 7.41ZM16 6H18V18H16V6Z" fill="#716E7B" stroke="#716E7B"/>
288
+ </svg>
289
+ </div><div style="line-height:2"> Show next ${min} nodes </div></div>
290
+ </div>
291
+ `;
292
+ },
293
+ /* You can access and modify actual node DOM element in runtime using this method. */
294
+ nodeUpdate: function (this: SVGGElement, d: OrgChartNode<Datum>, _i: number, _arr: SVGGElement[] | ArrayLike<SVGGElement>) {
295
+ d3.select(this)
296
+ .select('.node-rect')
297
+ .attr('stroke', () => (d.data._highlighted || d.data._upToTheRootHighlighted ? '#E27396' : 'none'))
298
+ .attr('stroke-width', d.data._highlighted || d.data._upToTheRootHighlighted ? 10 : 2);
299
+ },
300
+ nodeEnter: (d: OrgChartNode<Datum>) => d, // Custom handling of node update
301
+ nodeExit: (d: OrgChartNode<Datum>) => d, // Custom handling of exit node
302
+ /* You can access and modify actual link DOM element in runtime using this method. */
303
+ linkUpdate: function (this: SVGPathElement, d: OrgChartNode<Datum>, _i: number, _arr: SVGPathElement[] | ArrayLike<SVGPathElement>) {
304
+ d3.select(this)
305
+ .attr('stroke', () => (d.data._upToTheRootHighlighted ? '#E27396' : '#E4E2E9'))
306
+ .attr('stroke-width', () => (d.data._upToTheRootHighlighted ? 5 : 1));
307
+
308
+ if (d.data._upToTheRootHighlighted) {
309
+ d3.select(this).raise();
310
+ }
311
+ },
312
+ /* Horizontal diagonal generation algorithm - https://observablehq.com/@bumbeishvili/curved-edges-compact-horizontal */
313
+ hdiagonal: function (s: Point, t: Point, m?: Point | null) {
314
+ // Define source and target x,y coordinates
315
+ const x = s.x;
316
+ const y = s.y;
317
+ const ex = t.x;
318
+ const ey = t.y;
319
+
320
+ const mx = m?.x ?? x; // This is a changed line
321
+ const my = m?.y ?? y; // This also is a changed line
322
+
323
+ // Values in case of top reversed and left reversed diagonals
324
+ const xrvs = ex - x < 0 ? -1 : 1;
325
+ const yrvs = ey - y < 0 ? -1 : 1;
326
+
327
+ // Define preferred curve radius
328
+ const rdef = 35;
329
+
330
+ // Reduce curve radius, if source-target x space is smaller
331
+ let r = Math.min(Math.abs(ex - x) / 2, rdef);
332
+
333
+ // Further reduce curve radius, is y space is more small
334
+ r = Math.min(Math.abs(ey - y) / 2, r);
335
+
336
+ // Defin width and height of link, excluding radius
337
+ // let h = Math.abs(ey - y) / 2 - r;
338
+ const w = Math.abs(ex - x) / 2 - r;
339
+
340
+ // Build and return custom arc command
341
+ return `
342
+ M ${mx} ${my}
343
+ L ${mx} ${y}
344
+ L ${x} ${y}
345
+ L ${x + w * xrvs} ${y}
346
+ C ${x + w * xrvs + r * xrvs} ${y}
347
+ ${x + w * xrvs + r * xrvs} ${y}
348
+ ${x + w * xrvs + r * xrvs} ${y + r * yrvs}
349
+ L ${x + w * xrvs + r * xrvs} ${ey - r * yrvs}
350
+ C ${x + w * xrvs + r * xrvs} ${ey}
351
+ ${x + w * xrvs + r * xrvs} ${ey}
352
+ ${ex - w * xrvs} ${ey}
353
+ L ${ex} ${ey}
354
+ `;
355
+ },
356
+ /* Vertical diagonal generation algorithm - https://observablehq.com/@bumbeishvili/curved-edges-compacty-vertical */
357
+ diagonal: function (s: Point, t: Point, m?: Point | null, offsets: { sy?: number; ty?: number } = { sy: 0 }) {
358
+ const x = s.x;
359
+ let y = s.y;
360
+
361
+ const ex = t.x;
362
+ const ey = t.y;
363
+
364
+ const mx = m?.x ?? x; // This is a changed line
365
+ const my = m?.y ?? y; // This also is a changed line
366
+
367
+ const xrvs = ex - x < 0 ? -1 : 1;
368
+ const yrvs = ey - y < 0 ? -1 : 1;
369
+
370
+ y += offsets.sy || 0;
371
+
372
+ const rdef = 35;
373
+ let r = Math.min(Math.abs(ex - x) / 2, rdef);
374
+
375
+ r = Math.min(Math.abs(ey - y) / 2, r);
376
+
377
+ const h = Math.abs(ey - y) / 2 - r;
378
+ const w = Math.abs(ex - x) - r * 2;
379
+ const path = `
380
+ M ${mx} ${my}
381
+ L ${x} ${my}
382
+ L ${x} ${y}
383
+ L ${x} ${y + h * yrvs}
384
+ C ${x} ${y + h * yrvs + r * yrvs} ${x} ${y + h * yrvs + r * yrvs} ${x + r * xrvs} ${y + h * yrvs + r * yrvs}
385
+ L ${x + w * xrvs + r * xrvs} ${y + h * yrvs + r * yrvs}
386
+ C ${ex} ${y + h * yrvs + r * yrvs} ${ex} ${y + h * yrvs + r * yrvs} ${ex} ${ey - h * yrvs}
387
+ L ${ex} ${ey}
388
+ `;
389
+ return path;
390
+ },
391
+ // Defining arrows with markers for connections
392
+ defs: function (_state: OrgChartAttrs<Datum>, visibleConnections: Connection<Datum>[]) {
393
+ return `<defs>
394
+ ${visibleConnections
395
+ .map((conn) => {
396
+ const labelWidth = 0; // Placeholder, will be calculated in actual rendering
397
+ return `
398
+ <marker id="${conn.from + '_' + conn.to}" refX="${conn._source!.x < conn._target!.x ? -7 : 7}" refY="5" markerWidth="500" markerHeight="500" orient="${conn._source!.x < conn._target!.x ? 'auto' : 'auto-start-reverse'}" >
399
+ <rect rx=0.5 width=${conn.label ? labelWidth + 3 : 0} height=3 y=1 fill="#E27396"></rect>
400
+ <text font-size="2px" x=1 fill="white" y=3>${conn.label || ''}</text>
401
+ </marker>
402
+
403
+ <marker id="arrow-${conn.from + '_' + conn.to}" markerWidth="500" markerHeight="500" refY="2" refX="1" orient="${conn._source!.x < conn._target!.x ? 'auto' : 'auto-start-reverse'}" >
404
+ <path transform="translate(0)" d='M0,0 V4 L2,2 Z' fill='#E27396' />
405
+ </marker>
406
+ `;
407
+ })
408
+ .join('')}
409
+ </defs>
410
+ `;
411
+ },
412
+ /* You can update connections with custom styling using this function */
413
+ connectionsUpdate: function (this: SVGPathElement, d: Connection<Datum>, _i: number, _arr: SVGPathElement[] | ArrayLike<SVGPathElement>) {
414
+ d3.select(this)
415
+ .attr('stroke', () => '#E27396')
416
+ .attr('stroke-linecap', 'round')
417
+ .attr('stroke-width', () => '5')
418
+ .attr('pointer-events', 'none')
419
+ .attr('marker-start', () => `url(#${d.from + '_' + d.to})`)
420
+ .attr('marker-end', () => `url(#arrow-${d.from + '_' + d.to})`);
421
+ },
422
+ // Link generator for connections
423
+ linkGroupArc: d3
424
+ .linkHorizontal()
425
+ .x((d) => d[0])
426
+ .y((d) => d[1]),
427
+
428
+ /*
429
+ * You can customize/offset positions for each node and link by overriding these functions
430
+ * For example, suppose you want to move link y position 30 px bellow in top layout. You can do it like this:
431
+ * ```javascript
432
+ * const layout = chart.layoutBindings();
433
+ * layout.top.linkY = node => node.y + 30;
434
+ * chart.layoutBindings(layout);
435
+ * ```
436
+ */
437
+ layoutBindings: {
438
+ left: {
439
+ nodeLeftX: (_) => 0,
440
+ nodeRightX: (node) => node.width,
441
+ nodeTopY: (node) => -node.height / 2,
442
+ nodeBottomY: (node) => node.height / 2,
443
+ nodeJoinX: (node) => node.x + node.width,
444
+ nodeJoinY: (node) => node.y - node.height / 2,
445
+ linkJoinX: (node) => node.x + node.width,
446
+ linkJoinY: (node) => node.y,
447
+ linkX: (node) => node.x,
448
+ linkY: (node) => node.y,
449
+ linkCompactXStart: (node) => node.x + node.width / 2, //node.x + (node.compactEven ? node.width / 2 : -node.width / 2),
450
+ linkCompactYStart: (node) => node.y + (node.compactEven ? node.height / 2 : -node.height / 2),
451
+ compactLinkMidX: (node, _) => node.firstCompactNode!.x, // node.firstCompactNode.x + node.firstCompactNode.flexCompactDim[0] / 4 + state.compactMarginPair(node) / 4,
452
+ compactLinkMidY: (node, state) => node.firstCompactNode!.y + (node.firstCompactNode!.flexCompactDim ? node.firstCompactNode!.flexCompactDim[0] / 4 : 0) + state.compactMarginPair(node) / 4,
453
+ linkParentX: (node) => node.parent!.x + node.parent!.width,
454
+ linkParentY: (node) => node.parent!.y,
455
+ buttonX: (node) => node.width,
456
+ buttonY: (node) => node.height / 2,
457
+ centerTransform: ({ rootMargin, centerY, scale }: { root: OrgChartNode<Datum>; rootMargin: number; scale: number; centerX: number; centerY: number }) => `translate(${rootMargin},${centerY}) scale(${scale})`,
458
+ compactDimension: {
459
+ sizeColumn: (node) => node.height,
460
+ sizeRow: (node) => node.width,
461
+ reverse: (arr) => arr.slice().reverse(),
462
+ },
463
+ nodeFlexSize: ({ height, width, siblingsMargin, childrenMargin, state, node }) => {
464
+ if (state.compact && node.flexCompactDim) {
465
+ const result: [number, number] = [node.flexCompactDim[0], node.flexCompactDim[1]];
466
+ return result;
467
+ }
468
+ const result: [number, number] = [height + siblingsMargin, width + childrenMargin];
469
+ return result;
470
+ },
471
+ zoomTransform: ({ x, y, k }: { x: number; y: number; k: number }) => `translate(${x},${y}) scale(${k})`,
472
+ diagonal: this.hdiagonal.bind(this),
473
+ swap: (d) => {
474
+ const x = d.x;
475
+ d.x = d.y;
476
+ d.y = x;
477
+ },
478
+ nodeUpdateTransform: ({ x, y, height }) => `translate(${x},${y - height / 2})`,
479
+ },
480
+ top: {
481
+ nodeLeftX: (node) => -node.width / 2,
482
+ nodeRightX: (node) => node.width / 2,
483
+ nodeTopY: (_) => 0,
484
+ nodeBottomY: (node) => node.height,
485
+ nodeJoinX: (node) => node.x - node.width / 2,
486
+ nodeJoinY: (node) => node.y + node.height,
487
+ linkJoinX: (node) => node.x,
488
+ linkJoinY: (node) => node.y + node.height,
489
+ linkCompactXStart: (node) => node.x + (node.compactEven ? node.width / 2 : -node.width / 2),
490
+ linkCompactYStart: (node) => node.y + node.height / 2,
491
+ compactLinkMidX: (node, state) => node.firstCompactNode!.x + (node.firstCompactNode!.flexCompactDim ? node.firstCompactNode!.flexCompactDim[0] / 4 : 0) + state.compactMarginPair(node) / 4,
492
+ compactLinkMidY: (node) => node.firstCompactNode!.y,
493
+ compactDimension: {
494
+ sizeColumn: (node) => node.width,
495
+ sizeRow: (node) => node.height,
496
+ reverse: (arr) => arr,
497
+ },
498
+ linkX: (node) => node.x,
499
+ linkY: (node) => node.y,
500
+ linkParentX: (node) => node.parent!.x,
501
+ linkParentY: (node) => node.parent!.y + node.parent!.height,
502
+ buttonX: (node) => node.width / 2,
503
+ buttonY: (node) => node.height,
504
+ centerTransform: ({ rootMargin, scale, centerX }: { root: OrgChartNode<Datum>; rootMargin: number; scale: number; centerX: number; centerY: number }) => `translate(${centerX},${rootMargin}) scale(${scale})`,
505
+ nodeFlexSize: ({ height, width, siblingsMargin, childrenMargin, state, node }) => {
506
+ if (state.compact && node.flexCompactDim) {
507
+ const result: [number, number] = [node.flexCompactDim[0], node.flexCompactDim[1]];
508
+ return result;
509
+ }
510
+ const result: [number, number] = [width + siblingsMargin, height + childrenMargin];
511
+ return result;
512
+ },
513
+ zoomTransform: ({ x, y, k }: { x: number; y: number; k: number }) => `translate(${x},${y}) scale(${k})`,
514
+ diagonal: this.diagonal.bind(this),
515
+ swap: (_d: any) => {},
516
+ nodeUpdateTransform: ({ x, y, width }: { x: number; y: number; width: number }) => `translate(${x - width / 2},${y})`,
517
+ },
518
+ bottom: {
519
+ nodeLeftX: (node) => -node.width / 2,
520
+ nodeRightX: (node) => node.width / 2,
521
+ nodeTopY: (node) => -node.height,
522
+ nodeBottomY: (_) => 0,
523
+ nodeJoinX: (node) => node.x - node.width / 2,
524
+ nodeJoinY: (node) => node.y - node.height - node.height,
525
+ linkJoinX: (node) => node.x,
526
+ linkJoinY: (node) => node.y - node.height,
527
+ linkCompactXStart: (node) => node.x + (node.compactEven ? node.width / 2 : -node.width / 2),
528
+ linkCompactYStart: (node) => node.y - node.height / 2,
529
+ compactLinkMidX: (node, state) => node.firstCompactNode!.x + (node.firstCompactNode!.flexCompactDim ? node.firstCompactNode!.flexCompactDim[0] / 4 : 0) + state.compactMarginPair(node) / 4,
530
+ compactLinkMidY: (node) => node.firstCompactNode!.y,
531
+ linkX: (node) => node.x,
532
+ linkY: (node) => node.y,
533
+ compactDimension: {
534
+ sizeColumn: (node) => node.width,
535
+ sizeRow: (node) => node.height,
536
+ reverse: (arr) => arr,
537
+ },
538
+ linkParentX: (node) => node.parent!.x,
539
+ linkParentY: (node) => node.parent!.y - node.parent!.height,
540
+ buttonX: (node) => node.width / 2,
541
+ buttonY: (_) => 0,
542
+ centerTransform: ({ rootMargin, scale, centerX }: { root: OrgChartNode<Datum>; rootMargin: number; scale: number; centerX: number; centerY: number; chartHeight?: number; chartWidth?: number }) => {
543
+ const attrs = this.getChartState();
544
+ return `translate(${centerX},${attrs.calc!.chartHeight - rootMargin}) scale(${scale})`;
545
+ },
546
+ nodeFlexSize: ({ height, width, siblingsMargin, childrenMargin, state, node }) => {
547
+ if (state.compact && node.flexCompactDim) {
548
+ const result: [number, number] = [node.flexCompactDim[0], node.flexCompactDim[1]];
549
+ return result;
550
+ }
551
+ const result: [number, number] = [width + siblingsMargin, height + childrenMargin];
552
+ return result;
553
+ },
554
+ zoomTransform: ({ x, y, k }: { x: number; y: number; k: number }) => `translate(${x},${y}) scale(${k})`,
555
+ diagonal: this.diagonal.bind(this),
556
+ swap: (d) => {
557
+ d.y = -d.y;
558
+ },
559
+ nodeUpdateTransform: ({ x, y, width, height }) => `translate(${x - width / 2},${y - height})`,
560
+ },
561
+ right: {
562
+ nodeLeftX: (node) => -node.width,
563
+ nodeRightX: (_) => 0,
564
+ nodeTopY: (node) => -node.height / 2,
565
+ nodeBottomY: (node) => node.height / 2,
566
+ nodeJoinX: (node) => node.x - node.width - node.width,
567
+ nodeJoinY: (node) => node.y - node.height / 2,
568
+ linkJoinX: (node) => node.x - node.width,
569
+ linkJoinY: (node) => node.y,
570
+ linkX: (node) => node.x,
571
+ linkY: (node) => node.y,
572
+ linkParentX: (node) => node.parent!.x - node.parent!.width,
573
+ linkParentY: (node) => node.parent!.y,
574
+ buttonX: (_) => 0,
575
+ buttonY: (node) => node.height / 2,
576
+ linkCompactXStart: (node) => node.x - node.width / 2, //node.x + (node.compactEven ? node.width / 2 : -node.width / 2),
577
+ linkCompactYStart: (node) => node.y + (node.compactEven ? node.height / 2 : -node.height / 2),
578
+ compactLinkMidX: (node, _) => node.firstCompactNode!.x, // node.firstCompactNode.x + node.firstCompactNode.flexCompactDim[0] / 4 + state.compactMarginPair(node) / 4,
579
+ compactLinkMidY: (node, state) => node.firstCompactNode!.y + (node.firstCompactNode!.flexCompactDim ? node.firstCompactNode!.flexCompactDim[0] / 4 : 0) + state.compactMarginPair(node) / 4,
580
+ centerTransform: ({ rootMargin, centerY, scale }: { root: OrgChartNode<Datum>; rootMargin: number; scale: number; centerX: number; centerY: number; chartWidth?: number; chartHeight?: number }) => {
581
+ const attrs = this.getChartState();
582
+ return `translate(${attrs.calc!.chartWidth - rootMargin},${centerY}) scale(${scale})`;
583
+ },
584
+ nodeFlexSize: ({ height, width, siblingsMargin, childrenMargin, state, node }) => {
585
+ if (state.compact && node.flexCompactDim) {
586
+ const result: [number, number] = [node.flexCompactDim[0], node.flexCompactDim[1]];
587
+ return result;
588
+ }
589
+ const result: [number, number] = [height + siblingsMargin, width + childrenMargin];
590
+ return result;
591
+ },
592
+ compactDimension: {
593
+ sizeColumn: (node) => node.height,
594
+ sizeRow: (node) => node.width,
595
+ reverse: (arr) => arr.slice().reverse(),
596
+ },
597
+ zoomTransform: ({ x, y, k }: { x: number; y: number; k: number }) => `translate(${x},${y}) scale(${k})`,
598
+ diagonal: this.hdiagonal.bind(this),
599
+ swap: (d) => {
600
+ const x = d.x;
601
+ d.x = -d.y;
602
+ d.y = x;
603
+ },
604
+ nodeUpdateTransform: ({ x, y, width, height }) => `translate(${x - width},${y - height / 2})`,
605
+ },
606
+ },
607
+ } as OrgChartAttrs<Datum>;
608
+
609
+ // Assign attrs to instance property
610
+ this.attrs = attrs;
611
+
612
+ // Assign getChartState method
613
+ this.getChartState = () => this.attrs;
614
+
615
+ this.initializeEnterExitUpdatePattern();
616
+ }
617
+
618
+ initializeEnterExitUpdatePattern(): void {
619
+ //Adding custom patternify method to d3.selection prototype
620
+ d3.selection.prototype.patternify = function (params: { selector: string; tag: string; data?: any[] | ((d: any) => any[]) }) {
621
+ const selector = params.selector;
622
+ const elementTag = params.tag;
623
+ const data = params.data || [selector];
624
+
625
+ // Pattern in action
626
+ let selection = this.selectAll('.' + selector).data(data, (d: any, i: number) => {
627
+ if (typeof d === 'object') {
628
+ if (d.id) {
629
+ return d.id;
630
+ }
631
+ }
632
+ return i;
633
+ });
634
+ selection.exit().remove();
635
+ selection = selection.enter().append(elementTag).merge(selection);
636
+ selection.attr('class', selector);
637
+ return selection;
638
+ };
639
+ }
640
+
641
+ // Configuration Methods
642
+ container(value?: string | HTMLElement): any {
643
+ if (arguments.length === 0) return this.attrs.container;
644
+ this.attrs.container = value!;
645
+ return this;
646
+ }
647
+ data(value?: Datum[]): any {
648
+ if (arguments.length === 0) return this.attrs.data;
649
+ this.attrs.data = value!;
650
+ return this;
651
+ }
652
+ svgWidth(value?: number): any {
653
+ if (arguments.length === 0) return this.attrs.svgWidth;
654
+ this.attrs.svgWidth = value!;
655
+ return this;
656
+ }
657
+ svgHeight(value?: number): any {
658
+ if (arguments.length === 0) return this.attrs.svgHeight;
659
+ this.attrs.svgHeight = value!;
660
+ return this;
661
+ }
662
+ compact(value?: boolean): any {
663
+ if (arguments.length === 0) return this.attrs.compact;
664
+ this.attrs.compact = value!;
665
+ return this;
666
+ }
667
+ layout(value?: LayoutType): any {
668
+ if (arguments.length === 0) return this.attrs.layout;
669
+ this.attrs.layout = value!;
670
+ return this;
671
+ }
672
+ duration(value?: number): any {
673
+ if (arguments.length === 0) return this.attrs.duration;
674
+ this.attrs.duration = value!;
675
+ return this;
676
+ }
677
+ connections(value?: Connection<Datum>[]): any {
678
+ if (arguments.length === 0) return this.attrs.connections;
679
+ this.attrs.connections = value!;
680
+ return this;
681
+ }
682
+ rootMargin(value?: number): any {
683
+ if (arguments.length === 0) return this.attrs.rootMargin;
684
+ this.attrs.rootMargin = value!;
685
+ return this;
686
+ }
687
+ setActiveNodeCentered(value?: boolean): any {
688
+ if (arguments.length === 0) return this.attrs.setActiveNodeCentered;
689
+ this.attrs.setActiveNodeCentered = value!;
690
+ return this;
691
+ }
692
+ scaleExtent(value?: [number, number]): any {
693
+ if (arguments.length === 0) return this.attrs.scaleExtent;
694
+ this.attrs.scaleExtent = value!;
695
+ return this;
696
+ }
697
+ defaultFont(value?: string): any {
698
+ if (arguments.length === 0) return this.attrs.defaultFont;
699
+ this.attrs.defaultFont = value!;
700
+ return this;
701
+ }
702
+ imageName(value?: string): any {
703
+ if (arguments.length === 0) return this.attrs.imageName;
704
+ this.attrs.imageName = value!;
705
+ return this;
706
+ }
707
+ linkYOffset(value?: number): any {
708
+ if (arguments.length === 0) return this.attrs.linkYOffset;
709
+ this.attrs.linkYOffset = value!;
710
+ return this;
711
+ }
712
+
713
+ // Accessor Methods
714
+ nodeId(value?: DataAccessor<string | number, Datum>): any {
715
+ if (arguments.length === 0) return this.attrs.nodeId;
716
+ this.attrs.nodeId = value!;
717
+ return this;
718
+ }
719
+ parentNodeId(value?: DataAccessor<string | number, Datum>): any {
720
+ if (arguments.length === 0) return this.attrs.parentNodeId;
721
+ this.attrs.parentNodeId = value!;
722
+ return this;
723
+ }
724
+ nodeWidth(value?: NodeAccessor<number, Datum>): any {
725
+ if (arguments.length === 0) return this.attrs.nodeWidth;
726
+ this.attrs.nodeWidth = value!;
727
+ return this;
728
+ }
729
+ nodeHeight(value?: NodeAccessor<number, Datum>): any {
730
+ if (arguments.length === 0) return this.attrs.nodeHeight;
731
+ this.attrs.nodeHeight = value!;
732
+ return this;
733
+ }
734
+ siblingsMargin(value?: NodeAccessor<number, Datum>): any {
735
+ if (arguments.length === 0) return this.attrs.siblingsMargin;
736
+ this.attrs.siblingsMargin = value!;
737
+ return this;
738
+ }
739
+ childrenMargin(value?: NodeAccessor<number, Datum>): any {
740
+ if (arguments.length === 0) return this.attrs.childrenMargin;
741
+ this.attrs.childrenMargin = value!;
742
+ return this;
743
+ }
744
+ neighbourMargin(value?: (node1: OrgChartNode<Datum>, node2: OrgChartNode<Datum>) => number): any {
745
+ if (arguments.length === 0) return this.attrs.neighbourMargin;
746
+ this.attrs.neighbourMargin = value!;
747
+ return this;
748
+ }
749
+ compactMarginPair(value?: NodeAccessor<number, Datum>): any {
750
+ if (arguments.length === 0) return this.attrs.compactMarginPair;
751
+ this.attrs.compactMarginPair = value!;
752
+ return this;
753
+ }
754
+ compactMarginBetween(value?: NodeAccessor<number, Datum>): any {
755
+ if (arguments.length === 0) return this.attrs.compactMarginBetween;
756
+ this.attrs.compactMarginBetween = value!;
757
+ return this;
758
+ }
759
+ initialExpandLevel(value?: number): any {
760
+ if (arguments.length === 0) return this.attrs.initialExpandLevel;
761
+ this.attrs.initialExpandLevel = value!;
762
+ return this;
763
+ }
764
+ nodeButtonWidth(value?: NodeAccessor<number, Datum>): any {
765
+ if (arguments.length === 0) return this.attrs.nodeButtonWidth;
766
+ this.attrs.nodeButtonWidth = value!;
767
+ return this;
768
+ }
769
+ nodeButtonHeight(value?: NodeAccessor<number, Datum>): any {
770
+ if (arguments.length === 0) return this.attrs.nodeButtonHeight;
771
+ this.attrs.nodeButtonHeight = value!;
772
+ return this;
773
+ }
774
+ nodeButtonX(value?: NodeAccessor<number, Datum>): any {
775
+ if (arguments.length === 0) return this.attrs.nodeButtonX;
776
+ this.attrs.nodeButtonX = value!;
777
+ return this;
778
+ }
779
+ nodeButtonY(value?: NodeAccessor<number, Datum>): any {
780
+ if (arguments.length === 0) return this.attrs.nodeButtonY;
781
+ this.attrs.nodeButtonY = value!;
782
+ return this;
783
+ }
784
+ pagingStep(value?: NodeAccessor<number, Datum>): any {
785
+ if (arguments.length === 0) return this.attrs.pagingStep;
786
+ this.attrs.pagingStep = value!;
787
+ return this;
788
+ }
789
+ minPagingVisibleNodes(value?: NodeAccessor<number, Datum>): any {
790
+ if (arguments.length === 0) return this.attrs.minPagingVisibleNodes;
791
+ this.attrs.minPagingVisibleNodes = value!;
792
+ return this;
793
+ }
794
+
795
+ // Callback Methods
796
+ nodeContent(value?: NodeContentCallback<Datum>): any {
797
+ if (arguments.length === 0) return this.attrs.nodeContent;
798
+ this.attrs.nodeContent = value!;
799
+ return this;
800
+ }
801
+ buttonContent(value?: ButtonContentCallback<Datum>): any {
802
+ if (arguments.length === 0) return this.attrs.buttonContent;
803
+ this.attrs.buttonContent = value!;
804
+ return this;
805
+ }
806
+ pagingButton(value?: PagingButtonCallback<Datum>): any {
807
+ if (arguments.length === 0) return this.attrs.pagingButton;
808
+ this.attrs.pagingButton = value!;
809
+ return this;
810
+ }
811
+ onNodeClick(value?: NodeClickCallback<Datum>): any {
812
+ if (arguments.length === 0) return this.attrs.onNodeClick;
813
+ this.attrs.onNodeClick = value!;
814
+ return this;
815
+ }
816
+ onExpandOrCollapse(value?: NodeExpandCollapseCallback<Datum>): any {
817
+ if (arguments.length === 0) return this.attrs.onExpandOrCollapse;
818
+ this.attrs.onExpandOrCollapse = value!;
819
+ return this;
820
+ }
821
+ onZoomStart(value?: ZoomCallback<Datum>): any {
822
+ if (arguments.length === 0) return this.attrs.onZoomStart;
823
+ this.attrs.onZoomStart = value!;
824
+ return this;
825
+ }
826
+ onZoom(value?: ZoomCallback<Datum>): any {
827
+ if (arguments.length === 0) return this.attrs.onZoom;
828
+ this.attrs.onZoom = value!;
829
+ return this;
830
+ }
831
+ onZoomEnd(value?: ZoomCallback<Datum>): any {
832
+ if (arguments.length === 0) return this.attrs.onZoomEnd;
833
+ this.attrs.onZoomEnd = value!;
834
+ return this;
835
+ }
836
+ nodeUpdate(value?: NodeUpdateCallback<Datum>): any {
837
+ if (arguments.length === 0) return this.attrs.nodeUpdate;
838
+ this.attrs.nodeUpdate = value!;
839
+ return this;
840
+ }
841
+ nodeEnter(value?: NodeEnterCallback<Datum>): any {
842
+ if (arguments.length === 0) return this.attrs.nodeEnter;
843
+ this.attrs.nodeEnter = value!;
844
+ return this;
845
+ }
846
+ nodeExit(value?: NodeExitCallback<Datum>): any {
847
+ if (arguments.length === 0) return this.attrs.nodeExit;
848
+ this.attrs.nodeExit = value!;
849
+ return this;
850
+ }
851
+ linkUpdate(value?: LinkUpdateCallback<Datum>): any {
852
+ if (arguments.length === 0) return this.attrs.linkUpdate;
853
+ this.attrs.linkUpdate = value!;
854
+ return this;
855
+ }
856
+ connectionsUpdate(value?: ConnectionsUpdateCallback<Datum>): any {
857
+ if (arguments.length === 0) return this.attrs.connectionsUpdate;
858
+ this.attrs.connectionsUpdate = value!;
859
+ return this;
860
+ }
861
+ defs(value?: DefsCallback<Datum>): any {
862
+ if (arguments.length === 0) return this.attrs.defs;
863
+ this.attrs.defs = value!;
864
+ return this;
865
+ }
866
+ lastTransform(value?: { x: number; y: number; k: number }): any {
867
+ if (arguments.length === 0) return this.attrs.lastTransform;
868
+ this.attrs.lastTransform = value!;
869
+ return this;
870
+ }
871
+
872
+ // This method retrieves passed node's children IDs (including node)
873
+ getNodeChildren({ data, children, _children }: { data: Datum; children?: OrgChartNode<Datum>[]; _children?: OrgChartNode<Datum>[] }, nodeStore: Datum[] = []): Datum[] {
874
+ // Store current node ID
875
+ nodeStore.push(data);
876
+
877
+ // Loop over children and recursively store descendants id (expanded nodes)
878
+ if (children) {
879
+ children.forEach((d) => {
880
+ this.getNodeChildren(d, nodeStore);
881
+ });
882
+ }
883
+
884
+ // Loop over _children and recursively store descendants id (collapsed nodes)
885
+ if (_children) {
886
+ _children.forEach((d) => {
887
+ this.getNodeChildren(d, nodeStore);
888
+ });
889
+ }
890
+
891
+ // Return result
892
+ return nodeStore;
893
+ }
894
+
895
+ // This method can be invoked via chart.setZoomFactor API, it zooms to particulat scale
896
+ initialZoom(zoomLevel: number): this {
897
+ const attrs = this.getChartState();
898
+ attrs.lastTransform.k = zoomLevel;
899
+ return this;
900
+ }
901
+
902
+ render(): this {
903
+ //InnerFunctions which will update visuals
904
+ const attrs: any = this.getChartState();
905
+ if (!attrs.data || attrs.data.length == 0) {
906
+ console.log('ORG CHART - Data is empty');
907
+ if (attrs.container) {
908
+ (select as any)(attrs.container).select('.nodes-wrapper').remove();
909
+ (select as any)(attrs.container).select('.links-wrapper').remove();
910
+ (select as any)(attrs.container).select('.connections-wrapper').remove();
911
+ }
912
+ return this;
913
+ }
914
+
915
+ //Drawing containers
916
+ const container = (d3.select as any)(attrs.container);
917
+ const containerNode = container.node();
918
+ if (containerNode && 'getBoundingClientRect' in containerNode) {
919
+ const containerRect = (containerNode as HTMLElement).getBoundingClientRect();
920
+ if (containerRect.width > 0) attrs.svgWidth = containerRect.width;
921
+ }
922
+
923
+ //Calculated properties
924
+ const calc: CalcProperties = {
925
+ id: `ID${crypto.randomUUID()}`, // id for event handlings,
926
+ chartWidth: attrs.svgWidth,
927
+ chartHeight: attrs.svgHeight,
928
+ centerX: attrs.svgWidth / 2,
929
+ centerY: attrs.svgHeight / 2,
930
+ };
931
+ attrs.calc = calc;
932
+
933
+ // ******************* BEHAVIORS **********************
934
+ if (attrs.firstDraw) {
935
+ const behaviors: any = {
936
+ zoom: null,
937
+ };
938
+
939
+ // Get zooming function
940
+ behaviors.zoom = attrs
941
+ .createZoom(attrs.root!)
942
+ .clickDistance(10)
943
+ .wheelDelta((event: any) => {
944
+ if (event.ctrlKey) {
945
+ event.preventDefault();
946
+
947
+ const isPinchGesture = event.ctrlKey && event.deltaMode === 0 && Math.abs(event.deltaY) < 50;
948
+ const isCtrlScrollReal = event.ctrlKey && Math.abs(event.deltaY) >= 50;
949
+ return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 0.002) * (isPinchGesture ? 10 : isCtrlScrollReal ? 1 : 1);
950
+ }
951
+
952
+ return 0;
953
+ })
954
+ .on('start', (event: any, _d: any) => attrs.onZoomStart(event))
955
+ .on('end', (event: any, _d: any) => attrs.onZoomEnd(event))
956
+ .on('zoom', (event: any, d: any) => {
957
+ attrs.onZoom(event);
958
+ this.zoomed(event, d);
959
+ })
960
+ .scaleExtent(attrs.scaleExtent);
961
+ attrs.zoomBehavior = behaviors.zoom;
962
+ }
963
+
964
+ //****************** ROOT node work ************************
965
+
966
+ attrs.flexTreeLayout = flextree<Datum>({
967
+ nodeSize: (node: any) => {
968
+ const width = attrs.nodeWidth(node);
969
+ const height = attrs.nodeHeight(node);
970
+ const siblingsMargin = attrs.siblingsMargin(node);
971
+ const childrenMargin = attrs.childrenMargin(node);
972
+ return attrs.layoutBindings[attrs.layout].nodeFlexSize({
973
+ state: attrs,
974
+ node: node as OrgChartNode<Datum>,
975
+ width,
976
+ height,
977
+ siblingsMargin,
978
+ childrenMargin,
979
+ });
980
+ },
981
+ }).spacing((nodeA: any, nodeB: any) => (nodeA.parent == nodeB.parent ? 0 : attrs.neighbourMargin(nodeA as OrgChartNode<Datum>, nodeB as OrgChartNode<Datum>)));
982
+
983
+ this.setLayouts({ expandNodesFirst: false });
984
+
985
+ // ************************* DRAWING **************************
986
+ //Add svg
987
+ const svg = container
988
+ .patternify({
989
+ tag: 'svg',
990
+ selector: 'svg-chart-container',
991
+ })
992
+ .attr('width', attrs.svgWidth)
993
+ .attr('height', attrs.svgHeight)
994
+ .attr('font-family', attrs.defaultFont);
995
+
996
+ if (attrs.firstDraw) {
997
+ svg.call(attrs.zoomBehavior)
998
+ .on('dblclick.zoom', null)
999
+ .on(
1000
+ 'wheel',
1001
+ (event: any) => {
1002
+ const t = d3.zoomTransform(svg.node());
1003
+ const k = t.k;
1004
+
1005
+ if (event.ctrlKey) {
1006
+ event.preventDefault();
1007
+ return;
1008
+ }
1009
+
1010
+ event.preventDefault();
1011
+ if (attrs.zoomBehavior) {
1012
+ svg.call(attrs.zoomBehavior.transform, d3.zoomIdentity.translate(t.x - event.deltaX, t.y - event.deltaY).scale(k));
1013
+ }
1014
+ },
1015
+ { passive: false }
1016
+ )
1017
+ .attr('cursor', 'move');
1018
+ }
1019
+
1020
+ attrs.svg = svg;
1021
+
1022
+ //Add container g element
1023
+ const chart = svg.patternify({
1024
+ tag: 'g',
1025
+ selector: 'chart',
1026
+ });
1027
+
1028
+ // Add one more container g element, for better positioning controls
1029
+ attrs.centerG = chart.patternify({
1030
+ tag: 'g',
1031
+ selector: 'center-group',
1032
+ });
1033
+
1034
+ attrs.linksWrapper = attrs.centerG!.patternify({
1035
+ tag: 'g',
1036
+ selector: 'links-wrapper',
1037
+ });
1038
+
1039
+ attrs.nodesWrapper = attrs.centerG!.patternify({
1040
+ tag: 'g',
1041
+ selector: 'nodes-wrapper',
1042
+ });
1043
+
1044
+ attrs.connectionsWrapper = attrs.centerG!.patternify({
1045
+ tag: 'g',
1046
+ selector: 'connections-wrapper',
1047
+ });
1048
+
1049
+ attrs.defsWrapper = svg.patternify({
1050
+ tag: 'g',
1051
+ selector: 'defs-wrapper',
1052
+ });
1053
+
1054
+ if (attrs.firstDraw) {
1055
+ attrs.centerG!.attr('transform', () => {
1056
+ return attrs.layoutBindings[attrs.layout].centerTransform({
1057
+ centerX: calc.centerX,
1058
+ centerY: calc.centerY,
1059
+ scale: attrs.lastTransform.k,
1060
+ rootMargin: attrs.rootMargin,
1061
+ root: attrs.root!,
1062
+ });
1063
+ });
1064
+ }
1065
+
1066
+ attrs.chart = chart;
1067
+
1068
+ // Display tree contenrs
1069
+ this.update(attrs.root!);
1070
+
1071
+ //######################################### UTIL FUNCS ##################################
1072
+ // This function restyles foreign object elements ()
1073
+
1074
+ d3.select(window).on(`resize.${attrs.id}`, () => {
1075
+ const containerNode = (d3.select as any)(attrs.container).node();
1076
+ if (containerNode && 'getBoundingClientRect' in containerNode) {
1077
+ const containerRect = (containerNode as HTMLElement).getBoundingClientRect();
1078
+ attrs.svg!.attr('width', containerRect.width);
1079
+ }
1080
+ });
1081
+
1082
+ if (attrs.firstDraw) {
1083
+ attrs.firstDraw = false;
1084
+ }
1085
+
1086
+ return this;
1087
+ }
1088
+
1089
+ // This function can be invoked via chart.addNode API, and it adds node in tree at runtime
1090
+ addNode(obj: Datum): this {
1091
+ const attrs = this.getChartState();
1092
+ if (obj && (attrs.parentNodeId(obj) == null || attrs.parentNodeId(obj) == attrs.nodeId(obj)) && (attrs.data?.length || 0) == 0) {
1093
+ attrs.data!.push(obj);
1094
+ this.render();
1095
+ return this;
1096
+ }
1097
+ const root = attrs.generateRoot!(attrs.data || []);
1098
+ const descendants = root.descendants();
1099
+ const nodeFound = descendants.filter(({ data }) => attrs.nodeId(data).toString() === attrs.nodeId(obj).toString())[0];
1100
+ if (nodeFound) {
1101
+ console.log(`ORG CHART - ADD - Node with id "${attrs.nodeId(obj)}" already exists in tree`);
1102
+ return this;
1103
+ }
1104
+
1105
+ if ((obj as any)._centered && !(obj as any)._expanded) (obj as any)._expanded = true;
1106
+ attrs.data!.push(obj);
1107
+
1108
+ // Update state of nodes and redraw graph
1109
+ this.updateNodesState();
1110
+
1111
+ return this;
1112
+ }
1113
+
1114
+ // This function can be invoked via chart.removeNode API, and it removes node from tree at runtime
1115
+ removeNode(nodeId: string | number): this {
1116
+ const attrs = this.getChartState();
1117
+ const root = attrs.generateRoot!(attrs.data || []);
1118
+ const descendants = root.descendants();
1119
+ const node = descendants.find(({ data }) => attrs.nodeId(data) == nodeId);
1120
+
1121
+ if (!node) {
1122
+ console.log(`ORG CHART - REMOVE - Node with id "${nodeId}" not found in the tree`);
1123
+ return this;
1124
+ }
1125
+
1126
+ // Get all node descendants
1127
+ const nodeDescendants = node.descendants();
1128
+
1129
+ // Mark all node children and node itself for removal
1130
+ nodeDescendants.forEach((d) => ((d.data as any)._filteredOut = true));
1131
+
1132
+ // Filter out retrieved nodes and reassign data
1133
+ attrs.data = attrs.data!.filter((d) => !(d as any)._filteredOut);
1134
+
1135
+ if ((attrs.data?.length || 0) == 0) {
1136
+ this.render();
1137
+ } else {
1138
+ const updateNodesState = this.updateNodesState.bind(this);
1139
+ // Update state of nodes and redraw graph
1140
+ updateNodesState();
1141
+ }
1142
+ return this;
1143
+ }
1144
+
1145
+ groupBy<T, K extends string | number>(array: T[], accessor: (item: T) => K, aggregator: (group: T[]) => any): [string, any][] {
1146
+ const grouped: Record<string, T[]> = {};
1147
+ array.forEach((item) => {
1148
+ const key = String(accessor(item));
1149
+ grouped[key] ??= [];
1150
+ grouped[key].push(item);
1151
+ });
1152
+
1153
+ Object.keys(grouped).forEach((key) => {
1154
+ grouped[key] = aggregator(grouped[key] as any);
1155
+ });
1156
+ return Object.entries(grouped);
1157
+ }
1158
+
1159
+ calculateCompactFlexDimensions(root: OrgChartNode<Datum>): void {
1160
+ const attrs = this.getChartState();
1161
+ root.eachBefore((node) => {
1162
+ node.firstCompact = undefined;
1163
+ node.compactEven = undefined;
1164
+ node.flexCompactDim = undefined;
1165
+ node.firstCompactNode = undefined;
1166
+ });
1167
+ root.eachBefore((node) => {
1168
+ if (node.children && node.children.length > 1) {
1169
+ const compactChildren = node.children.filter((d) => !d.children);
1170
+
1171
+ if (compactChildren.length < 2) return;
1172
+ compactChildren.forEach((child, i) => {
1173
+ if (!i) child.firstCompact = true;
1174
+ if (i % 2) child.compactEven = false;
1175
+ else child.compactEven = true;
1176
+ child.row = Math.floor(i / 2);
1177
+ });
1178
+ const evenMaxColumnDimension =
1179
+ d3.max(
1180
+ compactChildren.filter((d) => d.compactEven),
1181
+ attrs.layoutBindings[attrs.layout].compactDimension.sizeColumn
1182
+ ) || 0;
1183
+ const oddMaxColumnDimension =
1184
+ d3.max(
1185
+ compactChildren.filter((d) => !d.compactEven),
1186
+ attrs.layoutBindings[attrs.layout].compactDimension.sizeColumn
1187
+ ) || 0;
1188
+ const columnSize = Math.max(evenMaxColumnDimension, oddMaxColumnDimension) * 2;
1189
+ const rowsMapNew = this.groupBy(
1190
+ compactChildren,
1191
+ (d) => d.row || 0,
1192
+ (reducedGroup) => d3.max(reducedGroup, (d) => attrs.layoutBindings[attrs.layout].compactDimension.sizeRow(d) + attrs.compactMarginBetween(d))
1193
+ );
1194
+ const rowSize = d3.sum(rowsMapNew.map((v) => v[1]));
1195
+ compactChildren.forEach((node) => {
1196
+ node.firstCompactNode = compactChildren[0];
1197
+ if (node.firstCompact) {
1198
+ node.flexCompactDim = [columnSize + attrs.compactMarginPair(node), rowSize - attrs.compactMarginBetween(node)];
1199
+ } else {
1200
+ node.flexCompactDim = [0, 0];
1201
+ }
1202
+ });
1203
+ node.flexCompactDim = undefined;
1204
+ }
1205
+ });
1206
+ }
1207
+
1208
+ calculateCompactFlexPositions(root: OrgChartNode<Datum>): void {
1209
+ const attrs = this.getChartState();
1210
+ root.eachBefore((node) => {
1211
+ if (node.children) {
1212
+ const compactChildren = node.children.filter((d) => d.flexCompactDim);
1213
+ const fch = compactChildren[0];
1214
+ if (!fch?.flexCompactDim) return;
1215
+ compactChildren.forEach((child, i, _arr) => {
1216
+ if (i == 0 && fch.flexCompactDim) fch.x -= fch.flexCompactDim[0] / 2;
1217
+ if (fch.flexCompactDim && i & ((i % 2) - 1)) child.x = fch.x + fch.flexCompactDim[0] * 0.25 - attrs.compactMarginPair(child) / 4;
1218
+ else if (i && fch.flexCompactDim) child.x = fch.x + fch.flexCompactDim[0] * 0.75 + attrs.compactMarginPair(child) / 4;
1219
+ });
1220
+ if (!fch.flexCompactDim) return;
1221
+ const centerX = fch.x + fch.flexCompactDim[0] * 0.5;
1222
+ fch.x = fch.x + fch.flexCompactDim[0] * 0.25 - attrs.compactMarginPair(fch) / 4;
1223
+ const offsetX = node.x - centerX;
1224
+ if (Math.abs(offsetX) < 10) {
1225
+ compactChildren.forEach((d) => (d.x += offsetX));
1226
+ }
1227
+
1228
+ const rowsMapNew = this.groupBy(
1229
+ compactChildren,
1230
+ (d) => d.row || 0,
1231
+ (reducedGroup) => d3.max(reducedGroup, (d) => attrs.layoutBindings[attrs.layout].compactDimension.sizeRow(d))
1232
+ );
1233
+ const cumSum = d3.cumsum(rowsMapNew.map((d) => d[1] + attrs.compactMarginBetween(fch)));
1234
+ compactChildren.forEach((node, _i) => {
1235
+ if (node.row) {
1236
+ const cumulativeValue = cumSum[(node.row ?? 0) - 1];
1237
+ node.y = fch.y + (cumulativeValue ?? 0);
1238
+ } else {
1239
+ node.y = fch.y;
1240
+ }
1241
+ });
1242
+ }
1243
+ });
1244
+ }
1245
+
1246
+ // This function basically redraws visible graph, based on nodes state
1247
+ update({ x0, y0, x = 0, y = 0, width, height }: UpdateParams): this {
1248
+ const attrs = this.getChartState();
1249
+
1250
+ // Paging
1251
+ if (attrs.compact) {
1252
+ this.calculateCompactFlexDimensions(attrs.root!);
1253
+ }
1254
+
1255
+ // Assigns the x and y position for the nodes
1256
+ const treeData = attrs.flexTreeLayout!(attrs.root! as any);
1257
+
1258
+ // Reassigns the x and y position for the based on the compact layout
1259
+ if (attrs.compact) {
1260
+ this.calculateCompactFlexPositions(attrs.root!);
1261
+ }
1262
+
1263
+ const nodes = treeData.descendants() as unknown as OrgChartNode<Datum>[];
1264
+
1265
+ // console.table(nodes.map(d => ({ x: d.x, y: d.y, width: d.width, height: d.height, flexCompactDim: d.flexCompactDim + "" })))
1266
+
1267
+ // Get all links
1268
+ const links = treeData.descendants().slice(1);
1269
+ nodes.forEach((element) => {
1270
+ return attrs.layoutBindings[attrs.layout].swap(element);
1271
+ });
1272
+
1273
+ // Connections
1274
+ const connections = attrs.connections;
1275
+ const allNodesMap: any = {};
1276
+ attrs.allNodes!.forEach((d) => (allNodesMap[attrs.nodeId(d.data)] = d));
1277
+
1278
+ const visibleNodesMap: any = {};
1279
+ nodes.forEach((d) => (visibleNodesMap[attrs.nodeId(d.data)] = d));
1280
+
1281
+ connections.forEach((connection) => {
1282
+ const source = allNodesMap[connection.from];
1283
+ const target = allNodesMap[connection.to];
1284
+ connection._source = source;
1285
+ connection._target = target;
1286
+ });
1287
+ const visibleConnections = connections.filter((d) => visibleNodesMap[d.from] && visibleNodesMap[d.to]);
1288
+ const defsString = attrs.defs.bind(this)(attrs, visibleConnections);
1289
+ const existingString = attrs.defsWrapper!.html();
1290
+ if (defsString !== existingString) {
1291
+ attrs.defsWrapper!.html(defsString);
1292
+ }
1293
+
1294
+ // -------------------------- LINKS ----------------------
1295
+ // Get links selection
1296
+ const linkSelection = attrs.linksWrapper!.selectAll('path.link').data(links, (d: any) => attrs.nodeId(d.data));
1297
+
1298
+ // Enter any new links at the parent's previous position.
1299
+ const linkEnter = linkSelection
1300
+ .enter()
1301
+ .insert('path', 'g')
1302
+ .attr('class', 'link')
1303
+ .attr('d', (_d: any) => {
1304
+ const xo = attrs.layoutBindings[attrs.layout].linkJoinX({ x: x0, y: y0, width, height });
1305
+ const yo = attrs.layoutBindings[attrs.layout].linkJoinY({ x: x0, y: y0, width, height });
1306
+ const o = { x: xo, y: yo };
1307
+ return attrs.layoutBindings[attrs.layout].diagonal(o, o, o);
1308
+ });
1309
+
1310
+ // Get links update selection
1311
+ const linkUpdate = (linkEnter as any).merge(linkSelection);
1312
+
1313
+ // Styling links
1314
+ linkUpdate.attr('fill', 'none');
1315
+
1316
+ if (this.isEdge()) {
1317
+ linkUpdate.style('display', (d: any) => {
1318
+ const display = d.data._pagingButton ? 'none' : 'auto';
1319
+ return display;
1320
+ });
1321
+ } else {
1322
+ linkUpdate.attr('display', (d: any) => {
1323
+ const display = d.data._pagingButton ? 'none' : 'auto';
1324
+ return display;
1325
+ });
1326
+ }
1327
+
1328
+ // Allow external modifications
1329
+ linkUpdate.each(attrs.linkUpdate as any);
1330
+
1331
+ // Transition back to the parent element position
1332
+ linkUpdate
1333
+ .transition()
1334
+ .duration(attrs.duration)
1335
+ .attr('d', (d: any) => {
1336
+ const n =
1337
+ attrs.compact && d.flexCompactDim
1338
+ ? {
1339
+ x: attrs.layoutBindings[attrs.layout].compactLinkMidX(d, attrs),
1340
+ y: attrs.layoutBindings[attrs.layout].compactLinkMidY(d, attrs),
1341
+ }
1342
+ : {
1343
+ x: attrs.layoutBindings[attrs.layout].linkX(d),
1344
+ y: attrs.layoutBindings[attrs.layout].linkY(d),
1345
+ };
1346
+
1347
+ const p = {
1348
+ x: attrs.layoutBindings[attrs.layout].linkParentX(d),
1349
+ y: attrs.layoutBindings[attrs.layout].linkParentY(d),
1350
+ };
1351
+
1352
+ const m =
1353
+ attrs.compact && d.flexCompactDim
1354
+ ? {
1355
+ x: attrs.layoutBindings[attrs.layout].linkCompactXStart(d),
1356
+ y: attrs.layoutBindings[attrs.layout].linkCompactYStart(d),
1357
+ }
1358
+ : n;
1359
+ return attrs.layoutBindings[attrs.layout].diagonal(n, p, m, { sy: attrs.linkYOffset });
1360
+ });
1361
+
1362
+ // Remove any links which is exiting after animation
1363
+ linkSelection
1364
+ .exit()
1365
+ .transition()
1366
+ .duration(attrs.duration)
1367
+ .attr('d', (_d: any) => {
1368
+ const xo = attrs.layoutBindings[attrs.layout].linkJoinX({ x, y, width, height });
1369
+ const yo = attrs.layoutBindings[attrs.layout].linkJoinY({ x, y, width, height });
1370
+ const o = { x: xo, y: yo };
1371
+ return attrs.layoutBindings[attrs.layout].diagonal(o, o, null, { sy: attrs.linkYOffset });
1372
+ })
1373
+ .remove();
1374
+
1375
+ // -------------------------- CONNECTIONS ----------------------
1376
+
1377
+ const connectionsSel = attrs.connectionsWrapper!.selectAll('path.connection').data(visibleConnections);
1378
+
1379
+ // Enter any new connections at the parent's previous position.
1380
+ const connEnter = connectionsSel
1381
+ .enter()
1382
+ .insert('path', 'g')
1383
+ .attr('class', 'connection')
1384
+ .attr('d', (_d: any) => {
1385
+ const xo = attrs.layoutBindings[attrs.layout].linkJoinX({ x: x0, y: y0, width, height });
1386
+ const yo = attrs.layoutBindings[attrs.layout].linkJoinY({ x: x0, y: y0, width, height });
1387
+ const o = { x: xo, y: yo };
1388
+ return attrs.layoutBindings[attrs.layout].diagonal(o, o, null, { sy: attrs.linkYOffset });
1389
+ });
1390
+
1391
+ // Get connections update selection
1392
+ const connUpdate = (connEnter as any).merge(connectionsSel);
1393
+
1394
+ // Styling connections
1395
+ (connUpdate as any).attr('fill', 'none');
1396
+
1397
+ // Transition back to the parent element position
1398
+ connUpdate
1399
+ .transition()
1400
+ .duration(attrs.duration)
1401
+ .attr('d', (d: any) => {
1402
+ const xs = attrs.layoutBindings[attrs.layout].linkX({ x: d._source.x, y: d._source.y, width: d._source.width, height: d._source.height } as any);
1403
+ const ys = attrs.layoutBindings[attrs.layout].linkY({ x: d._source.x, y: d._source.y, width: d._source.width, height: d._source.height } as any);
1404
+ const xt = attrs.layoutBindings[attrs.layout].linkJoinX({ x: d._target.x, y: d._target.y, width: d._target.width, height: d._target.height } as any);
1405
+ const yt = attrs.layoutBindings[attrs.layout].linkJoinY({ x: d._target.x, y: d._target.y, width: d._target.width, height: d._target.height } as any);
1406
+ return attrs.linkGroupArc({ source: { x: xs, y: ys }, target: { x: xt, y: yt } });
1407
+ });
1408
+
1409
+ // Allow external modifications
1410
+ connUpdate.each(attrs.connectionsUpdate);
1411
+
1412
+ // Remove any links which is exiting after animation
1413
+ connectionsSel.exit().transition().duration(attrs.duration).attr('opacity', 0).remove();
1414
+
1415
+ // -------------------------- NODES ----------------------
1416
+ // Get nodes selection
1417
+ const nodesSelection = attrs.nodesWrapper!.selectAll('g.node').data(nodes, (d: any) => attrs.nodeId(d.data));
1418
+
1419
+ // Enter any new nodes at the parent's previous position.
1420
+ const nodeEnter: any = nodesSelection
1421
+ .enter()
1422
+ .append('g')
1423
+ .attr('class', 'node')
1424
+ .attr('transform', (d: any) => {
1425
+ if (d == attrs.root) return `translate(${x0},${y0})`;
1426
+ const xj = attrs.layoutBindings[attrs.layout].nodeJoinX({ x: x0, y: y0, width, height });
1427
+ const yj = attrs.layoutBindings[attrs.layout].nodeJoinY({ x: x0, y: y0, width, height });
1428
+ return `translate(${xj},${yj})`;
1429
+ })
1430
+ .attr('cursor', 'pointer')
1431
+ .on('click.node', (event: any, node: any) => {
1432
+ const { data } = node;
1433
+ if ([...event.srcElement.classList].includes('node-button-foreign-object')) {
1434
+ return;
1435
+ }
1436
+ if ([...event.srcElement.classList].includes('paging-button-wrapper')) {
1437
+ this.loadPagingNodes(node);
1438
+ return;
1439
+ }
1440
+ if (!data._pagingButton) {
1441
+ attrs.onNodeClick(node);
1442
+ }
1443
+ })
1444
+ // Event handler to the expand button
1445
+ .on('keydown.node', (event, node) => {
1446
+ const { data: _data } = node;
1447
+ if (event.key === 'Enter' || event.key === ' ' || event.key === 'Spacebar') {
1448
+ if ([...event.srcElement.classList].includes('node-button-foreign-object')) {
1449
+ return;
1450
+ }
1451
+ if ([...event.srcElement.classList].includes('paging-button-wrapper')) {
1452
+ this.loadPagingNodes(node);
1453
+ return;
1454
+ }
1455
+ if (event.key === 'Enter' || event.key === ' ' || event.key === 'Spacebar') {
1456
+ this.onButtonClick(event, node);
1457
+ }
1458
+ }
1459
+ });
1460
+ nodeEnter.each(attrs.nodeEnter);
1461
+
1462
+ // Add background rectangle for the nodes
1463
+ nodeEnter.patternify({
1464
+ tag: 'rect',
1465
+ selector: 'node-rect',
1466
+ data: ((d: any) => [d]) as any,
1467
+ });
1468
+
1469
+ // Node update styles
1470
+ const nodeUpdate = nodeEnter.merge(nodesSelection).style('font', '12px sans-serif');
1471
+
1472
+ // Add foreignObject element inside rectangle
1473
+ const fo = nodeUpdate
1474
+ .patternify({
1475
+ tag: 'foreignObject',
1476
+ selector: 'node-foreign-object',
1477
+ data: (d: any) => [d],
1478
+ })
1479
+ .style('overflow', 'visible');
1480
+
1481
+ // Add foreign object
1482
+ fo.patternify({
1483
+ tag: 'xhtml:div',
1484
+ selector: 'node-foreign-object-div',
1485
+ data: (d: any) => [d],
1486
+ });
1487
+
1488
+ this.restyleForeignObjectElements();
1489
+
1490
+ // Add Node button circle's group (expand-collapse button)
1491
+ const nodeButtonGroups = nodeEnter
1492
+ .patternify({
1493
+ tag: 'g',
1494
+ selector: 'node-button-g',
1495
+ data: (d: any) => [d],
1496
+ })
1497
+ .on('click', (event: any, d: OrgChartNode<Datum>) => this.onButtonClick(event, d))
1498
+ .on('keydown', (event: { key: string }, d: OrgChartNode<Datum>) => {
1499
+ if (event.key === 'Enter' || event.key === ' ' || event.key === 'Spacebar') {
1500
+ this.onButtonClick(event, d);
1501
+ }
1502
+ });
1503
+
1504
+ nodeButtonGroups
1505
+ .patternify({
1506
+ tag: 'rect',
1507
+ selector: 'node-button-rect',
1508
+ data: ((d: any) => [d]) as any,
1509
+ })
1510
+ .attr('opacity', 0)
1511
+ .attr('pointer-events', 'all')
1512
+ .attr('width', (d: any) => attrs.nodeButtonWidth(d))
1513
+ .attr('height', (d: any) => attrs.nodeButtonHeight(d))
1514
+ .attr('x', (d: any) => attrs.nodeButtonX(d))
1515
+ .attr('y', (d: any) => attrs.nodeButtonY(d));
1516
+
1517
+ // Add expand collapse button content
1518
+ nodeButtonGroups
1519
+ .patternify({
1520
+ tag: 'foreignObject',
1521
+ selector: 'node-button-foreign-object',
1522
+ data: (d: any) => [d],
1523
+ })
1524
+ .attr('width', (d: any) => attrs.nodeButtonWidth(d))
1525
+ .attr('height', (d: any) => attrs.nodeButtonHeight(d))
1526
+ .attr('x', (d: any) => attrs.nodeButtonX(d))
1527
+ .attr('y', (d: any) => attrs.nodeButtonY(d))
1528
+ .style('overflow', 'visible')
1529
+ .patternify({
1530
+ tag: 'xhtml:div',
1531
+ selector: 'node-button-div',
1532
+ data: ((d: any) => [d]) as any,
1533
+ })
1534
+ .style('pointer-events', 'none')
1535
+ .style('display', 'flex')
1536
+ .style('width', '100%')
1537
+ .style('height', '100%');
1538
+
1539
+ // Transition to the proper position for the node
1540
+ nodeUpdate
1541
+ .transition()
1542
+ .attr('opacity', 0)
1543
+ .duration(attrs.duration)
1544
+ .attr('transform', ({ x, y, width, height }: { x: any; y: any; width: any; height: any }) => {
1545
+ return attrs.layoutBindings[attrs.layout].nodeUpdateTransform({ x, y, width, height } as any, attrs);
1546
+ })
1547
+ .attr('opacity', 1);
1548
+
1549
+ // Style node rectangles
1550
+ nodeUpdate
1551
+ .select('.node-rect')
1552
+ .attr('width', (d: any) => d.width)
1553
+ .attr('height', (d: any) => d.height)
1554
+ .attr('x', (_d: any) => 0)
1555
+ .attr('y', (_d: any) => 0)
1556
+ .attr('cursor', 'pointer')
1557
+ .attr('rx', 3)
1558
+ .attr('fill', attrs.nodeDefaultBackground);
1559
+
1560
+ nodeUpdate
1561
+ .select('.node-button-g')
1562
+ .attr('transform', (d: any) => {
1563
+ const x = attrs.layoutBindings[attrs.layout].buttonX(d);
1564
+ const y = attrs.layoutBindings[attrs.layout].buttonY(d);
1565
+ return `translate(${x},${y})`;
1566
+ })
1567
+ .attr('display', ({ data }: { data: any }) => {
1568
+ return data._directSubordinates > 0 ? null : 'none';
1569
+ })
1570
+ .attr('opacity', (d: any) => {
1571
+ if (d.data._pagingButton) {
1572
+ return 0;
1573
+ }
1574
+ if (d.children || d._children) {
1575
+ return 1;
1576
+ }
1577
+ return 0;
1578
+ });
1579
+
1580
+ // Restyle node button circle
1581
+ nodeUpdate.select('.node-button-foreign-object .node-button-div').html((node: any) => {
1582
+ return attrs.buttonContent({ node, state: attrs });
1583
+ });
1584
+
1585
+ // Restyle button texts
1586
+ nodeUpdate
1587
+ .select('.node-button-text')
1588
+ .attr('text-anchor', 'middle')
1589
+ .attr('alignment-baseline', 'middle')
1590
+ .attr('font-size', ({ children }: { children: any }) => {
1591
+ if (children) return 40;
1592
+ return 26;
1593
+ })
1594
+ .text(({ children }: { children: any }) => {
1595
+ if (children) return '-';
1596
+ return '+';
1597
+ })
1598
+ .attr('y', this.isEdge() ? 10 : 0);
1599
+
1600
+ nodeUpdate.each(attrs.nodeUpdate as any);
1601
+
1602
+ // Remove any exiting nodes after transition
1603
+ const nodeExitTransition = nodesSelection.exit();
1604
+ nodeExitTransition.each(attrs.nodeExit as any);
1605
+
1606
+ const maxDepthNode: any = nodeExitTransition.data().reduce((a: any, b: any) => (a.depth < b.depth ? a : b), { depth: Infinity });
1607
+
1608
+ nodeExitTransition
1609
+ .attr('opacity', 1)
1610
+ .transition()
1611
+ .duration(attrs.duration)
1612
+ .attr('transform', (_d: any) => {
1613
+ const { x, y, width, height } = maxDepthNode.parent || {};
1614
+ const ex = attrs.layoutBindings[attrs.layout].nodeJoinX({ x, y, width, height } as any);
1615
+ const ey = attrs.layoutBindings[attrs.layout].nodeJoinY({ x, y, width, height } as any);
1616
+ return `translate(${ex},${ey})`;
1617
+ })
1618
+ .on('end', function () {
1619
+ d3.select(this).remove();
1620
+ })
1621
+ .attr('opacity', 0);
1622
+
1623
+ // Store the old positions for transition.
1624
+ nodes.forEach((d: any) => {
1625
+ d.x0 = d.x;
1626
+ d.y0 = d.y;
1627
+ });
1628
+
1629
+ // CHECK FOR CENTERING
1630
+ const centeredNode = attrs.allNodes!.find((d) => d.data._centered);
1631
+ if (centeredNode) {
1632
+ let centeredNodes = [centeredNode];
1633
+ if (centeredNode.data._centeredWithDescendants) {
1634
+ if (attrs.compact) {
1635
+ centeredNodes = centeredNode.descendants().filter((_, i) => i < 7);
1636
+ } else {
1637
+ centeredNodes = centeredNode.descendants().filter((_, i, arr) => {
1638
+ const h = Math.round(arr.length / 2);
1639
+ const spread = 2;
1640
+ if (arr.length % 2) {
1641
+ return i > h - spread && i < h + spread - 1;
1642
+ }
1643
+
1644
+ return i > h - spread && i < h + spread;
1645
+ });
1646
+ }
1647
+ }
1648
+ centeredNode.data._centeredWithDescendants = undefined;
1649
+ centeredNode.data._centered = undefined;
1650
+ this.fit({
1651
+ animate: true,
1652
+ scale: false,
1653
+ nodes: centeredNodes,
1654
+ });
1655
+ }
1656
+
1657
+ return this;
1658
+ }
1659
+
1660
+ // This function detects whether current browser is edge
1661
+ isEdge(): boolean {
1662
+ return globalThis.navigator.userAgent.includes('Edge');
1663
+ }
1664
+
1665
+ // Generate horizontal diagonal - play with it here - https://observablehq.com/@bumbeishvili/curved-edges-horizontal-d3-v3-v4-v5-v6
1666
+ hdiagonal(s: Point, t: Point, m?: Point | null, offsets?: any): string {
1667
+ const state = this.getChartState();
1668
+ return state.hdiagonal!(s, t, m, offsets);
1669
+ }
1670
+
1671
+ // Generate custom diagonal - play with it here - https://observablehiq.com/@bumbeishvili/curved-edges
1672
+ diagonal(s: Point, t: Point, m?: Point | null, offsets?: any): string {
1673
+ const state = this.getChartState();
1674
+ return state.diagonal!(s, t, m, offsets);
1675
+ }
1676
+
1677
+ restyleForeignObjectElements(): void {
1678
+ const attrs = this.getChartState();
1679
+
1680
+ attrs
1681
+ .svg!.selectAll('.node-foreign-object')
1682
+ .attr('width', (d: any) => d.width)
1683
+ .attr('height', (d: any) => d.height)
1684
+ .attr('x', (_d: any) => 0)
1685
+ .attr('y', (_d: any) => 0);
1686
+ attrs
1687
+ .svg!.selectAll('.node-foreign-object-div')
1688
+ .style('width', (d: any) => `${d.width}px`)
1689
+ .style('height', (d: any) => `${d.height}px`)
1690
+ .html(function (this: any, d: any, i: number, arr: any) {
1691
+ if (d.data._pagingButton) {
1692
+ return `<div class="paging-button-wrapper"><div style="pointer-events:none">${attrs.pagingButton(d, i, arr, attrs)}</div></div>`;
1693
+ }
1694
+ return vnodeToHTML(attrs.nodeContent.bind(this)(d));
1695
+ });
1696
+ }
1697
+
1698
+ // Toggle children on click.
1699
+ onButtonClick(event: any, d: OrgChartNode<Datum>): void {
1700
+ const attrs = this.getChartState();
1701
+ if (d.data._pagingButton) {
1702
+ return;
1703
+ }
1704
+ if (attrs.setActiveNodeCentered) {
1705
+ (d.data as any)._centered = true;
1706
+ (d.data as any)._centeredWithDescendants = true;
1707
+ }
1708
+
1709
+ // If childrens are expanded
1710
+ if (d.children) {
1711
+ //Collapse them
1712
+ d._children = d.children;
1713
+ d.children = undefined;
1714
+
1715
+ // Set descendants expanded property to false
1716
+ this.setExpansionFlagToChildren(d, false);
1717
+ } else {
1718
+ // Expand children
1719
+ d.children = d._children;
1720
+ d._children = undefined;
1721
+
1722
+ // Set each children as expanded
1723
+ if (d.children) {
1724
+ d.children.forEach(({ data }) => ((data as any)._expanded = true));
1725
+ }
1726
+ }
1727
+
1728
+ // Redraw Graph
1729
+ this.update({ x0: d.x0 || 0, y0: d.y0 || 0, width: d.width, height: d.height });
1730
+ event.stopPropagation();
1731
+
1732
+ // Trigger callback
1733
+ attrs.onExpandOrCollapse(d);
1734
+ }
1735
+
1736
+ // This function changes `expanded` property to descendants
1737
+ setExpansionFlagToChildren({ data, children, _children }: OrgChartNode<Datum>, flag: boolean): void {
1738
+ // Set flag to the current property
1739
+ (data as any)._expanded = flag;
1740
+
1741
+ // Loop over and recursively update expanded children's descendants
1742
+ if (children) {
1743
+ children.forEach((d) => {
1744
+ this.setExpansionFlagToChildren(d, flag);
1745
+ });
1746
+ }
1747
+
1748
+ // Loop over and recursively update collapsed children's descendants
1749
+ if (_children) {
1750
+ _children.forEach((d) => {
1751
+ this.setExpansionFlagToChildren(d, flag);
1752
+ });
1753
+ }
1754
+ }
1755
+
1756
+ // Method which only expands nodes, which have property set "expanded=true"
1757
+ expandSomeNodes(d: OrgChartNode<Datum>): void {
1758
+ // If node has expanded property set
1759
+ if ((d.data as any)._expanded) {
1760
+ // Retrieve node's parent
1761
+ let parent = d.parent;
1762
+
1763
+ // While we can go up
1764
+ while (parent && parent._children) {
1765
+ // Expand all current parent's children
1766
+ parent.children = parent._children;
1767
+ parent._children = undefined;
1768
+ // Replace current parent holding object
1769
+ parent = parent.parent;
1770
+ }
1771
+ }
1772
+
1773
+ // Recursively do the same for collapsed nodes
1774
+ if (d._children) {
1775
+ d._children.forEach((ch) => this.expandSomeNodes(ch));
1776
+ }
1777
+
1778
+ // Recursively do the same for expanded nodes
1779
+ if (d.children) {
1780
+ d.children.forEach((ch) => this.expandSomeNodes(ch));
1781
+ }
1782
+ }
1783
+
1784
+ // This function updates nodes state and redraws graph, usually after data change
1785
+ updateNodesState(): void {
1786
+ const attrs = this.getChartState();
1787
+
1788
+ this.setLayouts({ expandNodesFirst: true });
1789
+
1790
+ // Redraw Graphs
1791
+ const root = attrs.root!;
1792
+ this.update({ x0: root.x0 || 0, y0: root.y0 || 0, width: root.width, height: root.height });
1793
+ }
1794
+
1795
+ setLayouts({ expandNodesFirst = true }: { expandNodesFirst?: boolean }): void {
1796
+ const attrs = this.getChartState();
1797
+ // Store new root by converting flat data to hierarchy
1798
+
1799
+ const stratify = d3
1800
+ .stratify<Datum>()
1801
+ .id((d) => attrs.nodeId(d as any) as string)
1802
+ .parentId((d) => attrs.parentNodeId(d as any) as string);
1803
+
1804
+ attrs.generateRoot = (data: Datum[]) => stratify(data as any) as any as OrgChartNode<Datum>;
1805
+ attrs.root = attrs.generateRoot(attrs.data || []);
1806
+
1807
+ const descendantsBefore = attrs.root.descendants();
1808
+ if (attrs.initialExpandLevel > 1 && descendantsBefore.length > 0) {
1809
+ descendantsBefore.forEach((d) => {
1810
+ if (d.depth <= attrs.initialExpandLevel) {
1811
+ (d.data as any)._expanded = true;
1812
+ }
1813
+ });
1814
+ attrs.initialExpandLevel = 1;
1815
+ }
1816
+
1817
+ const hiddenNodesMap: Record<string, boolean> = {};
1818
+ attrs.root
1819
+ .descendants()
1820
+ .filter((node) => node.children)
1821
+ .filter((node) => !node.data._pagingStep)
1822
+ .forEach((node) => {
1823
+ node.data._pagingStep = attrs.minPagingVisibleNodes(node);
1824
+ });
1825
+
1826
+ attrs.root.eachBefore((node: OrgChartNode, _i: number) => {
1827
+ node.data._directSubordinatesPaging = node.children ? node.children.length : 0;
1828
+ if (node.children) {
1829
+ node.children.forEach((child: OrgChartNode, j: number) => {
1830
+ child.data._pagingButton = false;
1831
+ if (j > node.data._pagingStep!) {
1832
+ hiddenNodesMap[child.id as string] = true;
1833
+ }
1834
+ if (j === node.data._pagingStep && node.children!.length - 1 > node.data._pagingStep!) {
1835
+ child.data._pagingButton = true;
1836
+ }
1837
+ if (child.parent && hiddenNodesMap[child.parent.id as string]) {
1838
+ hiddenNodesMap[child.id as string] = true;
1839
+ }
1840
+ if (child.data._expanded || child.data._centered || child.data._highlighted || child.data._upToTheRootHighlighted) {
1841
+ let localNode: OrgChartNode | null = child;
1842
+ while (localNode && (hiddenNodesMap[localNode.id as string] || localNode.data._pagingButton)) {
1843
+ hiddenNodesMap[localNode.id as string] = false;
1844
+ if (localNode.data._pagingButton) {
1845
+ localNode.data._pagingButton = false;
1846
+ localNode.parent?.children?.forEach((ch: OrgChartNode) => {
1847
+ ch.data._expanded = true;
1848
+ hiddenNodesMap[ch.id as string] = false;
1849
+ });
1850
+ }
1851
+ localNode = localNode.parent;
1852
+ }
1853
+ }
1854
+ });
1855
+ }
1856
+ });
1857
+
1858
+ attrs.root = d3
1859
+ .stratify<Datum>()
1860
+ .id((d) => attrs.nodeId(d as any) as string)
1861
+ .parentId((d) => attrs.parentNodeId(d as any) as string)(attrs.data!.filter((d) => hiddenNodesMap[attrs.nodeId(d as any) as string] !== true) as any) as any as OrgChartNode<Datum>;
1862
+
1863
+ attrs.root.each((node: OrgChartNode, _i: number, _thisNode: OrgChartNode) => {
1864
+ const _hierarchyHeight = (node as any)._hierarchyHeight || node.height;
1865
+ const width = attrs.nodeWidth(node);
1866
+ const height = attrs.nodeHeight(node);
1867
+ Object.assign(node, { width, height, _hierarchyHeight });
1868
+ });
1869
+
1870
+ // Store positions, where children appear during their enter animation
1871
+ attrs.root.x0 = 0;
1872
+ attrs.root.y0 = 0;
1873
+ attrs.allNodes = attrs.root.descendants();
1874
+
1875
+ // Store direct and total descendants count
1876
+ attrs.allNodes.forEach((d) => {
1877
+ Object.assign(d.data, {
1878
+ _directSubordinates: d.children ? d.children.length : 0,
1879
+ _totalSubordinates: d.descendants().length - 1,
1880
+ });
1881
+ });
1882
+
1883
+ if (attrs.root.children) {
1884
+ if (expandNodesFirst) {
1885
+ // Expand all nodes first
1886
+ attrs.root.children.forEach(this.expand);
1887
+ }
1888
+ // Then collapse them all
1889
+ attrs.root.children.forEach((d) => this.collapse(d));
1890
+
1891
+ // Collapse root if level is 0
1892
+ if (attrs.initialExpandLevel == 0) {
1893
+ attrs.root._children = attrs.root.children;
1894
+ attrs.root.children = undefined;
1895
+ }
1896
+
1897
+ // Then only expand nodes, which have expanded property set to true
1898
+ if (attrs.root) {
1899
+ [attrs.root].forEach((ch) => this.expandSomeNodes(ch));
1900
+ }
1901
+ }
1902
+ }
1903
+
1904
+ // Function which collapses passed node and it's descendants
1905
+ collapse(d: OrgChartNode): this {
1906
+ if (d.children) {
1907
+ d._children = d.children;
1908
+ d._children.forEach((ch) => this.collapse(ch));
1909
+ d.children = undefined;
1910
+ }
1911
+ return this;
1912
+ }
1913
+
1914
+ // Function which expands passed node and it's descendants
1915
+ expand(d: OrgChartNode): this {
1916
+ if (d._children) {
1917
+ d.children = d._children;
1918
+ d.children.forEach((ch) => this.expand(ch));
1919
+ d._children = undefined;
1920
+ }
1921
+ return this;
1922
+ }
1923
+
1924
+ // Zoom handler function
1925
+ zoomed(event: D3ZoomEvent<SVGSVGElement, OrgChartNodeData>, _d?: OrgChartNode): void {
1926
+ const attrs = this.getChartState();
1927
+ const chart = attrs.chart!;
1928
+
1929
+ // Get d3 event's transform object
1930
+ const transform = event.transform;
1931
+
1932
+ // Store it
1933
+ attrs.lastTransform = transform;
1934
+
1935
+ // Reposition and rescale chart accordingly
1936
+ chart.attr('transform', transform.toString());
1937
+
1938
+ // Apply new styles to the foreign object element
1939
+ if (this.isEdge()) {
1940
+ this.restyleForeignObjectElements();
1941
+ }
1942
+ }
1943
+
1944
+ zoomTreeBounds({ x0, x1, y0, y1, params = { animate: true, scale: true, onCompleted: () => {} } }: ZoomToBoundsParams): void {
1945
+ const { centerG, svgWidth: w, svgHeight: h, svg, zoomBehavior, duration, lastTransform } = this.getChartState();
1946
+ const scaleVal = Math.min(8, 0.9 / Math.max((x1 - x0) / w, (y1 - y0) / h));
1947
+ let identity = d3.zoomIdentity.translate(w / 2, h / 2);
1948
+ identity = identity.scale(params?.scale ? scaleVal : lastTransform.k);
1949
+
1950
+ identity = identity.translate(-(x0 + x1) / 2, -(y0 + y1) / 2);
1951
+ // Transition zoom wrapper component into specified bounds
1952
+ (svg!.transition().duration(params?.animate ? duration : 0) as any).call(zoomBehavior!.transform, identity);
1953
+ centerG!
1954
+ .transition()
1955
+ .duration(params?.animate ? duration : 0)
1956
+ .attr('transform', 'translate(0,0)')
1957
+ .on('end', function () {
1958
+ if (params?.onCompleted) {
1959
+ params.onCompleted();
1960
+ }
1961
+ });
1962
+ }
1963
+
1964
+ fit({ animate = true, nodes, scale = true, onCompleted = () => {} }: FitParams = {}): this {
1965
+ const attrs = this.getChartState();
1966
+ const { root } = attrs;
1967
+ const descendants = nodes ?? root!.descendants();
1968
+ const minX = d3.min(descendants, (d) => d.x + attrs.layoutBindings[attrs.layout].nodeLeftX(d)) || 0;
1969
+ const maxX = d3.max(descendants, (d) => d.x + attrs.layoutBindings[attrs.layout].nodeRightX(d)) || 0;
1970
+ const minY = d3.min(descendants, (d) => d.y + attrs.layoutBindings[attrs.layout].nodeTopY(d)) || 0;
1971
+ const maxY = d3.max(descendants, (d) => d.y + attrs.layoutBindings[attrs.layout].nodeBottomY(d)) || 0;
1972
+
1973
+ this.zoomTreeBounds({
1974
+ params: { animate: animate, scale, onCompleted },
1975
+ x0: minX - 50,
1976
+ x1: maxX + 50,
1977
+ y0: minY - 50,
1978
+ y1: maxY + 50,
1979
+ });
1980
+ return this;
1981
+ }
1982
+
1983
+ // Load Paging Nodes
1984
+ loadPagingNodes(node: OrgChartNode): void {
1985
+ const attrs = this.getChartState();
1986
+ node.data._pagingButton = false;
1987
+ const current = node.parent!.data._pagingStep!;
1988
+ const step = attrs.pagingStep(node.parent!);
1989
+ const newPagingIndex = current + step;
1990
+ node.parent!.data._pagingStep = newPagingIndex;
1991
+ this.updateNodesState();
1992
+ }
1993
+
1994
+ // This function can be invoked via chart.setExpanded API, it expands or collapses particular node
1995
+ setExpanded(id: string | number, expandedFlag: boolean = true): this {
1996
+ const attrs = this.getChartState();
1997
+ // Retrieve node by node Id
1998
+ const node = attrs.allNodes!.find(({ data }) => attrs.nodeId(data) == id);
1999
+
2000
+ if (!node) {
2001
+ console.log(`ORG CHART - ${expandedFlag ? 'EXPAND' : 'COLLAPSE'} - Node with id (${id}) not found in the tree`);
2002
+ return this;
2003
+ }
2004
+ node.data._expanded = expandedFlag;
2005
+ if (!expandedFlag) {
2006
+ const parent = node.parent || { descendants: () => [] };
2007
+ const descendants = parent.descendants().filter((d) => d != parent);
2008
+ descendants.forEach((d) => (d.data._expanded = false));
2009
+ }
2010
+
2011
+ return this;
2012
+ }
2013
+
2014
+ setCentered(nodeId: string | number): this {
2015
+ const attrs = this.getChartState();
2016
+ // this.setExpanded(nodeId)
2017
+ const root = attrs.generateRoot!(attrs.data || []);
2018
+ const descendants = root.descendants();
2019
+ const node = descendants.find(({ data }) => attrs.nodeId(data).toString() == nodeId.toString());
2020
+ if (!node) {
2021
+ console.log(`ORG CHART - CENTER - Node with id (${nodeId}) not found in the tree`);
2022
+ return this;
2023
+ }
2024
+ const ancestors = node.ancestors();
2025
+ ancestors.forEach((d) => (d.data._expanded = true));
2026
+ node.data._centered = true;
2027
+ node.data._expanded = true;
2028
+ return this;
2029
+ }
2030
+
2031
+ setHighlighted(nodeId: string | number | null): this {
2032
+ const attrs = this.getChartState();
2033
+ const root = attrs.generateRoot!(attrs.data || []);
2034
+ const descendants = root.descendants();
2035
+ const node = nodeId ? descendants.find((d) => attrs.nodeId(d.data).toString() === nodeId.toString()) : null;
2036
+ if (!node) {
2037
+ console.log(`ORG CHART - HIGHLIGHT - Node with id (${nodeId}) not found in the tree`);
2038
+ return this;
2039
+ }
2040
+ const ancestors = node.ancestors();
2041
+ ancestors.forEach((d) => (d.data._expanded = true));
2042
+ node.data._highlighted = true;
2043
+ node.data._expanded = true;
2044
+ node.data._centered = true;
2045
+ return this;
2046
+ }
2047
+
2048
+ setUpToTheRootHighlighted(nodeId: string | number | null): this {
2049
+ const attrs = this.getChartState();
2050
+ const root = attrs.generateRoot!(attrs.data || []);
2051
+ const descendants = root.descendants();
2052
+ const node = nodeId ? descendants.find((d) => attrs.nodeId(d.data).toString() === nodeId.toString()) : null;
2053
+ if (!node) {
2054
+ console.log(`ORG CHART - HIGHLIGHTROOT - Node with id (${nodeId}) not found in the tree`);
2055
+ return this;
2056
+ }
2057
+ const ancestors = node.ancestors();
2058
+ ancestors.forEach((d) => (d.data._expanded = true));
2059
+ node.data._upToTheRootHighlighted = true;
2060
+ node.data._expanded = true;
2061
+ node.ancestors().forEach((d) => (d.data._upToTheRootHighlighted = true));
2062
+ return this;
2063
+ }
2064
+
2065
+ clearHighlighting(): this {
2066
+ const attrs = this.getChartState();
2067
+ attrs.allNodes!.forEach((d) => {
2068
+ d.data._highlighted = false;
2069
+ d.data._upToTheRootHighlighted = false;
2070
+ });
2071
+ const root = attrs.root!;
2072
+ this.update({ x0: root.x0 || 0, y0: root.y0 || 0, width: root.width, height: root.height });
2073
+ return this;
2074
+ }
2075
+
2076
+ // It can take selector which would go fullscreen
2077
+ fullscreen(elem?: HTMLElement): void {
2078
+ const attrs = this.getChartState();
2079
+ const el = (elem ? d3.select(elem as any) : d3.select(attrs.container as any)).node() as any;
2080
+
2081
+ d3.select(document).on('fullscreenchange.' + attrs.id, function (_d: any) {
2082
+ const fsElement = (document as any).fullscreenElement || (document as any).mozFullscreenElement || (document as any).webkitFullscreenElement;
2083
+ if (fsElement == el) {
2084
+ setTimeout((_d: any) => {
2085
+ attrs.svg!.attr('height', window.innerHeight - 40);
2086
+ }, 500);
2087
+ } else {
2088
+ attrs.svg!.attr('height', attrs.svgHeight);
2089
+ }
2090
+ });
2091
+
2092
+ if (el.requestFullscreen) {
2093
+ el.requestFullscreen();
2094
+ } else if (el.mozRequestFullScreen) {
2095
+ el.mozRequestFullScreen();
2096
+ } else if (el.webkitRequestFullscreen) {
2097
+ el.webkitRequestFullscreen();
2098
+ } else if (el.msRequestFullscreen) {
2099
+ el.msRequestFullscreen();
2100
+ }
2101
+ }
2102
+
2103
+ // Zoom in exposed method
2104
+ zoomIn(): this {
2105
+ const { svg, zoomBehavior } = this.getChartState();
2106
+ (svg as any).transition().call(zoomBehavior!.scaleBy, 1.3);
2107
+ return this;
2108
+ }
2109
+
2110
+ // Zoom out exposed method
2111
+ zoomOut(): this {
2112
+ const { svg, zoomBehavior } = this.getChartState();
2113
+ (svg as any).transition().call(zoomBehavior!.scaleBy, 0.78);
2114
+ return this;
2115
+ }
2116
+
2117
+ toDataURL(url: string, callback: (result: string | ArrayBuffer | null) => void): void {
2118
+ const xhr = new XMLHttpRequest();
2119
+ xhr.onload = function () {
2120
+ if (xhr.status >= 200 && xhr.status < 300) {
2121
+ const reader = new FileReader();
2122
+ reader.onloadend = function () {
2123
+ callback(reader.result);
2124
+ };
2125
+ reader.readAsDataURL(xhr.response);
2126
+ } else {
2127
+ callback(null);
2128
+ }
2129
+ };
2130
+ xhr.onerror = function () {
2131
+ callback(null);
2132
+ };
2133
+ xhr.open('GET', url);
2134
+ xhr.responseType = 'blob';
2135
+ xhr.send();
2136
+ }
2137
+
2138
+ exportImg({ full = false, scale = 3, onLoad = (_d: any) => _d, save = true, backgroundColor = '#FAFAFA' }: ExportImageParams = {}): void {
2139
+ const attrs = this.getChartState();
2140
+ const { svg: svgImg } = attrs;
2141
+ let count = 0;
2142
+ const selection = svgImg!.selectAll('img');
2143
+ const total = selection.size();
2144
+
2145
+ const exportImage = () => {
2146
+ const duration = this.duration();
2147
+ if (full) {
2148
+ this.fit();
2149
+ }
2150
+ const { svg } = this.getChartState();
2151
+
2152
+ setTimeout(
2153
+ (_d: any) => {
2154
+ this.downloadImage({
2155
+ node: svg!.node()!,
2156
+ scale,
2157
+ isSvg: false,
2158
+ backgroundColor,
2159
+ onAlreadySerialized: (_d: any) => {
2160
+ const root = this.getChartState().root!;
2161
+ this.update({ x0: root.x0 || 0, y0: root.y0 || 0, width: root.width, height: root.height });
2162
+ },
2163
+ imageName: attrs.imageName,
2164
+ onLoad: onLoad,
2165
+ save,
2166
+ });
2167
+ },
2168
+ full ? duration + 10 : 0
2169
+ );
2170
+ };
2171
+
2172
+ if (total > 0) {
2173
+ const imgNodes = selection.nodes() as HTMLImageElement[];
2174
+ imgNodes.forEach((imgElement) => {
2175
+ this.toDataURL(imgElement.src, (dataUrl) => {
2176
+ if (dataUrl) imgElement.src = dataUrl as string;
2177
+ if (++count === total) {
2178
+ exportImage();
2179
+ }
2180
+ });
2181
+ });
2182
+ } else {
2183
+ exportImage();
2184
+ }
2185
+ }
2186
+
2187
+ exportSvg(): this {
2188
+ const { svg, imageName } = this.getChartState();
2189
+ this.downloadImage({ imageName: imageName, node: svg!.node()!, scale: 3, isSvg: true });
2190
+ return this;
2191
+ }
2192
+
2193
+ expandAll(): this {
2194
+ const { data } = this.getChartState();
2195
+ data!.forEach((d) => ((d as any)._expanded = true));
2196
+ this.render();
2197
+ return this;
2198
+ }
2199
+
2200
+ collapseAll(): this {
2201
+ const { allNodes } = this.getChartState();
2202
+ allNodes!.forEach((d) => (d.data._expanded = false));
2203
+ this.initialExpandLevel(0);
2204
+ this.render();
2205
+ return this;
2206
+ }
2207
+
2208
+ downloadImage({ node, scale = 2, imageName = 'graph', isSvg = false, save = true, backgroundColor = '#FAFAFA', onAlreadySerialized = (_d: any) => {}, onLoad = (_d: any) => {} }: DownloadImageParams): void {
2209
+ // Retrieve svg node
2210
+ const svgNode = node as SVGSVGElement;
2211
+
2212
+ function saveAs(uri: string, filename: string): void {
2213
+ // create link
2214
+ const link = document.createElement('a');
2215
+ if (typeof link.download === 'string') {
2216
+ document.body.appendChild(link); // Firefox requires the link to be in the body
2217
+ link.download = filename;
2218
+ link.href = uri;
2219
+ link.click();
2220
+ link.remove(); // remove the link when done
2221
+ } else {
2222
+ location.replace(uri);
2223
+ }
2224
+ }
2225
+ // This function serializes SVG and sets all necessary attributes
2226
+ function serializeString(svg: any) {
2227
+ const xmlns = 'http://www.w3.org/2000/xmlns/';
2228
+ const xlinkns = 'http://www.w3.org/1999/xlink';
2229
+ const svgns = 'http://www.w3.org/2000/svg';
2230
+
2231
+ // Clone the SVG
2232
+ const clonedSvg = svg.cloneNode(true);
2233
+
2234
+ // Copy computed styles from original to cloned elements
2235
+ const originalWalker = document.createTreeWalker(svg, NodeFilter.SHOW_ELEMENT);
2236
+ const clonedWalker = document.createTreeWalker(clonedSvg, NodeFilter.SHOW_ELEMENT);
2237
+
2238
+ // Process root SVG element
2239
+ copyComputedStyle(svg, clonedSvg);
2240
+
2241
+ // Process all child elements
2242
+ while (originalWalker.nextNode() && clonedWalker.nextNode()) {
2243
+ const originalNode = originalWalker.currentNode as Element;
2244
+ const clonedNode = clonedWalker.currentNode as Element;
2245
+
2246
+ // Copy computed styles
2247
+ copyComputedStyle(originalNode, clonedNode);
2248
+
2249
+ // Fix fragment references
2250
+ for (const attr of Array.from(clonedNode.attributes)) {
2251
+ if (attr.value.includes(globalThis.location.href + '#')) {
2252
+ attr.value = attr.value.replace(globalThis.location.href + '#', '#');
2253
+ }
2254
+ }
2255
+ }
2256
+
2257
+ clonedSvg.setAttributeNS(xmlns, 'xmlns', svgns);
2258
+ clonedSvg.setAttributeNS(xmlns, 'xmlns:xlink', xlinkns);
2259
+ const serializer = new XMLSerializer();
2260
+ const string = serializer.serializeToString(clonedSvg);
2261
+ return string;
2262
+ }
2263
+
2264
+ // Helper function to copy computed styles
2265
+ function copyComputedStyle(source: Element, target: Element) {
2266
+ const computedStyle = globalThis.getComputedStyle(source);
2267
+
2268
+ // List of CSS properties to copy
2269
+ const propertiesToCopy = [
2270
+ 'font-family',
2271
+ 'font-size',
2272
+ 'font-weight',
2273
+ 'font-style',
2274
+ 'fill',
2275
+ 'stroke',
2276
+ 'stroke-width',
2277
+ 'stroke-dasharray',
2278
+ 'stroke-linecap',
2279
+ 'stroke-linejoin',
2280
+ 'opacity',
2281
+ 'color',
2282
+ 'text-anchor',
2283
+ 'dominant-baseline',
2284
+ 'alignment-baseline',
2285
+ 'display',
2286
+ 'visibility',
2287
+ 'transform',
2288
+ 'transform-origin',
2289
+ 'background',
2290
+ 'background-color',
2291
+ 'border',
2292
+ 'border-width',
2293
+ 'border-color',
2294
+ 'border-style',
2295
+ 'border-radius',
2296
+ 'padding',
2297
+ 'margin',
2298
+ 'width',
2299
+ 'height',
2300
+ 'overflow',
2301
+ ];
2302
+
2303
+ // Apply computed styles as inline styles
2304
+ propertiesToCopy.forEach((property) => {
2305
+ const value = computedStyle.getPropertyValue(property);
2306
+ if (value && value !== '' && value !== 'none') {
2307
+ (target as HTMLElement).style.setProperty(property, value);
2308
+ }
2309
+ });
2310
+ }
2311
+
2312
+ if (isSvg) {
2313
+ let source = serializeString(svgNode);
2314
+ //add xml declaration
2315
+ source = '<?xml version="1.0" standalone="no"?>\r\n' + source;
2316
+ //convert svg source to URI data scheme.
2317
+ const url = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(source);
2318
+ saveAs(url, imageName + '.svg');
2319
+ onAlreadySerialized?.(source);
2320
+ return;
2321
+ }
2322
+ // Get image quality index (basically, index you can zoom in)
2323
+ const quality = scale;
2324
+ // Create image
2325
+ const image = document.createElement('img');
2326
+ image.onload = function () {
2327
+ // Create image canvas
2328
+ const canvas = document.createElement('canvas');
2329
+ // Set width and height based on SVG node
2330
+ const rect = svgNode.getBoundingClientRect();
2331
+ canvas.width = rect.width * quality;
2332
+ canvas.height = rect.height * quality;
2333
+ // Draw background
2334
+ const context = canvas.getContext('2d');
2335
+ context!.fillStyle = backgroundColor;
2336
+ context!.fillRect(0, 0, rect.width * quality, rect.height * quality);
2337
+ context!.drawImage(image, 0, 0, rect.width * quality, rect.height * quality);
2338
+ // Set some image metadata
2339
+ const dt = canvas.toDataURL('image/png');
2340
+ if (onLoad) {
2341
+ const img = new Image();
2342
+ img.src = dt;
2343
+ onLoad(img);
2344
+ }
2345
+ if (save) {
2346
+ // Invoke saving function
2347
+ saveAs(dt, imageName + '.png');
2348
+ }
2349
+ };
2350
+
2351
+ const url = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(serializeString(svgNode));
2352
+
2353
+ onAlreadySerialized?.(serializeString(svgNode));
2354
+
2355
+ image.src = url; // URL.createObjectURL(blob);
2356
+ // This function invokes save window
2357
+ }
2358
+
2359
+ // Calculate what size text will take
2360
+ getTextWidth(text: string, { fontSize = 14, fontWeight = '400', defaultFont = 'Helvetice', ctx }: Partial<TextMeasurementParams>): number {
2361
+ ctx!.font = `${fontWeight || ''} ${fontSize}px ${defaultFont} `;
2362
+ const measurement = ctx!.measureText(text);
2363
+ return measurement.width;
2364
+ }
2365
+
2366
+ // Clear after moving off from the page
2367
+ clear(): void {
2368
+ const attrs = this.getChartState();
2369
+ d3.select(window).on(`resize.${attrs.id}`, null);
2370
+ attrs.svg?.selectAll('*').remove();
2371
+ }
2372
+ }