@datarecce/ui 0.1.41 → 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 (728) hide show
  1. package/README.md +28 -133
  2. package/dist/AuthModal-C8LetZNB.js +23 -0
  3. package/dist/AuthModal-C8LetZNB.js.map +1 -0
  4. package/dist/LineageCanvas-CR38SDYr.d.ts +41 -0
  5. package/dist/LineageCanvas-CR38SDYr.d.ts.map +1 -0
  6. package/dist/ResultErrorFallback-C7c-TN1p.js +3 -0
  7. package/dist/ResultErrorFallback-C7c-TN1p.js.map +1 -0
  8. package/dist/RouteConfigContext-z8YNimdP.d.ts +172 -0
  9. package/dist/RouteConfigContext-z8YNimdP.d.ts.map +1 -0
  10. package/dist/RunProgress-DyFIALbI.d.ts +429 -0
  11. package/dist/RunProgress-DyFIALbI.d.ts.map +1 -0
  12. package/dist/ScreenshotDataGrid-BfxYUThx.d.ts +64 -0
  13. package/dist/ScreenshotDataGrid-BfxYUThx.d.ts.map +1 -0
  14. package/dist/SplitPane-B-BLxZaQ.d.ts +1427 -0
  15. package/dist/SplitPane-B-BLxZaQ.d.ts.map +1 -0
  16. package/dist/advanced.d.ts +18 -0
  17. package/dist/advanced.d.ts.map +1 -0
  18. package/dist/advanced.js +3 -0
  19. package/dist/advanced.js.map +1 -0
  20. package/dist/api-ZZ4cc9b9.d.ts +255 -0
  21. package/dist/api-ZZ4cc9b9.d.ts.map +1 -0
  22. package/dist/api-_i6BZPkM.js +3 -0
  23. package/dist/api-_i6BZPkM.js.map +1 -0
  24. package/dist/api.d.ts +3 -2
  25. package/dist/api.js +2 -100
  26. package/dist/colors--47Kkns4.js +3 -0
  27. package/dist/colors--47Kkns4.js.map +1 -0
  28. package/dist/colors-vY9Yzui0.d.ts +255 -0
  29. package/dist/colors-vY9Yzui0.d.ts.map +1 -0
  30. package/dist/components-run.d.ts +8 -0
  31. package/dist/components-run.js +2 -0
  32. package/dist/components.d.ts +22 -2
  33. package/dist/components.js +2 -86
  34. package/dist/const-DbXBkrxT.js +3 -0
  35. package/dist/const-DbXBkrxT.js.map +1 -0
  36. package/dist/constants-DD5vJv2q.js +3 -0
  37. package/dist/constants-DD5vJv2q.js.map +1 -0
  38. package/dist/constants.d.ts +3 -0
  39. package/dist/constants.js +2 -0
  40. package/dist/contexts.d.ts +7 -0
  41. package/dist/contexts.js +2 -0
  42. package/dist/flag-CiR2E5oz.d.ts +898 -0
  43. package/dist/flag-CiR2E5oz.d.ts.map +1 -0
  44. package/dist/flag-koeDAqr3.js +3 -0
  45. package/dist/flag-koeDAqr3.js.map +1 -0
  46. package/dist/hooks.d.ts +15 -2
  47. package/dist/hooks.js +2 -43
  48. package/dist/index-BFkbe0aF.d.ts +698 -0
  49. package/dist/index-BFkbe0aF.d.ts.map +1 -0
  50. package/dist/index-Ba3hp2Ng.d.ts +471 -0
  51. package/dist/index-Ba3hp2Ng.d.ts.map +1 -0
  52. package/dist/index-C_kD4ZQ3.d.ts +1079 -0
  53. package/dist/index-C_kD4ZQ3.d.ts.map +1 -0
  54. package/dist/index-CiPcALu4.d.ts +146 -0
  55. package/dist/index-CiPcALu4.d.ts.map +1 -0
  56. package/dist/index-CkXLPYZY.d.ts +13 -0
  57. package/dist/index-CkXLPYZY.d.ts.map +1 -0
  58. package/dist/index-DTCpHvX_.d.ts +211 -0
  59. package/dist/index-DTCpHvX_.d.ts.map +1 -0
  60. package/dist/index-DVoQsx5c.d.ts +349 -0
  61. package/dist/index-DVoQsx5c.d.ts.map +1 -0
  62. package/dist/index-DmwYRgDR.d.ts +192 -0
  63. package/dist/index-DmwYRgDR.d.ts.map +1 -0
  64. package/dist/index-N8N7XmRj.d.ts +130 -0
  65. package/dist/index-N8N7XmRj.d.ts.map +1 -0
  66. package/dist/index-h_fw6R9U.d.ts +1501 -0
  67. package/dist/index-h_fw6R9U.d.ts.map +1 -0
  68. package/dist/index-o48TPoFN.d.ts +734 -0
  69. package/dist/index-o48TPoFN.d.ts.map +1 -0
  70. package/dist/index.d.ts +24 -2
  71. package/dist/index.js +2 -198
  72. package/dist/keepAlive-CEzyrDfg.js +3 -0
  73. package/dist/keepAlive-CEzyrDfg.js.map +1 -0
  74. package/dist/lib/api/axiosClient.d.ts +8 -0
  75. package/dist/lib/api/axiosClient.d.ts.map +1 -0
  76. package/dist/lib/api/axiosClient.js +3 -0
  77. package/dist/lib/api/axiosClient.js.map +1 -0
  78. package/dist/lib/api/track.d.ts +137 -0
  79. package/dist/lib/api/track.d.ts.map +1 -0
  80. package/dist/lib/api/track.js +2 -0
  81. package/dist/lib/api/user.d.ts +16 -0
  82. package/dist/lib/api/user.d.ts.map +1 -0
  83. package/dist/lib/api/user.js +2 -0
  84. package/dist/lib/const.d.ts +8 -0
  85. package/dist/lib/const.d.ts.map +1 -0
  86. package/dist/lib/const.js +2 -0
  87. package/dist/lib/result/ResultErrorFallback.d.ts +8 -0
  88. package/dist/lib/result/ResultErrorFallback.d.ts.map +1 -0
  89. package/dist/lib/result/ResultErrorFallback.js +2 -0
  90. package/dist/primitives-CgGUvwHB.d.ts +914 -0
  91. package/dist/primitives-CgGUvwHB.d.ts.map +1 -0
  92. package/dist/primitives.d.ts +12 -0
  93. package/dist/primitives.js +2 -0
  94. package/dist/result.d.ts +4 -0
  95. package/dist/result.js +2 -0
  96. package/dist/src-BgHSbbHk.js +67 -0
  97. package/dist/src-BgHSbbHk.js.map +1 -0
  98. package/dist/styles.css +478 -4
  99. package/dist/theme-CeWzymUn.js +64 -0
  100. package/dist/theme-CeWzymUn.js.map +1 -0
  101. package/dist/theme.d.ts +3 -2
  102. package/dist/theme.js +2 -9
  103. package/dist/track-9ZQpBlUK.js +3 -0
  104. package/dist/track-9ZQpBlUK.js.map +1 -0
  105. package/dist/types-CFbNxrx2.d.ts +171 -0
  106. package/dist/types-CFbNxrx2.d.ts.map +1 -0
  107. package/dist/types-CZre3j02.d.ts +231 -0
  108. package/dist/types-CZre3j02.d.ts.map +1 -0
  109. package/dist/types.d.ts +14 -2
  110. package/dist/types.js +3 -9
  111. package/dist/types.js.map +1 -0
  112. package/dist/useRecceServerFlag-Bg5R67J4.js +3 -0
  113. package/dist/useRecceServerFlag-Bg5R67J4.js.map +1 -0
  114. package/dist/useThemeColors--prVbMmM.js +3 -0
  115. package/dist/useThemeColors--prVbMmM.js.map +1 -0
  116. package/dist/useThemeColors-DHEroo8f.d.ts +104 -0
  117. package/dist/useThemeColors-DHEroo8f.d.ts.map +1 -0
  118. package/dist/user-DMT7E0fc.js +3 -0
  119. package/dist/user-DMT7E0fc.js.map +1 -0
  120. package/dist/utils-CW2skXm_.js +3 -0
  121. package/dist/utils-CW2skXm_.js.map +1 -0
  122. package/dist/utils-CXWhfyxC.js +5 -0
  123. package/dist/utils-CXWhfyxC.js.map +1 -0
  124. package/dist/utils.d.ts +7 -0
  125. package/dist/utils.js +2 -0
  126. package/package.json +115 -107
  127. package/LICENSE +0 -201
  128. package/dist/RecceCheckContext-BJprb2xR.js +0 -7968
  129. package/dist/RecceCheckContext-BJprb2xR.js.map +0 -1
  130. package/dist/RecceCheckContext-DPnWB_aU.css +0 -215
  131. package/dist/RecceCheckContext-DPnWB_aU.css.map +0 -1
  132. package/dist/RecceCheckContext-DbZ7BdRy.mjs +0 -7426
  133. package/dist/RecceCheckContext-DbZ7BdRy.mjs.map +0 -1
  134. package/dist/RecceCheckContext-DyxOeUsX.css +0 -215
  135. package/dist/RecceCheckContext-DyxOeUsX.css.map +0 -1
  136. package/dist/api.d.mts +0 -3
  137. package/dist/api.js.map +0 -1
  138. package/dist/api.mjs +0 -46
  139. package/dist/api.mjs.map +0 -1
  140. package/dist/components-BeAjVBV3.css +0 -70
  141. package/dist/components-BeAjVBV3.css.map +0 -1
  142. package/dist/components-DfXnN1Hx.js +0 -14689
  143. package/dist/components-DfXnN1Hx.js.map +0 -1
  144. package/dist/components-iUxcqtUB.css +0 -70
  145. package/dist/components-iUxcqtUB.css.map +0 -1
  146. package/dist/components-jh6r4tQn.mjs +0 -12348
  147. package/dist/components-jh6r4tQn.mjs.map +0 -1
  148. package/dist/components.d.mts +0 -3
  149. package/dist/components.mjs +0 -9
  150. package/dist/const-CaIm1Z8g.mjs +0 -12
  151. package/dist/const-CaIm1Z8g.mjs.map +0 -1
  152. package/dist/const-CvdZO0FN.js +0 -24
  153. package/dist/const-CvdZO0FN.js.map +0 -1
  154. package/dist/hooks-cQsBXBd1.js +0 -40
  155. package/dist/hooks-cQsBXBd1.js.map +0 -1
  156. package/dist/hooks-eaHm_yEp.mjs +0 -33
  157. package/dist/hooks-eaHm_yEp.mjs.map +0 -1
  158. package/dist/hooks.d.mts +0 -3
  159. package/dist/hooks.mjs +0 -8
  160. package/dist/html2canvas-pro.esm-CsuSOHXp.js +0 -7250
  161. package/dist/html2canvas-pro.esm-CsuSOHXp.js.map +0 -1
  162. package/dist/html2canvas-pro.esm-E7kpobrC.mjs +0 -7249
  163. package/dist/html2canvas-pro.esm-E7kpobrC.mjs.map +0 -1
  164. package/dist/index-B5bpmv0i.d.mts +0 -2172
  165. package/dist/index-B5bpmv0i.d.mts.map +0 -1
  166. package/dist/index-B9lSPJTi.d.ts +0 -2170
  167. package/dist/index-B9lSPJTi.d.ts.map +0 -1
  168. package/dist/index.d.mts +0 -3
  169. package/dist/index.js.map +0 -1
  170. package/dist/index.mjs +0 -20
  171. package/dist/index.mjs.map +0 -1
  172. package/dist/mui-theme-CUhybmBq.mjs +0 -696
  173. package/dist/mui-theme-CUhybmBq.mjs.map +0 -1
  174. package/dist/mui-theme-iBHkjXJq.js +0 -732
  175. package/dist/mui-theme-iBHkjXJq.js.map +0 -1
  176. package/dist/state-CTITyT0R.js +0 -795
  177. package/dist/state-CTITyT0R.js.map +0 -1
  178. package/dist/state-Sc2b4jri.mjs +0 -382
  179. package/dist/state-Sc2b4jri.mjs.map +0 -1
  180. package/dist/theme.d.mts +0 -3
  181. package/dist/theme.mjs +0 -4
  182. package/dist/tooltipMessage-BC5W7H3X.js +0 -13
  183. package/dist/tooltipMessage-BC5W7H3X.js.map +0 -1
  184. package/dist/tooltipMessage-B_xMIKWL.mjs +0 -7
  185. package/dist/tooltipMessage-B_xMIKWL.mjs.map +0 -1
  186. package/dist/types.d.mts +0 -3
  187. package/dist/types.mjs +0 -6
  188. package/dist/urls-BQW5wjg-.js +0 -13
  189. package/dist/urls-BQW5wjg-.js.map +0 -1
  190. package/dist/urls-DT7FVEcS.mjs +0 -7
  191. package/dist/urls-DT7FVEcS.mjs.map +0 -1
  192. package/dist/version-B9s8yne-.js +0 -300
  193. package/dist/version-B9s8yne-.js.map +0 -1
  194. package/dist/version-DP1kU_7v.mjs +0 -162
  195. package/dist/version-DP1kU_7v.mjs.map +0 -1
  196. package/recce-source/.editorconfig +0 -26
  197. package/recce-source/.flake8 +0 -37
  198. package/recce-source/.github/ISSUE_TEMPLATE/bug_report.yml +0 -67
  199. package/recce-source/.github/ISSUE_TEMPLATE/custom.md +0 -10
  200. package/recce-source/.github/ISSUE_TEMPLATE/feature_request.yml +0 -42
  201. package/recce-source/.github/PULL_REQUEST_TEMPLATE.md +0 -21
  202. package/recce-source/.github/copilot-instructions.md +0 -331
  203. package/recce-source/.github/instructions/backend-instructions.md +0 -541
  204. package/recce-source/.github/instructions/frontend-instructions.md +0 -317
  205. package/recce-source/.github/workflows/build-statics.yaml +0 -72
  206. package/recce-source/.github/workflows/bump.yaml +0 -48
  207. package/recce-source/.github/workflows/integration-tests-cloud.yaml +0 -92
  208. package/recce-source/.github/workflows/integration-tests-sqlmesh.yaml +0 -33
  209. package/recce-source/.github/workflows/integration-tests.yaml +0 -52
  210. package/recce-source/.github/workflows/nightly.yaml +0 -246
  211. package/recce-source/.github/workflows/release.yaml +0 -196
  212. package/recce-source/.github/workflows/tests-js.yaml +0 -58
  213. package/recce-source/.github/workflows/tests-python.yaml +0 -128
  214. package/recce-source/.pre-commit-config.yaml +0 -26
  215. package/recce-source/CLAUDE.md +0 -483
  216. package/recce-source/CODE_OF_CONDUCT.md +0 -128
  217. package/recce-source/CONTRIBUTING.md +0 -107
  218. package/recce-source/LICENSE +0 -201
  219. package/recce-source/Makefile +0 -126
  220. package/recce-source/README.md +0 -182
  221. package/recce-source/RECCE_CLOUD.md +0 -81
  222. package/recce-source/SECURITY.md +0 -25
  223. package/recce-source/docs/PACKAGING.md +0 -340
  224. package/recce-source/docs/README.md +0 -1
  225. package/recce-source/docs/plans/2024-12-31-csv-download-design.md +0 -121
  226. package/recce-source/docs/plans/2024-12-31-csv-download-implementation.md +0 -930
  227. package/recce-source/integration_tests/dbt/dbt_project.yml +0 -26
  228. package/recce-source/integration_tests/dbt/models/customers.sql +0 -69
  229. package/recce-source/integration_tests/dbt/models/docs.md +0 -14
  230. package/recce-source/integration_tests/dbt/models/orders.sql +0 -56
  231. package/recce-source/integration_tests/dbt/models/schema.yml +0 -82
  232. package/recce-source/integration_tests/dbt/models/staging/schema.yml +0 -31
  233. package/recce-source/integration_tests/dbt/models/staging/stg_customers.sql +0 -22
  234. package/recce-source/integration_tests/dbt/models/staging/stg_orders.sql +0 -23
  235. package/recce-source/integration_tests/dbt/models/staging/stg_payments.sql +0 -25
  236. package/recce-source/integration_tests/dbt/packages.yml +0 -7
  237. package/recce-source/integration_tests/dbt/profiles.yml +0 -8
  238. package/recce-source/integration_tests/dbt/seeds/raw_customers.csv +0 -101
  239. package/recce-source/integration_tests/dbt/seeds/raw_orders.csv +0 -100
  240. package/recce-source/integration_tests/dbt/seeds/raw_payments.csv +0 -114
  241. package/recce-source/integration_tests/dbt/seeds/raw_statuses.csv +0 -5
  242. package/recce-source/integration_tests/dbt/smoke_test.sh +0 -72
  243. package/recce-source/integration_tests/dbt/smoke_test_cloud.sh +0 -71
  244. package/recce-source/integration_tests/sqlmesh/__init__.py +0 -0
  245. package/recce-source/integration_tests/sqlmesh/audits/assert_item_price_above_zero.sql +0 -9
  246. package/recce-source/integration_tests/sqlmesh/audits/items.sql +0 -7
  247. package/recce-source/integration_tests/sqlmesh/audits/order_items.sql +0 -7
  248. package/recce-source/integration_tests/sqlmesh/config.py +0 -171
  249. package/recce-source/integration_tests/sqlmesh/helper.py +0 -20
  250. package/recce-source/integration_tests/sqlmesh/hooks/__init__.py +0 -0
  251. package/recce-source/integration_tests/sqlmesh/macros/__init__.py +0 -0
  252. package/recce-source/integration_tests/sqlmesh/macros/macros.py +0 -8
  253. package/recce-source/integration_tests/sqlmesh/macros/macros.sql +0 -8
  254. package/recce-source/integration_tests/sqlmesh/macros/utils.py +0 -11
  255. package/recce-source/integration_tests/sqlmesh/metrics/metrics.sql +0 -25
  256. package/recce-source/integration_tests/sqlmesh/models/customer_revenue_by_day.sql +0 -41
  257. package/recce-source/integration_tests/sqlmesh/models/customer_revenue_lifetime.sql +0 -60
  258. package/recce-source/integration_tests/sqlmesh/models/customers.sql +0 -32
  259. package/recce-source/integration_tests/sqlmesh/models/items.py +0 -95
  260. package/recce-source/integration_tests/sqlmesh/models/marketing.sql +0 -15
  261. package/recce-source/integration_tests/sqlmesh/models/order_items.py +0 -95
  262. package/recce-source/integration_tests/sqlmesh/models/orders.py +0 -70
  263. package/recce-source/integration_tests/sqlmesh/models/raw_marketing.py +0 -62
  264. package/recce-source/integration_tests/sqlmesh/models/top_waiters.sql +0 -23
  265. package/recce-source/integration_tests/sqlmesh/models/waiter_as_customer_by_day.sql +0 -29
  266. package/recce-source/integration_tests/sqlmesh/models/waiter_names.sql +0 -10
  267. package/recce-source/integration_tests/sqlmesh/models/waiter_revenue_by_day.sql +0 -29
  268. package/recce-source/integration_tests/sqlmesh/models/waiters.py +0 -62
  269. package/recce-source/integration_tests/sqlmesh/prep_env.sh +0 -16
  270. package/recce-source/integration_tests/sqlmesh/schema.yaml +0 -5
  271. package/recce-source/integration_tests/sqlmesh/seeds/waiter_names.csv +0 -11
  272. package/recce-source/integration_tests/sqlmesh/test_server.sh +0 -29
  273. package/recce-source/integration_tests/sqlmesh/tests/test_customer_revenue_by_day.yaml +0 -63
  274. package/recce-source/integration_tests/sqlmesh/tests/test_order_items.yaml +0 -72
  275. package/recce-source/js/.editorconfig +0 -27
  276. package/recce-source/js/.env.development +0 -5
  277. package/recce-source/js/.husky/pre-commit +0 -29
  278. package/recce-source/js/.nvmrc +0 -1
  279. package/recce-source/js/README.md +0 -39
  280. package/recce-source/js/app/(mainComponents)/DisplayModeToggle.tsx +0 -65
  281. package/recce-source/js/app/(mainComponents)/NavBar.tsx +0 -228
  282. package/recce-source/js/app/(mainComponents)/RecceVersionBadge.tsx +0 -107
  283. package/recce-source/js/app/(mainComponents)/TopBar.tsx +0 -252
  284. package/recce-source/js/app/@lineage/default.tsx +0 -20
  285. package/recce-source/js/app/@lineage/page.tsx +0 -14
  286. package/recce-source/js/app/MainLayout.tsx +0 -170
  287. package/recce-source/js/app/Providers.tsx +0 -49
  288. package/recce-source/js/app/checks/page.tsx +0 -296
  289. package/recce-source/js/app/error.tsx +0 -93
  290. package/recce-source/js/app/favicon.ico +0 -0
  291. package/recce-source/js/app/global-error.tsx +0 -115
  292. package/recce-source/js/app/global.css +0 -82
  293. package/recce-source/js/app/layout.tsx +0 -48
  294. package/recce-source/js/app/lineage/page.tsx +0 -15
  295. package/recce-source/js/app/page.tsx +0 -12
  296. package/recce-source/js/app/query/page.tsx +0 -8
  297. package/recce-source/js/biome.json +0 -313
  298. package/recce-source/js/jest.config.js +0 -34
  299. package/recce-source/js/jest.globals.d.ts +0 -32
  300. package/recce-source/js/jest.setup.js +0 -91
  301. package/recce-source/js/next.config.js +0 -16
  302. package/recce-source/js/package-lock.json +0 -13843
  303. package/recce-source/js/package.json +0 -123
  304. package/recce-source/js/pnpm-lock.yaml +0 -9235
  305. package/recce-source/js/pnpm-workspace.yaml +0 -6
  306. package/recce-source/js/postcss.config.js +0 -5
  307. package/recce-source/js/public/auth_callback.html +0 -68
  308. package/recce-source/js/public/imgs/feedback/thumbs-down.png +0 -0
  309. package/recce-source/js/public/imgs/feedback/thumbs-up.png +0 -0
  310. package/recce-source/js/public/imgs/reload-image.svg +0 -4
  311. package/recce-source/js/public/logo/recce-logo-white.png +0 -0
  312. package/recce-source/js/src/components/AuthModal/AuthModal.tsx +0 -202
  313. package/recce-source/js/src/components/app/AvatarDropdown.tsx +0 -159
  314. package/recce-source/js/src/components/app/EnvInfo.tsx +0 -357
  315. package/recce-source/js/src/components/app/Filename.tsx +0 -388
  316. package/recce-source/js/src/components/app/SetupConnectionPopover.tsx +0 -91
  317. package/recce-source/js/src/components/app/StateExporter.tsx +0 -57
  318. package/recce-source/js/src/components/app/StateImporter.tsx +0 -198
  319. package/recce-source/js/src/components/app/StateSharing.tsx +0 -145
  320. package/recce-source/js/src/components/app/StateSynchronizer.tsx +0 -205
  321. package/recce-source/js/src/components/charts/HistogramChart.tsx +0 -291
  322. package/recce-source/js/src/components/charts/SquareIcon.tsx +0 -51
  323. package/recce-source/js/src/components/charts/TopKSummaryList.tsx +0 -457
  324. package/recce-source/js/src/components/charts/chartTheme.ts +0 -74
  325. package/recce-source/js/src/components/check/CheckBreadcrumb.tsx +0 -97
  326. package/recce-source/js/src/components/check/CheckDescription.tsx +0 -134
  327. package/recce-source/js/src/components/check/CheckDetail.tsx +0 -797
  328. package/recce-source/js/src/components/check/CheckEmptyState.tsx +0 -84
  329. package/recce-source/js/src/components/check/CheckList.tsx +0 -320
  330. package/recce-source/js/src/components/check/LineageDiffView.tsx +0 -32
  331. package/recce-source/js/src/components/check/PresetCheckTemplateView.tsx +0 -48
  332. package/recce-source/js/src/components/check/SchemaDiffView.tsx +0 -290
  333. package/recce-source/js/src/components/check/check.ts +0 -25
  334. package/recce-source/js/src/components/check/timeline/CheckTimeline.tsx +0 -163
  335. package/recce-source/js/src/components/check/timeline/CommentInput.tsx +0 -84
  336. package/recce-source/js/src/components/check/timeline/TimelineEvent.tsx +0 -468
  337. package/recce-source/js/src/components/check/timeline/index.ts +0 -12
  338. package/recce-source/js/src/components/check/utils.ts +0 -12
  339. package/recce-source/js/src/components/data-grid/ScreenshotDataGrid.tsx +0 -333
  340. package/recce-source/js/src/components/data-grid/agGridStyles.css +0 -55
  341. package/recce-source/js/src/components/data-grid/agGridTheme.ts +0 -43
  342. package/recce-source/js/src/components/editor/CodeEditor.tsx +0 -107
  343. package/recce-source/js/src/components/editor/DiffEditor.tsx +0 -162
  344. package/recce-source/js/src/components/editor/index.ts +0 -12
  345. package/recce-source/js/src/components/errorboundary/ErrorBoundary.tsx +0 -87
  346. package/recce-source/js/src/components/histogram/HistogramDiffForm.tsx +0 -147
  347. package/recce-source/js/src/components/histogram/HistogramDiffResultView.tsx +0 -63
  348. package/recce-source/js/src/components/icons/index.tsx +0 -142
  349. package/recce-source/js/src/components/lineage/ActionControl.tsx +0 -63
  350. package/recce-source/js/src/components/lineage/ActionTag.tsx +0 -141
  351. package/recce-source/js/src/components/lineage/ChangeStatusLegend.tsx +0 -46
  352. package/recce-source/js/src/components/lineage/ColumnLevelLineageControl.tsx +0 -327
  353. package/recce-source/js/src/components/lineage/ColumnLevelLineageLegend.tsx +0 -57
  354. package/recce-source/js/src/components/lineage/GraphColumnNode.tsx +0 -199
  355. package/recce-source/js/src/components/lineage/GraphEdge.tsx +0 -59
  356. package/recce-source/js/src/components/lineage/GraphNode.tsx +0 -555
  357. package/recce-source/js/src/components/lineage/LineagePage.tsx +0 -10
  358. package/recce-source/js/src/components/lineage/LineageView.tsx +0 -1384
  359. package/recce-source/js/src/components/lineage/LineageViewContext.tsx +0 -86
  360. package/recce-source/js/src/components/lineage/LineageViewContextMenu.tsx +0 -637
  361. package/recce-source/js/src/components/lineage/LineageViewNotification.tsx +0 -64
  362. package/recce-source/js/src/components/lineage/LineageViewTopBar.tsx +0 -596
  363. package/recce-source/js/src/components/lineage/NodeSqlView.tsx +0 -136
  364. package/recce-source/js/src/components/lineage/NodeTag.tsx +0 -278
  365. package/recce-source/js/src/components/lineage/NodeView.tsx +0 -642
  366. package/recce-source/js/src/components/lineage/SandboxView.tsx +0 -436
  367. package/recce-source/js/src/components/lineage/ServerDisconnectedModalContent.tsx +0 -105
  368. package/recce-source/js/src/components/lineage/SetupConnectionBanner.tsx +0 -52
  369. package/recce-source/js/src/components/lineage/SingleEnvironmentQueryView.tsx +0 -152
  370. package/recce-source/js/src/components/lineage/graph.test.ts +0 -31
  371. package/recce-source/js/src/components/lineage/graph.ts +0 -58
  372. package/recce-source/js/src/components/lineage/lineage.test.ts +0 -169
  373. package/recce-source/js/src/components/lineage/lineage.ts +0 -521
  374. package/recce-source/js/src/components/lineage/styles.css +0 -42
  375. package/recce-source/js/src/components/lineage/styles.tsx +0 -165
  376. package/recce-source/js/src/components/lineage/useMultiNodesAction.ts +0 -352
  377. package/recce-source/js/src/components/lineage/useValueDiffAlertDialog.tsx +0 -108
  378. package/recce-source/js/src/components/onboarding-guide/Notification.tsx +0 -62
  379. package/recce-source/js/src/components/profile/ProfileDiffForm.tsx +0 -134
  380. package/recce-source/js/src/components/profile/ProfileDiffResultView.tsx +0 -243
  381. package/recce-source/js/src/components/query/ChangedOnlyCheckbox.tsx +0 -29
  382. package/recce-source/js/src/components/query/DiffText.tsx +0 -120
  383. package/recce-source/js/src/components/query/QueryDiffResultView.tsx +0 -468
  384. package/recce-source/js/src/components/query/QueryForm.tsx +0 -80
  385. package/recce-source/js/src/components/query/QueryPage.tsx +0 -282
  386. package/recce-source/js/src/components/query/QueryResultView.tsx +0 -180
  387. package/recce-source/js/src/components/query/SetupConnectionGuide.tsx +0 -57
  388. package/recce-source/js/src/components/query/SqlEditor.tsx +0 -245
  389. package/recce-source/js/src/components/query/ToggleSwitch.tsx +0 -84
  390. package/recce-source/js/src/components/query/styles.css +0 -21
  391. package/recce-source/js/src/components/routing/DirectUrlAccess.test.tsx +0 -428
  392. package/recce-source/js/src/components/routing/LineageStatePreservation.test.tsx +0 -311
  393. package/recce-source/js/src/components/routing/Navigation.test.tsx +0 -256
  394. package/recce-source/js/src/components/rowcount/RowCountDiffResultView.tsx +0 -108
  395. package/recce-source/js/src/components/rowcount/delta.test.ts +0 -51
  396. package/recce-source/js/src/components/rowcount/delta.ts +0 -16
  397. package/recce-source/js/src/components/run/RunList.tsx +0 -303
  398. package/recce-source/js/src/components/run/RunModal.tsx +0 -191
  399. package/recce-source/js/src/components/run/RunPage.tsx +0 -26
  400. package/recce-source/js/src/components/run/RunResultPane.tsx +0 -578
  401. package/recce-source/js/src/components/run/RunStatusAndDate.tsx +0 -106
  402. package/recce-source/js/src/components/run/RunToolbar.tsx +0 -70
  403. package/recce-source/js/src/components/run/RunView.tsx +0 -196
  404. package/recce-source/js/src/components/run/registry.ts +0 -214
  405. package/recce-source/js/src/components/run/types.ts +0 -14
  406. package/recce-source/js/src/components/schema/ColumnNameCell.test.tsx +0 -169
  407. package/recce-source/js/src/components/schema/ColumnNameCell.tsx +0 -198
  408. package/recce-source/js/src/components/schema/SchemaView.tsx +0 -336
  409. package/recce-source/js/src/components/schema/schemaDiff.ts +0 -32
  410. package/recce-source/js/src/components/schema/style.css +0 -134
  411. package/recce-source/js/src/components/screenshot/ScreenshotBox.tsx +0 -39
  412. package/recce-source/js/src/components/shared/HistoryToggle.tsx +0 -35
  413. package/recce-source/js/src/components/split/Split.tsx +0 -40
  414. package/recce-source/js/src/components/split/styles.css +0 -24
  415. package/recce-source/js/src/components/summary/ChangeSummary.tsx +0 -264
  416. package/recce-source/js/src/components/summary/SchemaSummary.tsx +0 -123
  417. package/recce-source/js/src/components/summary/SummaryView.tsx +0 -29
  418. package/recce-source/js/src/components/timeout/IdleTimeoutBadge.tsx +0 -48
  419. package/recce-source/js/src/components/top-k/TopKDiffForm.tsx +0 -58
  420. package/recce-source/js/src/components/top-k/TopKDiffResultView.tsx +0 -73
  421. package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnGroupHeader.tsx +0 -228
  422. package/recce-source/js/src/components/ui/dataGrid/DataFrameColumnHeader.tsx +0 -113
  423. package/recce-source/js/src/components/ui/dataGrid/defaultRenderCell.tsx +0 -72
  424. package/recce-source/js/src/components/ui/dataGrid/index.ts +0 -23
  425. package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.test.tsx +0 -607
  426. package/recce-source/js/src/components/ui/dataGrid/inlineRenderCell.tsx +0 -211
  427. package/recce-source/js/src/components/ui/dataGrid/schemaCells.test.tsx +0 -452
  428. package/recce-source/js/src/components/ui/dataGrid/schemaCells.tsx +0 -142
  429. package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.test.tsx +0 -178
  430. package/recce-source/js/src/components/ui/dataGrid/valueDiffCells.tsx +0 -275
  431. package/recce-source/js/src/components/ui/markdown/ExternalLinkConfirmDialog.tsx +0 -134
  432. package/recce-source/js/src/components/ui/markdown/MarkdownContent.tsx +0 -364
  433. package/recce-source/js/src/components/ui/mui/index.ts +0 -13
  434. package/recce-source/js/src/components/ui/mui-provider.tsx +0 -67
  435. package/recce-source/js/src/components/ui/mui-theme.ts +0 -1039
  436. package/recce-source/js/src/components/ui/mui-utils.ts +0 -113
  437. package/recce-source/js/src/components/ui/toaster.tsx +0 -288
  438. package/recce-source/js/src/components/valuediff/ValueDiffDetailResultView.tsx +0 -216
  439. package/recce-source/js/src/components/valuediff/ValueDiffForm.tsx +0 -246
  440. package/recce-source/js/src/components/valuediff/ValueDiffResultView.tsx +0 -81
  441. package/recce-source/js/src/components/valuediff/shared.ts +0 -33
  442. package/recce-source/js/src/constants/tooltipMessage.ts +0 -3
  443. package/recce-source/js/src/constants/urls.ts +0 -1
  444. package/recce-source/js/src/lib/UrlHash.ts +0 -12
  445. package/recce-source/js/src/lib/api/adhocQuery.ts +0 -70
  446. package/recce-source/js/src/lib/api/axiosClient.ts +0 -9
  447. package/recce-source/js/src/lib/api/cacheKeys.ts +0 -13
  448. package/recce-source/js/src/lib/api/checkEvents.ts +0 -252
  449. package/recce-source/js/src/lib/api/checks.ts +0 -129
  450. package/recce-source/js/src/lib/api/cll.ts +0 -53
  451. package/recce-source/js/src/lib/api/connectToCloud.ts +0 -13
  452. package/recce-source/js/src/lib/api/flag.ts +0 -37
  453. package/recce-source/js/src/lib/api/info.ts +0 -198
  454. package/recce-source/js/src/lib/api/instanceInfo.ts +0 -25
  455. package/recce-source/js/src/lib/api/keepAlive.ts +0 -108
  456. package/recce-source/js/src/lib/api/lineagecheck.ts +0 -35
  457. package/recce-source/js/src/lib/api/localStorageKeys.ts +0 -7
  458. package/recce-source/js/src/lib/api/models.ts +0 -59
  459. package/recce-source/js/src/lib/api/profile.ts +0 -65
  460. package/recce-source/js/src/lib/api/rowcount.ts +0 -19
  461. package/recce-source/js/src/lib/api/runs.ts +0 -174
  462. package/recce-source/js/src/lib/api/schemacheck.ts +0 -31
  463. package/recce-source/js/src/lib/api/select.ts +0 -25
  464. package/recce-source/js/src/lib/api/sessionStorageKeys.ts +0 -8
  465. package/recce-source/js/src/lib/api/state.ts +0 -117
  466. package/recce-source/js/src/lib/api/track.ts +0 -281
  467. package/recce-source/js/src/lib/api/types.ts +0 -284
  468. package/recce-source/js/src/lib/api/user.ts +0 -42
  469. package/recce-source/js/src/lib/api/valuediff.ts +0 -46
  470. package/recce-source/js/src/lib/api/version.ts +0 -40
  471. package/recce-source/js/src/lib/const.ts +0 -9
  472. package/recce-source/js/src/lib/csv/extractors.test.ts +0 -456
  473. package/recce-source/js/src/lib/csv/extractors.ts +0 -468
  474. package/recce-source/js/src/lib/csv/format.test.ts +0 -211
  475. package/recce-source/js/src/lib/csv/format.ts +0 -44
  476. package/recce-source/js/src/lib/csv/index.test.ts +0 -155
  477. package/recce-source/js/src/lib/csv/index.ts +0 -109
  478. package/recce-source/js/src/lib/dataGrid/crossFunctionConsistency.test.ts +0 -626
  479. package/recce-source/js/src/lib/dataGrid/dataGridFactory.test.ts +0 -2140
  480. package/recce-source/js/src/lib/dataGrid/dataGridFactory.ts +0 -397
  481. package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.test.ts +0 -132
  482. package/recce-source/js/src/lib/dataGrid/generators/rowCountUtils.ts +0 -126
  483. package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.test.ts +0 -1627
  484. package/recce-source/js/src/lib/dataGrid/generators/toDataDiffGrid.ts +0 -140
  485. package/recce-source/js/src/lib/dataGrid/generators/toDataGrid.ts +0 -67
  486. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.test.ts +0 -142
  487. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDataGrid.ts +0 -71
  488. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.test.ts +0 -258
  489. package/recce-source/js/src/lib/dataGrid/generators/toRowCountDiffDataGrid.ts +0 -153
  490. package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.test.ts +0 -951
  491. package/recce-source/js/src/lib/dataGrid/generators/toSchemaDataGrid.ts +0 -221
  492. package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.test.ts +0 -395
  493. package/recce-source/js/src/lib/dataGrid/generators/toValueDataGrid.ts +0 -184
  494. package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.test.ts +0 -884
  495. package/recce-source/js/src/lib/dataGrid/generators/toValueDiffGrid.ts +0 -113
  496. package/recce-source/js/src/lib/dataGrid/index.ts +0 -51
  497. package/recce-source/js/src/lib/dataGrid/propertyBased.test.ts +0 -858
  498. package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.test.ts +0 -482
  499. package/recce-source/js/src/lib/dataGrid/shared/columnBuilders.ts +0 -345
  500. package/recce-source/js/src/lib/dataGrid/shared/dataTypeEdgeCases.test.ts +0 -698
  501. package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.test.tsx +0 -820
  502. package/recce-source/js/src/lib/dataGrid/shared/diffColumnBuilder.tsx +0 -277
  503. package/recce-source/js/src/lib/dataGrid/shared/gridUtils.test.ts +0 -785
  504. package/recce-source/js/src/lib/dataGrid/shared/gridUtils.ts +0 -370
  505. package/recce-source/js/src/lib/dataGrid/shared/index.ts +0 -81
  506. package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.test.ts +0 -909
  507. package/recce-source/js/src/lib/dataGrid/shared/rowBuilders.ts +0 -325
  508. package/recce-source/js/src/lib/dataGrid/shared/simpleColumnBuilder.tsx +0 -240
  509. package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.test.tsx +0 -719
  510. package/recce-source/js/src/lib/dataGrid/shared/toDiffColumn.tsx +0 -231
  511. package/recce-source/js/src/lib/dataGrid/shared/validation.test.ts +0 -559
  512. package/recce-source/js/src/lib/dataGrid/shared/validation.ts +0 -367
  513. package/recce-source/js/src/lib/dataGrid/warehouseNamingConventions.test.ts +0 -1117
  514. package/recce-source/js/src/lib/formatSelect.ts +0 -50
  515. package/recce-source/js/src/lib/hooks/ApiConfigContext.tsx +0 -181
  516. package/recce-source/js/src/lib/hooks/IdleTimeoutContext.tsx +0 -177
  517. package/recce-source/js/src/lib/hooks/LineageGraphContext.tsx +0 -512
  518. package/recce-source/js/src/lib/hooks/RecceActionContext.tsx +0 -269
  519. package/recce-source/js/src/lib/hooks/RecceCheckContext.tsx +0 -33
  520. package/recce-source/js/src/lib/hooks/RecceContextProvider.tsx +0 -54
  521. package/recce-source/js/src/lib/hooks/RecceInstanceContext.tsx +0 -129
  522. package/recce-source/js/src/lib/hooks/RecceQueryContext.tsx +0 -98
  523. package/recce-source/js/src/lib/hooks/RecceShareStateContext.tsx +0 -59
  524. package/recce-source/js/src/lib/hooks/ScreenShot.tsx +0 -399
  525. package/recce-source/js/src/lib/hooks/useAppRouter.test.ts +0 -211
  526. package/recce-source/js/src/lib/hooks/useAppRouter.ts +0 -200
  527. package/recce-source/js/src/lib/hooks/useCSVExport.ts +0 -136
  528. package/recce-source/js/src/lib/hooks/useCheckEvents.ts +0 -99
  529. package/recce-source/js/src/lib/hooks/useCheckToast.tsx +0 -14
  530. package/recce-source/js/src/lib/hooks/useClipBoardToast.tsx +0 -27
  531. package/recce-source/js/src/lib/hooks/useCountdownToast.tsx +0 -102
  532. package/recce-source/js/src/lib/hooks/useFeedbackCollectionToast.tsx +0 -130
  533. package/recce-source/js/src/lib/hooks/useGuideToast.tsx +0 -45
  534. package/recce-source/js/src/lib/hooks/useIdleDetection.tsx +0 -185
  535. package/recce-source/js/src/lib/hooks/useModelColumns.tsx +0 -113
  536. package/recce-source/js/src/lib/hooks/useRecceInstanceInfo.tsx +0 -13
  537. package/recce-source/js/src/lib/hooks/useRecceServerFlag.tsx +0 -13
  538. package/recce-source/js/src/lib/hooks/useRun.tsx +0 -89
  539. package/recce-source/js/src/lib/hooks/useThemeColors.ts +0 -115
  540. package/recce-source/js/src/lib/mergeKeys.test.ts +0 -89
  541. package/recce-source/js/src/lib/mergeKeys.ts +0 -86
  542. package/recce-source/js/src/lib/result/ResultErrorFallback.tsx +0 -9
  543. package/recce-source/js/src/lib/utils/formatTime.ts +0 -84
  544. package/recce-source/js/src/lib/utils/urls.ts +0 -16
  545. package/recce-source/js/src/utils/DropdownValuesInput.tsx +0 -297
  546. package/recce-source/js/src/utils/formatters.tsx +0 -237
  547. package/recce-source/js/src/utils/transforms.ts +0 -81
  548. package/recce-source/js/tsconfig.json +0 -47
  549. package/recce-source/macros/README.md +0 -8
  550. package/recce-source/macros/recce_athena.sql +0 -73
  551. package/recce-source/pyproject.toml +0 -109
  552. package/recce-source/recce/VERSION +0 -1
  553. package/recce-source/recce/__init__.py +0 -84
  554. package/recce-source/recce/adapter/__init__.py +0 -0
  555. package/recce-source/recce/adapter/base.py +0 -109
  556. package/recce-source/recce/adapter/dbt_adapter/__init__.py +0 -1699
  557. package/recce-source/recce/adapter/dbt_adapter/dbt_version.py +0 -42
  558. package/recce-source/recce/adapter/sqlmesh_adapter.py +0 -141
  559. package/recce-source/recce/apis/__init__.py +0 -0
  560. package/recce-source/recce/apis/check_api.py +0 -203
  561. package/recce-source/recce/apis/check_events_api.py +0 -353
  562. package/recce-source/recce/apis/check_func.py +0 -130
  563. package/recce-source/recce/apis/run_api.py +0 -130
  564. package/recce-source/recce/apis/run_func.py +0 -258
  565. package/recce-source/recce/artifact.py +0 -266
  566. package/recce-source/recce/cli.py +0 -1846
  567. package/recce-source/recce/config.py +0 -127
  568. package/recce-source/recce/connect_to_cloud.py +0 -138
  569. package/recce-source/recce/core.py +0 -334
  570. package/recce-source/recce/diff.py +0 -26
  571. package/recce-source/recce/event/CONFIG +0 -1
  572. package/recce-source/recce/event/SENTRY_DNS +0 -1
  573. package/recce-source/recce/event/__init__.py +0 -304
  574. package/recce-source/recce/event/collector.py +0 -184
  575. package/recce-source/recce/event/track.py +0 -158
  576. package/recce-source/recce/exceptions.py +0 -21
  577. package/recce-source/recce/git.py +0 -77
  578. package/recce-source/recce/github.py +0 -222
  579. package/recce-source/recce/mcp_server.py +0 -885
  580. package/recce-source/recce/models/__init__.py +0 -6
  581. package/recce-source/recce/models/check.py +0 -481
  582. package/recce-source/recce/models/run.py +0 -46
  583. package/recce-source/recce/models/types.py +0 -218
  584. package/recce-source/recce/pull_request.py +0 -124
  585. package/recce-source/recce/run.py +0 -390
  586. package/recce-source/recce/server.py +0 -877
  587. package/recce-source/recce/state/__init__.py +0 -31
  588. package/recce-source/recce/state/cloud.py +0 -644
  589. package/recce-source/recce/state/const.py +0 -26
  590. package/recce-source/recce/state/local.py +0 -56
  591. package/recce-source/recce/state/state.py +0 -119
  592. package/recce-source/recce/state/state_loader.py +0 -174
  593. package/recce-source/recce/summary.py +0 -575
  594. package/recce-source/recce/tasks/__init__.py +0 -23
  595. package/recce-source/recce/tasks/core.py +0 -134
  596. package/recce-source/recce/tasks/dataframe.py +0 -170
  597. package/recce-source/recce/tasks/histogram.py +0 -433
  598. package/recce-source/recce/tasks/lineage.py +0 -19
  599. package/recce-source/recce/tasks/profile.py +0 -298
  600. package/recce-source/recce/tasks/query.py +0 -450
  601. package/recce-source/recce/tasks/rowcount.py +0 -277
  602. package/recce-source/recce/tasks/schema.py +0 -65
  603. package/recce-source/recce/tasks/top_k.py +0 -172
  604. package/recce-source/recce/tasks/utils.py +0 -147
  605. package/recce-source/recce/tasks/valuediff.py +0 -497
  606. package/recce-source/recce/util/__init__.py +0 -4
  607. package/recce-source/recce/util/api_token.py +0 -80
  608. package/recce-source/recce/util/breaking.py +0 -330
  609. package/recce-source/recce/util/cache.py +0 -25
  610. package/recce-source/recce/util/cll.py +0 -355
  611. package/recce-source/recce/util/cloud/__init__.py +0 -15
  612. package/recce-source/recce/util/cloud/base.py +0 -115
  613. package/recce-source/recce/util/cloud/check_events.py +0 -190
  614. package/recce-source/recce/util/cloud/checks.py +0 -242
  615. package/recce-source/recce/util/io.py +0 -120
  616. package/recce-source/recce/util/lineage.py +0 -83
  617. package/recce-source/recce/util/logger.py +0 -25
  618. package/recce-source/recce/util/onboarding_state.py +0 -45
  619. package/recce-source/recce/util/perf_tracking.py +0 -85
  620. package/recce-source/recce/util/pydantic_model.py +0 -22
  621. package/recce-source/recce/util/recce_cloud.py +0 -454
  622. package/recce-source/recce/util/singleton.py +0 -18
  623. package/recce-source/recce/util/startup_perf.py +0 -121
  624. package/recce-source/recce/yaml/__init__.py +0 -58
  625. package/recce-source/recce_cloud/README.md +0 -780
  626. package/recce-source/recce_cloud/VERSION +0 -1
  627. package/recce-source/recce_cloud/__init__.py +0 -24
  628. package/recce-source/recce_cloud/api/__init__.py +0 -17
  629. package/recce-source/recce_cloud/api/base.py +0 -132
  630. package/recce-source/recce_cloud/api/client.py +0 -186
  631. package/recce-source/recce_cloud/api/exceptions.py +0 -26
  632. package/recce-source/recce_cloud/api/factory.py +0 -63
  633. package/recce-source/recce_cloud/api/github.py +0 -106
  634. package/recce-source/recce_cloud/api/gitlab.py +0 -111
  635. package/recce-source/recce_cloud/artifact.py +0 -57
  636. package/recce-source/recce_cloud/ci_providers/__init__.py +0 -9
  637. package/recce-source/recce_cloud/ci_providers/base.py +0 -82
  638. package/recce-source/recce_cloud/ci_providers/detector.py +0 -147
  639. package/recce-source/recce_cloud/ci_providers/github_actions.py +0 -136
  640. package/recce-source/recce_cloud/ci_providers/gitlab_ci.py +0 -130
  641. package/recce-source/recce_cloud/cli.py +0 -434
  642. package/recce-source/recce_cloud/download.py +0 -230
  643. package/recce-source/recce_cloud/hatch_build.py +0 -20
  644. package/recce-source/recce_cloud/pyproject.toml +0 -49
  645. package/recce-source/recce_cloud/upload.py +0 -214
  646. package/recce-source/test.py +0 -0
  647. package/recce-source/tests/__init__.py +0 -0
  648. package/recce-source/tests/adapter/__init__.py +0 -0
  649. package/recce-source/tests/adapter/dbt_adapter/__init__.py +0 -0
  650. package/recce-source/tests/adapter/dbt_adapter/conftest.py +0 -17
  651. package/recce-source/tests/adapter/dbt_adapter/dbt_test_helper.py +0 -298
  652. package/recce-source/tests/adapter/dbt_adapter/test_dbt_adapter.py +0 -25
  653. package/recce-source/tests/adapter/dbt_adapter/test_dbt_cll.py +0 -717
  654. package/recce-source/tests/adapter/dbt_adapter/test_proj/dbt_project.yml +0 -4
  655. package/recce-source/tests/adapter/dbt_adapter/test_proj/manifest.json +0 -1
  656. package/recce-source/tests/adapter/dbt_adapter/test_proj/package-lock.yml +0 -8
  657. package/recce-source/tests/adapter/dbt_adapter/test_proj/packages.yml +0 -7
  658. package/recce-source/tests/adapter/dbt_adapter/test_proj/profiles.yml +0 -6
  659. package/recce-source/tests/adapter/dbt_adapter/test_selector.py +0 -205
  660. package/recce-source/tests/apis/__init__.py +0 -0
  661. package/recce-source/tests/apis/row_count_diff.json +0 -59
  662. package/recce-source/tests/apis/test_check_events_api.py +0 -615
  663. package/recce-source/tests/apis/test_run_func.py +0 -433
  664. package/recce-source/tests/catalog.json +0 -527
  665. package/recce-source/tests/data/manifest/base/catalog.json +0 -1
  666. package/recce-source/tests/data/manifest/base/manifest.json +0 -1
  667. package/recce-source/tests/data/manifest/pr2/catalog.json +0 -1
  668. package/recce-source/tests/data/manifest/pr2/manifest.json +0 -1
  669. package/recce-source/tests/manifest.json +0 -10655
  670. package/recce-source/tests/models/__init__.py +0 -0
  671. package/recce-source/tests/models/test_check.py +0 -731
  672. package/recce-source/tests/models/test_run_models.py +0 -295
  673. package/recce-source/tests/recce_cloud/__init__.py +0 -0
  674. package/recce-source/tests/recce_cloud/test_ci_providers.py +0 -351
  675. package/recce-source/tests/recce_cloud/test_cli.py +0 -735
  676. package/recce-source/tests/recce_cloud/test_client.py +0 -379
  677. package/recce-source/tests/recce_cloud/test_platform_clients.py +0 -483
  678. package/recce-source/tests/recce_state.json +0 -1
  679. package/recce-source/tests/state/test_cloud.py +0 -719
  680. package/recce-source/tests/state/test_local.py +0 -164
  681. package/recce-source/tests/state/test_state_loader.py +0 -211
  682. package/recce-source/tests/tasks/__init__.py +0 -0
  683. package/recce-source/tests/tasks/conftest.py +0 -4
  684. package/recce-source/tests/tasks/test_histogram.py +0 -129
  685. package/recce-source/tests/tasks/test_lineage.py +0 -55
  686. package/recce-source/tests/tasks/test_preset_checks.py +0 -64
  687. package/recce-source/tests/tasks/test_profile.py +0 -397
  688. package/recce-source/tests/tasks/test_query.py +0 -528
  689. package/recce-source/tests/tasks/test_row_count.py +0 -133
  690. package/recce-source/tests/tasks/test_schema.py +0 -122
  691. package/recce-source/tests/tasks/test_top_k.py +0 -77
  692. package/recce-source/tests/tasks/test_utils.py +0 -439
  693. package/recce-source/tests/tasks/test_valuediff.py +0 -361
  694. package/recce-source/tests/test_cli.py +0 -236
  695. package/recce-source/tests/test_cli_mcp_optional.py +0 -45
  696. package/recce-source/tests/test_cloud_listing_cli.py +0 -324
  697. package/recce-source/tests/test_config.py +0 -43
  698. package/recce-source/tests/test_connect_to_cloud.py +0 -82
  699. package/recce-source/tests/test_core.py +0 -174
  700. package/recce-source/tests/test_dbt.py +0 -36
  701. package/recce-source/tests/test_mcp_server.py +0 -505
  702. package/recce-source/tests/test_pull_request.py +0 -130
  703. package/recce-source/tests/test_server.py +0 -202
  704. package/recce-source/tests/test_server_lifespan.py +0 -138
  705. package/recce-source/tests/test_summary.py +0 -73
  706. package/recce-source/tests/util/__init__.py +0 -0
  707. package/recce-source/tests/util/cloud/__init__.py +0 -0
  708. package/recce-source/tests/util/cloud/test_check_events.py +0 -255
  709. package/recce-source/tests/util/cloud/test_checks.py +0 -204
  710. package/recce-source/tests/util/test_api_token.py +0 -119
  711. package/recce-source/tests/util/test_breaking.py +0 -1427
  712. package/recce-source/tests/util/test_cll.py +0 -706
  713. package/recce-source/tests/util/test_lineage.py +0 -122
  714. package/recce-source/tests/util/test_onboarding_state.py +0 -84
  715. package/recce-source/tests/util/test_recce_cloud.py +0 -231
  716. package/recce-source/tox.ini +0 -40
  717. package/recce-source/uv.lock +0 -3928
  718. package/src/api/index.ts +0 -32
  719. package/src/components/index.ts +0 -154
  720. package/src/global.d.ts +0 -14
  721. package/src/hooks/index.ts +0 -56
  722. package/src/index.ts +0 -17
  723. package/src/lib/hooks/RouteConfigContext.ts +0 -139
  724. package/src/lib/hooks/useAppRouter.ts +0 -240
  725. package/src/mui-augmentation.d.ts +0 -139
  726. package/src/theme/index.ts +0 -13
  727. package/src/theme.ts +0 -23
  728. package/src/types/index.ts +0 -23
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useThemeColors--prVbMmM.js","names":["ThemeProvider","IconAdded: IconComponent","IconRemoved: IconComponent","IconModified: IconComponent","IconChanged: IconComponent","IconModel: IconComponent","IconSource: IconComponent","IconSeed: IconComponent","IconSnapshot: IconComponent","IconMetric: IconComponent","IconExposure: IconComponent","IconSemanticModel: IconComponent","changeStatusColors: Record<ChangeStatus | \"unchanged\", string>","changeStatusBackgroundsLight: Record<\n ChangeStatus | \"unchanged\",\n string\n>","changeStatusBackgroundsDark: Record<\n ChangeStatus | \"unchanged\",\n string\n>","statusColors: Record<EdgeChangeStatus, string>","changeStatus: EdgeChangeStatus","CHANGE_CATEGORY_LABELS: Record<ChangeCategory, string>","useMuiTheme"],"sources":["../src/providers/contexts/ThemeContext.tsx","../src/hooks/useIsDark.ts","../src/components/lineage/styles.tsx","../src/components/lineage/edges/LineageEdge.tsx","../src/components/lineage/nodes/LineageNode.tsx","../src/components/lineage/LineageCanvas.tsx","../src/hooks/useThemeColors.ts"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useState,\n} from \"react\";\n\n/**\n * Theme mode selection for {@link ThemeProvider}.\n */\ntype ThemeMode = \"light\" | \"dark\" | \"system\";\n\n/**\n * Theme context values exposed by {@link useRecceTheme}.\n */\ninterface ThemeContextValue {\n mode: ThemeMode;\n resolvedMode: \"light\" | \"dark\";\n setMode: (mode: ThemeMode) => void;\n}\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\nThemeContext.displayName = \"RecceThemeContext\";\n\n/**\n * Access the theme context.\n *\n * @throws Error if used outside {@link RecceProvider}.\n */\nexport function useRecceTheme(): ThemeContextValue {\n const context = useContext(ThemeContext);\n if (!context) {\n throw new Error(\"useRecceTheme must be used within RecceProvider\");\n }\n return context;\n}\n\n/**\n * Non-throwing version of {@link useRecceTheme}.\n *\n * @returns Theme context values, or null if outside {@link RecceProvider}.\n */\nexport function useRecceThemeOptional(): ThemeContextValue | null {\n return useContext(ThemeContext);\n}\n\n/**\n * Props for {@link ThemeProvider}.\n */\ninterface ThemeProviderProps {\n children: ReactNode;\n defaultMode?: ThemeMode;\n}\n\n/**\n * Provides theme mode and resolved color scheme for UI components.\n */\nexport function ThemeProvider({\n children,\n defaultMode = \"system\",\n}: ThemeProviderProps) {\n const [mode, setMode] = useState<ThemeMode>(defaultMode);\n\n // SSR-safe initialization: compute initial resolved mode to prevent hydration mismatch\n const [resolvedMode, setResolvedMode] = useState<\"light\" | \"dark\">(() => {\n // On server, always return \"light\" for consistent initial render\n if (typeof window === \"undefined\") return \"light\";\n // On client, compute actual value during initialization\n if (defaultMode !== \"system\") return defaultMode;\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\";\n });\n\n useEffect(() => {\n if (mode === \"system\") {\n const mediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\");\n setResolvedMode(mediaQuery.matches ? \"dark\" : \"light\");\n\n const handler = (e: MediaQueryListEvent) => {\n setResolvedMode(e.matches ? \"dark\" : \"light\");\n };\n mediaQuery.addEventListener(\"change\", handler);\n return () => mediaQuery.removeEventListener(\"change\", handler);\n } else {\n setResolvedMode(mode);\n }\n }, [mode]);\n\n useEffect(() => {\n // Skip on server (SSR safety)\n if (typeof window === \"undefined\") return;\n // Toggle .dark class on document for CSS variables\n document.documentElement.classList.toggle(\"dark\", resolvedMode === \"dark\");\n }, [resolvedMode]);\n\n return (\n <ThemeContext.Provider value={{ mode, resolvedMode, setMode }}>\n {children}\n </ThemeContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { useRecceThemeOptional } from \"../providers/contexts/ThemeContext\";\n\n/**\n * Simple dark mode detection hook\n *\n * Uses RecceTheme context when available for reliable dark mode detection.\n * Falls back to DOM class detection when not within RecceProvider,\n * allowing components to work in both contexts (e.g., OSS app with next-themes\n * and Recce Cloud with RecceProvider).\n *\n * For more theme colors, use useThemeColors() instead.\n *\n * @returns true if dark mode is active, false otherwise\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const isDark = useIsDark();\n * return <Box bgcolor={isDark ? \"grey.900\" : \"grey.100\"}>Content</Box>;\n * }\n * ```\n */\nexport function useIsDark(): boolean {\n // Try to use theme context (returns null if not in provider)\n const themeContext = useRecceThemeOptional();\n const [mounted, setMounted] = useState(false);\n const [isDarkClass, setIsDarkClass] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n\n // If no context, fall back to DOM class detection\n // This allows the hook to work in OSS app (next-themes) and Recce Cloud (RecceProvider)\n if (!themeContext) {\n const checkDarkClass = () => {\n setIsDarkClass(document.documentElement.classList.contains(\"dark\"));\n };\n checkDarkClass();\n\n // Watch for class changes (both next-themes and RecceProvider toggle .dark)\n const observer = new MutationObserver(checkDarkClass);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => observer.disconnect();\n }\n }, [themeContext]);\n\n // Prevent hydration mismatch by returning false during SSR\n if (!mounted) return false;\n\n // Prefer context if available, otherwise use DOM detection\n return themeContext ? themeContext.resolvedMode === \"dark\" : isDarkClass;\n}\n","\"use client\";\n\n/**\n * @file styles.ts\n * @description Styling utilities for lineage components\n *\n * Provides icons, colors, and styling helpers for:\n * - Change status visualization (added, removed, modified)\n * - Resource type icons (model, source, seed, etc.)\n *\n * Source: Ported from OSS js/src/components/lineage/styles.tsx\n */\n\nimport type { ComponentType, SVGProps } from \"react\";\nimport { colors } from \"../../theme/colors\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Change status for diff visualization\n */\nexport type ChangeStatus = \"added\" | \"removed\" | \"modified\" | \"unchanged\";\n\n/**\n * Resource types supported by dbt/lineage\n */\nexport type ResourceType =\n | \"model\"\n | \"source\"\n | \"seed\"\n | \"snapshot\"\n | \"metric\"\n | \"exposure\"\n | \"semantic_model\";\n\n/**\n * Icon component type\n */\nexport type IconComponent = ComponentType<SVGProps<SVGSVGElement>>;\n\n/**\n * Result from getIconForChangeStatus\n */\nexport interface ChangeStatusStyle {\n /** CSS color value for the status */\n color: string;\n /** Hex color value (same as color for compatibility) */\n hexColor: string;\n /** Background color for light/dark mode */\n backgroundColor: string;\n /** Hex background color (same as backgroundColor for compatibility) */\n hexBackgroundColor: string;\n /** Icon component for the status, undefined if no change */\n icon: IconComponent | undefined;\n}\n\n/**\n * Result from getIconForResourceType\n */\nexport interface ResourceTypeStyle {\n /** CSS color value for the resource type */\n color: string;\n /** Icon component for the resource type, undefined if unknown */\n icon: IconComponent | undefined;\n}\n\n// =============================================================================\n// SVG ICON COMPONENTS\n// =============================================================================\n\n/**\n * Plus icon for \"added\" status\n * Based on VSCode's VscDiffAdded\n */\nexport const IconAdded: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 16 16\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M1.5 1h13l.5.5v13l-.5.5h-13l-.5-.5v-13l.5-.5zM2 2v12h12V2H2zm6.5 2.5v2.5h2.5v1H8.5v2.5h-1V8H5V7h2.5V4.5h1z\"\n />\n </svg>\n);\n\n/**\n * Minus icon for \"removed\" status\n * Based on VSCode's VscDiffRemoved\n */\nexport const IconRemoved: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 16 16\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M1.5 1h13l.5.5v13l-.5.5h-13l-.5-.5v-13l.5-.5zM2 2v12h12V2H2zm3 5.5h6v1H5v-1z\"\n />\n </svg>\n);\n\n/**\n * Tilde icon for \"modified\" status\n * Based on VSCode's VscDiffModified\n */\nexport const IconModified: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 16 16\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path d=\"M1.5 1h13l.5.5v13l-.5.5h-13l-.5-.5v-13l.5-.5zM2 2v12h12V2H2z\" />\n <path d=\"M10.6 8.7c-.1.1-.3.2-.5.2h-.1l-1.4-.3c-.5-.1-1.1-.3-1.8-.3-.6 0-1 .2-1.3.5-.2.2-.2.4-.2.7v.1l-.9.3v-.2c0-.3 0-.6.1-.9.2-.4.5-.8 1-1.1.5-.4 1.2-.5 2-.5h.2l1.5.4h.1c.5.1 1 .3 1.5.3.6 0 .9-.2 1.2-.4.2-.2.3-.5.3-.8v-.3l.8-.3h.1v.3c0 .6-.2 1.2-.6 1.6-.2.2-.3.4-.5.5l-.5.2z\" />\n </svg>\n);\n\n/**\n * Dot icon for \"changed\" status (generic change indicator)\n */\nexport const IconChanged: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 16 16\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M8 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6z\"\n />\n </svg>\n);\n\n/**\n * Icon for modified with downstream impact indicator\n */\nexport const IconModifiedDownstream: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 16 16\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M1.5 1h13l.5.5v13l-.5.5h-13l-.5-.5v-13l.5-.5zM2 2v4h-1v4h1v4h4v1h4v-1h4v-4h1v-4h-1v-4h-4v-1h-4v1h-4z\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M8 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6z\"\n />\n </svg>\n);\n\n// =============================================================================\n// RESOURCE TYPE ICONS (inline SVGs to avoid react-icons dependency)\n// =============================================================================\n\n/**\n * Cube icon for \"model\" resource type\n */\nexport const IconModel: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 512 512\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path d=\"M239.1 6.3l-208 78c-18.7 7-31.1 25-31.1 45v225.1c0 18.2 10.3 34.8 26.5 42.9l208 104c13.5 6.8 29.4 6.8 42.9 0l208-104c16.3-8.1 26.5-24.8 26.5-42.9V129.3c0-20-12.4-37.9-31.1-44.9l-208-78C262 2.2 250 2.2 239.1 6.3zM256 68.4l192 72v1.1l-192 78-192-78v-1.1l192-72zm32 356V275.5l160-65v133.9l-160 80z\" />\n </svg>\n);\n\n/**\n * Database icon for \"source\" resource type\n */\nexport const IconSource: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 448 512\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path d=\"M448 73.143v45.714C448 159.143 347.667 192 224 192S0 159.143 0 118.857V73.143C0 32.857 100.333 0 224 0s224 32.857 224 73.143zM448 176v102.857C448 319.143 347.667 352 224 352S0 319.143 0 278.857V176c48.125 33.143 136.208 48.572 224 48.572S399.874 209.143 448 176zm0 160v102.857C448 479.143 347.667 512 224 512S0 479.143 0 438.857V336c48.125 33.143 136.208 48.572 224 48.572S399.874 369.143 448 336z\" />\n </svg>\n);\n\n/**\n * Seedling icon for \"seed\" resource type\n */\nexport const IconSeed: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 512 512\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path d=\"M64 96H0c0 123.7 100.3 224 224 224v144c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16V320C288 196.3 187.7 96 64 96zm384-64c-84.2 0-157.4 46.5-195.7 115.2 27.7 30.2 48.2 66.9 59 107.6C424 243.1 512 147.9 512 32h-64z\" />\n </svg>\n);\n\n/**\n * Camera icon for \"snapshot\" resource type\n */\nexport const IconSnapshot: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 512 512\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path d=\"M512 144v288c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V144c0-26.5 21.5-48 48-48h88l12.3-32.9c7-18.7 24.9-31.1 44.9-31.1h125.5c20 0 37.9 12.4 44.9 31.1L376 96h88c26.5 0 48 21.5 48 48zM376 288c0-66.2-53.8-120-120-120s-120 53.8-120 120 53.8 120 120 120 120-53.8 120-120zm-32 0c0 48.5-39.5 88-88 88s-88-39.5-88-88 39.5-88 88-88 88 39.5 88 88z\" />\n </svg>\n);\n\n/**\n * Chart icon for \"metric\" resource type\n */\nexport const IconMetric: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 448 512\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path d=\"M160 80c0-26.5 21.5-48 48-48h32c26.5 0 48 21.5 48 48v352c0 26.5-21.5 48-48 48h-32c-26.5 0-48-21.5-48-48V80zM0 272c0-26.5 21.5-48 48-48h32c26.5 0 48 21.5 48 48v160c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V272zM368 96h32c26.5 0 48 21.5 48 48v288c0 26.5-21.5 48-48 48h-32c-26.5 0-48-21.5-48-48V144c0-26.5 21.5-48 48-48z\" />\n </svg>\n);\n\n/**\n * Gauge icon for \"exposure\" resource type\n */\nexport const IconExposure: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 512 512\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path d=\"M0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zm320 96c0-15.9-5.8-30.4-15.3-41.6l76.6-147.4c6.1-11.8 1.5-26.3-10.2-32.4s-26.2-1.5-32.4 10.2L262.1 288.3c-2-.2-4-.3-6.1-.3c-35.3 0-64 28.7-64 64s28.7 64 64 64s64-28.7 64-64z\" />\n </svg>\n);\n\n/**\n * Nodes icon for \"semantic_model\" resource type\n */\nexport const IconSemanticModel: IconComponent = (props) => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 512 512\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n {...props}\n >\n <path d=\"M418.4 157.9c35.3-8.3 61.6-40 61.6-77.9c0-44.2-35.8-80-80-80c-43.4 0-78.7 34.5-80 77.5L136.2 151.1C121.7 136.8 101.9 128 80 128c-44.2 0-80 35.8-80 80s35.8 80 80 80c12.2 0 23.8-2.7 34.1-7.6L259.7 407.8c-2.4 7.6-3.7 15.8-3.7 24.2c0 44.2 35.8 80 80 80s80-35.8 80-80c0-27.7-14-52.1-35.4-66.4l37.8-207.7zM156.3 232.2c2.2-6.9 3.5-14.2 3.7-21.7l183.8-73.5c3.6 3.5 7.4 6.7 11.6 9.5L317.6 354.1c-5.5 1.3-10.8 3.1-15.8 5.5L156.3 232.2z\" />\n </svg>\n);\n\n// =============================================================================\n// STYLING FUNCTIONS\n// =============================================================================\n\n/**\n * Get icon and colors for a change status\n *\n * @param changeStatus - The change status (added, removed, modified)\n * @param isDark - Whether dark mode is active\n * @returns Object containing color values and icon component\n *\n * @example\n * ```tsx\n * const { color, icon: Icon } = getIconForChangeStatus(\"added\");\n * return <Icon style={{ color }} />;\n * ```\n */\nexport function getIconForChangeStatus(\n changeStatus?: ChangeStatus,\n isDark?: boolean,\n): ChangeStatusStyle {\n if (changeStatus === \"added\") {\n return {\n color: colors.green[500],\n hexColor: colors.green[500],\n backgroundColor: isDark ? colors.green[900] : colors.green[100],\n hexBackgroundColor: isDark ? colors.green[900] : colors.green[100],\n icon: IconAdded,\n };\n }\n\n if (changeStatus === \"removed\") {\n return {\n color: colors.red[500],\n hexColor: colors.red[500],\n backgroundColor: isDark ? colors.red[950] : colors.red[200],\n hexBackgroundColor: isDark ? colors.red[950] : colors.red[200],\n icon: IconRemoved,\n };\n }\n\n if (changeStatus === \"modified\") {\n return {\n color: colors.amber[500],\n hexColor: colors.amber[500],\n backgroundColor: isDark ? colors.amber[900] : colors.amber[100],\n hexBackgroundColor: isDark ? colors.amber[900] : colors.amber[100],\n icon: IconModified,\n };\n }\n\n // Default: no change\n return {\n color: colors.neutral[500],\n hexColor: colors.neutral[500],\n backgroundColor: isDark ? colors.neutral[700] : colors.white,\n hexBackgroundColor: isDark ? colors.neutral[700] : colors.white,\n icon: undefined,\n };\n}\n\n/**\n * Get icon and color for a resource type\n *\n * @param resourceType - The resource type (model, source, seed, etc.)\n * @returns Object containing color and icon component\n *\n * @example\n * ```tsx\n * const { color, icon: Icon } = getIconForResourceType(\"model\");\n * return Icon ? <Icon style={{ color }} /> : null;\n * ```\n */\nexport function getIconForResourceType(\n resourceType?: string,\n): ResourceTypeStyle {\n switch (resourceType) {\n case \"model\":\n return {\n color: colors.cyan[200],\n icon: IconModel,\n };\n case \"source\":\n return {\n color: colors.green[300],\n icon: IconSource,\n };\n case \"seed\":\n return {\n color: colors.green[500],\n icon: IconSeed,\n };\n case \"snapshot\":\n return {\n color: colors.green[500],\n icon: IconSnapshot,\n };\n case \"metric\":\n return {\n color: colors.rose[200],\n icon: IconMetric,\n };\n case \"exposure\":\n return {\n color: colors.rose[200],\n icon: IconExposure,\n };\n case \"semantic_model\":\n return {\n color: colors.rose[400],\n icon: IconSemanticModel,\n };\n default:\n return {\n color: \"inherit\",\n icon: undefined,\n };\n }\n}\n\n// =============================================================================\n// STYLE CONSTANTS\n// =============================================================================\n\n/**\n * Pre-defined colors for change status (for direct usage without function call)\n */\nexport const changeStatusColors: Record<ChangeStatus | \"unchanged\", string> = {\n added: colors.green[500],\n removed: colors.red[500],\n modified: colors.amber[500],\n unchanged: colors.neutral[500],\n};\n\n/**\n * Pre-defined background colors for change status (light mode)\n */\nexport const changeStatusBackgroundsLight: Record<\n ChangeStatus | \"unchanged\",\n string\n> = {\n added: colors.green[100],\n removed: colors.red[200],\n modified: colors.amber[100],\n unchanged: colors.white,\n};\n\n/**\n * Pre-defined background colors for change status (dark mode)\n */\nexport const changeStatusBackgroundsDark: Record<\n ChangeStatus | \"unchanged\",\n string\n> = {\n added: colors.green[900],\n removed: colors.red[950],\n modified: colors.amber[900],\n unchanged: colors.neutral[700],\n};\n","\"use client\";\n\nimport {\n BaseEdge,\n type Edge,\n EdgeLabelRenderer,\n type EdgeProps,\n getBezierPath,\n} from \"@xyflow/react\";\nimport { memo } from \"react\";\n\nexport type EdgeChangeStatus = \"added\" | \"removed\" | \"modified\" | \"unchanged\";\n\nexport interface LineageEdgeData extends Record<string, unknown> {\n /** Change status for diff visualization */\n changeStatus?: EdgeChangeStatus;\n /** Whether this edge is highlighted */\n isHighlighted?: boolean;\n /** Label to display on edge */\n label?: string;\n}\n\nexport type LineageEdgeType = Edge<LineageEdgeData>;\n\nexport type LineageEdgeProps = EdgeProps<LineageEdgeType>;\n\nconst statusColors: Record<EdgeChangeStatus, string> = {\n added: \"#22c55e\",\n removed: \"#ef4444\",\n modified: \"#f59e0b\",\n unchanged: \"#94a3b8\",\n};\n\nfunction LineageEdgeComponent({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n data,\n selected,\n}: LineageEdgeProps) {\n const changeStatus: EdgeChangeStatus = data?.changeStatus ?? \"unchanged\";\n const isHighlighted = data?.isHighlighted ?? false;\n const label = data?.label;\n\n const [edgePath, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n\n const strokeColor = statusColors[changeStatus];\n const strokeWidth = isHighlighted || selected ? 2.5 : 1.5;\n const strokeOpacity = isHighlighted || selected ? 1 : 0.6;\n\n return (\n <>\n <BaseEdge\n id={id}\n path={edgePath}\n style={{\n stroke: strokeColor,\n strokeWidth,\n opacity: strokeOpacity,\n }}\n />\n {label && (\n <EdgeLabelRenderer>\n <div\n style={{\n position: \"absolute\",\n transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,\n fontSize: 10,\n fontWeight: 500,\n background: \"white\",\n padding: \"2px 4px\",\n borderRadius: 4,\n pointerEvents: \"all\",\n }}\n >\n {label}\n </div>\n </EdgeLabelRenderer>\n )}\n </>\n );\n}\n\nexport const LineageEdge = memo(LineageEdgeComponent);\nLineageEdge.displayName = \"LineageEdge\";\n","\"use client\";\n\n/**\n * @file LineageNode.tsx\n * @description Pure presentation component for displaying nodes in a lineage graph\n *\n * This component is designed to work with @xyflow/react and receives all data via props.\n * It does not perform any data fetching or state management - it is purely presentational.\n *\n * Features:\n * - Change status visualization (added, removed, modified, unchanged)\n * - Selection modes (normal, selecting, action_result)\n * - Interactive checkbox for multi-select\n * - Action tag display for run status\n * - Resource type and change status icons\n * - Hover menu with context actions\n * - Column container support\n *\n * Source: Enhanced from UI package primitive + OSS js/src/components/lineage/GraphNode.tsx\n */\n\nimport Box from \"@mui/material/Box\";\nimport Checkbox from \"@mui/material/Checkbox\";\nimport Stack from \"@mui/material/Stack\";\nimport Tooltip from \"@mui/material/Tooltip\";\nimport Typography from \"@mui/material/Typography\";\nimport { Handle, Position } from \"@xyflow/react\";\nimport { type MouseEvent, memo, type ReactNode, useState } from \"react\";\nimport { getIconForChangeStatus, getIconForResourceType } from \"../styles\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\n/**\n * Change status for node visualization\n */\nexport type NodeChangeStatus = \"added\" | \"removed\" | \"modified\" | \"unchanged\";\n\n/**\n * Selection mode for the node\n */\nexport type SelectMode = \"normal\" | \"selecting\" | \"action_result\";\n\n/**\n * Change category from column-level lineage analysis\n */\nexport type ChangeCategory =\n | \"breaking\"\n | \"non_breaking\"\n | \"partial_breaking\"\n | \"unknown\";\n\n/**\n * Data structure for lineage node\n */\nexport interface LineageNodeData extends Record<string, unknown> {\n /** Display label for the node */\n label: string;\n /** Node type (model, source, seed, etc.) */\n nodeType?: string;\n /** Change status for diff visualization */\n changeStatus?: NodeChangeStatus;\n /** Whether this node is currently selected */\n isSelected?: boolean;\n /** Resource type for icon display */\n resourceType?: string;\n /** Package name */\n packageName?: string;\n /** Whether to show column-level details */\n showColumns?: boolean;\n /** Column data if showing columns */\n columns?: Array<{\n name: string;\n type?: string;\n changeStatus?: NodeChangeStatus;\n }>;\n}\n\n/**\n * Props for LineageNode component\n */\nexport interface LineageNodeProps {\n /** Node ID */\n id: string;\n /** Node data */\n data: LineageNodeData;\n /** Whether the node is selected (from React Flow) */\n selected?: boolean;\n\n // === Interactive Mode Props ===\n /** Enable interactive mode with checkbox */\n interactive?: boolean;\n /** Selection mode */\n selectMode?: SelectMode;\n /** Whether the node is selected (checkbox state) */\n isNodeSelected?: boolean;\n /** Whether the node is focused */\n isFocused?: boolean;\n /** Whether the node is highlighted */\n isHighlighted?: boolean;\n /** Whether to show content (zoom level visibility) */\n showContent?: boolean;\n\n // === Action Display Props ===\n /** Action tag to display (for action_result mode) */\n actionTag?: ReactNode;\n /** Whether to show change analysis mode */\n showChangeAnalysis?: boolean;\n /** Change category text */\n changeCategory?: ChangeCategory;\n /** Runs aggregated display component */\n runsAggregatedTag?: ReactNode;\n\n // === Layout Props ===\n /** Whether node has parent nodes (show left handle) */\n hasParents?: boolean;\n /** Whether node has child nodes (show right handle) */\n hasChildren?: boolean;\n /** Number of columns for column container height */\n columnCount?: number;\n /** Height per column in pixels */\n columnHeight?: number;\n\n // === Theme Props ===\n /** Whether dark mode is active */\n isDark?: boolean;\n\n // === Callbacks ===\n /** Callback when node is clicked */\n onNodeClick?: (nodeId: string) => void;\n /** Callback when node is double-clicked */\n onNodeDoubleClick?: (nodeId: string) => void;\n /** Callback when checkbox is clicked */\n onSelect?: (nodeId: string) => void;\n /** Callback when context menu is requested */\n onContextMenu?: (event: MouseEvent, nodeId: string) => void;\n /** Callback when impact radius button is clicked */\n onShowImpactRadius?: (nodeId: string) => void;\n}\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\nconst CHANGE_CATEGORY_LABELS: Record<ChangeCategory, string> = {\n breaking: \"Breaking\",\n non_breaking: \"Non Breaking\",\n partial_breaking: \"Partial Breaking\",\n unknown: \"Unknown\",\n};\n\nconst DEFAULT_COLUMN_HEIGHT = 28;\n\n// =============================================================================\n// ICONS\n// =============================================================================\n\n/**\n * Kebab menu icon\n */\nconst KebabIcon = () => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 16 16\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M8 3a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm0 6.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm0 6.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z\" />\n </svg>\n);\n\n/**\n * Impact radius icon (dot circle)\n */\nconst ImpactRadiusIcon = () => (\n <svg\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 512 512\"\n height=\"1em\"\n width=\"1em\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M256 56c110.532 0 200 89.451 200 200 0 110.532-89.451 200-200 200-110.532 0-200-89.451-200-200 0-110.532 89.451-200 200-200m0-48C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 168c-44.183 0-80 35.817-80 80s35.817 80 80 80 80-35.817 80-80-35.817-80-80-80z\" />\n </svg>\n);\n\n// =============================================================================\n// HELPER COMPONENTS\n// =============================================================================\n\n/**\n * Node title with tooltip\n */\nfunction NodeTitle({\n name,\n color,\n resourceType,\n}: {\n name: string;\n color: string;\n resourceType?: string;\n}) {\n const tooltipTitle =\n resourceType === \"model\" ? name : `${name} (${resourceType || \"unknown\"})`;\n\n return (\n <Box\n sx={{\n flex: 1,\n color,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n <Tooltip title={tooltipTitle} placement=\"top\">\n <span>{name}</span>\n </Tooltip>\n </Box>\n );\n}\n\n// =============================================================================\n// MAIN COMPONENT\n// =============================================================================\n\n/**\n * LineageNode - Pure presentation component for displaying nodes in a lineage graph\n *\n * This component is designed to be used with @xyflow/react and receives all data via props.\n * It does not perform any data fetching or state management - it is purely presentational.\n *\n * @example Basic usage\n * ```tsx\n * <LineageNode\n * id=\"model.my_model\"\n * data={{\n * label: \"my_model\",\n * nodeType: \"model\",\n * changeStatus: \"modified\",\n * resourceType: \"model\"\n * }}\n * selected={false}\n * onNodeClick={(nodeId) => console.log(\"Clicked:\", nodeId)}\n * />\n * ```\n *\n * @example Interactive mode with selection\n * ```tsx\n * <LineageNode\n * id=\"model.my_model\"\n * data={{ label: \"my_model\", changeStatus: \"added\" }}\n * interactive\n * selectMode=\"selecting\"\n * isNodeSelected={selectedNodes.has(\"model.my_model\")}\n * onSelect={(nodeId) => toggleSelection(nodeId)}\n * />\n * ```\n *\n * @example Action result mode\n * ```tsx\n * <LineageNode\n * id=\"model.my_model\"\n * data={{ label: \"my_model\", changeStatus: \"modified\" }}\n * selectMode=\"action_result\"\n * actionTag={<ActionTag status=\"running\" progress={{ percentage: 0.5 }} />}\n * />\n * ```\n */\nfunction LineageNodeComponent({\n id,\n data,\n selected,\n // Interactive props\n interactive = false,\n selectMode = \"normal\",\n isNodeSelected = false,\n isFocused = false,\n isHighlighted = true,\n showContent = true,\n // Action display props\n actionTag,\n showChangeAnalysis = false,\n changeCategory,\n runsAggregatedTag,\n // Layout props\n hasParents = true,\n hasChildren = true,\n columnCount = 0,\n columnHeight = DEFAULT_COLUMN_HEIGHT,\n // Theme props\n isDark = false,\n // Callbacks\n onNodeClick,\n onNodeDoubleClick,\n onSelect,\n onContextMenu,\n onShowImpactRadius,\n}: LineageNodeProps) {\n const [isHovered, setIsHovered] = useState(false);\n\n const {\n label,\n changeStatus = \"unchanged\",\n isSelected: dataIsSelected,\n resourceType,\n } = data;\n\n // Use isNodeSelected prop, fall back to data.isSelected, then to selected\n const isSelected = isNodeSelected || dataIsSelected || selected || false;\n const showColumns = columnCount > 0;\n const hasAction = selectMode === \"action_result\" && actionTag;\n\n // Get icons and colors\n const {\n icon: IconChangeStatus,\n color: colorChangeStatus,\n backgroundColor: backgroundColorChangeStatus,\n } = getIconForChangeStatus(changeStatus, isDark);\n const { icon: ResourceIcon } = getIconForResourceType(resourceType);\n\n // Calculate styles based on state\n const borderWidth = \"2px\";\n const borderColor = colorChangeStatus;\n\n // Node background color logic\n const nodeBackgroundColor = (() => {\n const paperBg = isDark ? \"#1e1e1e\" : \"#ffffff\";\n\n if (showContent) {\n if (selectMode === \"selecting\") {\n return isSelected ? colorChangeStatus : paperBg;\n }\n if (selectMode === \"action_result\") {\n if (!hasAction) return paperBg;\n return isFocused || isSelected || isHovered\n ? backgroundColorChangeStatus\n : colorChangeStatus;\n }\n return isFocused || isSelected || isHovered\n ? backgroundColorChangeStatus\n : paperBg;\n }\n return isFocused || isSelected || isHovered\n ? colorChangeStatus\n : backgroundColorChangeStatus;\n })();\n\n // Text color logic\n const titleColor = (() => {\n const primaryText = isDark ? \"#ffffff\" : \"#000000\";\n const invertedText = isDark ? \"#000000\" : \"#ffffff\";\n\n if (selectMode === \"selecting\") {\n return isSelected ? invertedText : primaryText;\n }\n if (selectMode === \"action_result\") {\n return hasAction && !isSelected ? invertedText : primaryText;\n }\n return primaryText;\n })();\n\n const iconColor = (() => {\n const primaryText = isDark ? \"#ffffff\" : \"#000000\";\n const invertedText = isDark ? \"#000000\" : \"#ffffff\";\n\n if (selectMode === \"selecting\") {\n return isSelected ? invertedText : primaryText;\n }\n if (selectMode === \"action_result\") {\n return hasAction && !isSelected ? invertedText : primaryText;\n }\n return primaryText;\n })();\n\n const changeStatusIconColor = (() => {\n const primaryText = isDark ? \"#ffffff\" : \"#000000\";\n const invertedText = isDark ? \"#000000\" : \"#ffffff\";\n\n if (selectMode === \"selecting\") {\n return isSelected ? invertedText : colorChangeStatus;\n }\n if (selectMode === \"action_result\") {\n return hasAction && !isSelected ? invertedText : primaryText;\n }\n return colorChangeStatus;\n })();\n\n // Filter for dimming\n const nodeFilter = (() => {\n if (selectMode === \"action_result\") {\n return hasAction ? \"none\" : \"opacity(0.2) grayscale(50%)\";\n }\n return isHighlighted || isFocused || isSelected || isHovered\n ? \"none\"\n : \"opacity(0.2) grayscale(50%)\";\n })();\n\n const handleCheckboxClick = (e: MouseEvent) => {\n if (selectMode === \"action_result\") return;\n e.stopPropagation();\n onSelect?.(id);\n };\n\n const handleContextMenuClick = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(e, id);\n };\n\n const handleImpactRadiusClick = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onShowImpactRadius?.(id);\n };\n\n return (\n <Box\n onClick={() => onNodeClick?.(id)}\n onDoubleClick={() => onNodeDoubleClick?.(id)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n sx={{\n display: \"flex\",\n flexDirection: \"column\",\n width: 300,\n cursor: selectMode === \"selecting\" ? \"pointer\" : \"inherit\",\n transition: \"box-shadow 0.2s ease-in-out\",\n padding: 0,\n filter: nodeFilter,\n }}\n >\n {/* Main node container */}\n <Box\n sx={{\n display: \"flex\",\n borderColor,\n borderWidth,\n borderStyle: \"solid\",\n borderTopLeftRadius: 8,\n borderTopRightRadius: 8,\n borderBottomLeftRadius: showColumns ? 0 : 8,\n borderBottomRightRadius: showColumns ? 0 : 8,\n backgroundColor: nodeBackgroundColor,\n height: 60,\n }}\n >\n {/* Left panel with checkbox */}\n <Box\n sx={{\n display: \"flex\",\n bgcolor: colorChangeStatus,\n padding: interactive ? \"8px\" : \"2px\",\n borderRightWidth: borderWidth,\n borderRightStyle: \"solid\",\n borderColor: selectMode === \"selecting\" ? \"#00000020\" : borderColor,\n alignItems: \"top\",\n visibility: showContent ? \"inherit\" : \"hidden\",\n }}\n >\n {interactive && (\n <Checkbox\n checked={\n (selectMode === \"selecting\" && isSelected) ||\n (selectMode === \"action_result\" && !!hasAction)\n }\n onClick={handleCheckboxClick}\n disabled={selectMode === \"action_result\"}\n size=\"small\"\n sx={{\n padding: 0,\n color: \"inherit\",\n \"&.Mui-checked\": { color: \"inherit\" },\n }}\n />\n )}\n </Box>\n\n {/* Content area */}\n <Box\n sx={{\n display: \"flex\",\n flex: \"1 0 auto\",\n mx: 0.5,\n width: 100,\n flexDirection: \"column\",\n }}\n >\n {/* Title row */}\n <Box\n sx={{\n display: \"flex\",\n width: \"100%\",\n textAlign: \"left\",\n fontWeight: 600,\n flex: 1,\n p: 0.5,\n gap: \"5px\",\n alignItems: \"center\",\n visibility: showContent ? \"inherit\" : \"hidden\",\n }}\n >\n <NodeTitle\n name={label}\n color={titleColor}\n resourceType={resourceType}\n />\n\n {/* Hover actions vs icons */}\n {isHovered ? (\n <>\n {changeStatus === \"modified\" && onShowImpactRadius && (\n <Tooltip title=\"Show Impact Radius\" placement=\"top\">\n <Box\n onClick={handleImpactRadiusClick}\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n color: \"text.secondary\",\n \"&:hover\": { color: \"text.primary\" },\n }}\n >\n <ImpactRadiusIcon />\n </Box>\n </Tooltip>\n )}\n {onContextMenu && (\n <Box\n onClick={handleContextMenuClick}\n sx={{\n cursor: \"pointer\",\n color: \"text.secondary\",\n \"&:hover\": { color: \"text.primary\" },\n }}\n >\n <KebabIcon />\n </Box>\n )}\n </>\n ) : (\n <>\n {ResourceIcon && (\n <Box sx={{ fontSize: 16, color: iconColor }}>\n <ResourceIcon />\n </Box>\n )}\n {changeStatus && IconChangeStatus && (\n <Box sx={{ color: changeStatusIconColor }}>\n <IconChangeStatus />\n </Box>\n )}\n </>\n )}\n </Box>\n\n {/* Bottom row - action tags, change analysis, or runs aggregated */}\n <Box\n sx={{\n display: \"flex\",\n flex: \"1 0 auto\",\n mx: 0.5,\n flexDirection: \"column\",\n paddingBottom: 0.5,\n visibility: showContent ? \"inherit\" : \"hidden\",\n }}\n >\n <Stack direction=\"row\" spacing={1}>\n {actionTag ? (\n <>\n <Box sx={{ flexGrow: 1 }} />\n {actionTag}\n </>\n ) : showChangeAnalysis && changeCategory ? (\n <Typography\n sx={{\n height: 20,\n color: \"text.secondary\",\n fontSize: \"9pt\",\n margin: 0,\n fontWeight: 600,\n }}\n >\n {CHANGE_CATEGORY_LABELS[changeCategory]}\n </Typography>\n ) : selectMode !== \"action_result\" && runsAggregatedTag ? (\n runsAggregatedTag\n ) : null}\n </Stack>\n </Box>\n </Box>\n </Box>\n\n {/* Column container */}\n {showColumns && (\n <Box\n sx={{\n p: \"10px 10px\",\n borderColor,\n borderWidth,\n borderStyle: \"solid\",\n borderTopWidth: 0,\n borderBottomLeftRadius: 8,\n borderBottomRightRadius: 8,\n }}\n >\n <Box\n sx={{\n height: `${columnCount * columnHeight}px`,\n overflow: \"auto\",\n }}\n />\n </Box>\n )}\n\n {/* Handles */}\n {hasParents && (\n <Handle type=\"target\" position={Position.Left} isConnectable={false} />\n )}\n {hasChildren && (\n <Handle type=\"source\" position={Position.Right} isConnectable={false} />\n )}\n </Box>\n );\n}\n\nexport const LineageNode = memo(LineageNodeComponent);\nLineageNode.displayName = \"LineageNode\";\n","\"use client\";\n\nimport {\n Background,\n Controls,\n type Edge,\n MiniMap,\n type Node,\n ReactFlow,\n useEdgesState,\n useNodesState,\n} from \"@xyflow/react\";\nimport \"@xyflow/react/dist/style.css\";\nimport Box from \"@mui/material/Box\";\nimport { useCallback } from \"react\";\n\nimport { LineageEdge, type LineageEdgeData } from \"./edges\";\nimport { LineageNode, type LineageNodeData } from \"./nodes\";\n\nexport interface LineageCanvasProps {\n /** Nodes to display */\n nodes: Node<LineageNodeData>[];\n /** Edges connecting nodes */\n edges: Edge<LineageEdgeData>[];\n /** Callback when node selection changes */\n onNodeSelect?: (nodeId: string | null) => void;\n /** Callback when node is double-clicked */\n onNodeDoubleClick?: (nodeId: string) => void;\n /** Whether to show minimap */\n showMiniMap?: boolean;\n /** Whether to show controls */\n showControls?: boolean;\n /** Whether to show background grid */\n showBackground?: boolean;\n /** Height of the graph container */\n height?: number | string;\n /** Whether the graph is interactive */\n interactive?: boolean;\n}\n\nconst nodeTypes = {\n lineageNode: LineageNode,\n};\n\nconst edgeTypes = {\n lineageEdge: LineageEdge,\n};\n\nexport function LineageCanvas({\n nodes: initialNodes,\n edges: initialEdges,\n onNodeSelect,\n onNodeDoubleClick,\n showMiniMap = true,\n showControls = true,\n showBackground = true,\n height = 600,\n interactive = true,\n}: LineageCanvasProps) {\n const [nodes, _setNodes, onNodesChange] = useNodesState(initialNodes);\n const [edges, _setEdges, onEdgesChange] = useEdgesState(initialEdges);\n\n const handleNodeClick = useCallback(\n (_event: React.MouseEvent, node: Node) => {\n onNodeSelect?.(node.id);\n },\n [onNodeSelect],\n );\n\n const handlePaneClick = useCallback(() => {\n onNodeSelect?.(null);\n }, [onNodeSelect]);\n\n const handleNodeDoubleClick = useCallback(\n (_event: React.MouseEvent, node: Node) => {\n onNodeDoubleClick?.(node.id);\n },\n [onNodeDoubleClick],\n );\n\n return (\n <Box sx={{ width: \"100%\", height }}>\n <ReactFlow\n nodes={nodes}\n edges={edges}\n onNodesChange={interactive ? onNodesChange : undefined}\n onEdgesChange={interactive ? onEdgesChange : undefined}\n onNodeClick={handleNodeClick}\n onNodeDoubleClick={handleNodeDoubleClick}\n onPaneClick={handlePaneClick}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n fitView\n nodesDraggable={interactive}\n nodesConnectable={false}\n elementsSelectable={interactive}\n >\n {showBackground && <Background />}\n {showControls && <Controls />}\n {showMiniMap && (\n <MiniMap\n nodeColor={(node) => {\n const data = node.data as LineageNodeData;\n switch (data.changeStatus) {\n case \"added\":\n return \"#22c55e\";\n case \"removed\":\n return \"#ef4444\";\n case \"modified\":\n return \"#f59e0b\";\n default:\n return \"#94a3b8\";\n }\n }}\n />\n )}\n </ReactFlow>\n </Box>\n );\n}\n","\"use client\";\n\nimport { useTheme as useMuiTheme } from \"@mui/material/styles\";\nimport { useEffect, useState } from \"react\";\nimport { useRecceThemeOptional } from \"../providers/contexts/ThemeContext\";\nimport { colors } from \"../theme/colors\";\nimport { useIsDark } from \"./useIsDark\";\n\n/**\n * Theme-aware color utility hook\n *\n * Returns a consistent set of colors based on the current theme mode.\n *\n * **Dual-Context Support:**\n * This hook works in two contexts:\n * 1. **With RecceProvider** (recce-cloud-infra): Uses ThemeContext for theme detection\n * 2. **Without RecceProvider** (Recce OSS with next-themes): Falls back to useIsDark\n * which uses DOM class detection (.dark on <html>)\n *\n * This allows @datarecce/ui components to work in both environments without\n * requiring the host application to wrap everything in RecceProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { isDark, background, text, border } = useThemeColors();\n *\n * return (\n * <Box sx={{\n * bgcolor: background.paper,\n * color: text.primary,\n * borderColor: border.default,\n * }}>\n * Content\n * </Box>\n * );\n * }\n * ```\n */\nexport function useThemeColors() {\n const muiTheme = useMuiTheme();\n // Try context first (returns null if not in RecceProvider)\n const themeContext = useRecceThemeOptional();\n // Fallback to useIsDark which has DOM class detection\n const isDarkFallback = useIsDark();\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n // Determine dark mode: prefer context if available, otherwise use fallback\n const isDark = mounted\n ? themeContext\n ? themeContext.resolvedMode === \"dark\"\n : isDarkFallback\n : false;\n\n return {\n /** Whether the current theme is dark mode */\n isDark,\n\n /** MUI theme object for direct access when needed */\n theme: muiTheme,\n\n /** Background colors */\n background: {\n /** Default page background */\n default: isDark ? colors.neutral[900] : colors.white,\n /** Paper/card background */\n paper: isDark ? colors.neutral[800] : colors.white,\n /** Subtle background for slight elevation (e.g., hover states, inputs) */\n subtle: isDark ? colors.neutral[800] : colors.neutral[50],\n /** Emphasized background for higher contrast areas */\n emphasized: isDark ? colors.neutral[700] : colors.neutral[100],\n },\n\n /** Text colors */\n text: {\n /** Primary text color */\n primary: isDark ? colors.neutral[50] : colors.neutral[900],\n /** Secondary/muted text color */\n secondary: isDark ? colors.neutral[400] : colors.neutral[600],\n /** Disabled text color */\n disabled: isDark ? colors.neutral[500] : colors.neutral[400],\n /** Inverted text (for use on dark backgrounds in light mode, etc.) */\n inverted: isDark ? colors.neutral[900] : colors.neutral[50],\n },\n\n /** Border colors */\n border: {\n /** Light border for subtle separations */\n light: isDark ? colors.neutral[700] : colors.neutral[200],\n /** Default border color */\n default: isDark ? colors.neutral[600] : colors.neutral[300],\n /** Strong border for emphasis */\n strong: isDark ? colors.neutral[500] : colors.neutral[400],\n },\n\n /** Status/semantic colors */\n status: {\n /** Added/success backgrounds */\n added: {\n bg: isDark ? colors.green[900] : colors.green[100],\n text: isDark ? colors.neutral[50] : colors.neutral[900],\n },\n /** Removed/error backgrounds */\n removed: {\n bg: isDark ? colors.red[950] : colors.red[200],\n text: isDark ? colors.neutral[50] : colors.neutral[900],\n },\n /** Modified/warning backgrounds */\n modified: {\n bg: isDark ? colors.yellow[900] : colors.amber[100],\n text: isDark ? colors.neutral[50] : colors.neutral[900],\n },\n },\n\n /** Interactive element colors */\n interactive: {\n /** Hover state background */\n hover: isDark ? colors.neutral[700] : colors.neutral[100],\n /** Active/pressed state background */\n active: isDark ? colors.neutral[600] : colors.neutral[200],\n /** Focus ring color */\n focus: colors.iochmara[500],\n },\n };\n}\n\nexport type ThemeColors = ReturnType<typeof useThemeColors>;\n"],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+
2
+ import * as _mui_material_styles0 from "@mui/material/styles";
3
+
4
+ //#region src/hooks/useThemeColors.d.ts
5
+
6
+ /**
7
+ * Theme-aware color utility hook
8
+ *
9
+ * Returns a consistent set of colors based on the current theme mode.
10
+ *
11
+ * **Dual-Context Support:**
12
+ * This hook works in two contexts:
13
+ * 1. **With RecceProvider** (recce-cloud-infra): Uses ThemeContext for theme detection
14
+ * 2. **Without RecceProvider** (Recce OSS with next-themes): Falls back to useIsDark
15
+ * which uses DOM class detection (.dark on <html>)
16
+ *
17
+ * This allows @datarecce/ui components to work in both environments without
18
+ * requiring the host application to wrap everything in RecceProvider.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * function MyComponent() {
23
+ * const { isDark, background, text, border } = useThemeColors();
24
+ *
25
+ * return (
26
+ * <Box sx={{
27
+ * bgcolor: background.paper,
28
+ * color: text.primary,
29
+ * borderColor: border.default,
30
+ * }}>
31
+ * Content
32
+ * </Box>
33
+ * );
34
+ * }
35
+ * ```
36
+ */
37
+ declare function useThemeColors(): {
38
+ /** Whether the current theme is dark mode */
39
+ isDark: boolean;
40
+ /** MUI theme object for direct access when needed */
41
+ theme: _mui_material_styles0.Theme;
42
+ /** Background colors */
43
+ background: {
44
+ /** Default page background */
45
+ default: "#FFFFFF" | "#171717";
46
+ /** Paper/card background */
47
+ paper: "#FFFFFF" | "#262626";
48
+ /** Subtle background for slight elevation (e.g., hover states, inputs) */
49
+ subtle: "#FAFAFA" | "#262626";
50
+ /** Emphasized background for higher contrast areas */
51
+ emphasized: "#F5F5F5" | "#404040";
52
+ };
53
+ /** Text colors */
54
+ text: {
55
+ /** Primary text color */
56
+ primary: "#FAFAFA" | "#171717";
57
+ /** Secondary/muted text color */
58
+ secondary: "#A3A3A3" | "#525252";
59
+ /** Disabled text color */
60
+ disabled: "#A3A3A3" | "#737373";
61
+ /** Inverted text (for use on dark backgrounds in light mode, etc.) */
62
+ inverted: "#FAFAFA" | "#171717";
63
+ };
64
+ /** Border colors */
65
+ border: {
66
+ /** Light border for subtle separations */
67
+ light: "#E5E5E5" | "#404040";
68
+ /** Default border color */
69
+ default: "#D4D4D4" | "#525252";
70
+ /** Strong border for emphasis */
71
+ strong: "#A3A3A3" | "#737373";
72
+ };
73
+ /** Status/semantic colors */
74
+ status: {
75
+ /** Added/success backgrounds */
76
+ added: {
77
+ bg: "#DCFCE7" | "#14532D";
78
+ text: "#FAFAFA" | "#171717";
79
+ };
80
+ /** Removed/error backgrounds */
81
+ removed: {
82
+ bg: "#FECACA" | "#450A0A";
83
+ text: "#FAFAFA" | "#171717";
84
+ };
85
+ /** Modified/warning backgrounds */
86
+ modified: {
87
+ bg: "#FEF3C7" | "#713F12";
88
+ text: "#FAFAFA" | "#171717";
89
+ };
90
+ };
91
+ /** Interactive element colors */
92
+ interactive: {
93
+ /** Hover state background */
94
+ hover: "#F5F5F5" | "#404040";
95
+ /** Active/pressed state background */
96
+ active: "#E5E5E5" | "#525252";
97
+ /** Focus ring color */
98
+ focus: "#3182CE";
99
+ };
100
+ };
101
+ type ThemeColors = ReturnType<typeof useThemeColors>;
102
+ //#endregion
103
+ export { useThemeColors as n, ThemeColors as t };
104
+ //# sourceMappingURL=useThemeColors-DHEroo8f.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useThemeColors-DHEroo8f.d.ts","names":[],"sources":["../src/hooks/useThemeColors.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAuCA;AA2FA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA3FgB,cAAA,CAAA;;;;SAAc,qBAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2FlB,WAAA,GAAc,kBAAkB"}
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import e from"axios";async function t(t=e){try{return(await t.get(`/api/users`)).data}catch(e){throw console.error(`Error fetching user data:`,e),e}}async function n(t){try{return(await e.get(`https://api.github.com/user/${t}`)).data.avatar_url}catch(e){return console.warn(`Failed to fetch GitHub avatar:`,e),null}}export{t as n,n as t};
3
+ //# sourceMappingURL=user-DMT7E0fc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-DMT7E0fc.js","names":[],"sources":["../src/lib/api/user.ts"],"sourcesContent":["import axios, { AxiosInstance, AxiosResponse } from \"axios\";\n\nexport interface User {\n id: string;\n login: string;\n login_type: string;\n email: string;\n onboarding_state: string;\n}\n\ninterface GitHubUser {\n login: string;\n id: number;\n avatar_url: string;\n}\n\nexport async function fetchUser(client: AxiosInstance = axios): Promise<User> {\n try {\n const response = await client.get<never, AxiosResponse<User>>(\"/api/users\");\n return response.data;\n } catch (error) {\n if (process.env.NODE_ENV !== \"test\") {\n console.error(\"Error fetching user data:\", error);\n }\n throw error;\n }\n}\n\nexport async function fetchGitHubAvatar(\n userId: string,\n): Promise<string | null> {\n try {\n const response = await axios.get<GitHubUser>(\n `https://api.github.com/user/${userId}`,\n );\n return response.data.avatar_url;\n } catch (error) {\n if (process.env.NODE_ENV !== \"test\") {\n console.warn(\"Failed to fetch GitHub avatar:\", error);\n }\n return null;\n }\n}\n"],"mappings":";qBAgBA,eAAsB,EAAU,EAAwB,EAAsB,CAC5E,GAAI,CAEF,OADiB,MAAM,EAAO,IAAgC,aAAa,EAC3D,WACT,EAAO,CAId,MAFE,QAAQ,MAAM,4BAA6B,EAAM,CAE7C,GAIV,eAAsB,EACpB,EACwB,CACxB,GAAI,CAIF,OAHiB,MAAM,EAAM,IAC3B,+BAA+B,IAChC,EACe,KAAK,iBACd,EAAO,CAId,OAFE,QAAQ,KAAK,iCAAkC,EAAM,CAEhD"}
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import{a as e,i as t,l as n,r,t as i,u as a}from"./keepAlive-CEzyrDfg.js";import{useQuery as o}from"@tanstack/react-query";import s from"axios";import{createContext as c,useCallback as l,useContext as u,useEffect as d,useMemo as f,useRef as p,useState as m}from"react";import{jsx as h,jsxs as g}from"react/jsx-runtime";import _ from"lodash/throttle";const v=c({runAction:()=>void 0,showRunId:()=>void 0,isRunResultOpen:!1,closeRunResult:()=>void 0,isHistoryOpen:!1,closeHistory:()=>void 0,showHistory:()=>void 0,setHistoryOpen:()=>void 0,clearRunResult:()=>void 0});v.displayName=`RecceActionContext`;function y({children:e,onRunAction:t,onShowRunId:n,initialRunId:r,initialHistoryOpen:i=!1}){let[a,o]=m(!!r),[s,c]=m(r),[u,d]=m(i),p=l(()=>{o(!1)},[]),g=l(()=>{c(void 0),o(!1)},[]),_=l(()=>{d(!0)},[]),y=l(()=>{d(!1)},[]),b=l((e,t)=>{c(e),o(!0),n?.(e,t)},[n]),x=l(async(e,n,r)=>{if(!t){console.warn(`RecceActionProvider: onRunAction not provided, cannot execute run`);return}let i=await t(e,n,r);typeof i==`string`&&b(i)},[t,b]),S=f(()=>({runAction:x,runId:s,showRunId:b,isRunResultOpen:a,closeRunResult:p,isHistoryOpen:u,closeHistory:y,showHistory:_,setHistoryOpen:d,clearRunResult:g}),[x,s,b,a,p,u,y,_,g]);return h(v.Provider,{value:S,children:e})}function b(){return u(v)}const x={mode:null,disableSaveToFile:!1,disableExportStateFile:!1,disableImportStateFile:!1,disableUpdateChecklist:!1,disableDatabaseQuery:!1,disableViewActionDropdown:!1,disableNodeActionDropdown:!1,disableShare:!1},S={singleEnv:!1,authed:!1,lifetimeExpiredAt:void 0,featureToggles:x,shareUrl:void 0,sessionId:void 0},C=s.create();function w(){let t=n()?.apiClient??C;return o({queryKey:a.instanceInfo(),queryFn:()=>e(t)})}const T=c(S);T.displayName=`RecceInstanceInfoContext`;function E({children:e}){let{data:t,isLoading:n}=w(),[r,i]=m(x),[a,o]=m(!1),[s,c]=m(!1),[l,u]=m(),[d,f]=m(),[p,g]=m(),[_,v]=m(t);if(!n&&t&&t!==_){v(t),o(t.single_env),c(t.authed),f(t.share_url),g(t.session_id),t.lifetime_expired_at&&(u(new Date(t.lifetime_expired_at)),console.log(`lifetime expired at`,t.lifetime_expired_at));let e={...x};t.server_mode===`read-only`?(e.mode=`read only`,e.disableSaveToFile=!0,e.disableExportStateFile=!0,e.disableImportStateFile=!0,e.disableUpdateChecklist=!0,e.disableDatabaseQuery=!0,e.disableViewActionDropdown=!0,e.disableNodeActionDropdown=!0,e.disableShare=!0):t.server_mode===`preview`&&(e.mode=`metadata only`,e.disableSaveToFile=!0,e.disableExportStateFile=!0,e.disableImportStateFile=!0,e.disableUpdateChecklist=!1,e.disableDatabaseQuery=!0,e.disableViewActionDropdown=!1,e.disableNodeActionDropdown=!1,e.disableShare=!0),t.single_env&&(e.disableUpdateChecklist=!0,e.disableShare=!0),t.cloud_instance&&(e.disableShare=!0),i(e)}return h(T.Provider,{value:{featureToggles:r,singleEnv:a,authed:s,lifetimeExpiredAt:l,shareUrl:d,sessionId:p},children:e})}function D(){return u(T)}const O=c(void 0);function k(){return u(O)??null}const A=s.create();function j(){return typeof window<`u`&&!!window.RECCE_DEBUG_IDLE}function M(e,t){j()&&(t?console.log(e,t):console.log(e))}const N={ACTIVITY_EVENTS:[`focus`,`mousemove`,`keydown`,`scroll`],EVENT_THROTTLE_MS:150};function P(){let{data:e,isLoading:t,isError:i}=w(),a=k()?.isDisconnected??!1,o=n()?.apiClient??A,s=e?.idle_timeout,c=s!==void 0&&s>0&&!a;M(`[Idle Detection] Instance info`,{isLoading:t,isError:i,hasIdleTimeout:s!==void 0,idleTimeout:s===void 0?`not configured`:`${s}s`,isDisconnected:a,isEnabled:c});let u=l(async()=>{document.hidden||await r(o)&&M(`[Idle Detection] Keep-alive sent successfully`,{timestamp:new Date().toISOString()})},[o]),p=l(e=>{c&&!document.hidden&&(M(`[Idle Detection] Activity detected`,{event:e.type,tabActive:!document.hidden}),u())},[c,u]),m=l(()=>{c&&(document.hidden||(M(`[Idle Detection] Tab became active`,{timestamp:new Date().toISOString()}),u()))},[c,u]),h=f(()=>_(p,N.EVENT_THROTTLE_MS,{leading:!0,trailing:!0}),[p]);d(()=>{if(!c){M(`[Idle Detection] Disabled`,{idleTimeout:s,reason:s===void 0?`idle_timeout not configured on server`:s===0?`idle_timeout is 0`:`disconnected`});return}return M(`[Idle Detection] Initialized`,{enabled:!0,idleTimeout:`${s}s`,eventThrottle:`${N.EVENT_THROTTLE_MS}ms`,apiThrottle:`3s (axios layer)`,monitoredEvents:N.ACTIVITY_EVENTS.join(`, `)}),N.ACTIVITY_EVENTS.forEach(e=>{window.addEventListener(e,h,{passive:!0})}),document.addEventListener(`visibilitychange`,m),()=>{M(`[Idle Detection] Cleanup - removing event listeners`),N.ACTIVITY_EVENTS.forEach(e=>{window.removeEventListener(e,h)}),document.removeEventListener(`visibilitychange`,m),h.cancel()}},[c,h,m,s])}function F({children:e}){let{data:n}=w(),r=p(Date.now()),[a,o]=m(null),[s,c]=m(!1),u=n?.idle_timeout??null,f=u!==null&&u>0,_=p(f);d(()=>{_.current=f},[f]),d(()=>{if(!f){t(null);return}t(e=>{_.current&&(r.current=e)});let e=i();return e>0&&(r.current=e),()=>{t(null)}},[f]);let v=l(()=>{c(!0)},[]),y=l(()=>{c(!1),r.current=Date.now()},[]);return d(()=>{if(!f||u===null){o(null);return}if(s)return;let e=()=>{let e=(Date.now()-r.current)/1e3;o(Math.max(0,u-e))};e();let t=setInterval(e,1e3);return()=>{clearInterval(t)}},[f,u,s]),g(O.Provider,{value:{remainingSeconds:a,idleTimeout:u,isEnabled:f,setDisconnected:v,resetConnection:y,isDisconnected:s},children:[h(I,{}),e]})}function I(){return P(),null}function L(){let e=u(O);if(!e)throw Error(`useIdleTimeout must be used within IdleTimeoutProvider`);return e}const R=c({isActionAvailable:()=>!0,isDemoSite:!1,isLoading:!0});R.displayName=`RecceLineageGraphContext`;function z({children:e,lineageGraph:t,envInfo:n,reviewMode:r,cloudMode:i,fileMode:a,fileName:o,isDemoSite:s=!1,isCodespace:c,isLoading:u,error:d,supportTasks:p,onRefetchLineageGraph:m,runsAggregated:g,onRefetchRunsAggregated:_}){let v=l(e=>p?p[e]??!0:!0,[p]),y=f(()=>({lineageGraph:t,envInfo:n,reviewMode:r,cloudMode:i,fileMode:a,fileName:o,isDemoSite:s,isCodespace:c,isLoading:u,error:d,supportTasks:p,retchLineageGraph:m,isActionAvailable:v,runsAggregated:g,refetchRunsAggregated:_}),[t,n,r,i,a,o,s,c,u,d,p,m,v,g,_]);return h(R.Provider,{value:y,children:e})}function B(){return u(R)}function V(){let{runsAggregated:e,refetchRunsAggregated:t}=B();return[e,t]}function H(e){return e.type===`lineageGraphNode`}function U(e){return e.type===`lineageGraphColumnNode`}const W=20;function G(...e){let t=new Set;for(let n of e)for(let e of n)t.add(e);return t}function K(...e){if(e.length===0)return new Set;let t=new Set(e[0]);for(let n of e)t=new Set([...t].filter(e=>n.has(e)));return t}function q(e,t,n=1e3){let r=new Set,i={},a=(e,n)=>{if(n<0||i[e]!=null&&i[e]>=n)return;i[e]=n;let o=t(e);for(let e of o)a(e,n-1);r.add(e)};for(let t of e)a(t,n);return r}function J(e,t,n){let r={},i={},a=(e,t)=>({id:e,data:{id:e,name:e,from:t,data:{base:void 0,current:void 0},parents:{},children:{}},type:`lineageGraphNode`});for(let[t,n]of Object.entries(e.nodes))r[t]=a(t,`base`),n&&(r[t].data.data.base=n,r[t].data.name=n.name,r[t].data.resourceType=n.resource_type,r[t].data.packageName=n.package_name);for(let[e,n]of Object.entries(t.nodes))r[e]?r[e].data.from=`both`:r[e]=a(e,`current`),n&&(r[e].data.data.current=t.nodes[e],r[e].data.name=n.name,r[e].data.resourceType=n.resource_type,r[e].data.packageName=n.package_name);for(let[t,n]of Object.entries(e.parent_map))for(let e of n){let n=r[t],a=r[e],o=`${e}_${t}`;if(!n||!a)continue;i[o]={id:o,source:a.id,target:n.id,data:{from:`base`}};let s=i[o];n.data.parents[e]=s,a.data.children[t]=s}for(let[e,n]of Object.entries(t.parent_map))for(let t of n){let n=r[e],a=r[t],o=`${t}_${e}`;if(!n||!a)continue;i[o]?.data&&i[o].data?i[o].data.from=`both`:i[o]={id:o,source:a.id,target:n.id,data:{from:`current`}};let s=i[o];n.data.parents[t]=s,a.data.children[e]=s}let o=[];for(let[e,t]of Object.entries(r)){let r=n?.[e];if(r)t.data.changeStatus=r.change_status,r.change&&(t.data.change={category:r.change.category,columns:r.change.columns}),o.push(e);else if(t.data.from===`base`)t.data.changeStatus=`removed`,o.push(t.id);else if(t.data.from===`current`)t.data.changeStatus=`added`,o.push(t.id);else{let e=t.data.data.base?.checksum?.checksum,n=t.data.data.current?.checksum?.checksum;e&&n&&e!==n&&(t.data.changeStatus=`modified`,o.push(t.id))}}for(let e of Object.values(i))e.data&&(e.data.from===`base`?e.data.changeStatus=`removed`:e.data.from===`current`&&(e.data.changeStatus=`added`));return{nodes:r,edges:i,modifiedSet:o,manifestMetadata:{base:e.manifest_metadata??void 0,current:t.manifest_metadata??void 0},catalogMetadata:{base:e.catalog_metadata??void 0,current:t.catalog_metadata??void 0}}}function Y(e,t,n=1e3){return q(t,t=>e.nodes[t]===void 0?[]:Object.keys(e.nodes[t].data.parents),n)}function X(e,t,n=1e3){return q(t,t=>e.nodes[t]===void 0?[]:Object.keys(e.nodes[t].data.children),n)}function Z(e,t){let n=[],r=[];function i(e){return e===`base`?0:e===`current`?2:1}function a(e,t){return i(e.data?.from)-i(t.data?.from)}let o=t===void 0?void 0:new Set(t),s=Object.values(e.nodes).sort(a);for(let e of s)o&&!o.has(e.id)||n.push({id:e.id,position:{x:0,y:0},width:300,height:60,className:`no-track-pii-safe`,data:{...e.data},type:`lineageGraphNode`,targetPosition:`left`,sourcePosition:`right`,style:{width:300,height:60}});let c=Object.values(e.edges).sort(a);for(let e of c)o&&(!o.has(e.source)||!o.has(e.target))||r.push({id:e.id,type:`lineageGraphEdge`,source:e.source,target:e.target,data:{...e.data}});return[n,r]}function Q(e,t,n,r=`LR`){let i=new e.graphlib.Graph;i.setDefaultEdgeLabel(()=>({})),i.setGraph({rankdir:r,ranksep:50,nodesep:30});for(let e of t){if(!H(e))continue;let t=300,n=60;e.style?.height&&e.style.width&&(t=parseInt(String(e.style.width),10),n=parseInt(String(e.style.height),10)),i.setNode(e.id,{width:t,height:n})}for(let e of n)i.setEdge(e.source,e.target);e.layout(i);for(let e of t){if(!H(e))continue;let t=e.style?.width??300,n=e.style?.height??60,r=i.node(e.id);e.position={x:r.x-Number(t)/2,y:r.y-Number(n)/2}}}export{S as C,x as S,b as T,P as _,Q as a,D as b,Z as c,H as d,z as f,L as g,F as h,K as i,G as l,V as m,J as n,X as o,B as p,q as r,Y as s,W as t,U as u,k as v,y as w,w as x,E as y};
3
+ //# sourceMappingURL=utils-CW2skXm_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-CW2skXm_.js","names":["defaultFeatureToggles: RecceFeatureToggles","defaultInstanceInfo: InstanceInfoType","defaultApiClient","visited: Record<string, number | undefined>","nodes: Record<string, LineageGraphNode>","edges: Record<string, LineageGraphEdge>","modifiedSet: string[]","nodes: LineageGraphNode[]","edges: LineageGraphEdge[]"],"sources":["../src/contexts/action/RecceActionContext.tsx","../src/contexts/instance/types.ts","../src/contexts/instance/useRecceInstanceInfo.ts","../src/contexts/instance/RecceInstanceContext.tsx","../src/contexts/idle/types.ts","../src/contexts/idle/useIdleDetection.ts","../src/contexts/idle/IdleTimeoutContext.tsx","../src/contexts/lineage/LineageGraphContext.tsx","../src/contexts/lineage/types.ts","../src/contexts/lineage/utils.ts"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useMemo,\n useState,\n} from \"react\";\nimport type {\n AxiosQueryParams,\n RecceActionContextType,\n RecceActionOptions,\n} from \"./types\";\n\n/**\n * Props for RecceActionProvider\n *\n * This is a props-driven provider - pass your own run execution handler.\n * The provider manages UI state (result pane, history panel) internally.\n */\nexport interface RecceActionProviderProps {\n children: ReactNode;\n\n /**\n * Handler called when a run action is requested.\n * Implement this to submit runs to your backend.\n *\n * @param type - The run type (e.g., \"row_count_diff\", \"value_diff\")\n * @param params - Query parameters for the run\n * @param options - Action options (showForm, trackProps)\n * @returns Promise that resolves to the run ID, or void if handled differently\n */\n onRunAction?: (\n type: string,\n params?: AxiosQueryParams,\n options?: RecceActionOptions,\n ) => Promise<string | undefined> | string | undefined;\n\n /**\n * Handler called when a run result should be shown.\n * Called by showRunId when displaying a specific run.\n *\n * @param runId - The run ID to display\n * @param refreshHistory - Whether to refresh the history list\n */\n onShowRunId?: (runId: string, refreshHistory?: boolean) => void;\n\n /** Initial run ID to display (optional) */\n initialRunId?: string;\n\n /** Initial state for history panel (default: false) */\n initialHistoryOpen?: boolean;\n}\n\nconst defaultContext: RecceActionContextType = {\n runAction: () => void 0,\n showRunId: () => void 0,\n isRunResultOpen: false,\n closeRunResult: () => void 0,\n isHistoryOpen: false,\n closeHistory: () => void 0,\n showHistory: () => void 0,\n setHistoryOpen: () => void 0,\n clearRunResult: () => void 0,\n};\n\nconst RecceActionContext =\n createContext<RecceActionContextType>(defaultContext);\nRecceActionContext.displayName = \"RecceActionContext\";\n\n/**\n * Provider for run action context.\n *\n * This is a props-driven provider designed for library consumers.\n * Pass your own `onRunAction` handler to execute runs.\n *\n * @example\n * ```tsx\n * const handleRunAction = async (type, params, options) => {\n * const response = await api.submitRun(type, params);\n * return response.run_id;\n * };\n *\n * <RecceActionProvider onRunAction={handleRunAction}>\n * <LineageView />\n * </RecceActionProvider>\n * ```\n */\nexport function RecceActionProvider({\n children,\n onRunAction,\n onShowRunId,\n initialRunId,\n initialHistoryOpen = false,\n}: RecceActionProviderProps) {\n // Run result pane state\n const [isRunResultOpen, setRunResultOpen] = useState(!!initialRunId);\n const [runId, setRunId] = useState<string | undefined>(initialRunId);\n\n // History panel state\n const [isHistoryOpen, setHistoryOpen] = useState(initialHistoryOpen);\n\n // Close run result pane\n const closeRunResult = useCallback(() => {\n setRunResultOpen(false);\n }, []);\n\n // Clear run result and close pane\n const clearRunResult = useCallback(() => {\n setRunId(undefined);\n setRunResultOpen(false);\n }, []);\n\n // History panel controls\n const showHistory = useCallback(() => {\n setHistoryOpen(true);\n }, []);\n\n const closeHistory = useCallback(() => {\n setHistoryOpen(false);\n }, []);\n\n // Show a specific run result\n const showRunId = useCallback(\n (newRunId: string, refreshHistory?: boolean) => {\n setRunId(newRunId);\n setRunResultOpen(true);\n onShowRunId?.(newRunId, refreshHistory);\n },\n [onShowRunId],\n );\n\n // Execute a run action\n const runAction = useCallback(\n async (\n type: string,\n params?: AxiosQueryParams,\n options?: RecceActionOptions,\n ) => {\n if (!onRunAction) {\n console.warn(\n \"RecceActionProvider: onRunAction not provided, cannot execute run\",\n );\n return;\n }\n\n const result = await onRunAction(type, params, options);\n\n // If the handler returns a run ID, show the result\n if (typeof result === \"string\") {\n showRunId(result);\n }\n },\n [onRunAction, showRunId],\n );\n\n const contextValue = useMemo<RecceActionContextType>(\n () => ({\n runAction,\n runId,\n showRunId,\n isRunResultOpen,\n closeRunResult,\n isHistoryOpen,\n closeHistory,\n showHistory,\n setHistoryOpen,\n clearRunResult,\n }),\n [\n runAction,\n runId,\n showRunId,\n isRunResultOpen,\n closeRunResult,\n isHistoryOpen,\n closeHistory,\n showHistory,\n clearRunResult,\n ],\n );\n\n return (\n <RecceActionContext.Provider value={contextValue}>\n {children}\n </RecceActionContext.Provider>\n );\n}\n\n/**\n * Hook to access the RecceAction context.\n *\n * @returns RecceActionContextType with run action methods and state\n */\nexport function useRecceActionContext(): RecceActionContextType {\n return useContext(RecceActionContext);\n}\n","\"use client\";\n\n/**\n * Feature mode for the Recce instance.\n * - \"read only\": No modifications allowed\n * - \"metadata only\": Database queries disabled\n * - null: Full functionality enabled\n */\nexport type RecceFeatureMode = \"read only\" | \"metadata only\" | null;\n\n/**\n * Feature toggles that control what actions are available in the UI.\n * These are derived from the server's instance info based on server mode.\n */\nexport interface RecceFeatureToggles {\n /** Current feature mode based on server_mode */\n mode: RecceFeatureMode;\n /** Disable saving state to file */\n disableSaveToFile: boolean;\n /** Disable exporting state file */\n disableExportStateFile: boolean;\n /** Disable importing state file */\n disableImportStateFile: boolean;\n /** Disable updating checklist */\n disableUpdateChecklist: boolean;\n /** Disable database query execution */\n disableDatabaseQuery: boolean;\n /** Disable view action dropdown menu */\n disableViewActionDropdown: boolean;\n /** Disable node action dropdown menu */\n disableNodeActionDropdown: boolean;\n /** Disable share functionality */\n disableShare: boolean;\n}\n\n/**\n * Instance information exposed through the RecceInstanceContext.\n * Contains feature toggles and session information.\n */\nexport interface InstanceInfoType {\n /** Whether running in single environment mode */\n singleEnv: boolean;\n /** Whether user is authenticated */\n authed: boolean;\n /** Feature toggles based on server mode */\n featureToggles: RecceFeatureToggles;\n /** When the instance lifetime expires */\n lifetimeExpiredAt?: Date;\n /** URL for sharing the instance */\n shareUrl?: string;\n /** Current session ID */\n sessionId?: string;\n}\n\n/**\n * Default feature toggles with all features enabled.\n */\nexport const defaultFeatureToggles: RecceFeatureToggles = {\n mode: null,\n disableSaveToFile: false,\n disableExportStateFile: false,\n disableImportStateFile: false,\n disableUpdateChecklist: false,\n disableDatabaseQuery: false,\n disableViewActionDropdown: false,\n disableNodeActionDropdown: false,\n disableShare: false,\n};\n\n/**\n * Default instance info values.\n */\nexport const defaultInstanceInfo: InstanceInfoType = {\n singleEnv: false,\n authed: false,\n lifetimeExpiredAt: undefined,\n featureToggles: defaultFeatureToggles,\n shareUrl: undefined,\n sessionId: undefined,\n};\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport axios from \"axios\";\n\nimport { cacheKeys } from \"../../api/cacheKeys\";\nimport {\n getRecceInstanceInfo,\n type RecceInstanceInfo,\n} from \"../../api/instanceInfo\";\nimport { useApiConfigOptional } from \"../../providers/contexts/ApiContext\";\n\n// Default axios client for use outside RecceProvider (OSS mode)\nconst defaultApiClient = axios.create();\n\n/**\n * Hook to fetch Recce instance information from the server.\n *\n * Uses TanStack Query to cache the response and the configured API client.\n * Works both inside RecceProvider (uses configured client) and outside (uses default axios).\n *\n * @returns Query result with RecceInstanceInfo data\n *\n * @example\n * ```tsx\n * function InstanceStatus() {\n * const { data, isLoading, error } = useRecceInstanceInfo();\n *\n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error loading instance info</div>;\n *\n * return <div>Server mode: {data?.server_mode}</div>;\n * }\n * ```\n */\nexport function useRecceInstanceInfo() {\n const apiConfig = useApiConfigOptional();\n const apiClient = apiConfig?.apiClient ?? defaultApiClient;\n\n return useQuery<RecceInstanceInfo>({\n queryKey: cacheKeys.instanceInfo(),\n queryFn: () => getRecceInstanceInfo(apiClient),\n });\n}\n","\"use client\";\n\nimport { createContext, type ReactNode, useContext, useState } from \"react\";\n\nimport {\n defaultFeatureToggles,\n defaultInstanceInfo,\n type InstanceInfoType,\n type RecceFeatureToggles,\n} from \"./types\";\nimport { useRecceInstanceInfo } from \"./useRecceInstanceInfo\";\n\nconst InstanceInfoContext =\n createContext<InstanceInfoType>(defaultInstanceInfo);\nInstanceInfoContext.displayName = \"RecceInstanceInfoContext\";\n\n/**\n * Provider that fetches and processes Recce instance information.\n *\n * This provider:\n * 1. Fetches instance info from the server using useRecceInstanceInfo\n * 2. Computes feature toggles based on server_mode\n * 3. Provides the processed data through context\n *\n * Feature toggles are computed based on:\n * - server_mode: \"read-only\" disables all modifications\n * - server_mode: \"preview\" disables database queries but allows metadata operations\n * - single_env: disables checklist updates and sharing\n * - cloud_instance: disables sharing\n *\n * @example\n * ```tsx\n * function App() {\n * return (\n * <RecceProvider api={{ baseUrl: \"/api\" }}>\n * <RecceInstanceInfoProvider>\n * <MyComponent />\n * </RecceInstanceInfoProvider>\n * </RecceProvider>\n * );\n * }\n * ```\n */\nexport function RecceInstanceInfoProvider({\n children,\n}: {\n children: ReactNode;\n}) {\n const { data: instanceInfo, isLoading } = useRecceInstanceInfo();\n const [featureToggles, setFeatureToggles] = useState<RecceFeatureToggles>(\n defaultFeatureToggles,\n );\n const [singleEnv, setSingleEnv] = useState<boolean>(false);\n const [authed, setAuthed] = useState<boolean>(false);\n const [lifetimeExpiredAt, setLifetimeExpiredAt] = useState<Date>();\n const [shareUrl, setShareUrl] = useState<string>();\n const [sessionId, setSessionId] = useState<string>();\n const [prevInstanceInfo, setPrevInstanceInfo] = useState(instanceInfo);\n\n // Adjust state during render when instanceInfo changes\n if (!isLoading && instanceInfo && instanceInfo !== prevInstanceInfo) {\n setPrevInstanceInfo(instanceInfo);\n\n setSingleEnv(instanceInfo.single_env);\n setAuthed(instanceInfo.authed);\n setShareUrl(instanceInfo.share_url);\n setSessionId(instanceInfo.session_id);\n\n if (instanceInfo.lifetime_expired_at) {\n setLifetimeExpiredAt(new Date(instanceInfo.lifetime_expired_at));\n console.log(\"lifetime expired at\", instanceInfo.lifetime_expired_at);\n }\n\n // Set feature toggles based on instanceInfo\n const toggles = { ...defaultFeatureToggles };\n if (instanceInfo.server_mode === \"read-only\") {\n toggles.mode = \"read only\";\n toggles.disableSaveToFile = true;\n toggles.disableExportStateFile = true;\n toggles.disableImportStateFile = true;\n toggles.disableUpdateChecklist = true;\n toggles.disableDatabaseQuery = true;\n toggles.disableViewActionDropdown = true;\n toggles.disableNodeActionDropdown = true;\n toggles.disableShare = true;\n } else if (instanceInfo.server_mode === \"preview\") {\n toggles.mode = \"metadata only\";\n toggles.disableSaveToFile = true;\n toggles.disableExportStateFile = true;\n toggles.disableImportStateFile = true;\n toggles.disableUpdateChecklist = false;\n toggles.disableDatabaseQuery = true;\n toggles.disableViewActionDropdown = false;\n toggles.disableNodeActionDropdown = false;\n toggles.disableShare = true;\n }\n if (instanceInfo.single_env) {\n toggles.disableUpdateChecklist = true;\n toggles.disableShare = true;\n }\n if (instanceInfo.cloud_instance) {\n toggles.disableShare = true;\n }\n setFeatureToggles(toggles);\n }\n\n return (\n <InstanceInfoContext.Provider\n value={{\n featureToggles,\n singleEnv,\n authed,\n lifetimeExpiredAt,\n shareUrl,\n sessionId,\n }}\n >\n {children}\n </InstanceInfoContext.Provider>\n );\n}\n\n/**\n * Hook to access the Recce instance context.\n *\n * Returns the current instance information including feature toggles,\n * authentication status, and session information.\n *\n * @returns InstanceInfoType with feature toggles and session info\n *\n * @example\n * ```tsx\n * function FeatureGate() {\n * const { featureToggles } = useRecceInstanceContext();\n *\n * if (featureToggles.disableDatabaseQuery) {\n * return <div>Database queries are disabled</div>;\n * }\n *\n * return <QueryEditor />;\n * }\n * ```\n */\nexport function useRecceInstanceContext(): InstanceInfoType {\n return useContext(InstanceInfoContext);\n}\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\n\n/**\n * Context for sharing idle timeout state across components\n *\n * IMPORTANT: The countdown is based on the last SUCCESSFUL keep-alive API call,\n * NOT on user activity. This ensures the countdown accurately reflects the\n * server's idle timeout state.\n */\nexport interface IdleTimeoutContextType {\n /** Remaining seconds until timeout (null if idle timeout not enabled) */\n remainingSeconds: number | null;\n /** Idle timeout value from server in seconds (null if not configured) */\n idleTimeout: number | null;\n /** Whether idle timeout is enabled */\n isEnabled: boolean;\n /** Mark as disconnected - stops countdown and keep-alive */\n setDisconnected: () => void;\n /** Reset connection state - restarts countdown and keep-alive after successful reconnect */\n resetConnection: () => void;\n /** Whether the connection is disconnected */\n isDisconnected: boolean;\n}\n\nexport const IdleTimeoutContext = createContext<\n IdleTimeoutContextType | undefined\n>(undefined);\n\n/**\n * Hook to access idle timeout context, returns null if outside provider\n * Used internally by useIdleDetection to avoid circular dependency\n */\nexport function useIdleTimeoutSafe(): IdleTimeoutContextType | null {\n return useContext(IdleTimeoutContext) ?? null;\n}\n","\"use client\";\n\nimport axios from \"axios\";\nimport throttle from \"lodash/throttle\";\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport { sendKeepAlive } from \"../../api/keepAlive\";\nimport { useApiConfigOptional } from \"../../providers/contexts/ApiContext\";\n\nimport { useRecceInstanceInfo } from \"../instance\";\nimport { useIdleTimeoutSafe } from \"./types\";\n\n// Default axios client for use outside RecceProvider (OSS mode)\nconst defaultApiClient = axios.create();\n\n/**\n * Check if debug logging is enabled via window.RECCE_DEBUG_IDLE\n * Enable in browser console: window.RECCE_DEBUG_IDLE = true\n * Disable: delete window.RECCE_DEBUG_IDLE\n */\nfunction isDebugEnabled(): boolean {\n // biome-ignore lint/suspicious/noExplicitAny: window flag for debug logging\n return typeof window !== \"undefined\" && !!(window as any).RECCE_DEBUG_IDLE;\n}\n\n/**\n * Log function that only outputs when debug is enabled\n */\nfunction debugLog(message: string, data?: Record<string, unknown>) {\n if (isDebugEnabled()) {\n if (data) {\n console.log(message, data);\n } else {\n console.log(message);\n }\n }\n}\n\n/**\n * Configuration for idle detection behavior\n */\nconst IDLE_DETECTION_CONFIG = {\n /** Events to listen for user activity */\n ACTIVITY_EVENTS: [\"focus\", \"mousemove\", \"keydown\", \"scroll\"] as const,\n /**\n * Throttle event handler execution to reduce JS overhead (150ms).\n * Uses lodash.throttle with { leading: true, trailing: true } to ensure\n * immediate response on first activity (leading) and also capture the final\n * event in a burst (trailing), which is important for user experience.\n */\n EVENT_THROTTLE_MS: 150,\n} as const;\n\n/**\n * Hook to detect user activity and send keep-alive signals to prevent server idle timeout.\n *\n * This hook:\n * - Listens for user activities (focus, mouse, keyboard, scroll)\n * - Sends keep-alive requests (throttled at axios layer to minimum 3 seconds)\n * - Pauses when the tab is inactive (using Page Visibility API)\n * - Immediately sends a keep-alive when tab becomes active\n * - Only activates when idle_timeout is configured on the server\n *\n * Note: The countdown in IdleTimeoutContext is based on successful keep-alive\n * API calls, not on user activity. This ensures accurate server state tracking.\n */\nexport function useIdleDetection() {\n const { data: instanceInfo, isLoading, isError } = useRecceInstanceInfo();\n const idleTimeoutContext = useIdleTimeoutSafe();\n const isDisconnected = idleTimeoutContext?.isDisconnected ?? false;\n const apiConfig = useApiConfigOptional();\n const apiClient = apiConfig?.apiClient ?? defaultApiClient;\n\n // Only enable idle detection if idle_timeout is configured and not disconnected\n const idleTimeout = instanceInfo?.idle_timeout;\n const isEnabled =\n idleTimeout !== undefined && idleTimeout > 0 && !isDisconnected;\n\n // Debug: Log instance info state when debug is enabled\n debugLog(\"[Idle Detection] Instance info\", {\n isLoading,\n isError,\n hasIdleTimeout: idleTimeout !== undefined,\n idleTimeout:\n idleTimeout !== undefined ? `${idleTimeout}s` : \"not configured\",\n isDisconnected,\n isEnabled,\n });\n\n /**\n * Send keep-alive signal to server\n * Throttling is handled at the axios layer (minimum 3 seconds between API calls)\n * The successful send will notify IdleTimeoutContext to reset countdown\n */\n const sendKeepAliveNow = useCallback(async () => {\n if (document.hidden) return;\n\n const sent = await sendKeepAlive(apiClient);\n\n if (sent) {\n debugLog(\"[Idle Detection] Keep-alive sent successfully\", {\n timestamp: new Date().toISOString(),\n });\n }\n }, [apiClient]);\n\n /**\n * Handle any user activity event\n * Attempts to send keep-alive (axios layer handles throttling)\n */\n const handleActivity = useCallback(\n (event: Event) => {\n if (isEnabled && !document.hidden) {\n debugLog(\"[Idle Detection] Activity detected\", {\n event: event.type,\n tabActive: !document.hidden,\n });\n\n // Send keep-alive API call (axios layer handles throttling)\n void sendKeepAliveNow();\n }\n },\n [isEnabled, sendKeepAliveNow],\n );\n\n /**\n * Handle tab visibility changes\n * When tab becomes active, attempt to send keep-alive\n */\n const handleVisibilityChange = useCallback(() => {\n if (!isEnabled) return;\n\n if (!document.hidden) {\n debugLog(\"[Idle Detection] Tab became active\", {\n timestamp: new Date().toISOString(),\n });\n\n // Send keep-alive (axios layer handles throttling)\n void sendKeepAliveNow();\n }\n }, [isEnabled, sendKeepAliveNow]);\n\n // Create throttled handler using lodash to reduce JS overhead from high-frequency events\n // useMemo ensures stable reference and proper cleanup\n const throttledHandler = useMemo(\n () =>\n throttle(handleActivity, IDLE_DETECTION_CONFIG.EVENT_THROTTLE_MS, {\n leading: true,\n trailing: true,\n }),\n [handleActivity],\n );\n\n useEffect(() => {\n if (!isEnabled) {\n debugLog(\"[Idle Detection] Disabled\", {\n idleTimeout: idleTimeout,\n reason:\n idleTimeout === undefined\n ? \"idle_timeout not configured on server\"\n : idleTimeout === 0\n ? \"idle_timeout is 0\"\n : \"disconnected\",\n });\n return;\n }\n\n debugLog(\"[Idle Detection] Initialized\", {\n enabled: true,\n idleTimeout: `${idleTimeout}s`,\n eventThrottle: `${IDLE_DETECTION_CONFIG.EVENT_THROTTLE_MS}ms`,\n apiThrottle: \"3s (axios layer)\",\n monitoredEvents: IDLE_DETECTION_CONFIG.ACTIVITY_EVENTS.join(\", \"),\n });\n\n // Register activity event listeners with throttled handler\n IDLE_DETECTION_CONFIG.ACTIVITY_EVENTS.forEach((eventType) => {\n window.addEventListener(eventType, throttledHandler, { passive: true });\n });\n\n // Register visibility change listener (not throttled - immediate response needed)\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n // Cleanup function\n return () => {\n debugLog(\"[Idle Detection] Cleanup - removing event listeners\");\n IDLE_DETECTION_CONFIG.ACTIVITY_EVENTS.forEach((eventType) => {\n window.removeEventListener(eventType, throttledHandler);\n });\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n throttledHandler.cancel(); // Cancel any pending throttled calls\n };\n }, [isEnabled, throttledHandler, handleVisibilityChange, idleTimeout]);\n}\n","\"use client\";\n\nimport {\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport {\n getLastKeepAliveTime,\n setKeepAliveCallback,\n} from \"../../api/keepAlive\";\nimport { useRecceInstanceInfo } from \"../instance\";\nimport { IdleTimeoutContext, type IdleTimeoutContextType } from \"./types\";\nimport { useIdleDetection } from \"./useIdleDetection\";\n\n/**\n * Provider for idle timeout state\n *\n * The countdown is based on lastServerSyncTime (when keep-alive API was last\n * successfully sent), not on user activity. This provides accurate server state.\n */\nexport function IdleTimeoutProvider({ children }: { children: ReactNode }) {\n const { data: instanceInfo } = useRecceInstanceInfo();\n // Track the last time we successfully synced with server (keep-alive sent)\n const lastServerSyncRef = useRef<number>(Date.now());\n const [remainingSeconds, setRemainingSeconds] = useState<number | null>(null);\n const [isDisconnected, setIsDisconnected] = useState(false);\n\n const idleTimeout = instanceInfo?.idle_timeout ?? null;\n const isEnabled = idleTimeout !== null && idleTimeout > 0;\n\n // Register callback to receive keep-alive success notifications\n // Use ref to track enabled state to avoid race condition in callback\n const isEnabledRef = useRef(isEnabled);\n useEffect(() => {\n isEnabledRef.current = isEnabled;\n }, [isEnabled]);\n\n useEffect(() => {\n if (!isEnabled) {\n setKeepAliveCallback(null);\n return;\n }\n\n setKeepAliveCallback((timestamp: number) => {\n // Check current enabled state to avoid updating after disabled\n if (isEnabledRef.current) {\n lastServerSyncRef.current = timestamp;\n }\n });\n\n // Initialize with current keep-alive time if available\n const currentTime = getLastKeepAliveTime();\n if (currentTime > 0) {\n lastServerSyncRef.current = currentTime;\n }\n\n return () => {\n setKeepAliveCallback(null);\n };\n }, [isEnabled]);\n\n const setDisconnected = useCallback(() => {\n setIsDisconnected(true);\n }, []);\n\n const resetConnection = useCallback(() => {\n // Reset disconnected state\n setIsDisconnected(false);\n // Reset server sync time to now (server just restarted, timer reset)\n lastServerSyncRef.current = Date.now();\n }, []);\n\n // Update remaining seconds every second based on server sync time\n useEffect(() => {\n if (!isEnabled || idleTimeout === null) {\n setRemainingSeconds(null);\n return;\n }\n\n // Stop updating countdown if disconnected\n if (isDisconnected) {\n return;\n }\n\n const updateCountdown = () => {\n const now = Date.now();\n const elapsedSeconds = (now - lastServerSyncRef.current) / 1000;\n const remaining = Math.max(0, idleTimeout - elapsedSeconds);\n setRemainingSeconds(remaining);\n };\n\n // Initial update\n updateCountdown();\n\n // Set up interval for updates\n const intervalId = setInterval(updateCountdown, 1000);\n\n return () => {\n clearInterval(intervalId);\n };\n }, [isEnabled, idleTimeout, isDisconnected]);\n\n return (\n <IdleTimeoutContext.Provider\n value={{\n remainingSeconds,\n idleTimeout,\n isEnabled,\n setDisconnected,\n resetConnection,\n isDisconnected,\n }}\n >\n <IdleDetector />\n {children}\n </IdleTimeoutContext.Provider>\n );\n}\n\n/**\n * Internal component that activates idle detection\n * Placed inside provider so it has access to context\n */\nfunction IdleDetector() {\n useIdleDetection();\n return null;\n}\n\n/**\n * Hook to access idle timeout context\n * @throws Error if used outside IdleTimeoutProvider\n */\nexport function useIdleTimeout() {\n const context = useContext(IdleTimeoutContext);\n if (!context) {\n throw new Error(\"useIdleTimeout must be used within IdleTimeoutProvider\");\n }\n return context;\n}\n\n// Re-export type and safe hook for backwards compatibility\nexport type { IdleTimeoutContextType } from \"./types\";\nexport { useIdleTimeoutSafe } from \"./types\";\n","\"use client\";\n\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useMemo,\n} from \"react\";\nimport type { RunsAggregated } from \"../../api/runs\";\nimport type { EnvInfo, LineageGraph, LineageGraphContextType } from \"./types\";\n\n/**\n * Props for LineageGraphProvider\n *\n * This is a props-driven provider - pass data from your data fetching layer.\n * The provider does NOT fetch data internally; consumers handle data fetching\n * and pass the results via props.\n */\nexport interface LineageGraphProviderProps {\n children: ReactNode;\n\n /** The processed lineage graph data */\n lineageGraph?: LineageGraph;\n\n /** Environment information (git, dbt, sqlmesh metadata) */\n envInfo?: EnvInfo;\n\n /** Whether in review mode (read-only checks) */\n reviewMode?: boolean;\n\n /** Whether in cloud mode (recce cloud) */\n cloudMode?: boolean;\n\n /** Whether in file mode (loading from file) */\n fileMode?: boolean;\n\n /** The state file name if in file mode */\n fileName?: string;\n\n /** Whether this is the demo site */\n isDemoSite?: boolean;\n\n /** Whether running in GitHub Codespace */\n isCodespace?: boolean;\n\n /** Loading state */\n isLoading?: boolean;\n\n /** Error message if loading failed */\n error?: string;\n\n /** Supported task types from server */\n supportTasks?: Record<string, boolean>;\n\n /** Callback to refetch the lineage graph */\n onRefetchLineageGraph?: () => void;\n\n /** Pre-aggregated run results by model */\n runsAggregated?: RunsAggregated;\n\n /** Callback to refetch aggregated runs */\n onRefetchRunsAggregated?: () => void;\n}\n\nconst defaultContext: LineageGraphContextType = {\n isActionAvailable: () => true,\n isDemoSite: false,\n isLoading: true, // Default to loading state for SSR hydration safety\n};\n\nconst LineageGraphContext =\n createContext<LineageGraphContextType>(defaultContext);\nLineageGraphContext.displayName = \"RecceLineageGraphContext\";\n\n/**\n * Provider for LineageGraph context.\n *\n * This is a props-driven provider designed for library consumers.\n * Pass data from your data fetching layer (e.g., TanStack Query).\n *\n * @example\n * ```tsx\n * const { data, isLoading, error, refetch } = useQuery({\n * queryKey: ['lineage'],\n * queryFn: fetchLineageData,\n * });\n *\n * <LineageGraphProvider\n * lineageGraph={data?.lineageGraph}\n * envInfo={data?.envInfo}\n * isLoading={isLoading}\n * error={error?.message}\n * onRefetchLineageGraph={refetch}\n * >\n * <LineageView />\n * </LineageGraphProvider>\n * ```\n */\nexport function LineageGraphProvider({\n children,\n lineageGraph,\n envInfo,\n reviewMode,\n cloudMode,\n fileMode,\n fileName,\n isDemoSite = false,\n isCodespace,\n isLoading,\n error,\n supportTasks,\n onRefetchLineageGraph,\n runsAggregated,\n onRefetchRunsAggregated,\n}: LineageGraphProviderProps) {\n // Create stable isActionAvailable function\n const isActionAvailable = useCallback(\n (name: string) => {\n if (supportTasks) {\n // Default to true if action not found in supportTasks\n return supportTasks[name] ?? true;\n }\n // If supportTasks not provided, all actions are available\n return true;\n },\n [supportTasks],\n );\n\n // Memoize the context value to prevent unnecessary re-renders\n const contextValue = useMemo<LineageGraphContextType>(\n () => ({\n lineageGraph,\n envInfo,\n reviewMode,\n cloudMode,\n fileMode,\n fileName,\n isDemoSite,\n isCodespace,\n isLoading,\n error,\n supportTasks,\n retchLineageGraph: onRefetchLineageGraph,\n isActionAvailable,\n runsAggregated,\n refetchRunsAggregated: onRefetchRunsAggregated,\n }),\n [\n lineageGraph,\n envInfo,\n reviewMode,\n cloudMode,\n fileMode,\n fileName,\n isDemoSite,\n isCodespace,\n isLoading,\n error,\n supportTasks,\n onRefetchLineageGraph,\n isActionAvailable,\n runsAggregated,\n onRefetchRunsAggregated,\n ],\n );\n\n return (\n <LineageGraphContext.Provider value={contextValue}>\n {children}\n </LineageGraphContext.Provider>\n );\n}\n\n/**\n * Hook to access the LineageGraph context.\n *\n * @returns LineageGraphContextType with lineage data and utilities\n * @throws Warning in dev mode if used outside provider (returns default context)\n */\nexport function useLineageGraphContext(): LineageGraphContextType {\n const context = useContext(LineageGraphContext);\n return context;\n}\n\n/**\n * Hook to access aggregated runs data.\n * Convenience wrapper around useLineageGraphContext.\n *\n * @returns Tuple of [runsAggregated, refetchRunsAggregated]\n */\nexport function useRunsAggregated(): [\n RunsAggregated | undefined,\n (() => void) | undefined,\n] {\n const { runsAggregated, refetchRunsAggregated } = useLineageGraphContext();\n return [runsAggregated, refetchRunsAggregated];\n}\n","import type { Edge, Node } from \"@xyflow/react\";\nimport type React from \"react\";\nimport type { CllInput, ColumnLineageData } from \"../../api/cll\";\nimport type {\n CatalogMetadata,\n GitInfo,\n ManifestMetadata,\n NodeData,\n PullRequestInfo,\n SQLMeshInfo,\n StateMetadata,\n} from \"../../api/info\";\nimport type { LineageDiffViewOptions } from \"../../api/lineagecheck\";\nimport type { RunsAggregated } from \"../../api/runs\";\nimport type { Run } from \"../../api/types\";\n\n/**\n * Environment information derived from server info\n */\nexport interface EnvInfo {\n stateMetadata?: StateMetadata;\n adapterType?: string;\n git?: GitInfo;\n pullRequest?: PullRequestInfo;\n dbt?: {\n base: ManifestMetadata | undefined | null;\n current: ManifestMetadata | undefined | null;\n };\n sqlmesh?: SQLMeshInfo | null;\n}\n\n/**\n * Which environment the node/edge comes from\n */\ntype LineageFrom = \"both\" | \"base\" | \"current\";\n\n/**\n * Lineage graph node type for React Flow\n */\nexport type LineageGraphNode = Node<\n {\n id: string;\n name: string;\n from: LineageFrom;\n data: {\n base?: NodeData;\n current?: NodeData;\n };\n changeStatus?: \"added\" | \"removed\" | \"modified\";\n change?: {\n category: \"breaking\" | \"non_breaking\" | \"partial_breaking\" | \"unknown\";\n columns: Record<string, \"added\" | \"removed\" | \"modified\"> | null;\n };\n resourceType?: string;\n packageName?: string;\n parents: Record<string, LineageGraphEdge>;\n children: Record<string, LineageGraphEdge>;\n },\n \"lineageGraphNode\"\n>;\n\n/**\n * Column-level lineage node type\n */\nexport type LineageGraphColumnNode = Node<\n {\n node: LineageGraphNode[\"data\"];\n column: string;\n type: string;\n transformationType?: string;\n changeStatus?: \"added\" | \"removed\" | \"modified\";\n },\n \"lineageGraphColumnNode\"\n>;\n\n/**\n * Lineage graph edge type for React Flow\n */\nexport type LineageGraphEdge = Edge<\n {\n from: LineageFrom;\n changeStatus?: \"added\" | \"removed\";\n },\n \"lineageGraphEdge\"\n>;\n\n/**\n * Union type for all lineage graph node types\n */\nexport type LineageGraphNodes = LineageGraphNode | LineageGraphColumnNode;\n\n/**\n * The main lineage graph data structure\n */\nexport interface LineageGraph {\n nodes: Record<string, LineageGraphNode>;\n edges: Record<string, LineageGraphEdge>;\n modifiedSet: string[];\n manifestMetadata: {\n base?: ManifestMetadata;\n current?: ManifestMetadata;\n };\n catalogMetadata: {\n base?: CatalogMetadata;\n current?: CatalogMetadata;\n };\n}\n\n/**\n * Type guard for LineageGraphNode\n */\nexport function isLineageGraphNode(\n node: LineageGraphNodes,\n): node is LineageGraphNode {\n return node.type === \"lineageGraphNode\";\n}\n\n/**\n * Type guard for LineageGraphColumnNode\n */\nexport function isLineageGraphColumnNode(\n node: LineageGraphNodes,\n): node is LineageGraphColumnNode {\n return node.type === \"lineageGraphColumnNode\";\n}\n\n/**\n * Context value exposed by LineageGraphContext\n */\nexport interface LineageGraphContextType {\n /** The processed lineage graph */\n lineageGraph?: LineageGraph;\n /** Environment metadata */\n envInfo?: EnvInfo;\n /** Whether in review mode (read-only checks) */\n reviewMode?: boolean;\n /** Whether in cloud mode (recce cloud) */\n cloudMode?: boolean;\n /** Whether in file mode (loading from file) */\n fileMode?: boolean;\n /** The state file name if in file mode */\n fileName?: string;\n /** Whether this is the demo site */\n isDemoSite: boolean;\n /** Whether running in GitHub Codespace */\n isCodespace?: boolean;\n /** Loading state */\n isLoading?: boolean;\n /** Error message if loading failed */\n error?: string;\n /** Supported task types from server */\n supportTasks?: Record<string, boolean>;\n /** Refetch the lineage graph data */\n retchLineageGraph?: () => void;\n /** Check if an action is available */\n isActionAvailable: (actionName: string) => boolean;\n /** Pre-aggregated run results by model */\n runsAggregated?: RunsAggregated;\n /** Refetch the aggregated runs */\n refetchRunsAggregated?: () => void;\n}\n\n// ============================================================================\n// LineageViewContext Types\n// ============================================================================\n\n/**\n * Action mode for node operations - single or multiple nodes\n */\nexport type ActionMode = \"per_node\" | \"multi_nodes\";\n\n/**\n * Select mode for multi-node selection\n */\nexport type SelectMode = \"selecting\" | \"action_result\" | undefined;\n\n/**\n * Action state for individual node operations\n */\nexport interface NodeAction {\n /** Whether this is a per-node or multi-node action */\n mode: ActionMode;\n /** Current status of this node's action */\n status?: \"pending\" | \"running\" | \"success\" | \"failure\" | \"skipped\";\n /** Reason why this node was skipped (if applicable) */\n skipReason?: string;\n /** The run associated with this action */\n run?: Run;\n}\n\n/**\n * Overall action state for batch operations\n */\nexport interface ActionState {\n /** Whether this is a per-node or multi-node action */\n mode: ActionMode;\n /** Overall status of the action batch */\n status: \"pending\" | \"running\" | \"canceling\" | \"canceled\" | \"completed\";\n /** Current run being executed */\n currentRun?: Partial<Run>;\n /** Number of completed actions */\n completed: number;\n /** Total number of actions */\n total: number;\n /** Per-node action state */\n actions: Record<string, NodeAction>;\n}\n\n/**\n * Context value exposed by LineageViewContext.\n * Provides state and methods for interacting with the lineage view.\n */\nexport interface LineageViewContextType {\n /** Whether the view is interactive (vs read-only) */\n interactive: boolean;\n /** All nodes in the current view */\n nodes: LineageGraphNodes[];\n /** Currently focused node (hovered/highlighted) */\n focusedNode?: LineageGraphNode;\n /** Currently selected nodes for batch operations */\n selectedNodes: LineageGraphNode[];\n /** Column-level lineage data if showing CLL */\n cll: ColumnLineageData | undefined;\n\n // Context menu\n /** Show the context menu for a node */\n showContextMenu: (event: React.MouseEvent, node: LineageGraphNodes) => void;\n\n // View options\n /** Current view options (filters, display settings) */\n viewOptions: LineageDiffViewOptions;\n /** Update view options */\n onViewOptionsChanged: (options: LineageDiffViewOptions) => void;\n\n // Multi-node selection\n /** Current selection mode */\n selectMode: SelectMode;\n /** Select/deselect a single node */\n selectNode: (nodeId: string) => void;\n /** Select all parent nodes up to a degree */\n selectParentNodes: (nodeId: string, degree?: number) => void;\n /** Select all child nodes up to a degree */\n selectChildNodes: (nodeId: string, degree?: number) => void;\n /** Clear selection */\n deselect: () => void;\n\n // Node state queries\n /** Check if a node is highlighted */\n isNodeHighlighted: (nodeId: string) => boolean;\n /** Check if a node is selected */\n isNodeSelected: (nodeId: string) => boolean;\n /** Check if an edge is highlighted */\n isEdgeHighlighted: (source: string, target: string) => boolean;\n /** Get the action state for a node */\n getNodeAction: (nodeId: string) => NodeAction;\n /** Get the columns visible for a node in CLL mode */\n getNodeColumnSet: (nodeId: string) => Set<string>;\n /** Check if a node is showing change analysis */\n isNodeShowingChangeAnalysis: (nodeId: string) => boolean;\n\n // Actions\n /** Run row count on selected nodes */\n runRowCount: () => Promise<void>;\n /** Run row count diff on selected nodes */\n runRowCountDiff: () => Promise<void>;\n /** Run value diff on selected nodes */\n runValueDiff: () => Promise<void>;\n /** Add a lineage diff check */\n addLineageDiffCheck: (viewMode?: string) => void;\n /** Add a schema diff check */\n addSchemaDiffCheck: () => void;\n /** Cancel the current action */\n cancel: () => void;\n /** Current action state */\n actionState: ActionState;\n\n // Column-level lineage\n /** Center the view on a specific node */\n centerNode: (nodeId: string) => void;\n /** Show column-level lineage for a node/column */\n showColumnLevelLineage: (cll?: CllInput) => Promise<void>;\n /** Reset column-level lineage view */\n resetColumnLevelLineage: (previous?: boolean) => Promise<void>;\n}\n","import type { Position } from \"@xyflow/react\";\nimport type { LineageDataFromMetadata, LineageDiffData } from \"../../api/info\";\nimport type {\n LineageGraph,\n LineageGraphColumnNode,\n LineageGraphEdge,\n LineageGraphNode,\n LineageGraphNodes,\n} from \"./types\";\nimport { isLineageGraphNode } from \"./types\";\n\n/**\n * Height of a column node in pixels\n */\nexport const COLUMN_HEIGHT = 20;\n\n/**\n * Map of node IDs to their column sets\n */\nexport type NodeColumnSetMap = Record<string, Set<string>>;\n\n// =============================================================================\n// Set Utilities\n// =============================================================================\n\n/**\n * Get the union of multiple sets\n */\nexport function union<T>(...sets: Set<T>[]): Set<T> {\n const unionSet = new Set<T>();\n for (const set of sets) {\n for (const key of set) {\n unionSet.add(key);\n }\n }\n return unionSet;\n}\n\n/**\n * Get the intersection of multiple sets\n */\nexport function intersect<T>(...sets: Set<T>[]): Set<T> {\n if (sets.length === 0) {\n return new Set<T>();\n }\n\n let intersection = new Set<T>(sets[0]);\n\n for (const set of sets) {\n intersection = new Set([...intersection].filter((x) => set.has(x)));\n }\n\n return intersection;\n}\n\n/**\n * Get a set of neighbor nodes up to a certain degree\n */\nexport function getNeighborSet(\n nodeIds: string[],\n getNeighbors: (id: string) => string[],\n degree = 1000,\n): Set<string> {\n const neighborSet = new Set<string>();\n const visited: Record<string, number | undefined> = {};\n\n const dfs = (id: string, currentDegree: number) => {\n if (currentDegree < 0) {\n return;\n }\n if (visited[id] != null && visited[id] >= currentDegree) {\n return;\n }\n visited[id] = currentDegree;\n\n const neighbors = getNeighbors(id);\n\n for (const neighborId of neighbors) {\n dfs(neighborId, currentDegree - 1);\n }\n\n neighborSet.add(id);\n };\n\n for (const nodeId of nodeIds) {\n dfs(nodeId, degree);\n }\n\n return neighborSet;\n}\n\n// =============================================================================\n// Lineage Graph Building\n// =============================================================================\n\n/**\n * Build a LineageGraph from base and current lineage data\n *\n * @param base - Base lineage data (before changes)\n * @param current - Current lineage data (after changes)\n * @param diff - Optional diff data for change status\n * @returns Processed LineageGraph structure\n *\n * @example\n * ```tsx\n * const lineageGraph = buildLineageGraph(\n * serverInfo.lineage.base,\n * serverInfo.lineage.current,\n * serverInfo.lineage.diff\n * );\n * ```\n */\nexport function buildLineageGraph(\n base: LineageDataFromMetadata,\n current: LineageDataFromMetadata,\n diff?: LineageDiffData,\n): LineageGraph {\n const nodes: Record<string, LineageGraphNode> = {};\n const edges: Record<string, LineageGraphEdge> = {};\n\n const buildNode = (\n key: string,\n from: \"base\" | \"current\",\n ): LineageGraphNode => {\n return {\n id: key,\n data: {\n id: key,\n name: key,\n from,\n data: {\n base: undefined,\n current: undefined,\n },\n parents: {},\n children: {},\n },\n type: \"lineageGraphNode\",\n } as LineageGraphNode;\n };\n\n // Process base nodes\n for (const [key, nodeData] of Object.entries(base.nodes)) {\n nodes[key] = buildNode(key, \"base\");\n if (nodeData) {\n nodes[key].data.data.base = nodeData;\n nodes[key].data.name = nodeData.name;\n nodes[key].data.resourceType = nodeData.resource_type;\n nodes[key].data.packageName = nodeData.package_name;\n }\n }\n\n // Process current nodes\n for (const [key, nodeData] of Object.entries(current.nodes)) {\n if (nodes[key] as LineageGraphNode | undefined) {\n nodes[key].data.from = \"both\";\n } else {\n nodes[key] = buildNode(key, \"current\");\n }\n if (nodeData) {\n nodes[key].data.data.current = current.nodes[key];\n nodes[key].data.name = nodeData.name;\n nodes[key].data.resourceType = nodeData.resource_type;\n nodes[key].data.packageName = nodeData.package_name;\n }\n }\n\n // Process base edges\n for (const [child, parents] of Object.entries(base.parent_map)) {\n for (const parent of parents) {\n const childNode = nodes[child] as LineageGraphNode | undefined;\n const parentNode = nodes[parent] as LineageGraphNode | undefined;\n const id = `${parent}_${child}`;\n\n if (!childNode || !parentNode) {\n continue;\n }\n edges[id] = {\n id,\n source: parentNode.id,\n target: childNode.id,\n data: {\n from: \"base\",\n },\n };\n const edge = edges[id];\n\n childNode.data.parents[parent] = edge;\n parentNode.data.children[child] = edge;\n }\n }\n\n // Process current edges\n for (const [child, parents] of Object.entries(current.parent_map)) {\n for (const parent of parents) {\n const childNode = nodes[child] as LineageGraphNode | undefined;\n const parentNode = nodes[parent] as LineageGraphNode | undefined;\n const id = `${parent}_${child}`;\n\n if (!childNode || !parentNode) {\n continue;\n }\n const existingEdge = edges[id] as LineageGraphEdge | undefined;\n if (existingEdge?.data && edges[id].data) {\n edges[id].data.from = \"both\";\n } else {\n edges[id] = {\n id,\n source: parentNode.id,\n target: childNode.id,\n data: {\n from: \"current\",\n },\n };\n }\n const edge = edges[id];\n\n childNode.data.parents[parent] = edge;\n parentNode.data.children[child] = edge;\n }\n }\n\n // Process diff and calculate modified set\n const modifiedSet: string[] = [];\n\n for (const [key, node] of Object.entries(nodes)) {\n const diffNode = diff?.[key];\n if (diffNode) {\n node.data.changeStatus = diffNode.change_status;\n if (diffNode.change) {\n node.data.change = {\n category: diffNode.change.category,\n columns: diffNode.change.columns,\n };\n }\n modifiedSet.push(key);\n } else if (node.data.from === \"base\") {\n node.data.changeStatus = \"removed\";\n modifiedSet.push(node.id);\n } else if (node.data.from === \"current\") {\n node.data.changeStatus = \"added\";\n modifiedSet.push(node.id);\n } else {\n const checksum1 = node.data.data.base?.checksum?.checksum;\n const checksum2 = node.data.data.current?.checksum?.checksum;\n\n if (checksum1 && checksum2 && checksum1 !== checksum2) {\n node.data.changeStatus = \"modified\";\n modifiedSet.push(node.id);\n }\n }\n }\n\n // Set edge change status\n for (const edge of Object.values(edges)) {\n if (edge.data) {\n if (edge.data.from === \"base\") {\n edge.data.changeStatus = \"removed\";\n } else if (edge.data.from === \"current\") {\n edge.data.changeStatus = \"added\";\n }\n }\n }\n\n return {\n nodes,\n edges,\n modifiedSet,\n manifestMetadata: {\n base: base.manifest_metadata ?? undefined,\n current: current.manifest_metadata ?? undefined,\n },\n catalogMetadata: {\n base: base.catalog_metadata ?? undefined,\n current: current.catalog_metadata ?? undefined,\n },\n };\n}\n\n// =============================================================================\n// Selection Utilities\n// =============================================================================\n\n/**\n * Select upstream nodes from the given node IDs\n *\n * @param lineageGraph - The lineage graph\n * @param nodeIds - Starting node IDs\n * @param degree - Maximum degree of separation (default: 1000)\n * @returns Set of upstream node IDs\n */\nexport function selectUpstream(\n lineageGraph: LineageGraph,\n nodeIds: string[],\n degree = 1000,\n): Set<string> {\n return getNeighborSet(\n nodeIds,\n (key) => {\n const maybeNodes = lineageGraph.nodes as unknown as Record<\n string,\n LineageGraphNode | undefined\n >;\n if (maybeNodes[key] === undefined) {\n return [];\n }\n return Object.keys(lineageGraph.nodes[key].data.parents);\n },\n degree,\n );\n}\n\n/**\n * Select downstream nodes from the given node IDs\n *\n * @param lineageGraph - The lineage graph\n * @param nodeIds - Starting node IDs\n * @param degree - Maximum degree of separation (default: 1000)\n * @returns Set of downstream node IDs\n */\nexport function selectDownstream(\n lineageGraph: LineageGraph,\n nodeIds: string[],\n degree = 1000,\n): Set<string> {\n return getNeighborSet(\n nodeIds,\n (key) => {\n if (\n (lineageGraph.nodes[key] as LineageGraphNode | undefined) === undefined\n ) {\n return [];\n }\n return Object.keys(lineageGraph.nodes[key].data.children);\n },\n degree,\n );\n}\n\n// =============================================================================\n// React Flow Conversion\n// =============================================================================\n\n/**\n * Convert a LineageGraph to React Flow nodes and edges\n *\n * This is a simplified version that converts the graph structure.\n * For full column-level lineage support, use the OSS implementation.\n *\n * @param lineageGraph - The lineage graph to convert\n * @param selectedNodes - Optional filter for which nodes to include\n * @returns Tuple of [nodes, edges]\n */\nexport function toReactFlowBasic(\n lineageGraph: LineageGraph,\n selectedNodes?: string[],\n): [LineageGraphNode[], LineageGraphEdge[]] {\n const nodes: LineageGraphNode[] = [];\n const edges: LineageGraphEdge[] = [];\n\n function getWeight(from?: string) {\n if (from === \"base\") {\n return 0;\n } else if (from === \"current\") {\n return 2;\n }\n return 1;\n }\n\n function compareFn(\n a: LineageGraphNode | LineageGraphEdge,\n b: LineageGraphNode | LineageGraphEdge,\n ) {\n const weightA = getWeight(a.data?.from);\n const weightB = getWeight(b.data?.from);\n return weightA - weightB;\n }\n\n const filterSet =\n selectedNodes !== undefined ? new Set(selectedNodes) : undefined;\n const sortedNodes = Object.values(lineageGraph.nodes).sort(compareFn);\n\n for (const node of sortedNodes) {\n if (filterSet && !filterSet.has(node.id)) {\n continue;\n }\n\n nodes.push({\n id: node.id,\n position: { x: 0, y: 0 },\n width: 300,\n height: 60,\n className: \"no-track-pii-safe\",\n data: {\n ...node.data,\n },\n type: \"lineageGraphNode\",\n targetPosition: \"left\" as Position,\n sourcePosition: \"right\" as Position,\n style: {\n width: 300,\n height: 60,\n },\n } as LineageGraphNode);\n }\n\n const sortedEdges = Object.values(lineageGraph.edges).sort(compareFn);\n for (const edge of sortedEdges) {\n if (\n filterSet &&\n (!filterSet.has(edge.source) || !filterSet.has(edge.target))\n ) {\n continue;\n }\n\n edges.push({\n id: edge.id,\n type: \"lineageGraphEdge\",\n source: edge.source,\n target: edge.target,\n data: {\n ...edge.data,\n },\n } as LineageGraphEdge);\n }\n\n return [nodes, edges];\n}\n\n/**\n * Apply dagre layout to nodes and edges\n *\n * NOTE: This function requires @dagrejs/dagre to be installed.\n * Import and call it as follows:\n *\n * @example\n * ```tsx\n * import dagre from '@dagrejs/dagre';\n * import { layoutWithDagre } from '@datarecce/ui';\n *\n * const [nodes, edges] = toReactFlowBasic(lineageGraph);\n * layoutWithDagre(dagre, nodes, edges);\n * ```\n *\n * @param dagre - The dagre library instance\n * @param nodes - Nodes to layout\n * @param edges - Edges for layout\n * @param direction - Layout direction (default: \"LR\" for left-to-right)\n */\nexport function layoutWithDagre(\n // biome-ignore lint/suspicious/noExplicitAny: dagre library is external, consumers provide their own instance\n dagre: any,\n nodes: LineageGraphNodes[],\n edges: LineageGraphEdge[],\n direction = \"LR\",\n): void {\n const dagreGraph = new dagre.graphlib.Graph();\n dagreGraph.setDefaultEdgeLabel(() => ({}));\n dagreGraph.setGraph({ rankdir: direction, ranksep: 50, nodesep: 30 });\n\n for (const node of nodes) {\n if (!isLineageGraphNode(node)) {\n continue;\n }\n let width = 300;\n let height = 60;\n if (node.style?.height && node.style.width) {\n width = parseInt(String(node.style.width), 10);\n height = parseInt(String(node.style.height), 10);\n }\n dagreGraph.setNode(node.id, { width, height });\n }\n\n for (const edge of edges) {\n dagreGraph.setEdge(edge.source, edge.target);\n }\n\n dagre.layout(dagreGraph);\n\n for (const node of nodes) {\n if (!isLineageGraphNode(node)) {\n continue;\n }\n\n const nodeWidth = node.style?.width ?? 300;\n const nodeHeight = node.style?.height ?? 60;\n const nodeWithPosition = dagreGraph.node(node.id);\n\n // Shift from center anchor to top-left anchor\n node.position = {\n x: nodeWithPosition.x - Number(nodeWidth) / 2,\n y: nodeWithPosition.y - Number(nodeHeight) / 2,\n };\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ "use client";
2
+ import{n as e}from"./colors--47Kkns4.js";import{createContext as t,useCallback as n,useContext as r,useState as i}from"react";import{Fragment as a,jsx as o,jsxs as s}from"react/jsx-runtime";import c from"@mui/material/Box";import l from"@mui/material/Stack";import u from"@mui/material/Typography";import d from"@mui/material/IconButton";import f from"@mui/material/CircularProgress";import p from"@mui/material/Tooltip";import{PiCopy as m,PiDotsThreeVertical as h}from"react-icons/pi";import g from"file-saver";import _ from"@mui/material/Menu";import v from"@mui/material/MenuItem";import y from"lodash";import{VscClose as b,VscKebabVertical as ee,VscKey as te,VscPin as x,VscPinned as ne}from"react-icons/vsc";import{format as S,formatDistance as C,parseISO as w}from"date-fns";import re from"@mui/material/Alert";import{useCopyToClipboard as T}from"usehooks-ts";import"@mui/material/Snackbar";function ie(e,t){g(new Blob([e],{type:`text/csv;charset=utf-8`}),t)}async function ae(e){if(typeof navigator>`u`||!navigator.clipboard?.writeText)throw Error(`Clipboard API not available. Ensure you're using HTTPS or localhost.`);await navigator.clipboard.writeText(e)}function oe(e,t){return(e==null?``:String(e))===(t==null?``:String(t))?e:`${e==null?``:`(${e})`} ${t==null?``:`(${t})`}`.trim()}function E(e){return!e||!e.columns||!e.data?null:{columns:e.columns.map(e=>e.name),rows:e.data.map(e=>[...e])}}function se(e){return E(e)}function ce(e){return E(e)}function le(e,t){let n=e,r=t?.displayMode??`inline`,i=t?.primaryKeys??[];return n?.diff?ue(n.diff,r,i):de(n,r)}function ue(e,t,n){if(!e?.columns||!e?.data)return null;let r=e.columns.findIndex(e=>e.key.toLowerCase()===`in_a`),i=e.columns.findIndex(e=>e.key.toLowerCase()===`in_b`),a=e.columns.filter(e=>e.key.toLowerCase()!==`in_a`&&e.key.toLowerCase()!==`in_b`),o=a.map(e=>e.name),s=a.map(t=>e.columns.findIndex(e=>e.key===t.key)),c=n.map(t=>e.columns.findIndex(e=>e.key===t)).filter(e=>e>=0),l=e=>s.map(t=>e[t]),u=e=>c.length===0?``:c.map(t=>String(e[t]??``)).join(`|||`),d=new Map,f=[];if(e.data.forEach((e,t)=>{let n=r>=0?e[r]:!0,a=i>=0?e[i]:!0,o=u(e);o===``&&(o=String(t)),d.has(o)||(d.set(o,{base:null,current:null}),f.push(o));let s=d.get(o);if(!s)return;let c=l(e);n&&(s.base=c),a&&(s.current=c)}),t===`side_by_side`){let e=[];o.forEach(t=>{e.push(`base__${t}`,`current__${t}`)});let t=[];for(let e of f){let n=d.get(e);if(!n)continue;let r=n.base,i=n.current,a=[];o.forEach((e,t)=>{a.push(r?r[t]:null),a.push(i?i[t]:null)}),t.push(a)}return{columns:e,rows:t}}let p=[...o],m=[];for(let e of f){let t=d.get(e);if(!t)continue;let n=t.base,r=t.current,i=[];o.forEach((e,t)=>{let a=n?n[t]:null,o=r?r[t]:null;i.push(oe(a,o))}),m.push(i)}return{columns:p,rows:m}}function de(e,t){let n=e?.current||e?.base;if(!n)return null;if(!e?.base||!e?.current)return E(n);let r=e.current.columns.map(e=>e.name);if(t===`side_by_side`){let t=[];r.forEach(e=>{t.push(`base__${e}`,`current__${e}`)});let n=[],i=Math.max(e.base.data.length,e.current.data.length);for(let t=0;t<i;t++){let i=[],a=t<e.base.data.length?e.base.data[t]:null,o=t<e.current.data.length?e.current.data[t]:null;r.forEach((e,t)=>{i.push(a?a[t]:null),i.push(o?o[t]:null)}),n.push(i)}return{columns:t,rows:n}}let i=[...r],a=[],o=Math.max(e.base.data.length,e.current.data.length);for(let t=0;t<o;t++){let n=t<e.base.data.length?e.base.data[t]:null,i=t<e.current.data.length?e.current.data[t]:null,o=[];r.forEach((e,t)=>{let r=n?n[t]:null,a=i?i[t]:null;o.push(oe(r,a))}),a.push(o)}return{columns:i,rows:a}}function fe(e){let t=e,n=t?.current||t?.base;if(!n)return null;if(t?.base&&t?.current){let e=[`_source`,...t.current.columns.map(e=>e.name)],n=[];return t.base.data.forEach(e=>{n.push([`base`,...e])}),t.current.data.forEach(e=>{n.push([`current`,...e])}),{columns:e,rows:n}}return E(n)}function pe(e){let t=e;if(!t||typeof t!=`object`)return null;let n=[`node`,`base_count`,`current_count`,`diff`,`diff_percent`],r=[];for(let[e,n]of Object.entries(t))if(n&&typeof n==`object`){let t=n.base,i=n.curr,a=t!=null&&i!=null?i-t:null,o=t&&a!==null?(a/t*100).toFixed(2)+`%`:null;r.push([e,t,i,a,o])}return{columns:n,rows:r}}function me(e){let t=e;return t?.data?E(t.data):null}function he(e){return E(e)}function ge(e){let t=e,n=!!t?.base?.values,r=!!t?.current?.values;if(!n&&!r)return null;let i=[`_source`,`value`,`count`],a=[];return t?.base?.values&&t.base.values.forEach((e,n)=>{a.push([`base`,e,t.base.counts[n]])}),t?.current?.values&&t.current.values.forEach((e,n)=>{a.push([`current`,e,t.current.counts[n]])}),{columns:i,rows:a}}const _e={query:se,query_base:ce,query_diff:le,profile:fe,profile_diff:fe,row_count:pe,row_count_diff:pe,value_diff:me,value_diff_detail:he,top_k_diff:ge};function ve(e,t,n){let r=_e[e];if(!r)return null;try{return r(t,n)}catch(t){return console.error(`Failed to extract CSV data for run type "${e}":`,t),null}}function ye(e){return e in _e}function be(e){if(e==null)return``;let t=typeof e==`object`?JSON.stringify(e):String(e);return t.includes(`,`)||t.includes(`"`)||t.includes(`
3
+ `)||t.includes(`\r`)?`"${t.replace(/"/g,`""`)}"`:t}function xe(e,t){return``+[e.map(be).join(`,`),...t.map(e=>e.map(be).join(`,`))].join(`\r
4
+ `)}function Se(){let e=new Date;return`${e.getFullYear()}${String(e.getMonth()+1).padStart(2,`0`)}${String(e.getDate()).padStart(2,`0`)}-${String(e.getHours()).padStart(2,`0`)}${String(e.getMinutes()).padStart(2,`0`)}${String(e.getSeconds()).padStart(2,`0`)}`}function Ce(e,t){let n=Se(),r=e.replace(/_/g,`-`),i;return t?.node_names&&Array.isArray(t.node_names)&&t.node_names.length===1?i=String(t.node_names[0]):t?.model&&typeof t.model==`string`&&(i=t.model),i?(i=i.replace(/[^a-zA-Z0-9_.-]/g,`-`).toLowerCase(),`${r}-${i}-${n}.csv`):`${r}-result-${n}.csv`}function we(e){let{primaryKeys:t,pinnedColumns:n,allColumns:r,excludeColumns:i=[]}=e,a=[],o=new Set,s=e=>i.includes(e);return t.forEach(e=>{!o.has(e)&&!s(e)&&(a.push(e),o.add(e))}),n.forEach(e=>{!o.has(e)&&!s(e)&&(a.push(e),o.add(e))}),r.forEach(e=>{!o.has(e)&&!s(e)&&(a.push(e),o.add(e))}),a}function Te(e,t,n){return!t||!n?!0:e===`added`||e===`removed`||e===`modified`}function D(e,t){return t.includes(e)}function O(e,t){return t.includes(e)}function k(e,t){return t.includes(e)}function Ee(e,t){return e[t]}function A(e){let{columnMap:t,primaryKeys:n,pinnedColumns:r,columnsRenderMode:i,changedOnly:a=!1,rowStats:o,excludeColumns:s=[],strictMode:c=!1}=e,l=(o?.modified??0)>0,u=[];return n.forEach(e=>{let n=Ee(t,e);if(!n){if(c)throw Error(`Primary key column "${e}" not found in columnMap`);return}u.push({key:e,name:e,columnType:n.colType,columnStatus:n.status,columnRenderMode:i[e],frozen:!0,isPrimaryKey:!0})}),r.forEach(e=>{if(D(e,n)||k(e,s))return;let r=Ee(t,e);if(!r){if(c)throw Error(`Pinned column "${e}" not found in columnMap`);return}u.push({key:e,name:e,columnType:r.colType,columnStatus:r.status,columnRenderMode:i[e],frozen:!0})}),Object.entries(t).forEach(([e,t])=>{D(e,n)||O(e,r)||k(e,s)||Te(t.status,a,l)&&u.push({key:e,name:e,columnType:t.colType,columnStatus:t.status,columnRenderMode:i[e]})}),u}function De(e){let{columnMap:t,primaryKeys:n,pinnedColumns:r,columnsRenderMode:i,excludeColumns:a=[],strictMode:o=!1}=e,s=[];return n.forEach(e=>{let n=t[e];if(!n){if(o)throw Error(`Primary key column "${e}" not found in columnMap`);return}s.push({key:e,name:e,columnType:n.colType,columnRenderMode:i[e],frozen:!0,isPrimaryKey:!0})}),r.forEach(e=>{if(n.includes(e)||a.includes(e))return;let r=t[e];if(!r){if(o)throw Error(`Pinned column "${e}" not found in columnMap`);return}s.push({key:r.key,name:e,columnType:r.colType,columnRenderMode:i[e],frozen:!0})}),Object.entries(t).forEach(([e,t])=>{n.includes(e)||r.includes(e)||a.includes(e)||s.push({key:t.key,name:e,columnType:t.colType,columnRenderMode:i[e]})}),s}function j(e,t){return[{value:`Show raw value`,onClick:()=>{t({[e]:`raw`})}},{value:`Show 2 decimal points`,onClick:()=>{t({[e]:2})}},{value:`Show as percentage`,onClick:()=>{t({[e]:`percent`})}},{value:`Show with net change`,onClick:()=>{t({[e]:`delta`})}}]}function M({value:t,colorPalette:n,grayOut:r,noCopy:a,fontSize:l,onCopy:u}){let[d,f]=i(!1),p=e[n][800],m=e[n][100];return s(c,{sx:{display:`flex`,p:`2px 5px`,minWidth:`30px`,maxWidth:`200px`,overflow:`hidden`,textOverflow:`ellipsis`,color:p,bgcolor:m,alignItems:`center`,gap:`2px`,borderRadius:`8px`,fontSize:l,flexShrink:a?0:`inherit`},onMouseEnter:()=>{f(!0)},onMouseLeave:()=>{f(!1)},children:[o(c,{sx:{overflow:`hidden`,textOverflow:`ellipsis`,color:r?`gray`:`inherit`},children:t}),o(Oe,{value:t,noCopy:a,grayOut:r,isHovered:d,onCopy:u})]})}function Oe({value:e,noCopy:t,grayOut:n,isHovered:r,onCopy:i}){if(t||n||!r)return null;let a=()=>{i?i(e):typeof navigator<`u`&&navigator.clipboard&&navigator.clipboard.writeText(e)};return o(p,{title:`Copy Value`,children:o(d,{"aria-label":`Copy`,size:`small`,onClick:a,sx:{minWidth:`0.625rem`,height:`0.625rem`,display:`flex`,alignItems:`center`,justifyContent:`center`,p:0,color:`inherit`},children:o(m,{size:`0.625rem`})})})}function ke({name:e,columnStatus:t,columnType:n,primaryKeys:r=[],onPrimaryKeyChange:l,pinnedColumns:u=[],onPinnedColumnsChange:f,onColumnsRenderModeChanged:p}){let[m,h]=i(null),g=!!m,y=e=>{h(e.currentTarget)},S=()=>{h(null)};if(e===`index`)return o(a,{});let C=r.includes(e),w=u.includes(e),re=t!==`added`&&t!==`removed`,T=[];return p&&(T=j(e,p)),s(c,{sx:{display:`flex`,alignItems:`center`,gap:`10px`,width:`100%`},className:`grid-header`,children:[C&&o(te,{}),o(c,{sx:{flex:1,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},children:e}),re&&l&&o(c,{component:C?b:te,className:C?`close-icon`:`key-icon`,sx:{display:C?`block`:`none`,cursor:`pointer`},onClick:C?()=>{l&&l(r.filter(t=>t!==e))}:()=>{l&&l([...r.filter(e=>e!==`index`),e])}}),!C&&f&&o(c,{component:w?ne:x,className:w?`unpin-icon`:`pin-icon`,sx:{display:w?`block`:`none`,cursor:`pointer`},onClick:w?()=>{f&&f(u.filter(t=>t!==e))}:()=>{f&&f([...u,e])}}),!C&&n===`number`&&T.length>0&&s(a,{children:[o(d,{"aria-label":`Options`,size:`small`,className:`!size-4 !min-w-4`,onClick:y,children:o(ee,{})}),o(_,{anchorEl:m,open:g,onClose:S,children:T.map(e=>o(v,{onClick:()=>{e.onClick(),S()},children:e.value},e.value))})]})]})}function Ae({name:e,pinnedColumns:t=[],onPinnedColumnsChange:n=()=>{},columnType:r,onColumnsRenderModeChanged:l}){let[u,f]=i(null),p=!!u,m=e=>{f(e.currentTarget)},g=()=>{f(null)},y=[];l&&(y=j(e,l));let b=t.includes(e);return s(c,{sx:{display:`flex`,alignItems:`center`,width:`100%`},className:`grid-header`,children:[o(c,{sx:{flex:1},children:e}),o(c,{component:b?ne:x,className:b?`unpin-icon`:`pin-icon`,sx:{display:b?`block`:`none`,cursor:`pointer`},onClick:b?()=>{n(t.filter(t=>t!==e))}:()=>{n([...t,e])}}),r===`number`&&s(a,{children:[o(d,{"aria-label":`Options`,size:`small`,className:`size-6!`,sx:{p:0},onClick:m,children:o(h,{})}),o(_,{anchorEl:u,open:p,onClose:g,children:y.map(e=>o(v,{onClick:()=>{e.onClick(),g()},children:e.value},e.value))})]})]})}function N(e){return e.data.map((t,n)=>({...e.columns.reduce((e,n,r)=>(e[n.key]=t[r],e),{}),__status:void 0,_index:n+1}))}function P(e){let t=Number(e);return!Number.isNaN(t)&&Number.isFinite(t)?t:je(e)}function je(e){let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);t=(t<<5)-t+r,t&=t}return Math.abs(t)}function Me(e,t){let n=t.toLowerCase();if(n in e)return e[n];let r=Object.keys(e).find(e=>e.toLowerCase()===n);return r?e[r]:void 0}function Ne(e,t){let n=e[t.toLowerCase()];return n||=e[t.toUpperCase()],n||=e[t],n}function F(e,t=`en-US`,n){return typeof e==`number`?new Intl.NumberFormat(t,n).format(e):e}function Pe(e){let t=e>0&&e<=.001,n=e<1&&e>=.999,r=(t=e)=>F(t,`en-US`,{style:`percent`,minimumFractionDigits:1});return t?`<${r(.001)}`:n?`>${r(.999)}`:r()}function Fe(e){if(typeof e!=`number`)return e;{let t=Math.abs(e),n=10**-2,r=10**3,i=10**6,a=10**9,o=10**12,s=10**15,c=t>=n,l=t>=1,u=t>=r,d=t>=i,f=t>=a,p=t>=o,m=t>=s;if(m||p)return new Intl.NumberFormat(`en-US`,{style:`unit`,unit:`liter`,unitDisplay:`narrow`,maximumFractionDigits:m?0:2}).format(e/0xe8d4a51000).replace(`L`,`T`);if(f||d||u){let t={base:f?a:d?i:r,unit:f?`B`:d?`M`:`K`};return new Intl.NumberFormat(`en-US`,{style:`unit`,unit:`liter`,unitDisplay:`narrow`,maximumFractionDigits:1}).format(e/t.base).replace(`L`,t.unit)}else if(l)return new Intl.NumberFormat(`en-US`,{maximumFractionDigits:2}).format(e);else return new Intl.NumberFormat(`en-US`,{maximumFractionDigits:c?3:2,notation:c||t===0?`standard`:`scientific`}).format(e)}}function I(e,t){let n=[...e],r=[...t],i=[];for(;n.length>0&&r.length>0;)if(i.includes(n[0]))n.shift();else if(i.includes(r[0]))r.shift();else if(n[0]===r[0])i.push(n[0]),n.shift(),r.shift();else if(r.includes(n[0])){let e=r.indexOf(n[0]);for(let t=0;t<e;t++)i.includes(r[t])||i.push(r[t]);i.push(n[0]),n.shift(),r.splice(0,e+1)}else i.push(n[0]),n.shift();return n.forEach(e=>{i.includes(e)||i.push(e)}),r.forEach(e=>{i.includes(e)||i.push(e)}),i}function L(e,t){let n=I(e,t),r={};for(let i of n)e.includes(i)?t.includes(i)?r[i]=void 0:r[i]=`removed`:r[i]=`added`;let i={};e.forEach((e,t)=>{i[e]=t});let a=-1;for(let e of n){let t=i[e];t!=null&&(t>a?a=t:r[e]=`reordered`)}return r}function Ie(e){let t={};return e.columns.forEach((e,n)=>{t[e.name]={key:e.key,index:n,colType:e.type}}),t}function Le(e){let t={};if(e.columns.forEach((e,n)=>{t[e.key]={key:e.key,index:n,colType:e.type}}),!t.in_a)throw Error(`Joined DataFrame missing required 'in_a' column`);if(!t.in_b)throw Error(`Joined DataFrame missing required 'in_b' column`);return t}function Re(e,t){let n={},r=L(e.columns.map(e=>e.key),t.columns.map(e=>e.key));return Object.entries(r).forEach(([r,i])=>{let a=e.columns.find(e=>e.key===r),o=t.columns.find(e=>e.key===r);n[r]={status:i,baseColumnKey:a?.key??`unknown`,currentColumnKey:o?.key??`unknown`,colType:a?.type??o?.type??`unknown`,key:a?.key??o?.key??`unknown`}}),n}function R(e,t){let n=[];for(let r of t){let t=e.find(e=>e.key===r);if(!t)throw Error(`Column ${r} not found`);n.push(t.key)}return n}function z(e,t,n){if(t.length===0)return String(n._index);let r=[];for(let i of t){let t=e.find(e=>e.key===i);if(!t)throw Error(`Primary Column ${i} not found`);let a=n[i];r.push(`${t.name}=${a}`)}return r.join(`|`)}function ze(e,t,n,r){if(!e)return`added`;if(!t)return`removed`;let i=e===t;for(let[a,o]of Object.entries(n)){if(a===`index`||r.includes(a))continue;let n,s;if(i){let r=`base__${o.key}`,i=`current__${o.key}`;n=e[r],s=t[i]}else n=e[o.key],s=t[o.key];if(!y.isEqual(n,s))return`modified`}}function B(e,t=2){let n=F(Object.is(e,-0)?0:e,`en-US`,{maximumFractionDigits:t,roundingMode:`halfEven`})??String(e);return n===`-0`?`0`:n}function V(e,t){return Number.isNaN(e)?`NaN`:Number.isFinite(e)?t===`raw`?String(e):typeof t==`number`?B(e,t):t===`percent`?F(e,`en-US`,{style:`percent`,maximumFractionDigits:2})??String(e):B(e,2):e>0?`∞`:`-∞`}function H(e,t,n,r){let i=Me(e,t);if(i==null)return[`-`,!0];let a,o=!1;return typeof i==`boolean`?a=i.toString():i===``?(a=`(empty)`,o=!0):a=typeof i==`number`?V(i,r):n===`number`?V(parseFloat(i),r):String(i),[a,o]}function Be(e,t,n,r){let i=e.__status;if(i===`removed`)return`diff-cell-removed`;if(i===`added`)return`diff-cell-added`;if(t===`added`||t===`removed`)return;let a=`base__${n}`.toLowerCase(),o=`current__${n}`.toLowerCase();if(!y.isEqual(e[a],e[o]))return r?`diff-cell-removed`:`diff-cell-added`}function Ve(e){if(e===`added`)return`diff-header-added`;if(e===`removed`)return`diff-header-removed`}const He=e=>{let t=e.colDef,n=t?.context?.columnType,r=t?.context?.columnRenderMode,i=t?.field??``;if(!e.data)return null;let[a,s]=H(e.data,i,n,r);return o(u,{component:`span`,style:{color:s?`gray`:`inherit`},children:a})};t(null);let Ue=0;const U=new Set,W={create:e=>{let t=e.id||`toast-${++Ue}`;return U.forEach(n=>n({type:`create`,options:{...e,id:t}})),t},success:e=>W.create({...e,type:`success`}),error:e=>W.create({...e,type:`error`}),warning:e=>W.create({...e,type:`warning`}),info:e=>W.create({...e,type:`info`}),loading:e=>W.create({...e,type:`loading`}),dismiss:e=>{U.forEach(t=>t({type:`dismiss`,id:e}))},remove:e=>{U.forEach(t=>t({type:`dismiss`,id:e}))},update:(e,t)=>{U.forEach(n=>n({type:`update`,id:e,options:t}))},subscribe:e=>(U.add(e),()=>U.delete(e))};function We(){function e(e){W.create({description:e,type:`info`,duration:5e3,closable:!0})}function t(e,t){W.create({title:e,description:String(t),type:`error`,duration:5e3,closable:!0})}return{successToast:e,failToast:t}}function Ge(e){let[,t]=T(),{successToast:n}=We(),r=e=>{t(e),n(`${e} copied`)};return o(M,{...e,onCopy:r})}function Ke(e={}){let t=e.DiffTextComponent??M;return e=>{let n=e.colDef,r=n?.context?.columnType,i=n?.context?.columnRenderMode,a=n?.field??``;if(!e.data)return null;let l=e.data,d=`base__${a}`.toLowerCase(),f=`current__${a}`.toLowerCase();if(!Object.hasOwn(l,d)&&!Object.hasOwn(l,f))return`-`;let m=Object.hasOwn(l,d),h=Object.hasOwn(l,f),[g,_]=H(l,`base__${a}`.toLowerCase(),r,i),[v,y]=H(l,`current__${a}`.toLowerCase(),r,i);if(l[d]===l[f])return o(u,{component:`span`,style:{color:y?`gray`:`inherit`},children:v});if(i===`delta`&&(r===`number`||r===`integer`)&&m&&h){let e=Je(l[d]),n=Je(l[f]);if(Number.isFinite(e)&&Number.isFinite(n)){let r=n-e,i=e===0?0:r/e*100,a=B(n),l=B(r),d=`(${r>=0?`+`:``}${l})`;return o(p,{title:`Base: ${e}\nCurrent: ${n}\nChange: ${r>=0?`+`:``}${r} (${i>=0?`+`:``}${i.toFixed(2)}%)`,slotProps:{tooltip:{sx:{whiteSpace:`pre-line`}}},enterDelay:300,placement:`top`,children:s(c,{gap:`5px`,display:`flex`,alignItems:`center`,lineHeight:`normal`,height:`100%`,children:[o(t,{value:a,colorPalette:`green`,grayOut:y}),o(u,{fontSize:`0.75rem`,color:r>=0?`green.600`:`red.600`,children:d})]})})}}return s(c,{sx:{display:`flex`,gap:`5px`,alignItems:`center`,lineHeight:`normal`,height:`100%`},children:[m&&o(t,{value:g,colorPalette:`red`,grayOut:_}),h&&o(t,{value:v,colorPalette:`green`,grayOut:y})]})}}const qe=Ke({DiffTextComponent:Ge});function Je(e){if(typeof e==`number`)return e;if(typeof e==`string`){let t=Number.parseFloat(e);return Number.isNaN(t)?0:t}return 0}function Ye(e,t){return n=>{let r=n.data;if(!r)return;let i=r.__status;if(i===`removed`)return`diff-cell-removed`;if(i===`added`)return`diff-cell-added`;if(t===`added`||t===`removed`)return;let a=`base__${e}`.toLowerCase(),o=`current__${e}`.toLowerCase();if(!y.isEqual(r[a],r[o]))return`diff-cell-removed`}}function Xe(e,t){return n=>{let r=n.data;if(!r)return;let i=r.__status;if(i===`removed`)return`diff-cell-removed`;if(i===`added`)return`diff-cell-added`;if(t===`added`||t===`removed`)return;let a=`base__${e}`.toLowerCase(),o=`current__${e}`.toLowerCase();if(!y.isEqual(r[a],r[o]))return`diff-cell-added`}}function G(e){let{name:t,columnStatus:n,columnType:r,columnRenderMode:i,displayMode:a,baseTitle:s=`Base`,currentTitle:c=`Current`,headerProps:l={},renderComponents:u}=e,{DataFrameColumnGroupHeader:d,defaultRenderCell:f,inlineRenderCell:p}=u,m=Ve(n),h=()=>o(d,{name:t,columnStatus:n,columnType:r,...l});if(a===`inline`)return{field:t,headerName:t,headerClass:m,headerComponent:h,cellRenderer:p,context:{columnType:r,columnRenderMode:i}};let g=Ye(t,n),_=Xe(t,n);return{headerName:t,headerClass:m,headerGroupComponent:h,context:{columnType:r,columnRenderMode:i},children:[{field:`base__${t}`,headerName:s,headerClass:m,cellClass:g,cellRenderer:f,context:{columnType:r,columnRenderMode:i}},{field:`current__${t}`,headerName:c,headerClass:m,cellClass:_,cellRenderer:f,context:{columnType:r,columnRenderMode:i}}]}}function Ze(){return{field:`_index`,headerName:``,width:50,maxWidth:100,cellClass:`index-column`,resizable:!1,pinned:`left`}}function Qe(e,t,n){let{key:r,name:i,columnType:a,columnStatus:s,columnRenderMode:c}=e,{DataFrameColumnGroupHeader:l,defaultRenderCell:u}=n;return{field:r,headerName:i,headerComponent:()=>o(l,{name:i,columnStatus:s??``,columnType:a,...t}),pinned:`left`,cellClass:e=>{if(e.data?.__status)return`diff-header-${e.data.__status}`},cellRenderer:u,context:{columnType:a,columnRenderMode:c}}}function $e(e,t,n,r,i,a){let{name:o,columnType:s,columnStatus:c,columnRenderMode:l}=e;return G({name:o,columnStatus:c??``,columnType:s,columnRenderMode:l,displayMode:t,baseTitle:i,currentTitle:a,headerProps:n,renderComponents:r})}function K(e){let{columns:t,displayMode:n,headerProps:r,baseTitle:i,currentTitle:a,allowIndexFallback:o=!1,renderComponents:s}=e,c=[],l=!1;!t.some(e=>e.isPrimaryKey)&&o&&(c.push(Ze()),l=!0);for(let e of t)if(e.isPrimaryKey)c.push(Qe(e,r,s));else{let t=$e(e,n,r,s,i,a);c.push({...t,pinned:e.frozen?`left`:void 0})}return{columns:c,usedIndexFallback:l}}function et(e){return`baseColumnKey`in e&&`currentColumnKey`in e}function tt(e,t){return t.includes(e)}function nt(e){return et(e)?{baseKey:e.baseColumnKey,currentKey:e.currentColumnKey}:{baseKey:e.key,currentKey:e.key}}function rt(e,t,n,r,i){n.forEach(n=>{let a=n.key;tt(a,i)?e[String(a).toLowerCase()]=t[a]:e[`${r}${a}`.toLowerCase()]=t[a]})}function it(e,t,n,r){let i=!1;for(let[a,o]of Object.entries(n)){if(a===`index`||tt(a,r))continue;let{baseKey:n,currentKey:s}=nt(o);if(n===`unknown`||s===`unknown`)continue;let c=e[n],l=t[s];y.isEqual(c,l)||(i=!0,o.status=`modified`)}return i}function q(e){let{baseMap:t,currentMap:n,baseColumns:r,currentColumns:i,columnMap:a,primaryKeys:o,changedOnly:s=!1}=e,c=L(Object.keys(t),Object.keys(n)),l={added:0,removed:0,modified:0},u=Object.entries(c).map(([e])=>{let s=t[e],c=n[e],u={_index:P(e),__status:void 0};return s&&rt(u,s,r,`base__`,o),c&&rt(u,c,i,`current__`,o),s?c?it(s,c,a,o)&&(u.__status=`modified`,l.modified++):(u.__status=`removed`,l.removed++):(u.__status=`added`,l.added++),u});return s&&(u=u.filter(e=>e.__status===`added`||e.__status===`removed`||e.__status===`modified`)),{rows:u,rowStats:l}}var J=class extends Error{constructor(e,t,n){super(t?`[${t}] ${e}`:e),this.context=t,this.details=n,this.name=`DataGridValidationError`}};function Y(e,t=`DataFrame`){if(e!=null){if(typeof e!=`object`)throw new J(`Expected an object, got ${typeof e}`,t);if(!(`columns`in e))throw new J(`Missing 'columns' property`,t,{receivedKeys:Object.keys(e)});if(!Array.isArray(e.columns))throw new J(`'columns' must be an array, got ${typeof e.columns}`,t);if(!(`data`in e))throw new J(`Missing 'data' property`,t,{receivedKeys:Object.keys(e)});if(!Array.isArray(e.data))throw new J(`'data' must be an array, got ${typeof e.data}`,t);at(e.columns,t),e.data.length>0&&ot(e,t)}}function at(e,t=`DataFrame`){e.forEach((e,n)=>{if(!e||typeof e!=`object`)throw new J(`Column at index ${n} is not an object`,t,{column:e});if(typeof e.key!=`string`||e.key===``)throw new J(`Column at index ${n} has invalid 'key': expected non-empty string, got ${JSON.stringify(e.key)}`,t,{column:e});if(typeof e.name!=`string`)throw new J(`Column '${e.key}' has invalid 'name': expected string, got ${typeof e.name}`,t,{column:e});if(typeof e.type!=`string`)throw new J(`Column '${e.key}' has invalid 'type': expected string, got ${typeof e.type}`,t,{column:e})})}function ot(e,t=`DataFrame`){let n=e.columns.length;for(let r=0;r<e.data.length;r++){let i=e.data[r];if(!Array.isArray(i))throw new J(`Row at index ${r} is not an array`,t,{row:i,rowType:typeof i});if(i.length!==n)throw new J(`Row ${r} has ${i.length} values but expected ${n} (column count)`,t,{rowIndex:r,rowLength:i.length,columnCount:n,columns:e.columns.map(e=>e.key)})}}function X(e,t,n={}){let{required:r=!1,caseInsensitive:i=!1,context:a=`primaryKeys`}=n;if(r&&(!e||e.length===0))throw new J(`Primary keys are required but none were provided`,a);if(!e||e.length===0)return;let o=t.map(e=>e.key),s=i?o.map(e=>e.toLowerCase()):o;for(let t of e){let e=i?t.toLowerCase():t;if(!(i?s.includes(e):o.includes(t)))throw new J(`Primary key column '${t}' not found in columns`,a,{requestedKey:t,availableColumns:o,caseInsensitive:i})}let c=new Set;for(let t of e){let n=i?t.toLowerCase():t;if(c.has(n))throw new J(`Duplicate primary key: '${t}'`,a,{primaryKeys:e});c.add(n)}}function st(e,t){Y(e,`dataframe`),e&&t?.primaryKeys&&X(t.primaryKeys,e.columns,{context:`toDataGrid`})}function ct(e,t,n){if(Y(e,`base`),Y(t,`current`),n?.primaryKeys&&n.primaryKeys.length>0){let r=e?.columns??[],i=t?.columns??[],a=new Set([...r.map(e=>e.key),...i.map(e=>e.key)]);for(let e of n.primaryKeys)if(!a.has(e))throw new J(`Primary key column '${e}' not found in either base or current DataFrame`,`toDataDiffGrid`,{requestedKey:e,baseColumns:r.map(e=>e.key),currentColumns:i.map(e=>e.key)})}}function lt(e,t){if(!e)throw new J(`DataFrame is required for value diff`);if(Y(e),!t||t.length===0)throw new J(`Primary keys are required for value diff`);X(t,e.columns,{required:!0,context:`toValueDiffGrid`});let n=e.columns.map(e=>e.key);if(!n.includes(`in_a`))throw new J(`Value diff DataFrame must include lowercase 'in_a' column`);if(!n.includes(`in_b`))throw new J(`Value diff DataFrame must include lowercase 'in_b' column`)}function ut(e,t,n,r){ct(e,t,n);let i=e??{columns:[],data:[]},a=t??{columns:[],data:[]},o=n?.primaryKeys??[],s=n?.pinnedColumns??[],c=n?.changedOnly??!1,l=n?.displayMode??`side_by_side`,u=n?.columnsRenderMode??{},d=N(i),f=N(a),p=Re(i,a),m={},h={},g=!1,_=!1;if(o.length===0)d.forEach(e=>{m[String(e._index)]=e}),f.forEach(e=>{h[String(e._index)]=e});else{let e=R(i.columns,o);d.forEach(t=>{let n=z(i.columns,e,t);n in m&&(g=!0),m[n]=t});let t=R(a.columns,o);f.forEach(e=>{let n=z(a.columns,t,e);n in h&&(_=!0),h[n]=e})}let{rows:v,rowStats:y}=q({baseMap:m,currentMap:h,baseColumns:i.columns,currentColumns:a.columns,columnMap:p,primaryKeys:o,changedOnly:c}),{columns:b}=K({columns:A({columnMap:p,primaryKeys:o,pinnedColumns:s,columnsRenderMode:u,changedOnly:c,rowStats:y,excludeColumns:[`index`],strictMode:!1}),displayMode:l,allowIndexFallback:!0,baseTitle:n?.baseTitle,currentTitle:n?.currentTitle,headerProps:{primaryKeys:o,pinnedColumns:s,onPrimaryKeyChange:n?.onPrimaryKeyChange,onPinnedColumnsChange:n?.onPinnedColumnsChange,onColumnsRenderModeChanged:n?.onColumnsRenderModeChanged},renderComponents:r?.renderComponents??{DataFrameColumnGroupHeader:()=>null,defaultRenderCell:()=>null,inlineRenderCell:()=>null}});return{columns:b,rows:v,invalidPKeyBase:g,invalidPKeyCurrent:_}}function dt(){return{field:`_index`,headerName:``,width:50,cellClass:`index-column`,resizable:!1,pinned:`left`}}function ft(e,t,n){let{key:r,name:i,columnType:a,columnRenderMode:s}=e,{DataFrameColumnGroupHeader:c,defaultRenderCell:l}=n;return{field:r,headerName:i,headerComponent:()=>o(c,{name:i,columnStatus:``,columnType:a,pinnedColumns:t.pinnedColumns,onPinnedColumnsChange:t.onPinnedColumnsChange,onColumnsRenderModeChanged:t.onColumnsRenderModeChanged}),pinned:`left`,cellRenderer:l,context:{columnType:a,columnRenderMode:s}}}function pt(e,t,n){let{key:r,name:i,columnType:a,columnRenderMode:s}=e,{DataFrameColumnHeader:c,defaultRenderCell:l}=n;return{field:r,headerName:i,headerComponent:()=>o(c,{name:i,columnType:a,pinnedColumns:t.pinnedColumns,onPinnedColumnsChange:t.onPinnedColumnsChange,onColumnsRenderModeChanged:t.onColumnsRenderModeChanged}),cellRenderer:l,context:{columnType:a,columnRenderMode:s}}}function Z(e){let{columns:t,headerProps:n,allowIndexFallback:r=!0,renderComponents:i}=e,a=[],o=!1;!t.some(e=>e.isPrimaryKey)&&r&&(a.push(dt()),o=!0);for(let e of t)if(e.isPrimaryKey)a.push(ft(e,n,i));else{let t=pt(e,n,i);a.push({...t,pinned:e.frozen?`left`:void 0})}return{columns:a,usedIndexFallback:o}}function mt(e,t,n){st(e,t);let r=t.primaryKeys??[],i=t.pinnedColumns??[],a=t.columnsRenderMode??{},{columns:o}=Z({columns:De({columnMap:Ie(e),primaryKeys:r,pinnedColumns:i,columnsRenderMode:a}),headerProps:{pinnedColumns:i,onPinnedColumnsChange:t.onPinnedColumnsChange,onColumnsRenderModeChanged:t.onColumnsRenderModeChanged},allowIndexFallback:!0,renderComponents:n.renderComponents});return{columns:o,rows:N(e)}}function ht(e,t,n,r){lt(e,t);let i=n?.pinnedColumns??[],a=n?.changedOnly??!1,o=n?.displayMode??`inline`,s=n?.columnsRenderMode??{},c=N(e),l=Le(e),u={},d={},f=R(e.columns,t),p=l.in_a.key,m=l.in_b.key;c.forEach(t=>{let n=z(e.columns,f,t);t[p]&&(u[n.toLowerCase()]=t),t[m]&&(d[n.toLowerCase()]=t)});let{rows:h,rowStats:g}=q({baseMap:u,currentMap:d,baseColumns:e.columns,currentColumns:e.columns,columnMap:l,primaryKeys:t,changedOnly:a}),{columns:_}=K({columns:A({columnMap:l,primaryKeys:t,pinnedColumns:i,columnsRenderMode:s,changedOnly:a,rowStats:g,excludeColumns:[`in_a`,`in_b`],strictMode:!0}),displayMode:o,allowIndexFallback:!1,baseTitle:n?.baseTitle,currentTitle:n?.currentTitle,headerProps:{primaryKeys:t,pinnedColumns:i,onPinnedColumnsChange:n?.onPinnedColumnsChange,onColumnsRenderModeChanged:n?.onColumnsRenderModeChanged},renderComponents:r?.renderComponents??{DataFrameColumnGroupHeader:()=>null,defaultRenderCell:()=>null,inlineRenderCell:()=>null}});return{columns:_,rows:h}}const Q={DataFrameColumnGroupHeader:ke,defaultRenderCell:He,inlineRenderCell:qe},$={DataFrameColumnGroupHeader:ke,DataFrameColumnHeader:Ae,defaultRenderCell:He};function gt(e){return G({...e,renderComponents:Q})}function _t(e){return K({...e,renderComponents:Q})}function vt(e,t,n){return ut(e,t,n,{renderComponents:Q})}function yt(e,t,n){return ht(e,t,n,{renderComponents:Q})}function bt(e,t){return mt(e,t,{renderComponents:$})}function xt(e){return Z({...e,renderComponents:$})}function St(e,t){if(e===0&&t!==0)return`N/A`;if(e<t){let n=(t-e)/e*100;return`+${n>=.1?n.toFixed(1):` <0.1 `}%`}else if(e>t){let n=(e-t)/e*100;return`-${n>=.1?n.toFixed(1):` <0.1 `}%`}else return`0`}function Ct(e,t){return e!==null&&t!==null?e===t?`0`:St(e,t):e===t?`N/A`:e===null?`Added`:t===null?`Removed`:`N/A`}function wt(e){return{columns:[{key:`name`,name:`Name`,type:`text`},{key:`base`,name:`Base Rows`,type:`number`},{key:`current`,name:`Current Rows`,type:`number`},{key:`delta`,name:`Delta`,type:`text`}],data:Object.entries(e).map(([e,t])=>{let n=typeof t.base==`number`?t.base:null,r=typeof t.curr==`number`?t.curr:null;return[e,n,r,Ct(n,r)]})}}function Tt(e){return{columns:[{key:`name`,name:`Name`,type:`text`},{key:`current`,name:`Row Count`,type:`number`}],data:Object.entries(e).map(([e,t])=>[e,typeof t.curr==`number`?t.curr:null])}}function Et(e,t){if(e===null&&t!==null)return`added`;if(e!==null&&t===null)return`removed`;if(e!==null&&t!==null&&e!==t)return`modified`}function Dt(e){return{columns:[{field:`name`,headerName:`Name`,resizable:!0},{field:`current`,headerName:`Row Count`,resizable:!0}],rows:N(Tt(e)).map(e=>({...e,current:e.current??`N/A`,__status:void 0}))}}function Ot(){return e=>{let t=e.data;if(!t)return;let n=t.base,r=t.current,i=n===`N/A`?null:n,a=r===`N/A`?null:r;if(i!==a){if(i===null||typeof i==`number`&&typeof a==`number`&&i<a)return`diff-cell-added`;if(a===null||typeof i==`number`&&typeof a==`number`&&i>a)return`diff-cell-removed`}}}function kt(e){let t=N(wt(e)).map(e=>{let t=e.base,n=e.current;return{...e,base:t??`N/A`,current:n??`N/A`,__status:Et(typeof t==`number`?t:null,typeof n==`number`?n:null)}}),n=Ot();return{columns:[{field:`name`,headerName:`Name`,resizable:!0,cellClass:n},{field:`base`,headerName:`Base Rows`,resizable:!0,cellClass:n},{field:`current`,headerName:`Current Rows`,resizable:!0,cellClass:n},{field:`delta`,headerName:`Delta`,resizable:!0,cellClass:n}],rows:t}}function At(e){let t=new Set,n=new Set;if(e?.nodes){let r=Object.values(e.nodes);for(let e of r)e.data.data.base?.schema&&t.add(e.data.data.base.schema),e.data.data.current?.schema&&n.add(e.data.data.current.schema)}return[t,n]}function jt(e,t){let n=I(e,t);if(n.length===0)return[];if(e.length===0||t.length===0)return n.map((e,t)=>t===n.length-1?e:e+`,`);let r=``;return n.forEach(n=>{e.includes(n)&&t.includes(n)&&(r=n)}),n.map((i,a)=>{let o;return o=e.includes(i)?t.includes(i)?i:`--- ${i} (Removed)`:`--- ${i} (Added)`,i===r||a===n.length-1?o:o+`,`})}function Mt(e){let t=Math.floor(e);return{hours:Math.floor(t/3600),minutes:Math.floor(t%3600/60),seconds:t%60}}function Nt({hours:e,minutes:t,seconds:n}){return e>0?`${e}:${t.toString().padStart(2,`0`)}:${n.toString().padStart(2,`0`)}`:`${t}:${n.toString().padStart(2,`0`)}`}function Pt({hours:e,minutes:t,seconds:n}){let r=[];return e>0&&r.push(`${e} hour${e===1?``:`s`}`),t>0&&r.push(`${t} min${t===1?``:`s`}`),e===0&&(r.length===0||n>0)&&r.push(`${n} second${n===1?``:`s`}`),r.join(` `)}function Ft(e,t=`verbose`){let n=Mt(e);return t===`compact`?Nt(n):Pt(n)}function It(e){return S(w(e),`yyyy-MM-dd'T'HH:mm:ss`)}function Lt(e){return C(w(e),new Date,{addSuffix:!0})}function Rt(e,t){if(!e||!t)return;let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!0;for(let e=0;e<n.length;e++)if(n[e]!==r[e])return!0;for(let n of r)if(!e[n]||e[n].type!==t[n]?.type)return!0;return!1}function zt(e,t){return e?.organization_name&&e.web_url?`${e.web_url}/organizations/${e.organization_name}/settings`:t}export{I as $,Y as A,We as B,ht as C,ae as Ct,J as D,ut as E,q as F,V as G,Ie as H,K as I,Be as J,ze as K,Ye as L,ct as M,st as N,ot as O,lt as P,R as Q,Xe as R,yt as S,ye as St,Z as T,Le as U,W as V,Re as W,z as X,Ve as Y,H as Z,Q as _,Te as _t,It as a,Me as at,bt as b,xe as bt,kt as c,P as ct,Et as d,we as dt,L as et,wt as f,A as ft,xt as g,D as gt,_t as h,O as ht,Lt as i,N as it,X as j,at as k,Dt as l,M as lt,St as m,k as mt,Rt as n,Pe as nt,jt as o,Ne as ot,Tt as p,De as pt,B as q,Ft as r,F as rt,At as s,je as st,zt as t,Fe as tt,Ct as u,j as ut,$ as v,Ce as vt,mt as w,ie as wt,gt as x,ve as xt,vt as y,Se as yt,G as z};
5
+ //# sourceMappingURL=utils-CXWhfyxC.js.map