react-native-debug-toolkit 0.6.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +149 -211
  3. package/README.zh-CN.md +150 -171
  4. package/lib/commonjs/components/ClipboardTab.js +91 -0
  5. package/lib/commonjs/components/ClipboardTab.js.map +1 -0
  6. package/lib/commonjs/components/ConsoleLogTab.js +162 -0
  7. package/lib/commonjs/components/ConsoleLogTab.js.map +1 -0
  8. package/lib/commonjs/components/DebugPanel.js +230 -0
  9. package/lib/commonjs/components/DebugPanel.js.map +1 -0
  10. package/lib/commonjs/components/DebugView.js +66 -0
  11. package/lib/commonjs/components/DebugView.js.map +1 -0
  12. package/lib/commonjs/components/EnvironmentTab.js +287 -0
  13. package/lib/commonjs/components/EnvironmentTab.js.map +1 -0
  14. package/lib/commonjs/components/FeatureTabBar.js +182 -0
  15. package/lib/commonjs/components/FeatureTabBar.js.map +1 -0
  16. package/lib/commonjs/components/FloatIcon.js +187 -0
  17. package/lib/commonjs/components/FloatIcon.js.map +1 -0
  18. package/lib/commonjs/components/FloatPanelView.js +214 -0
  19. package/lib/commonjs/components/FloatPanelView.js.map +1 -0
  20. package/lib/commonjs/components/NavigationLogTab.js +131 -0
  21. package/lib/commonjs/components/NavigationLogTab.js.map +1 -0
  22. package/lib/commonjs/components/NetworkLogTab.js +404 -0
  23. package/lib/commonjs/components/NetworkLogTab.js.map +1 -0
  24. package/lib/commonjs/components/ThirdPartyLibsTab.js +97 -0
  25. package/lib/commonjs/components/ThirdPartyLibsTab.js.map +1 -0
  26. package/lib/commonjs/components/TrackLogTab.js +230 -0
  27. package/lib/commonjs/components/TrackLogTab.js.map +1 -0
  28. package/lib/commonjs/components/ZustandLogTab.js +311 -0
  29. package/lib/commonjs/components/ZustandLogTab.js.map +1 -0
  30. package/lib/commonjs/components/shared/CollapsibleSection.js +84 -0
  31. package/lib/commonjs/components/shared/CollapsibleSection.js.map +1 -0
  32. package/lib/commonjs/components/shared/CopyButton.js +64 -0
  33. package/lib/commonjs/components/shared/CopyButton.js.map +1 -0
  34. package/lib/commonjs/components/shared/JsonView.js +157 -0
  35. package/lib/commonjs/components/shared/JsonView.js.map +1 -0
  36. package/lib/commonjs/components/shared/LogListScreen.js +174 -0
  37. package/lib/commonjs/components/shared/LogListScreen.js.map +1 -0
  38. package/lib/commonjs/core/DebugToolkit.js +122 -0
  39. package/lib/commonjs/core/DebugToolkit.js.map +1 -0
  40. package/lib/commonjs/core/DebugToolkitProvider.js +66 -0
  41. package/lib/commonjs/core/DebugToolkitProvider.js.map +1 -0
  42. package/lib/commonjs/features/ClipboardFeature.js +21 -0
  43. package/lib/commonjs/features/ClipboardFeature.js.map +1 -0
  44. package/lib/commonjs/features/ConsoleLogFeature.js +115 -0
  45. package/lib/commonjs/features/ConsoleLogFeature.js.map +1 -0
  46. package/lib/commonjs/features/EnvironmentFeature.js +160 -0
  47. package/lib/commonjs/features/EnvironmentFeature.js.map +1 -0
  48. package/lib/commonjs/features/NavigationLogFeature.js +39 -0
  49. package/lib/commonjs/features/NavigationLogFeature.js.map +1 -0
  50. package/lib/commonjs/features/NetworkFeature.js +107 -0
  51. package/lib/commonjs/features/NetworkFeature.js.map +1 -0
  52. package/lib/commonjs/features/ThirdPartyLibsFeature.js +51 -0
  53. package/lib/commonjs/features/ThirdPartyLibsFeature.js.map +1 -0
  54. package/lib/commonjs/features/TrackFeature.js +34 -0
  55. package/lib/commonjs/features/TrackFeature.js.map +1 -0
  56. package/lib/commonjs/features/ZustandLogFeature.js +59 -0
  57. package/lib/commonjs/features/ZustandLogFeature.js.map +1 -0
  58. package/lib/commonjs/hooks/useNavigationLogger.js +78 -0
  59. package/lib/commonjs/hooks/useNavigationLogger.js.map +1 -0
  60. package/lib/commonjs/hooks/useSlideDetailAnimation.js +53 -0
  61. package/lib/commonjs/hooks/useSlideDetailAnimation.js.map +1 -0
  62. package/lib/commonjs/index.js +152 -0
  63. package/lib/commonjs/index.js.map +1 -0
  64. package/lib/commonjs/initialize.js +84 -0
  65. package/lib/commonjs/initialize.js.map +1 -0
  66. package/lib/commonjs/interceptors/networkInterceptor.js +466 -0
  67. package/lib/commonjs/interceptors/networkInterceptor.js.map +1 -0
  68. package/lib/commonjs/native/NativeDebugLibs.js +58 -0
  69. package/lib/commonjs/native/NativeDebugLibs.js.map +1 -0
  70. package/lib/commonjs/package.json +1 -0
  71. package/lib/commonjs/types/index.js +6 -0
  72. package/lib/commonjs/types/index.js.map +1 -0
  73. package/lib/commonjs/utils/colors.js +48 -0
  74. package/lib/commonjs/utils/colors.js.map +1 -0
  75. package/lib/commonjs/utils/copyToComputer.js +97 -0
  76. package/lib/commonjs/utils/copyToComputer.js.map +1 -0
  77. package/lib/commonjs/utils/createChannelFeature.js +48 -0
  78. package/lib/commonjs/utils/createChannelFeature.js.map +1 -0
  79. package/lib/commonjs/utils/createEventChannel.js +21 -0
  80. package/lib/commonjs/utils/createEventChannel.js.map +1 -0
  81. package/lib/commonjs/utils/createObservableStore.js +38 -0
  82. package/lib/commonjs/utils/createObservableStore.js.map +1 -0
  83. package/lib/commonjs/utils/layout.js +8 -0
  84. package/lib/commonjs/utils/layout.js.map +1 -0
  85. package/lib/commonjs/utils/safeStringify.js +27 -0
  86. package/lib/commonjs/utils/safeStringify.js.map +1 -0
  87. package/lib/commonjs/utils/urlRewriterRegistry.js +14 -0
  88. package/lib/commonjs/utils/urlRewriterRegistry.js.map +1 -0
  89. package/lib/module/components/ClipboardTab.js +86 -0
  90. package/lib/module/components/ClipboardTab.js.map +1 -0
  91. package/lib/module/components/ConsoleLogTab.js +157 -0
  92. package/lib/module/components/ConsoleLogTab.js.map +1 -0
  93. package/lib/module/components/DebugPanel.js +225 -0
  94. package/lib/module/components/DebugPanel.js.map +1 -0
  95. package/lib/module/components/DebugView.js +61 -0
  96. package/lib/module/components/DebugView.js.map +1 -0
  97. package/lib/module/components/EnvironmentTab.js +282 -0
  98. package/lib/module/components/EnvironmentTab.js.map +1 -0
  99. package/lib/module/components/FeatureTabBar.js +177 -0
  100. package/lib/module/components/FeatureTabBar.js.map +1 -0
  101. package/lib/module/components/FloatIcon.js +182 -0
  102. package/lib/module/components/FloatIcon.js.map +1 -0
  103. package/lib/module/components/FloatPanelView.js +209 -0
  104. package/lib/module/components/FloatPanelView.js.map +1 -0
  105. package/lib/module/components/NavigationLogTab.js +126 -0
  106. package/lib/module/components/NavigationLogTab.js.map +1 -0
  107. package/lib/module/components/NetworkLogTab.js +399 -0
  108. package/lib/module/components/NetworkLogTab.js.map +1 -0
  109. package/lib/module/components/ThirdPartyLibsTab.js +91 -0
  110. package/lib/module/components/ThirdPartyLibsTab.js.map +1 -0
  111. package/lib/module/components/TrackLogTab.js +225 -0
  112. package/lib/module/components/TrackLogTab.js.map +1 -0
  113. package/lib/module/components/ZustandLogTab.js +306 -0
  114. package/lib/module/components/ZustandLogTab.js.map +1 -0
  115. package/lib/module/components/shared/CollapsibleSection.js +78 -0
  116. package/lib/module/components/shared/CollapsibleSection.js.map +1 -0
  117. package/lib/module/components/shared/CopyButton.js +58 -0
  118. package/lib/module/components/shared/CopyButton.js.map +1 -0
  119. package/lib/module/components/shared/JsonView.js +152 -0
  120. package/lib/module/components/shared/JsonView.js.map +1 -0
  121. package/lib/module/components/shared/LogListScreen.js +169 -0
  122. package/lib/module/components/shared/LogListScreen.js.map +1 -0
  123. package/lib/module/core/DebugToolkit.js +118 -0
  124. package/lib/module/core/DebugToolkit.js.map +1 -0
  125. package/lib/module/core/DebugToolkitProvider.js +60 -0
  126. package/lib/module/core/DebugToolkitProvider.js.map +1 -0
  127. package/lib/module/features/ClipboardFeature.js +16 -0
  128. package/lib/module/features/ClipboardFeature.js.map +1 -0
  129. package/lib/module/features/ConsoleLogFeature.js +109 -0
  130. package/lib/module/features/ConsoleLogFeature.js.map +1 -0
  131. package/lib/module/features/EnvironmentFeature.js +156 -0
  132. package/lib/module/features/EnvironmentFeature.js.map +1 -0
  133. package/lib/module/features/NavigationLogFeature.js +32 -0
  134. package/lib/module/features/NavigationLogFeature.js.map +1 -0
  135. package/lib/module/features/NetworkFeature.js +101 -0
  136. package/lib/module/features/NetworkFeature.js.map +1 -0
  137. package/lib/module/features/ThirdPartyLibsFeature.js +46 -0
  138. package/lib/module/features/ThirdPartyLibsFeature.js.map +1 -0
  139. package/lib/module/features/TrackFeature.js +27 -0
  140. package/lib/module/features/TrackFeature.js.map +1 -0
  141. package/lib/module/features/ZustandLogFeature.js +53 -0
  142. package/lib/module/features/ZustandLogFeature.js.map +1 -0
  143. package/lib/module/hooks/useNavigationLogger.js +74 -0
  144. package/lib/module/hooks/useNavigationLogger.js.map +1 -0
  145. package/lib/module/hooks/useSlideDetailAnimation.js +50 -0
  146. package/lib/module/hooks/useSlideDetailAnimation.js.map +1 -0
  147. package/lib/module/index.js +28 -0
  148. package/lib/module/index.js.map +1 -0
  149. package/lib/module/initialize.js +80 -0
  150. package/lib/module/initialize.js.map +1 -0
  151. package/lib/module/interceptors/networkInterceptor.js +460 -0
  152. package/lib/module/interceptors/networkInterceptor.js.map +1 -0
  153. package/lib/module/native/NativeDebugLibs.js +54 -0
  154. package/lib/module/native/NativeDebugLibs.js.map +1 -0
  155. package/lib/module/package.json +1 -0
  156. package/lib/module/types/index.js +4 -0
  157. package/lib/module/types/index.js.map +1 -0
  158. package/lib/module/utils/colors.js +43 -0
  159. package/lib/module/utils/colors.js.map +1 -0
  160. package/lib/module/utils/copyToComputer.js +91 -0
  161. package/lib/module/utils/copyToComputer.js.map +1 -0
  162. package/lib/module/utils/createChannelFeature.js +44 -0
  163. package/lib/module/utils/createChannelFeature.js.map +1 -0
  164. package/lib/module/utils/createEventChannel.js +17 -0
  165. package/lib/module/utils/createEventChannel.js.map +1 -0
  166. package/lib/module/utils/createObservableStore.js +34 -0
  167. package/lib/module/utils/createObservableStore.js.map +1 -0
  168. package/lib/module/utils/layout.js +4 -0
  169. package/lib/module/utils/layout.js.map +1 -0
  170. package/lib/module/utils/safeStringify.js +23 -0
  171. package/lib/module/utils/safeStringify.js.map +1 -0
  172. package/lib/module/utils/urlRewriterRegistry.js +10 -0
  173. package/lib/module/utils/urlRewriterRegistry.js.map +1 -0
  174. package/lib/typescript/src/components/ClipboardTab.d.ts +4 -0
  175. package/lib/typescript/src/components/ClipboardTab.d.ts.map +1 -0
  176. package/lib/typescript/src/components/ConsoleLogTab.d.ts +4 -0
  177. package/lib/typescript/src/components/ConsoleLogTab.d.ts.map +1 -0
  178. package/lib/typescript/src/components/DebugPanel.d.ts +9 -0
  179. package/lib/typescript/src/components/DebugPanel.d.ts.map +1 -0
  180. package/lib/typescript/src/components/DebugView.d.ts +19 -0
  181. package/lib/typescript/src/components/DebugView.d.ts.map +1 -0
  182. package/lib/typescript/src/components/EnvironmentTab.d.ts +4 -0
  183. package/lib/typescript/src/components/EnvironmentTab.d.ts.map +1 -0
  184. package/lib/typescript/src/components/FeatureTabBar.d.ts +13 -0
  185. package/lib/typescript/src/components/FeatureTabBar.d.ts.map +1 -0
  186. package/lib/typescript/src/components/FloatIcon.d.ts +12 -0
  187. package/lib/typescript/src/components/FloatIcon.d.ts.map +1 -0
  188. package/lib/typescript/src/components/FloatPanelView.d.ts +9 -0
  189. package/lib/typescript/src/components/FloatPanelView.d.ts.map +1 -0
  190. package/lib/typescript/src/components/NavigationLogTab.d.ts +4 -0
  191. package/lib/typescript/src/components/NavigationLogTab.d.ts.map +1 -0
  192. package/lib/typescript/src/components/NetworkLogTab.d.ts +4 -0
  193. package/lib/typescript/src/components/NetworkLogTab.d.ts.map +1 -0
  194. package/lib/typescript/src/components/ThirdPartyLibsTab.d.ts +4 -0
  195. package/lib/typescript/src/components/ThirdPartyLibsTab.d.ts.map +1 -0
  196. package/lib/typescript/src/components/TrackLogTab.d.ts +4 -0
  197. package/lib/typescript/src/components/TrackLogTab.d.ts.map +1 -0
  198. package/lib/typescript/src/components/ZustandLogTab.d.ts +4 -0
  199. package/lib/typescript/src/components/ZustandLogTab.d.ts.map +1 -0
  200. package/lib/typescript/src/components/shared/CollapsibleSection.d.ts +9 -0
  201. package/lib/typescript/src/components/shared/CollapsibleSection.d.ts.map +1 -0
  202. package/lib/typescript/src/components/shared/CopyButton.d.ts +12 -0
  203. package/lib/typescript/src/components/shared/CopyButton.d.ts.map +1 -0
  204. package/lib/typescript/src/components/shared/JsonView.d.ts +6 -0
  205. package/lib/typescript/src/components/shared/JsonView.d.ts.map +1 -0
  206. package/lib/typescript/src/components/shared/LogListScreen.d.ts +21 -0
  207. package/lib/typescript/src/components/shared/LogListScreen.d.ts.map +1 -0
  208. package/lib/typescript/src/core/DebugToolkit.d.ts +20 -0
  209. package/lib/typescript/src/core/DebugToolkit.d.ts.map +1 -0
  210. package/lib/typescript/src/core/DebugToolkitProvider.d.ts +15 -0
  211. package/lib/typescript/src/core/DebugToolkitProvider.d.ts.map +1 -0
  212. package/lib/typescript/src/features/ClipboardFeature.d.ts +7 -0
  213. package/lib/typescript/src/features/ClipboardFeature.d.ts.map +1 -0
  214. package/lib/typescript/src/features/ConsoleLogFeature.d.ts +9 -0
  215. package/lib/typescript/src/features/ConsoleLogFeature.d.ts.map +1 -0
  216. package/lib/typescript/src/features/EnvironmentFeature.d.ts +8 -0
  217. package/lib/typescript/src/features/EnvironmentFeature.d.ts.map +1 -0
  218. package/lib/typescript/src/features/NavigationLogFeature.d.ts +10 -0
  219. package/lib/typescript/src/features/NavigationLogFeature.d.ts.map +1 -0
  220. package/lib/typescript/src/features/NetworkFeature.d.ts +15 -0
  221. package/lib/typescript/src/features/NetworkFeature.d.ts.map +1 -0
  222. package/lib/typescript/src/features/ThirdPartyLibsFeature.d.ts +3 -0
  223. package/lib/typescript/src/features/ThirdPartyLibsFeature.d.ts.map +1 -0
  224. package/lib/typescript/src/features/TrackFeature.d.ts +14 -0
  225. package/lib/typescript/src/features/TrackFeature.d.ts.map +1 -0
  226. package/lib/typescript/src/features/ZustandLogFeature.d.ts +31 -0
  227. package/lib/typescript/src/features/ZustandLogFeature.d.ts.map +1 -0
  228. package/lib/typescript/src/hooks/useNavigationLogger.d.ts +13 -0
  229. package/lib/typescript/src/hooks/useNavigationLogger.d.ts.map +1 -0
  230. package/lib/typescript/src/hooks/useSlideDetailAnimation.d.ts +11 -0
  231. package/lib/typescript/src/hooks/useSlideDetailAnimation.d.ts.map +1 -0
  232. package/lib/typescript/src/index.d.ts +26 -0
  233. package/lib/typescript/src/index.d.ts.map +1 -0
  234. package/lib/typescript/src/initialize.d.ts +32 -0
  235. package/lib/typescript/src/initialize.d.ts.map +1 -0
  236. package/lib/typescript/src/interceptors/networkInterceptor.d.ts +18 -0
  237. package/lib/typescript/src/interceptors/networkInterceptor.d.ts.map +1 -0
  238. package/lib/typescript/src/native/NativeDebugLibs.d.ts +11 -0
  239. package/lib/typescript/src/native/NativeDebugLibs.d.ts.map +1 -0
  240. package/lib/typescript/src/types/index.d.ts +109 -0
  241. package/lib/typescript/src/types/index.d.ts.map +1 -0
  242. package/lib/typescript/src/utils/colors.d.ts +21 -0
  243. package/lib/typescript/src/utils/colors.d.ts.map +1 -0
  244. package/lib/typescript/src/utils/copyToComputer.d.ts +30 -0
  245. package/lib/typescript/src/utils/copyToComputer.d.ts.map +1 -0
  246. package/lib/typescript/src/utils/createChannelFeature.d.ts +18 -0
  247. package/lib/typescript/src/utils/createChannelFeature.d.ts.map +1 -0
  248. package/lib/typescript/src/utils/createEventChannel.d.ts +7 -0
  249. package/lib/typescript/src/utils/createEventChannel.d.ts.map +1 -0
  250. package/lib/typescript/src/utils/createObservableStore.d.ts +9 -0
  251. package/lib/typescript/src/utils/createObservableStore.d.ts.map +1 -0
  252. package/lib/typescript/src/utils/layout.d.ts +2 -0
  253. package/lib/typescript/src/utils/layout.d.ts.map +1 -0
  254. package/lib/typescript/src/utils/safeStringify.d.ts +6 -0
  255. package/lib/typescript/src/utils/safeStringify.d.ts.map +1 -0
  256. package/lib/typescript/src/utils/urlRewriterRegistry.d.ts +7 -0
  257. package/lib/typescript/src/utils/urlRewriterRegistry.d.ts.map +1 -0
  258. package/package.json +67 -24
  259. package/src/components/ClipboardTab.tsx +81 -0
  260. package/src/components/ConsoleLogTab.tsx +95 -0
  261. package/src/components/DebugPanel.tsx +215 -0
  262. package/src/components/DebugView.tsx +80 -0
  263. package/src/components/EnvironmentTab.tsx +276 -0
  264. package/src/components/FeatureTabBar.tsx +204 -0
  265. package/src/components/FloatIcon.tsx +171 -0
  266. package/src/components/FloatPanelView.tsx +202 -0
  267. package/src/components/NavigationLogTab.tsx +66 -0
  268. package/src/components/NetworkLogTab.tsx +270 -0
  269. package/src/components/ThirdPartyLibsTab.tsx +63 -0
  270. package/src/components/TrackLogTab.tsx +110 -0
  271. package/src/components/ZustandLogTab.tsx +203 -0
  272. package/src/components/shared/CollapsibleSection.tsx +78 -0
  273. package/src/components/shared/CopyButton.tsx +68 -0
  274. package/src/components/shared/JsonView.tsx +125 -0
  275. package/src/components/shared/LogListScreen.tsx +164 -0
  276. package/src/core/DebugToolkit.tsx +150 -0
  277. package/src/core/DebugToolkitProvider.tsx +83 -0
  278. package/src/features/ClipboardFeature.ts +15 -0
  279. package/src/features/ConsoleLogFeature.ts +116 -0
  280. package/src/features/EnvironmentFeature.ts +186 -0
  281. package/src/features/NavigationLogFeature.ts +44 -0
  282. package/src/features/NetworkFeature.ts +126 -0
  283. package/src/features/ThirdPartyLibsFeature.ts +42 -0
  284. package/src/features/TrackFeature.ts +34 -0
  285. package/src/features/ZustandLogFeature.ts +101 -0
  286. package/src/hooks/useNavigationLogger.ts +102 -0
  287. package/src/hooks/useSlideDetailAnimation.ts +45 -0
  288. package/src/index.ts +48 -0
  289. package/src/initialize.ts +122 -0
  290. package/src/interceptors/networkInterceptor.ts +646 -0
  291. package/src/native/NativeDebugLibs.ts +74 -0
  292. package/src/types/index.ts +127 -0
  293. package/src/utils/colors.ts +38 -0
  294. package/src/utils/copyToComputer.ts +104 -0
  295. package/src/utils/createChannelFeature.ts +55 -0
  296. package/src/utils/createEventChannel.ts +22 -0
  297. package/src/utils/createObservableStore.ts +42 -0
  298. package/src/utils/layout.ts +1 -0
  299. package/src/utils/safeStringify.ts +25 -0
  300. package/src/utils/urlRewriterRegistry.ts +10 -0
  301. package/.cursor/rules/react-native.mdc +0 -41
  302. package/index.js +0 -41
  303. package/ios/BuildTypeModule.h +0 -9
  304. package/ios/BuildTypeModule.m +0 -42
  305. package/ios/RNDebugLibs.h +0 -10
  306. package/ios/RNDebugLibs.m +0 -79
  307. package/lib/DebugToolKit.js +0 -126
  308. package/lib/EnvironmentManager.ts +0 -80
  309. package/lib/NativeDebugLibs.js +0 -67
  310. package/lib/features/ConsoleLogFeature.js +0 -70
  311. package/lib/features/NavigationLogFeature.js +0 -45
  312. package/lib/features/NetworkFeature.js +0 -389
  313. package/lib/features/PerformanceFeature.js +0 -390
  314. package/lib/features/ThirdPartyLibsFeature.js +0 -63
  315. package/lib/features/TrackFeature.js +0 -94
  316. package/lib/features/ZustandLogFeature.js +0 -44
  317. package/lib/hooks/useNavigationLogger.js +0 -92
  318. package/lib/index.js +0 -114
  319. package/lib/navigation/NavigationLogger.js +0 -1
  320. package/lib/types/TrackTypes.ts +0 -92
  321. package/lib/utils/DebugConst.js +0 -67
  322. package/lib/utils/StorageUtils.js +0 -80
  323. package/lib/views/ConsoleLogDetails.js +0 -314
  324. package/lib/views/FloatPanelView.js +0 -697
  325. package/lib/views/HttpLogDetails.js +0 -648
  326. package/lib/views/NavigationLogDetails.js +0 -302
  327. package/lib/views/RestartModal.js +0 -75
  328. package/lib/views/SubViewConsoleLogs.js +0 -209
  329. package/lib/views/SubViewEnvironment.js +0 -73
  330. package/lib/views/SubViewHTTPLogs.js +0 -235
  331. package/lib/views/SubViewNavigationLogs.js +0 -199
  332. package/lib/views/SubViewPerformance.js +0 -515
  333. package/lib/views/SubViewThirdPartyLibs.js +0 -239
  334. package/lib/views/SubViewTrackLogs.js +0 -318
  335. package/lib/views/SubViewZustandLogs.js +0 -279
  336. package/lib/views/TabView.js +0 -66
  337. package/lib/views/TrackLogDetails.js +0 -481
  338. package/lib/views/ZustandLogDetails.js +0 -355
  339. package/react-native-debug-toolkit.podspec +0 -25
  340. package/react-native.config.js +0 -18
@@ -0,0 +1,164 @@
1
+ import React, { useMemo, useState } from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ FlatList,
6
+ TouchableOpacity,
7
+ StyleSheet,
8
+ Animated,
9
+ } from 'react-native';
10
+ import { Colors } from '../../utils/colors';
11
+ import { useSlideDetailAnimation } from '../../hooks/useSlideDetailAnimation';
12
+
13
+ interface LogListItem {
14
+ id: string;
15
+ }
16
+
17
+ interface LogListScreenProps<T extends LogListItem> {
18
+ data: T[];
19
+ renderRow: (item: T) => React.ReactElement;
20
+ renderListHeader?: () => React.ReactElement;
21
+ renderDetailHeader?: (item: T) => React.ReactNode;
22
+ renderDetailBody: (item: T) => React.ReactElement;
23
+ emptyText: string;
24
+ reversed?: boolean;
25
+ }
26
+
27
+ /**
28
+ * Shared list→detail screen with slide animation.
29
+ * Handles: selected state, FlatList, empty state, back button, push navigation.
30
+ * Each tab provides renderRow, renderDetailBody, and optional renderDetailHeader.
31
+ */
32
+ export function LogListScreen<T extends LogListItem>({
33
+ data,
34
+ renderRow,
35
+ renderListHeader,
36
+ renderDetailHeader,
37
+ renderDetailBody,
38
+ emptyText,
39
+ reversed = true,
40
+ }: LogListScreenProps<T>) {
41
+ const [selected, setSelected] = useState<T | null>(null);
42
+ const { detailTranslateX, listTranslateX, listOpacity } = useSlideDetailAnimation(selected);
43
+
44
+ const displayData = useMemo(
45
+ () => (reversed ? [...data].reverse() : data),
46
+ [data, reversed],
47
+ );
48
+
49
+ return (
50
+ <View style={styles.container}>
51
+ {/* List */}
52
+ <Animated.View
53
+ style={[
54
+ styles.listWrap,
55
+ selected
56
+ ? { opacity: listOpacity, transform: [{ translateX: listTranslateX }] }
57
+ : null,
58
+ ]}
59
+ >
60
+ {renderListHeader?.()}
61
+ {displayData.length === 0 ? (
62
+ <View style={styles.emptyContainer}>
63
+ <Text style={styles.emptyIcon}>~</Text>
64
+ <Text style={styles.empty}>{emptyText}</Text>
65
+ </View>
66
+ ) : (
67
+ <FlatList
68
+ data={displayData}
69
+ renderItem={({ item }) => (
70
+ <TouchableOpacity
71
+ style={styles.card}
72
+ onPress={() => setSelected(item)}
73
+ activeOpacity={0.6}
74
+ >
75
+ {renderRow(item)}
76
+ </TouchableOpacity>
77
+ )}
78
+ keyExtractor={(item) => item.id}
79
+ contentContainerStyle={styles.listContent}
80
+ initialNumToRender={20}
81
+ maxToRenderPerBatch={10}
82
+ windowSize={5}
83
+ removeClippedSubviews={true}
84
+ />
85
+ )}
86
+ </Animated.View>
87
+
88
+ {/* Detail */}
89
+ {selected && (
90
+ <Animated.View
91
+ style={[styles.detailOverlay, { transform: [{ translateX: detailTranslateX }] }]}
92
+ >
93
+ <View style={styles.detailWrap}>
94
+ <View style={styles.detailHeader}>
95
+ <TouchableOpacity
96
+ onPress={() => setSelected(null)}
97
+ style={styles.backBtn}
98
+ activeOpacity={0.6}
99
+ >
100
+ <Text style={styles.backIcon}>‹</Text>
101
+ <Text style={styles.backText}>Back</Text>
102
+ </TouchableOpacity>
103
+ {renderDetailHeader?.(selected)}
104
+ </View>
105
+ {renderDetailBody(selected)}
106
+ </View>
107
+ </Animated.View>
108
+ )}
109
+ </View>
110
+ );
111
+ }
112
+
113
+ const styles = StyleSheet.create({
114
+ container: { flex: 1, backgroundColor: Colors.background },
115
+ listWrap: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 },
116
+ listContent: { padding: 12 },
117
+ emptyContainer: { flex: 1, alignItems: 'center', justifyContent: 'center' },
118
+ emptyIcon: { fontSize: 40, color: Colors.textLight, marginBottom: 4 },
119
+ empty: { textAlign: 'center', color: Colors.textLight, fontSize: 14 },
120
+ card: {
121
+ backgroundColor: Colors.surface,
122
+ borderRadius: 12,
123
+ marginBottom: 8,
124
+ overflow: 'hidden',
125
+ },
126
+ detailOverlay: {
127
+ position: 'absolute',
128
+ top: 0,
129
+ left: 0,
130
+ right: 0,
131
+ bottom: 0,
132
+ backgroundColor: Colors.background,
133
+ },
134
+ detailWrap: { flex: 1, backgroundColor: Colors.background },
135
+ detailHeader: {
136
+ flexDirection: 'row',
137
+ alignItems: 'center',
138
+ paddingHorizontal: 8,
139
+ paddingVertical: 10,
140
+ backgroundColor: Colors.surface,
141
+ borderBottomWidth: StyleSheet.hairlineWidth,
142
+ borderBottomColor: Colors.border,
143
+ gap: 8,
144
+ },
145
+ backBtn: {
146
+ flexDirection: 'row',
147
+ alignItems: 'center',
148
+ paddingHorizontal: 6,
149
+ paddingVertical: 4,
150
+ borderRadius: 8,
151
+ },
152
+ backIcon: {
153
+ fontSize: 24,
154
+ fontWeight: '300',
155
+ color: Colors.primary,
156
+ marginTop: -2,
157
+ marginRight: 2,
158
+ },
159
+ backText: {
160
+ fontSize: 16,
161
+ color: Colors.primary,
162
+ fontWeight: '500',
163
+ },
164
+ });
@@ -0,0 +1,150 @@
1
+ import type { AnyDebugFeature } from '../types';
2
+
3
+ type Listener = () => void;
4
+
5
+ const listeners = new Set<Listener>();
6
+ let _features: AnyDebugFeature[] = [];
7
+ let _panelVisible = false;
8
+ let _enabled = true;
9
+
10
+ function notify(): void {
11
+ listeners.forEach((l) => l());
12
+ }
13
+
14
+ function setupFeature(feature: AnyDebugFeature): void {
15
+ feature.setup?.();
16
+ }
17
+
18
+ function cleanupFeature(feature: AnyDebugFeature): void {
19
+ feature.cleanup?.();
20
+ }
21
+
22
+ export const DebugToolkit = {
23
+ subscribe(listener: Listener): () => void {
24
+ listeners.add(listener);
25
+ return () => {
26
+ listeners.delete(listener);
27
+ };
28
+ },
29
+
30
+ get features(): AnyDebugFeature[] {
31
+ return [..._features];
32
+ },
33
+
34
+ get enabled(): boolean {
35
+ return _enabled;
36
+ },
37
+
38
+ get panelVisible(): boolean {
39
+ return _panelVisible;
40
+ },
41
+
42
+ setEnabled(enabled: boolean): void {
43
+ if (_enabled === enabled) return;
44
+ _enabled = enabled;
45
+ if (!enabled) {
46
+ _panelVisible = false;
47
+ _features.forEach(cleanupFeature);
48
+ _features = [];
49
+ }
50
+ notify();
51
+ },
52
+
53
+ replaceFeatures(features: AnyDebugFeature[]): void {
54
+ if (!_enabled) return;
55
+ const next = features.filter(
56
+ (f, i, arr) =>
57
+ f && typeof f.name === 'string' && arr.findIndex((item) => item.name === f.name) === i,
58
+ );
59
+ const prevMap = new Map(_features.map((f) => [f.name, f]));
60
+ const nextMap = new Map(next.map((f) => [f.name, f]));
61
+
62
+ _features.forEach((f) => {
63
+ if (!nextMap.get(f.name) || nextMap.get(f.name) !== f) cleanupFeature(f);
64
+ });
65
+ next.forEach((f) => {
66
+ if (!prevMap.get(f.name) || prevMap.get(f.name) !== f) setupFeature(f);
67
+ });
68
+
69
+ _features = next;
70
+ notify();
71
+ },
72
+
73
+ addFeature(feature: AnyDebugFeature): void {
74
+ if (!_enabled || !feature || typeof feature.name !== 'string') {
75
+ return;
76
+ }
77
+
78
+ const existingIndex = _features.findIndex((f) => f.name === feature.name);
79
+ if (existingIndex >= 0) {
80
+ const existing = _features[existingIndex]!;
81
+ if (existing === feature) {
82
+ return;
83
+ }
84
+
85
+ cleanupFeature(existing);
86
+ setupFeature(feature);
87
+ _features = [
88
+ ..._features.slice(0, existingIndex),
89
+ feature,
90
+ ..._features.slice(existingIndex + 1),
91
+ ];
92
+ notify();
93
+ return;
94
+ }
95
+
96
+ setupFeature(feature);
97
+ _features = [..._features, feature];
98
+ notify();
99
+ },
100
+
101
+ removeFeature(name: string): void {
102
+ if (!_enabled) {
103
+ return;
104
+ }
105
+
106
+ const feature = _features.find((f) => f.name === name);
107
+ if (!feature) {
108
+ return;
109
+ }
110
+
111
+ cleanupFeature(feature);
112
+ _features = _features.filter((f) => f.name !== name);
113
+ if (_features.length === 0) {
114
+ _panelVisible = false;
115
+ }
116
+ notify();
117
+ },
118
+
119
+ reset(): void {
120
+ _panelVisible = false;
121
+ _features.forEach(cleanupFeature);
122
+ _features = [];
123
+ notify();
124
+ },
125
+
126
+ hasFeatures(): boolean {
127
+ return _features.length > 0;
128
+ },
129
+
130
+ showPanel(): void {
131
+ if (!_enabled) return;
132
+ _panelVisible = true;
133
+ notify();
134
+ },
135
+
136
+ hidePanel(): void {
137
+ _panelVisible = false;
138
+ notify();
139
+ },
140
+
141
+ clearAll(): void {
142
+ _features.forEach((f) => f.clear?.());
143
+ notify();
144
+ },
145
+
146
+ destroy(): void {
147
+ this.reset();
148
+ listeners.clear();
149
+ },
150
+ };
@@ -0,0 +1,83 @@
1
+ import React, { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';
2
+ import { DebugToolkit } from './DebugToolkit';
3
+ import { FloatPanelView } from '../components/FloatPanelView';
4
+ import type { AnyDebugFeature } from '../types';
5
+
6
+ interface ToolkitContextValue {
7
+ features: AnyDebugFeature[];
8
+ showPanel: () => void;
9
+ hidePanel: () => void;
10
+ clearAll: () => void;
11
+ }
12
+
13
+ const ToolkitContext = createContext<ToolkitContextValue | null>(null);
14
+
15
+ interface ProviderState {
16
+ panelVisible: boolean;
17
+ features: AnyDebugFeature[];
18
+ }
19
+
20
+ interface DebugToolkitProviderProps {
21
+ children: ReactNode;
22
+ }
23
+
24
+ export function DebugToolkitProvider({ children }: DebugToolkitProviderProps) {
25
+ const [state, setState] = useState<ProviderState>(() => ({
26
+ panelVisible: DebugToolkit.panelVisible,
27
+ features: DebugToolkit.features,
28
+ }));
29
+
30
+ useEffect(() => {
31
+ // Sync current state — initializeDebugToolkit() may have been called
32
+ // in a child useEffect that runs before this parent effect subscribes.
33
+ setState({
34
+ panelVisible: DebugToolkit.panelVisible,
35
+ features: DebugToolkit.features,
36
+ });
37
+
38
+ const unsubscribe = DebugToolkit.subscribe(() => {
39
+ setState({
40
+ panelVisible: DebugToolkit.panelVisible,
41
+ features: DebugToolkit.features,
42
+ });
43
+ });
44
+ return unsubscribe;
45
+ }, []);
46
+
47
+ const showPanel = useCallback(() => { DebugToolkit.showPanel(); }, []);
48
+ const hidePanel = useCallback(() => { DebugToolkit.hidePanel(); }, []);
49
+ const clearAll = useCallback(() => { DebugToolkit.clearAll(); }, []);
50
+
51
+ const contextValue = useMemo<ToolkitContextValue>(
52
+ () => ({
53
+ features: state.features,
54
+ showPanel,
55
+ hidePanel,
56
+ clearAll,
57
+ }),
58
+ [state.features, showPanel, hidePanel, clearAll],
59
+ );
60
+
61
+ return (
62
+ <ToolkitContext.Provider value={contextValue}>
63
+ {children}
64
+ {state.panelVisible && (
65
+ <FloatPanelView
66
+ features={state.features}
67
+ onClearAll={() => DebugToolkit.clearAll()}
68
+ />
69
+ )}
70
+ </ToolkitContext.Provider>
71
+ );
72
+ }
73
+
74
+ export function useDebugToolkit(): ToolkitContextValue {
75
+ const context = useContext(ToolkitContext);
76
+ if (!context) {
77
+ throw new Error(
78
+ 'useDebugToolkit must be used within a <DebugToolkitProvider>. ' +
79
+ 'Wrap your app with <DebugToolkitProvider>.',
80
+ );
81
+ }
82
+ return context;
83
+ }
@@ -0,0 +1,15 @@
1
+ import { ClipboardTab } from '../components/ClipboardTab';
2
+ import type { DebugFeature } from '../types';
3
+
4
+ /**
5
+ * Clipboard feature — all logic lives in ClipboardTab.
6
+ * Data flow is user-driven (TextInput), not event-based.
7
+ */
8
+ export const createClipboardFeature = (): DebugFeature<void> => ({
9
+ name: 'clipboard',
10
+ label: 'Clipboard',
11
+ renderContent: ClipboardTab,
12
+ setup() {},
13
+ getData: () => [],
14
+ cleanup() {},
15
+ });
@@ -0,0 +1,116 @@
1
+ import { ConsoleLogTab } from '../components/ConsoleLogTab';
2
+ import type { ConsoleLogEntry, DebugFeature } from '../types';
3
+ import { createObservableStore } from '../utils/createObservableStore';
4
+
5
+ const LEVELS: ConsoleLogEntry['level'][] = ['log', 'info', 'warn', 'error'];
6
+
7
+ // ─── Console capture manager (encapsulated mutable state) ──
8
+
9
+ const consoleCapture = (() => {
10
+ const originalMethods: Partial<Record<ConsoleLogEntry['level'], (...args: unknown[]) => void>> = {};
11
+ let refCount = 0;
12
+
13
+ function stop(): void {
14
+ refCount = Math.max(0, refCount - 1);
15
+ if (refCount > 0) return;
16
+
17
+ LEVELS.forEach((level) => {
18
+ const original = originalMethods[level];
19
+ if (original) {
20
+ console[level] = original;
21
+ delete originalMethods[level];
22
+ }
23
+ });
24
+ }
25
+
26
+ function isIntercepted(): boolean {
27
+ return LEVELS.some((level) => originalMethods[level] !== undefined);
28
+ }
29
+
30
+ function start(emit: (entry: ConsoleLogEntry) => void): () => void {
31
+ refCount += 1;
32
+ if (isIntercepted()) {
33
+ return () => { stop(); };
34
+ }
35
+
36
+ LEVELS.forEach((level) => {
37
+ originalMethods[level] = console[level];
38
+
39
+ console[level] = (...args: unknown[]) => {
40
+ originalMethods[level]?.apply(console, args);
41
+ if (level === 'log' && typeof args[0] === 'string' && args[0].startsWith('[DebugToolkit:Copy]')) {
42
+ return;
43
+ }
44
+ emit({
45
+ id: '',
46
+ timestamp: Date.now(),
47
+ level,
48
+ data: args,
49
+ });
50
+ };
51
+ });
52
+
53
+ return () => { stop(); };
54
+ }
55
+
56
+ return {
57
+ start,
58
+ reset() {
59
+ LEVELS.forEach((level) => {
60
+ const original = originalMethods[level];
61
+ if (original) {
62
+ console[level] = original;
63
+ delete originalMethods[level];
64
+ }
65
+ });
66
+ refCount = 0;
67
+ },
68
+ };
69
+ })();
70
+
71
+ // ─── Feature factory ──────────────────────────────────
72
+
73
+ const DEFAULT_MAX_LOGS = 200;
74
+
75
+ export interface ConsoleFeatureConfig {
76
+ /** Maximum number of console logs to keep (default: 200) */
77
+ maxLogs?: number;
78
+ }
79
+
80
+ export const createConsoleLogFeature = (config?: ConsoleFeatureConfig): DebugFeature<ConsoleLogEntry> => {
81
+ const maxLogs = config?.maxLogs ?? DEFAULT_MAX_LOGS;
82
+ const logStore = createObservableStore<ConsoleLogEntry>();
83
+ let nextId = 0;
84
+ let initialized = false;
85
+ let stopCapture: (() => void) | null = null;
86
+
87
+ return {
88
+ name: 'console',
89
+ label: 'Console',
90
+ renderContent: ConsoleLogTab,
91
+ setup: () => {
92
+ if (initialized) return;
93
+
94
+ stopCapture = consoleCapture.start((entry) => {
95
+ logStore.push({ ...entry, id: String(nextId++) }, maxLogs);
96
+ });
97
+ initialized = true;
98
+ },
99
+ getData: () => logStore.getData(),
100
+ clear: () => { logStore.clear(); },
101
+ cleanup: () => {
102
+ if (!initialized) return;
103
+
104
+ stopCapture?.();
105
+ stopCapture = null;
106
+ logStore.clear();
107
+ initialized = false;
108
+ },
109
+ subscribe: (listener) => logStore.subscribe(listener),
110
+ };
111
+ };
112
+
113
+ /** Reset module-level state for testing */
114
+ export function _resetConsoleForTesting(): void {
115
+ consoleCapture.reset();
116
+ }
@@ -0,0 +1,186 @@
1
+ import { EnvironmentTab } from '../components/EnvironmentTab';
2
+ import type { DebugFeature, EnvironmentConfig, EnvironmentState } from '../types';
3
+ import { createObservableStore } from '../utils/createObservableStore';
4
+ import { urlRewriter } from '../utils/urlRewriterRegistry';
5
+
6
+ // Lazy AsyncStorage loader
7
+ type AsyncStorageModule = {
8
+ getItem: (key: string) => Promise<string | null>;
9
+ setItem: (key: string, value: string) => Promise<void>;
10
+ };
11
+
12
+ let asyncStorageModule: AsyncStorageModule | null = null;
13
+ let asyncStorageChecked = false;
14
+
15
+ function getAsyncStorage(): AsyncStorageModule | null {
16
+ if (asyncStorageChecked) {
17
+ return asyncStorageModule;
18
+ }
19
+ asyncStorageChecked = true;
20
+ try {
21
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
22
+ asyncStorageModule = require('@react-native-async-storage/async-storage').default;
23
+ } catch {
24
+ asyncStorageModule = null;
25
+ }
26
+ return asyncStorageModule;
27
+ }
28
+
29
+ const STORAGE_KEY = 'debug_toolkit_env_id';
30
+
31
+ // Module-level state for synchronous URL rewriting
32
+ let currentHostsMap: Map<string, string> | null = null;
33
+ let activeEnvironmentId: string | null = null;
34
+
35
+ function buildHostsMap(
36
+ environments: EnvironmentConfig[],
37
+ targetId: string | null,
38
+ ): Map<string, string> | null {
39
+ if (!targetId) return null;
40
+ const target = environments.find((e) => e.id === targetId);
41
+ if (!target) return null;
42
+
43
+ const map = new Map<string, string>();
44
+ for (const env of environments) {
45
+ if (env.id !== targetId) {
46
+ map.set(env.host, target.host);
47
+ }
48
+ }
49
+ return map;
50
+ }
51
+
52
+ function createUrlRewriter(): (url: string) => string {
53
+ return (url: string): string => {
54
+ if (!currentHostsMap) return url;
55
+
56
+ try {
57
+ const parsed = new URL(url);
58
+ const targetHost = currentHostsMap.get(parsed.host);
59
+ if (targetHost) {
60
+ return url.replace(parsed.host, targetHost);
61
+ }
62
+ } catch {
63
+ // Not a valid URL or relative URL — return unchanged
64
+ }
65
+
66
+ return url;
67
+ };
68
+ }
69
+
70
+ export interface EnvironmentFeatureAPI extends DebugFeature<EnvironmentState> {
71
+ registerEnvironments: (environments: EnvironmentConfig[]) => void;
72
+ switchEnvironment: (environmentId: string | null) => void;
73
+ getCurrentEnvironmentId: () => string | null;
74
+ }
75
+
76
+ export const createEnvironmentFeature = (
77
+ initialEnvironments?: EnvironmentConfig[],
78
+ ): EnvironmentFeatureAPI => {
79
+ const stateStore = createObservableStore<EnvironmentState>();
80
+ let environments: EnvironmentConfig[] = initialEnvironments ?? [];
81
+ let initialized = false;
82
+
83
+ const getCurrentState = (): EnvironmentState => ({
84
+ environments,
85
+ currentEnvironmentId: activeEnvironmentId,
86
+ });
87
+
88
+ const updateStore = () => {
89
+ stateStore.clear();
90
+ stateStore.push(getCurrentState());
91
+ };
92
+
93
+ const applyEnvironment = (envId: string | null) => {
94
+ activeEnvironmentId = envId;
95
+ currentHostsMap = buildHostsMap(environments, envId);
96
+
97
+ if (initialized) {
98
+ try {
99
+ if (envId && environments.length > 0) {
100
+ urlRewriter.set(createUrlRewriter());
101
+ } else {
102
+ urlRewriter.set(null);
103
+ }
104
+ } catch (err) {
105
+ if (__DEV__) console.warn('[DebugToolkit] Failed to set URL rewriter:', err);
106
+ }
107
+ }
108
+
109
+ updateStore();
110
+ };
111
+
112
+ const persistSelection = async (envId: string | null) => {
113
+ const storage = getAsyncStorage();
114
+ if (!storage) return;
115
+ try {
116
+ await storage.setItem(STORAGE_KEY, envId ?? '');
117
+ } catch (err) {
118
+ if (__DEV__) console.warn('[DebugToolkit] Failed to persist environment selection:', err);
119
+ }
120
+ };
121
+
122
+ const loadPersistedSelection = async () => {
123
+ const storage = getAsyncStorage();
124
+ if (!storage) return;
125
+ try {
126
+ const stored = await storage.getItem(STORAGE_KEY);
127
+ if (stored && stored !== '' && environments.some((e) => e.id === stored)) {
128
+ applyEnvironment(stored);
129
+ }
130
+ } catch (err) {
131
+ if (__DEV__) console.warn('[DebugToolkit] Failed to load persisted environment:', err);
132
+ }
133
+ };
134
+
135
+ return {
136
+ name: 'environment',
137
+ label: 'Environment',
138
+ renderContent: EnvironmentTab,
139
+ setup: () => {
140
+ if (initialized) return;
141
+
142
+ updateStore();
143
+ initialized = true;
144
+
145
+ // Install rewriter if an environment is already selected
146
+ if (activeEnvironmentId && environments.length > 0) {
147
+ urlRewriter.set(createUrlRewriter());
148
+ }
149
+
150
+ // Async persistence load (will override if a preference exists)
151
+ loadPersistedSelection();
152
+ },
153
+ getData: () => stateStore.getData(),
154
+ clear: () => {
155
+ applyEnvironment(null);
156
+ persistSelection(null);
157
+ },
158
+ cleanup: () => {
159
+ if (!initialized) return;
160
+ urlRewriter.set(null);
161
+ activeEnvironmentId = null;
162
+ currentHostsMap = null;
163
+ stateStore.clear();
164
+ initialized = false;
165
+ },
166
+ subscribe: (listener) => stateStore.subscribe(listener),
167
+ registerEnvironments: (envs: EnvironmentConfig[]) => {
168
+ environments = envs;
169
+ applyEnvironment(activeEnvironmentId);
170
+ },
171
+ switchEnvironment: (envId: string | null) => {
172
+ applyEnvironment(envId);
173
+ persistSelection(envId);
174
+ },
175
+ getCurrentEnvironmentId: () => activeEnvironmentId,
176
+ badge: () => {
177
+ if (!activeEnvironmentId) return null;
178
+ const env = environments.find((e) => e.id === activeEnvironmentId);
179
+ if (!env) return null;
180
+ return {
181
+ label: env.label.substring(0, 3).toUpperCase(),
182
+ color: env.color ?? '#FF9500',
183
+ };
184
+ },
185
+ };
186
+ };