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,202 @@
1
+ import React, { Component, useCallback, useEffect, useRef, useState } from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ StyleSheet,
6
+ Animated,
7
+ PanResponder,
8
+ Easing,
9
+ } from 'react-native';
10
+ import type { AnyDebugFeature } from '../types';
11
+ import { FloatIcon } from './FloatIcon';
12
+ import { DebugPanel } from './DebugPanel';
13
+ import { FeatureTabBar } from './FeatureTabBar';
14
+ import type { TabItem } from './FeatureTabBar';
15
+
16
+ // ─── Error Boundary ────────────────────────────────────
17
+ interface ErrorBoundaryState {
18
+ hasError: boolean;
19
+ }
20
+
21
+ class DebugErrorBoundary extends Component<
22
+ { children: React.ReactNode; onError: () => void },
23
+ ErrorBoundaryState
24
+ > {
25
+ state: ErrorBoundaryState = { hasError: false };
26
+
27
+ static getDerivedStateFromError(): ErrorBoundaryState {
28
+ return { hasError: true };
29
+ }
30
+
31
+ componentDidCatch(error: Error, info: React.ErrorInfo) {
32
+ console.error('[DebugToolkit] Panel crashed:', error, info.componentStack);
33
+ this.props.onError();
34
+ }
35
+
36
+ render() {
37
+ if (this.state.hasError) return null;
38
+ return this.props.children;
39
+ }
40
+ }
41
+
42
+ interface FloatPanelViewProps {
43
+ features: AnyDebugFeature[];
44
+ onClearAll: () => void;
45
+ }
46
+
47
+ export function FloatPanelView({ features, onClearAll }: FloatPanelViewProps) {
48
+ const [isOpen, setIsOpen] = useState(false);
49
+ const [activeTab, setActiveTab] = useState(0);
50
+
51
+ // Content slide animation
52
+ const contentOpacity = useRef(new Animated.Value(1)).current;
53
+ const contentTranslateX = useRef(new Animated.Value(0)).current;
54
+ const isSwitchingTab = useRef(false);
55
+
56
+ // Refs to avoid stale closures in PanResponder
57
+ const activeTabRef = useRef(0);
58
+ activeTabRef.current = activeTab;
59
+ const featuresLengthRef = useRef(features.length);
60
+ featuresLengthRef.current = features.length;
61
+ const switchTabRef = useRef<(index: number) => void>(() => {});
62
+
63
+ // Swipe-to-switch responder
64
+ const swipeResponder = useRef(
65
+ PanResponder.create({
66
+ onStartShouldSetPanResponder: () => false,
67
+ onMoveShouldSetPanResponder: (_, gs) => {
68
+ if (isSwitchingTab.current) return false;
69
+ return Math.abs(gs.dx) > 25 && Math.abs(gs.dx) > Math.abs(gs.dy) * 2.5;
70
+ },
71
+ onPanResponderRelease: (_, gs) => {
72
+ const tab = activeTabRef.current;
73
+ if (gs.dx < -40 && tab < featuresLengthRef.current - 1) switchTabRef.current(tab + 1);
74
+ else if (gs.dx > 40 && tab > 0) switchTabRef.current(tab - 1);
75
+ },
76
+ onPanResponderTerminationRequest: () => true,
77
+ }),
78
+ ).current;
79
+
80
+ // Feature subscription → re-render on data changes
81
+ const [, setTick] = useState(0);
82
+ const refreshQueued = useRef(false);
83
+ const scheduleRefresh = useCallback(() => {
84
+ if (refreshQueued.current) return;
85
+ refreshQueued.current = true;
86
+ requestAnimationFrame(() => {
87
+ refreshQueued.current = false;
88
+ setTick((t) => t + 1);
89
+ });
90
+ }, []);
91
+
92
+ useEffect(() => {
93
+ const unsubs = features
94
+ .map((f) => f.subscribe?.(() => scheduleRefresh()))
95
+ .filter((u): u is () => void => typeof u === 'function');
96
+ return () => unsubs.forEach((u) => u());
97
+ }, [features, scheduleRefresh]);
98
+
99
+ // Reset activeTab if features shrink
100
+ useEffect(() => {
101
+ if (activeTab >= features.length) setActiveTab(0);
102
+ }, [features.length, activeTab]);
103
+
104
+ // Tab switching with content animation
105
+ const switchTab = useCallback(
106
+ (index: number) => {
107
+ if (isSwitchingTab.current || index === activeTabRef.current) return;
108
+ isSwitchingTab.current = true;
109
+ const direction = index > activeTabRef.current ? 1 : -1;
110
+
111
+ Animated.parallel([
112
+ Animated.timing(contentOpacity, { toValue: 0, duration: 80, useNativeDriver: true }),
113
+ Animated.timing(contentTranslateX, {
114
+ toValue: -direction * 40,
115
+ duration: 80,
116
+ useNativeDriver: true,
117
+ }),
118
+ ]).start(() => {
119
+ setActiveTab(index);
120
+ contentTranslateX.setValue(direction * 40);
121
+ Animated.parallel([
122
+ Animated.timing(contentOpacity, { toValue: 1, duration: 150, useNativeDriver: true }),
123
+ Animated.timing(contentTranslateX, {
124
+ toValue: 0,
125
+ duration: 200,
126
+ easing: Easing.out(Easing.cubic),
127
+ useNativeDriver: true,
128
+ }),
129
+ ]).start(() => {
130
+ isSwitchingTab.current = false;
131
+ });
132
+ });
133
+ },
134
+ [contentOpacity, contentTranslateX],
135
+ );
136
+
137
+ // Keep ref in sync
138
+ switchTabRef.current = switchTab;
139
+
140
+ // Badge (first feature that returns one)
141
+ const envBadge = features.map((f) => f.badge?.()).find((b) => b != null) ?? null;
142
+ const tabs: TabItem[] = features.map((f) => ({ label: f.label, id: f.name }));
143
+
144
+ // Render active feature content
145
+ const renderFeatureContent = () => {
146
+ if (features.length === 0) {
147
+ return <Text style={styles.emptyText}>No debug features enabled</Text>;
148
+ }
149
+ const feature = features[activeTab];
150
+ if (!feature) return <Text style={styles.emptyText}>Feature not found</Text>;
151
+ const data = feature.getData();
152
+ const TabComponent = feature.renderContent;
153
+ if (TabComponent) return <TabComponent data={data} feature={feature} />;
154
+ return (
155
+ <View style={styles.genericContent}>
156
+ <Text style={styles.jsonContent}>{JSON.stringify(data, null, 2)}</Text>
157
+ </View>
158
+ );
159
+ };
160
+
161
+ return (
162
+ <DebugErrorBoundary onError={() => setIsOpen(false)}>
163
+ <View style={styles.container} pointerEvents="box-none">
164
+ <FloatIcon visible={!isOpen} onPress={() => setIsOpen(true)} badge={envBadge} />
165
+ {isOpen && (
166
+ <DebugPanel onClose={() => setIsOpen(false)} onClearAll={onClearAll}>
167
+ <FeatureTabBar tabs={tabs} activeIndex={activeTab} onSelectTab={switchTab} />
168
+ <Animated.View
169
+ style={[
170
+ styles.contentContainer,
171
+ { opacity: contentOpacity, transform: [{ translateX: contentTranslateX }] },
172
+ ]}
173
+ {...swipeResponder.panHandlers}
174
+ >
175
+ {renderFeatureContent()}
176
+ </Animated.View>
177
+ </DebugPanel>
178
+ )}
179
+ </View>
180
+ </DebugErrorBoundary>
181
+ );
182
+ }
183
+
184
+ const styles = StyleSheet.create({
185
+ container: {
186
+ position: 'absolute',
187
+ top: 0,
188
+ left: 0,
189
+ right: 0,
190
+ bottom: 0,
191
+ zIndex: 999,
192
+ },
193
+ contentContainer: { flex: 1 },
194
+ emptyText: {
195
+ padding: 20,
196
+ textAlign: 'center',
197
+ color: '#C7C7CC',
198
+ fontSize: 13,
199
+ },
200
+ genericContent: { padding: 16, flex: 1 },
201
+ jsonContent: { fontFamily: 'monospace', fontSize: 12, color: '#1C1C1E' },
202
+ });
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import { View, Text, FlatList, StyleSheet } from 'react-native';
3
+ import { Colors } from '../utils/colors';
4
+ import { CopyButton } from './shared/CopyButton';
5
+ import type { DebugFeatureRenderProps, NavigationLogEntry } from '../types';
6
+
7
+ export const NavigationLogTab: React.FC<DebugFeatureRenderProps<NavigationLogEntry>> = React.memo(({
8
+ data,
9
+ }) => {
10
+ const renderItem = ({ item }: { item: NavigationLogEntry }) => (
11
+ <View style={styles.logItem}>
12
+ <View style={styles.header}>
13
+ <Text style={styles.action}>{item.action}</Text>
14
+ <View style={styles.headerRight}>
15
+ {item.duration != null && <Text style={styles.duration}>{item.duration}ms</Text>}
16
+ <CopyButton
17
+ text={`${item.action}: ${item.from || '—'} → ${item.to}`}
18
+ label="Navigation"
19
+ compact
20
+ />
21
+ </View>
22
+ </View>
23
+ <View style={styles.routeRow}>
24
+ <Text style={styles.routeLabel}>From:</Text>
25
+ <Text style={styles.routeValue}>{item.from || '—'}</Text>
26
+ </View>
27
+ <View style={styles.routeRow}>
28
+ <Text style={styles.routeLabel}>To:</Text>
29
+ <Text style={styles.routeValue}>{item.to}</Text>
30
+ </View>
31
+ <Text style={styles.time}>{new Date(item.timestamp).toLocaleTimeString()}</Text>
32
+ </View>
33
+ );
34
+
35
+ return (
36
+ <View style={styles.container}>
37
+ {data.length === 0 ? (
38
+ <Text style={styles.empty}>No navigation events</Text>
39
+ ) : (
40
+ <FlatList
41
+ data={[...data].reverse()}
42
+ renderItem={renderItem}
43
+ keyExtractor={(item) => item.id}
44
+ initialNumToRender={20}
45
+ maxToRenderPerBatch={10}
46
+ windowSize={5}
47
+ removeClippedSubviews={true}
48
+ />
49
+ )}
50
+ </View>
51
+ );
52
+ });
53
+
54
+ const styles = StyleSheet.create({
55
+ container: { flex: 1, backgroundColor: Colors.surface },
56
+ empty: { textAlign: 'center', color: Colors.textLight, marginTop: 20 },
57
+ logItem: { padding: 12, borderBottomWidth: 1, borderBottomColor: '#EEE' },
58
+ header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 },
59
+ headerRight: { flexDirection: 'row', alignItems: 'center', gap: 8 },
60
+ action: { fontSize: 14, fontWeight: 'bold', color: Colors.primary },
61
+ duration: { fontSize: 13, color: Colors.textLight },
62
+ routeRow: { flexDirection: 'row', marginBottom: 3 },
63
+ routeLabel: { fontSize: 13, color: Colors.textSecondary, marginRight: 8, fontWeight: '600' },
64
+ routeValue: { fontSize: 13, color: Colors.text, flex: 1 },
65
+ time: { fontSize: 12, color: Colors.textLight, marginTop: 4 },
66
+ });
@@ -0,0 +1,270 @@
1
+ import React, { useState } from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ StyleSheet,
6
+ TextInput,
7
+ ScrollView,
8
+ } from 'react-native';
9
+ import { Colors, getMethodColor } from '../utils/colors';
10
+ import { CollapsibleSection } from './shared/CollapsibleSection';
11
+ import { JsonView } from './shared/JsonView';
12
+ import { CopyButton } from './shared/CopyButton';
13
+ import { fmt } from '../utils/copyToComputer';
14
+ import { LogListScreen } from './shared/LogListScreen';
15
+ import type { DebugFeatureRenderProps, NetworkLogEntry } from '../types';
16
+
17
+ const formatSize = (data: unknown): string => {
18
+ if (!data) return '';
19
+ try {
20
+ const len = (typeof data === 'string' ? data : JSON.stringify(data)).length;
21
+ if (len < 1024) return `(${len} B)`;
22
+ if (len < 1024 * 1024) return `(${(len / 1024).toFixed(1)} KB)`;
23
+ return `(${(len / (1024 * 1024)).toFixed(1)} MB)`;
24
+ } catch {
25
+ return '';
26
+ }
27
+ };
28
+
29
+ const buildCurl = (log: NetworkLogEntry): string => {
30
+ let c = `curl -X ${log.request.method} '${log.request.url}'`;
31
+ if (log.request.headers) {
32
+ Object.entries(log.request.headers).forEach(([k, v]) => (c += ` \\\n -H '${k}: ${v}'`));
33
+ }
34
+ if (log.request.body) {
35
+ c += ` \\\n -d '${typeof log.request.body === 'string' ? log.request.body : JSON.stringify(log.request.body)}'`;
36
+ }
37
+ return c;
38
+ };
39
+
40
+ export const NetworkLogTab: React.FC<DebugFeatureRenderProps<NetworkLogEntry>> = React.memo(({
41
+ data,
42
+ }) => {
43
+ const [search, setSearch] = useState('');
44
+
45
+ const filtered = search
46
+ ? data.filter(
47
+ (l) =>
48
+ l.request.url.toLowerCase().includes(search.toLowerCase()) ||
49
+ l.request.method.toLowerCase().includes(search.toLowerCase()),
50
+ )
51
+ : data;
52
+
53
+ const sorted = [...filtered].sort((a, b) => b.timestamp - a.timestamp);
54
+
55
+ return (
56
+ <LogListScreen
57
+ data={sorted}
58
+ reversed={false}
59
+ emptyText="No HTTP requests logged"
60
+ renderListHeader={() => (
61
+ <View style={s.searchContainer}>
62
+ <View style={s.searchBar}>
63
+ <Text style={s.searchIcon}>⌕</Text>
64
+ <TextInput
65
+ style={s.search}
66
+ placeholder="Search URLs..."
67
+ placeholderTextColor={Colors.textLight}
68
+ value={search}
69
+ onChangeText={setSearch}
70
+ />
71
+ </View>
72
+ </View>
73
+ )}
74
+ renderRow={(item) => {
75
+ const ok = !item.error && (!item.response || item.response.status < 400);
76
+ const sc = ok ? Colors.success : Colors.error;
77
+ return (
78
+ <View style={s.cardRow}>
79
+ <View style={[s.statusIndicator, { backgroundColor: sc }]} />
80
+ <View style={s.cardBody}>
81
+ <View style={s.cardMeta}>
82
+ <Text style={[s.methodText, { color: getMethodColor(item.request.method) }]}>
83
+ {item.request.method}
84
+ </Text>
85
+ <View style={[s.miniPill, { backgroundColor: sc }]}>
86
+ <Text style={s.miniPillText}>{item.response?.status ?? 'ERR'}</Text>
87
+ </View>
88
+ {item.duration != null && <Text style={s.durationText}>{item.duration}ms</Text>}
89
+ </View>
90
+ <Text style={[s.url, !ok && { color: Colors.error }]} numberOfLines={2}>
91
+ {item.request.url}
92
+ </Text>
93
+ <Text style={s.time}>{new Date(item.timestamp).toLocaleTimeString()}</Text>
94
+ </View>
95
+ </View>
96
+ );
97
+ }}
98
+ renderDetailHeader={(log) => {
99
+ const statusColor = log.error || (log.response && log.response.status >= 400) ? Colors.error : Colors.success;
100
+ return (
101
+ <View style={s.detailHeaderCenter}>
102
+ <View style={[s.methodBadge, { backgroundColor: getMethodColor(log.request.method) }]}>
103
+ <Text style={s.methodBadgeText}>{log.request.method}</Text>
104
+ </View>
105
+ <View style={[s.statusPill, { backgroundColor: statusColor }]}>
106
+ <Text style={s.statusPillText}>{log.response?.status ?? 'ERR'}</Text>
107
+ </View>
108
+ {log.duration != null && <Text style={s.durationText}>{log.duration}ms</Text>}
109
+ </View>
110
+ );
111
+ }}
112
+ renderDetailBody={(log) => {
113
+ const curlStr = buildCurl(log);
114
+ return (
115
+ <ScrollView style={s.detailBody} contentContainerStyle={s.detailBodyContent}>
116
+ <View style={s.urlCard}>
117
+ <Text style={s.urlText} selectable numberOfLines={3}>{log.request.url}</Text>
118
+ <CopyButton text={log.request.url} label="URL" />
119
+ </View>
120
+
121
+ <CollapsibleSection title="Request Body" initiallyExpanded>
122
+ {log.request.body != null ? (
123
+ <View style={s.sectionWithCopy}>
124
+ <CopyButton text={fmt(log.request.body)} label="Request Body" />
125
+ <JsonView data={log.request.body} maxHeight={250} />
126
+ </View>
127
+ ) : (
128
+ <Text style={s.emptySection}>No request body</Text>
129
+ )}
130
+ </CollapsibleSection>
131
+
132
+ <CollapsibleSection title="Request Headers">
133
+ {log.request.headers ? (
134
+ <View style={s.sectionWithCopy}>
135
+ <CopyButton text={fmt(log.request.headers)} label="Request Headers" />
136
+ <JsonView data={log.request.headers} maxHeight={200} />
137
+ </View>
138
+ ) : (
139
+ <Text style={s.emptySection}>No headers</Text>
140
+ )}
141
+ </CollapsibleSection>
142
+
143
+ <CollapsibleSection title={`Response ${formatSize(log.response?.data)}`} initiallyExpanded>
144
+ {log.error && (
145
+ <View style={s.errorBox}>
146
+ <Text style={s.errorIcon}>⚠</Text>
147
+ <Text style={s.errorText}>{log.error}</Text>
148
+ </View>
149
+ )}
150
+ {log.response?.data != null ? (
151
+ <View style={s.sectionWithCopy}>
152
+ <CopyButton text={fmt(log.response.data)} label="Response Body" />
153
+ <JsonView data={log.response.data} maxHeight={300} />
154
+ </View>
155
+ ) : (
156
+ <Text style={s.emptySection}>No response body</Text>
157
+ )}
158
+ </CollapsibleSection>
159
+
160
+ {log.response?.headers && (
161
+ <CollapsibleSection title="Response Headers">
162
+ <View style={s.sectionWithCopy}>
163
+ <CopyButton text={fmt(log.response.headers)} label="Response Headers" />
164
+ <JsonView data={log.response.headers} maxHeight={200} />
165
+ </View>
166
+ </CollapsibleSection>
167
+ )}
168
+
169
+ <CollapsibleSection title="cURL">
170
+ <View style={s.sectionWithCopy}>
171
+ <CopyButton text={curlStr} label="cURL" />
172
+ <View style={s.codeBlock}>
173
+ <Text style={s.codeText} selectable>{curlStr}</Text>
174
+ </View>
175
+ </View>
176
+ </CollapsibleSection>
177
+ </ScrollView>
178
+ );
179
+ }}
180
+ />
181
+ );
182
+ });
183
+
184
+ const s = StyleSheet.create({
185
+ // Search
186
+ searchContainer: {
187
+ paddingHorizontal: 12,
188
+ paddingTop: 10,
189
+ paddingBottom: 6,
190
+ backgroundColor: Colors.background,
191
+ },
192
+ searchBar: {
193
+ flexDirection: 'row',
194
+ alignItems: 'center',
195
+ backgroundColor: Colors.surface,
196
+ borderRadius: 10,
197
+ paddingHorizontal: 10,
198
+ height: 38,
199
+ },
200
+ searchIcon: { fontSize: 16, color: Colors.textLight, marginRight: 6 },
201
+ search: {
202
+ flex: 1,
203
+ fontSize: 14,
204
+ color: Colors.text,
205
+ padding: 0,
206
+ },
207
+
208
+ // Row
209
+ cardRow: { flexDirection: 'row', padding: 14 },
210
+ statusIndicator: { width: 3, borderRadius: 2, marginRight: 12 },
211
+ cardBody: { flex: 1 },
212
+ cardMeta: { flexDirection: 'row', alignItems: 'center', marginBottom: 6, gap: 6 },
213
+ methodText: { fontSize: 13, fontWeight: '700' },
214
+ miniPill: { paddingHorizontal: 7, paddingVertical: 2, borderRadius: 4 },
215
+ miniPillText: { color: '#FFF', fontSize: 10, fontWeight: '700' },
216
+ durationText: { fontSize: 12, color: Colors.textSecondary, fontWeight: '500' },
217
+ url: { fontSize: 13, color: Colors.textSecondary, marginBottom: 4, lineHeight: 18 },
218
+ time: { fontSize: 11, color: Colors.textLight },
219
+
220
+ // Detail header
221
+ detailHeaderCenter: {
222
+ flexDirection: 'row',
223
+ alignItems: 'center',
224
+ gap: 8,
225
+ flex: 1,
226
+ },
227
+ methodBadge: {
228
+ paddingHorizontal: 10,
229
+ paddingVertical: 4,
230
+ borderRadius: 6,
231
+ },
232
+ methodBadgeText: { color: '#FFF', fontSize: 12, fontWeight: '700' },
233
+ statusPill: { paddingHorizontal: 9, paddingVertical: 3, borderRadius: 6 },
234
+ statusPillText: { color: '#FFF', fontSize: 11, fontWeight: '700' },
235
+
236
+ // Detail body
237
+ detailBody: { flex: 1 },
238
+ detailBodyContent: { padding: 12, paddingBottom: 40 },
239
+ urlCard: {
240
+ flexDirection: 'row',
241
+ alignItems: 'center',
242
+ backgroundColor: Colors.surface,
243
+ borderRadius: 12,
244
+ padding: 14,
245
+ marginBottom: 8,
246
+ gap: 8,
247
+ },
248
+ urlText: { flex: 1, fontSize: 13, color: Colors.textSecondary, lineHeight: 18 },
249
+ sectionWithCopy: { gap: 8 },
250
+ emptySection: { fontSize: 13, color: Colors.textLight, paddingVertical: 4 },
251
+ errorBox: {
252
+ backgroundColor: 'rgba(255,59,48,0.06)',
253
+ borderWidth: 1,
254
+ borderColor: 'rgba(255,59,48,0.15)',
255
+ borderRadius: 10,
256
+ padding: 12,
257
+ marginBottom: 10,
258
+ flexDirection: 'row',
259
+ alignItems: 'flex-start',
260
+ gap: 8,
261
+ },
262
+ errorIcon: { fontSize: 14, color: Colors.error },
263
+ errorText: { flex: 1, fontSize: 13, color: Colors.error, lineHeight: 18 },
264
+ codeBlock: {
265
+ backgroundColor: '#1E1E2E',
266
+ borderRadius: 12,
267
+ padding: 12,
268
+ },
269
+ codeText: { fontFamily: 'Courier', fontSize: 12, color: '#CDD6F4', lineHeight: 18 },
270
+ });
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
3
+ import { Colors } from '../utils/colors';
4
+ import type { DebugFeatureRenderProps, ThirdPartyLib, ThirdPartyLibAction } from '../types';
5
+
6
+ export const ThirdPartyLibsTab: React.FC<DebugFeatureRenderProps<ThirdPartyLib>> = ({
7
+ data,
8
+ }) => {
9
+ if (data.length === 0) {
10
+ return (
11
+ <View style={styles.container}>
12
+ <Text style={styles.empty}>No debug libraries available for this platform</Text>
13
+ </View>
14
+ );
15
+ }
16
+
17
+ return (
18
+ <View style={styles.container}>
19
+ {data.map((lib) => (
20
+ <View key={lib.id} style={styles.libCard}>
21
+ <Text style={styles.libName}>{lib.name}</Text>
22
+ <Text style={styles.libDesc}>{lib.description}</Text>
23
+ <View style={styles.actions}>
24
+ {lib.actions.map((action: ThirdPartyLibAction) => (
25
+ <TouchableOpacity
26
+ key={action.id}
27
+ style={styles.actionButton}
28
+ onPress={action.onPress}
29
+ >
30
+ <Text style={styles.actionText}>{action.label}</Text>
31
+ </TouchableOpacity>
32
+ ))}
33
+ </View>
34
+ </View>
35
+ ))}
36
+ </View>
37
+ );
38
+ };
39
+
40
+ const styles = StyleSheet.create({
41
+ container: { flex: 1, backgroundColor: Colors.surface, padding: 15 },
42
+ empty: { textAlign: 'center', color: Colors.textLight, marginTop: 20 },
43
+ libCard: {
44
+ backgroundColor: Colors.background,
45
+ borderRadius: 8,
46
+ padding: 15,
47
+ marginBottom: 12,
48
+ borderWidth: 1,
49
+ borderColor: Colors.border,
50
+ },
51
+ libName: { fontSize: 16, fontWeight: 'bold', color: Colors.text, marginBottom: 4 },
52
+ libDesc: { fontSize: 13, color: Colors.textSecondary, marginBottom: 12 },
53
+ actions: { flexDirection: 'row', flexWrap: 'wrap' },
54
+ actionButton: {
55
+ backgroundColor: Colors.primary,
56
+ paddingHorizontal: 14,
57
+ paddingVertical: 8,
58
+ borderRadius: 6,
59
+ marginRight: 8,
60
+ marginBottom: 8,
61
+ },
62
+ actionText: { color: '#FFF', fontSize: 14, fontWeight: '600' },
63
+ });