react-native-inapp-inspector 2.3.5 → 2.3.6

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 (226) hide show
  1. package/dist/commonjs/analytics.d.ts +0 -4
  2. package/dist/commonjs/analytics.js +0 -4
  3. package/dist/commonjs/bundle.d.ts +0 -4
  4. package/dist/commonjs/bundle.js +0 -4
  5. package/dist/commonjs/components/AnalyticsDetail.js +18 -27
  6. package/dist/commonjs/components/AnalyticsEventCard.js +9 -12
  7. package/dist/commonjs/components/AnalyticsGraph.js +10 -15
  8. package/dist/commonjs/components/AppHeaderLogo.js +0 -3
  9. package/dist/commonjs/components/BrandCircleIcon.js +15 -15
  10. package/dist/commonjs/components/BrandSquareIcon.js +20 -20
  11. package/dist/commonjs/components/CodeSnippet.js +6 -19
  12. package/dist/commonjs/components/ConsoleLogCard.js +0 -1
  13. package/dist/commonjs/components/CopyButton.js +0 -4
  14. package/dist/commonjs/components/DiffViewer.js +0 -2
  15. package/dist/commonjs/components/DomainHeader.js +0 -4
  16. package/dist/commonjs/components/EmptyState.js +0 -3
  17. package/dist/commonjs/components/ErrorBoundary.js +5 -10
  18. package/dist/commonjs/components/HeadersSection.js +0 -5
  19. package/dist/commonjs/components/HighlightText.js +1 -4
  20. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +11 -26
  21. package/dist/commonjs/components/Inspector/AnalyticsTab.js +34 -40
  22. package/dist/commonjs/components/Inspector/BundleTab.js +56 -84
  23. package/dist/commonjs/components/Inspector/ConsoleTab.js +7 -7
  24. package/dist/commonjs/components/Inspector/CrashDetail.js +18 -20
  25. package/dist/commonjs/components/Inspector/CrashFilterModal.js +0 -1
  26. package/dist/commonjs/components/Inspector/CrashTab.js +11 -20
  27. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +12 -24
  28. package/dist/commonjs/components/Inspector/FabLauncher.js +1 -1
  29. package/dist/commonjs/components/Inspector/InspectorContext.js +0 -2
  30. package/dist/commonjs/components/Inspector/InspectorHeader.js +7 -8
  31. package/dist/commonjs/components/Inspector/LogDetail.js +27 -29
  32. package/dist/commonjs/components/Inspector/MainScreen.js +9 -10
  33. package/dist/commonjs/components/Inspector/NetworkDetail.js +10 -11
  34. package/dist/commonjs/components/Inspector/NetworkTab.js +14 -14
  35. package/dist/commonjs/components/Inspector/NpmUpdateToast.js +6 -9
  36. package/dist/commonjs/components/Inspector/PerformanceTab.js +30 -43
  37. package/dist/commonjs/components/Inspector/ReduxDetail.js +18 -34
  38. package/dist/commonjs/components/Inspector/ReduxTab.js +11 -20
  39. package/dist/commonjs/components/Inspector/SettingsPanel.js +32 -36
  40. package/dist/commonjs/components/Inspector/SkeletonPlaceholder.js +6 -6
  41. package/dist/commonjs/components/Inspector/StorageTab.js +14 -26
  42. package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +5 -6
  43. package/dist/commonjs/components/JsonViewer.js +3 -10
  44. package/dist/commonjs/components/LogCard.js +7 -7
  45. package/dist/commonjs/components/MetaAccordion.js +1 -7
  46. package/dist/commonjs/components/NetworkIcons.js +12 -16
  47. package/dist/commonjs/components/SectionHeader.js +0 -4
  48. package/dist/commonjs/components/SkeletonPlaceholder.js +6 -6
  49. package/dist/commonjs/components/Slider.js +6 -6
  50. package/dist/commonjs/components/SourcePageCard.js +0 -4
  51. package/dist/commonjs/components/TreeNode.js +0 -4
  52. package/dist/commonjs/console.d.ts +0 -4
  53. package/dist/commonjs/console.js +0 -4
  54. package/dist/commonjs/constants/index.js +6 -9
  55. package/dist/commonjs/constants/telemetryConfig.d.ts +7 -0
  56. package/dist/commonjs/constants/telemetryConfig.js +10 -0
  57. package/dist/commonjs/constants/version.d.ts +1 -1
  58. package/dist/commonjs/constants/version.js +1 -3
  59. package/dist/commonjs/crash.d.ts +0 -4
  60. package/dist/commonjs/crash.js +0 -4
  61. package/dist/commonjs/customHooks/analyticsLogger.d.ts +0 -7
  62. package/dist/commonjs/customHooks/analyticsLogger.js +3 -59
  63. package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +0 -9
  64. package/dist/commonjs/customHooks/bundleAnalyzer.js +3 -86
  65. package/dist/commonjs/customHooks/consoleLogger.js +0 -16
  66. package/dist/commonjs/customHooks/crashHandler.d.ts +0 -28
  67. package/dist/commonjs/customHooks/crashHandler.js +0 -55
  68. package/dist/commonjs/customHooks/logFilters.d.ts +0 -4
  69. package/dist/commonjs/customHooks/logFilters.js +0 -11
  70. package/dist/commonjs/customHooks/networkLogger.js +2 -13
  71. package/dist/commonjs/customHooks/performanceTracker.d.ts +0 -27
  72. package/dist/commonjs/customHooks/performanceTracker.js +0 -31
  73. package/dist/commonjs/customHooks/reduxLogger.d.ts +0 -12
  74. package/dist/commonjs/customHooks/reduxLogger.js +0 -51
  75. package/dist/commonjs/customHooks/storageInspector.d.ts +0 -40
  76. package/dist/commonjs/customHooks/storageInspector.js +1 -56
  77. package/dist/commonjs/decorators/index.d.ts +0 -37
  78. package/dist/commonjs/decorators/index.js +0 -42
  79. package/dist/commonjs/helpers/gaAnalyticsRegistry.d.ts +0 -10
  80. package/dist/commonjs/helpers/gaAnalyticsRegistry.js +0 -26
  81. package/dist/commonjs/helpers/index.d.ts +0 -7
  82. package/dist/commonjs/helpers/index.js +1 -42
  83. package/dist/commonjs/helpers/memoryManager.d.ts +0 -11
  84. package/dist/commonjs/helpers/memoryManager.js +0 -13
  85. package/dist/commonjs/helpers/searchQueryParser.d.ts +0 -4
  86. package/dist/commonjs/helpers/searchQueryParser.js +0 -18
  87. package/dist/commonjs/helpers/settingsStore.js +0 -8
  88. package/dist/commonjs/helpers/telemetry.d.ts +2 -0
  89. package/dist/commonjs/helpers/telemetry.js +302 -0
  90. package/dist/commonjs/i18n/index.d.ts +0 -9
  91. package/dist/commonjs/i18n/index.js +0 -15
  92. package/dist/commonjs/index.js +15 -97
  93. package/dist/commonjs/native/NativeInspector.d.ts +0 -54
  94. package/dist/commonjs/native/NativeInspector.js +0 -56
  95. package/dist/commonjs/network.d.ts +0 -4
  96. package/dist/commonjs/network.js +0 -4
  97. package/dist/commonjs/performance.d.ts +0 -4
  98. package/dist/commonjs/performance.js +0 -4
  99. package/dist/commonjs/redux.d.ts +0 -4
  100. package/dist/commonjs/redux.js +0 -4
  101. package/dist/commonjs/storage.d.ts +0 -4
  102. package/dist/commonjs/storage.js +0 -4
  103. package/dist/commonjs/styles/AppColors.d.ts +0 -3
  104. package/dist/commonjs/styles/AppColors.js +15 -30
  105. package/dist/commonjs/styles/AppFonts.d.ts +0 -4
  106. package/dist/commonjs/styles/AppFonts.js +0 -4
  107. package/dist/commonjs/styles/common.js +0 -11
  108. package/dist/commonjs/styles/index.js +0 -8
  109. package/dist/commonjs/types/enums.js +0 -3
  110. package/dist/commonjs/types/interfaces.d.ts +3 -3
  111. package/dist/esm/analytics.d.ts +0 -4
  112. package/dist/esm/analytics.js +0 -4
  113. package/dist/esm/bundle.d.ts +0 -4
  114. package/dist/esm/bundle.js +0 -4
  115. package/dist/esm/components/AnalyticsDetail.js +18 -27
  116. package/dist/esm/components/AnalyticsEventCard.js +9 -12
  117. package/dist/esm/components/AnalyticsGraph.js +10 -15
  118. package/dist/esm/components/AppHeaderLogo.js +0 -3
  119. package/dist/esm/components/BrandCircleIcon.js +15 -15
  120. package/dist/esm/components/BrandSquareIcon.js +20 -20
  121. package/dist/esm/components/CodeSnippet.js +6 -19
  122. package/dist/esm/components/ConsoleLogCard.js +0 -1
  123. package/dist/esm/components/CopyButton.js +0 -4
  124. package/dist/esm/components/DiffViewer.js +0 -2
  125. package/dist/esm/components/DomainHeader.js +0 -4
  126. package/dist/esm/components/EmptyState.js +0 -3
  127. package/dist/esm/components/ErrorBoundary.js +5 -10
  128. package/dist/esm/components/HeadersSection.js +0 -5
  129. package/dist/esm/components/HighlightText.js +1 -4
  130. package/dist/esm/components/Inspector/AnalyticsFilterModal.js +11 -26
  131. package/dist/esm/components/Inspector/AnalyticsTab.js +34 -40
  132. package/dist/esm/components/Inspector/BundleTab.js +56 -84
  133. package/dist/esm/components/Inspector/ConsoleTab.js +7 -7
  134. package/dist/esm/components/Inspector/CrashDetail.js +18 -20
  135. package/dist/esm/components/Inspector/CrashFilterModal.js +0 -1
  136. package/dist/esm/components/Inspector/CrashTab.js +11 -20
  137. package/dist/esm/components/Inspector/DeviceInfoTab.js +12 -24
  138. package/dist/esm/components/Inspector/FabLauncher.js +1 -1
  139. package/dist/esm/components/Inspector/InspectorContext.js +0 -2
  140. package/dist/esm/components/Inspector/InspectorHeader.js +7 -8
  141. package/dist/esm/components/Inspector/LogDetail.js +27 -29
  142. package/dist/esm/components/Inspector/MainScreen.js +9 -10
  143. package/dist/esm/components/Inspector/NetworkDetail.js +10 -11
  144. package/dist/esm/components/Inspector/NetworkTab.js +14 -14
  145. package/dist/esm/components/Inspector/NpmUpdateToast.js +6 -9
  146. package/dist/esm/components/Inspector/PerformanceTab.js +30 -43
  147. package/dist/esm/components/Inspector/ReduxDetail.js +18 -34
  148. package/dist/esm/components/Inspector/ReduxTab.js +11 -20
  149. package/dist/esm/components/Inspector/SettingsPanel.js +32 -36
  150. package/dist/esm/components/Inspector/SkeletonPlaceholder.js +6 -6
  151. package/dist/esm/components/Inspector/StorageTab.js +14 -26
  152. package/dist/esm/components/Inspector/UpdateAvailableModal.js +5 -6
  153. package/dist/esm/components/JsonViewer.js +3 -10
  154. package/dist/esm/components/LogCard.js +7 -7
  155. package/dist/esm/components/MetaAccordion.js +1 -7
  156. package/dist/esm/components/NetworkIcons.js +12 -16
  157. package/dist/esm/components/SectionHeader.js +0 -4
  158. package/dist/esm/components/SkeletonPlaceholder.js +6 -6
  159. package/dist/esm/components/Slider.js +6 -6
  160. package/dist/esm/components/SourcePageCard.js +0 -4
  161. package/dist/esm/components/TreeNode.js +0 -4
  162. package/dist/esm/console.d.ts +0 -4
  163. package/dist/esm/console.js +0 -4
  164. package/dist/esm/constants/index.js +6 -9
  165. package/dist/esm/constants/telemetryConfig.d.ts +7 -0
  166. package/dist/esm/constants/telemetryConfig.js +7 -0
  167. package/dist/esm/constants/version.d.ts +1 -1
  168. package/dist/esm/constants/version.js +1 -3
  169. package/dist/esm/crash.d.ts +0 -4
  170. package/dist/esm/crash.js +0 -4
  171. package/dist/esm/customHooks/analyticsLogger.d.ts +0 -7
  172. package/dist/esm/customHooks/analyticsLogger.js +3 -59
  173. package/dist/esm/customHooks/bundleAnalyzer.d.ts +0 -9
  174. package/dist/esm/customHooks/bundleAnalyzer.js +3 -86
  175. package/dist/esm/customHooks/consoleLogger.js +0 -16
  176. package/dist/esm/customHooks/crashHandler.d.ts +0 -28
  177. package/dist/esm/customHooks/crashHandler.js +0 -55
  178. package/dist/esm/customHooks/logFilters.d.ts +0 -4
  179. package/dist/esm/customHooks/logFilters.js +0 -11
  180. package/dist/esm/customHooks/networkLogger.js +2 -13
  181. package/dist/esm/customHooks/performanceTracker.d.ts +0 -27
  182. package/dist/esm/customHooks/performanceTracker.js +0 -31
  183. package/dist/esm/customHooks/reduxLogger.d.ts +0 -12
  184. package/dist/esm/customHooks/reduxLogger.js +0 -51
  185. package/dist/esm/customHooks/storageInspector.d.ts +0 -40
  186. package/dist/esm/customHooks/storageInspector.js +1 -56
  187. package/dist/esm/decorators/index.d.ts +0 -37
  188. package/dist/esm/decorators/index.js +0 -42
  189. package/dist/esm/helpers/gaAnalyticsRegistry.d.ts +0 -10
  190. package/dist/esm/helpers/gaAnalyticsRegistry.js +0 -26
  191. package/dist/esm/helpers/index.d.ts +0 -7
  192. package/dist/esm/helpers/index.js +1 -42
  193. package/dist/esm/helpers/memoryManager.d.ts +0 -11
  194. package/dist/esm/helpers/memoryManager.js +0 -13
  195. package/dist/esm/helpers/searchQueryParser.d.ts +0 -4
  196. package/dist/esm/helpers/searchQueryParser.js +0 -18
  197. package/dist/esm/helpers/settingsStore.js +0 -8
  198. package/dist/esm/helpers/telemetry.d.ts +2 -0
  199. package/dist/esm/helpers/telemetry.js +298 -0
  200. package/dist/esm/i18n/index.d.ts +0 -9
  201. package/dist/esm/i18n/index.js +0 -15
  202. package/dist/esm/index.js +15 -97
  203. package/dist/esm/native/NativeInspector.d.ts +0 -54
  204. package/dist/esm/native/NativeInspector.js +0 -56
  205. package/dist/esm/network.d.ts +0 -4
  206. package/dist/esm/network.js +0 -4
  207. package/dist/esm/performance.d.ts +0 -4
  208. package/dist/esm/performance.js +0 -4
  209. package/dist/esm/redux.d.ts +0 -4
  210. package/dist/esm/redux.js +0 -4
  211. package/dist/esm/storage.d.ts +0 -4
  212. package/dist/esm/storage.js +0 -4
  213. package/dist/esm/styles/AppColors.d.ts +0 -3
  214. package/dist/esm/styles/AppColors.js +15 -30
  215. package/dist/esm/styles/AppFonts.d.ts +0 -4
  216. package/dist/esm/styles/AppFonts.js +0 -4
  217. package/dist/esm/styles/common.js +0 -11
  218. package/dist/esm/styles/index.js +0 -8
  219. package/dist/esm/types/enums.js +0 -3
  220. package/dist/esm/types/interfaces.d.ts +3 -3
  221. package/package.json +2 -2
  222. package/src/constants/telemetryConfig.ts +16 -0
  223. package/src/constants/version.ts +1 -1
  224. package/src/helpers/telemetry.ts +341 -0
  225. package/src/index.tsx +15 -1
  226. package/src/types/interfaces.ts +3 -0
@@ -1,7 +1,4 @@
1
1
  "use strict";
2
- // ─── Enums & Constants ─────────────────────────────────────────────────────────
3
- // Universal TypeScript Enum Objects and Type Aliases.
4
- // Allows both enum-style access (e.g. ActiveTab.Apis) and string literals ('apis').
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.BreadcrumbType = exports.CrashFilterType = exports.CrashDetailSubTab = exports.CrashExportFormat = exports.CrashType = exports.PerformanceSubTab = exports.BundleSubTab = exports.DiffResultType = exports.StackFrameType = exports.GAEventCategory = exports.AnalyticsEventSource = exports.ConsoleLogType = exports.LogFilter = exports.SettingsSubTab = exports.SettingsPage = exports.ModalAnimationType = exports.LocalFilter = exports.SortOrder = exports.StatusFilter = exports.Method = exports.ActiveTab = void 0;
7
4
  exports.ActiveTab = {
@@ -55,7 +55,6 @@ export interface ConsoleLog {
55
55
  errorStack?: string;
56
56
  rawArgs?: any[];
57
57
  sourceMethod?: 'log' | 'info' | 'warn' | 'error';
58
- /** #9 — number of consecutive identical logs collapsed into this entry. */
59
58
  duplicateCount?: number;
60
59
  }
61
60
  export interface AnalyticsEvent {
@@ -101,9 +100,7 @@ export interface NetworkLog {
101
100
  response?: unknown;
102
101
  requestHeaders?: Record<string, string>;
103
102
  responseHeaders?: Record<string, string>;
104
- /** #9 — number of consecutive identical requests collapsed into this entry. */
105
103
  duplicateCount?: number;
106
- /** Client identifier: axios, fetch, xhr, apollo, etc. */
107
104
  client?: 'axios' | 'fetch' | 'xhr' | 'apollo' | 'graphql' | string;
108
105
  caller?: string;
109
106
  routeInfo?: RouteInfo;
@@ -154,9 +151,12 @@ export interface PersistedSettings {
154
151
  reduxExpandDepth?: number;
155
152
  showDuplicateLogs?: boolean;
156
153
  showUpdateToast?: boolean;
154
+ telemetryClientId?: string;
155
+ telemetryLastPing?: number;
157
156
  }
158
157
  export interface NetworkInspectorProps {
159
158
  enabled?: boolean;
159
+ telemetry?: boolean;
160
160
  storage?: InspectorStorage;
161
161
  navigationRef?: any;
162
162
  appIcon?: any;
@@ -1,7 +1,3 @@
1
- /**
2
- * Sub-module entry point: react-native-inapp-inspector/analytics
3
- * Clean tree-shaking & isolated Firebase/custom Analytics logger.
4
- */
5
1
  export { setupAnalyticsLogger, autoSetupAnalyticsLogger, logAnalyticsEvent, subscribeAnalyticsEvents, clearAnalyticsEvents, getAnalyticsEvents, isAnalyticsConnected, isFirebaseAnalyticsPatched, setAnalyticsModuleEnabled, getAnalyticsModuleEnabled, getCurrentUserProperties, getCurrentUserId, getDefaultEventParameters, getCollectionEnabled, setMaxAnalyticsLogsLimit, getMaxAnalyticsLogsLimit, pruneAnalyticsLogs, } from './customHooks/analyticsLogger';
6
2
  export { getEventCategory, registerGAPlugin, type GAPlugin, } from './helpers/gaAnalyticsRegistry';
7
3
  export type { AnalyticsEvent, AnalyticsEventSource, GAEventCategory, } from './types';
@@ -1,6 +1,2 @@
1
- /**
2
- * Sub-module entry point: react-native-inapp-inspector/analytics
3
- * Clean tree-shaking & isolated Firebase/custom Analytics logger.
4
- */
5
1
  export { setupAnalyticsLogger, autoSetupAnalyticsLogger, logAnalyticsEvent, subscribeAnalyticsEvents, clearAnalyticsEvents, getAnalyticsEvents, isAnalyticsConnected, isFirebaseAnalyticsPatched, setAnalyticsModuleEnabled, getAnalyticsModuleEnabled, getCurrentUserProperties, getCurrentUserId, getDefaultEventParameters, getCollectionEnabled, setMaxAnalyticsLogsLimit, getMaxAnalyticsLogsLimit, pruneAnalyticsLogs, } from './customHooks/analyticsLogger';
6
2
  export { getEventCategory, registerGAPlugin, } from './helpers/gaAnalyticsRegistry';
@@ -1,6 +1,2 @@
1
- /**
2
- * Sub-module entry point: react-native-inapp-inspector/bundle
3
- * Clean tree-shaking & isolated JS bundle size analyzer.
4
- */
5
1
  export { analyzeHostAppBundle, parseBundleSource, getInitialBundleAnalysis, getCachedBundleAnalysis, clearCachedBundleAnalysis, setBundleModuleEnabled, getBundleModuleEnabled, getHostScriptURL, trackRuntimeModuleExecution, trackRuntimeDefine, type HostBundleAnalysisResult, type HostBundleFileItem, type HostBundlePackageItem, type HostBinaryComponentItem, type FileTypeCategory, } from './customHooks/bundleAnalyzer';
6
2
  export { BundleSubTab, } from './types';
@@ -1,6 +1,2 @@
1
- /**
2
- * Sub-module entry point: react-native-inapp-inspector/bundle
3
- * Clean tree-shaking & isolated JS bundle size analyzer.
4
- */
5
1
  export { analyzeHostAppBundle, parseBundleSource, getInitialBundleAnalysis, getCachedBundleAnalysis, clearCachedBundleAnalysis, setBundleModuleEnabled, getBundleModuleEnabled, getHostScriptURL, trackRuntimeModuleExecution, trackRuntimeDefine, } from './customHooks/bundleAnalyzer';
6
2
  export { BundleSubTab, } from './types';
@@ -1,12 +1,10 @@
1
1
  import React, { useState, useMemo } from 'react';
2
2
  import { Pressable, ScrollView, StyleSheet, Text, TextInput, View, } from 'react-native';
3
- // Components
4
3
  import CopyButton from './CopyButton';
5
4
  import JsonViewer from './JsonViewer';
6
5
  import SegmentedTabs from './SegmentedTabs';
7
6
  import HighlightText from './HighlightText';
8
7
  import AnimatedEntrance from './AnimatedEntrance';
9
- // Helpers & Icons
10
8
  import { AppFonts } from '../styles/AppFonts';
11
9
  import { AppColors } from '../styles/AppColors';
12
10
  import { getSize, formatDateTime } from '../helpers';
@@ -22,7 +20,6 @@ const AnalyticsDetail = ({ event, }) => {
22
20
  const paramKeys = useMemo(() => Object.keys(params), [params]);
23
21
  const userPropKeys = useMemo(() => Object.keys(userProperties), [userProperties]);
24
22
  const category = useMemo(() => getEventCategory(event.name, params), [event.name, params]);
25
- // Combined full JSON payload
26
23
  const fullJsonData = useMemo(() => ({
27
24
  name: event.name,
28
25
  timestamp: event.timestamp,
@@ -35,7 +32,6 @@ const AnalyticsDetail = ({ event, }) => {
35
32
  params,
36
33
  ...(userPropKeys.length > 0 ? { userProperties } : {}),
37
34
  }), [event, params, userPropKeys.length, userProperties]);
38
- // E-commerce revenue calculation
39
35
  const revenueInfo = useMemo(() => {
40
36
  const val = params.value ?? params.price;
41
37
  const currency = params.currency ?? 'USD';
@@ -47,14 +43,12 @@ const AnalyticsDetail = ({ event, }) => {
47
43
  }
48
44
  return null;
49
45
  }, [params]);
50
- // Items count if an items array exists
51
46
  const itemsCount = useMemo(() => {
52
47
  if (Array.isArray(params.items)) {
53
48
  return params.items.length;
54
49
  }
55
50
  return null;
56
51
  }, [params.items]);
57
- // Screen Context
58
52
  const screenContext = useMemo(() => {
59
53
  return (event.screenName ||
60
54
  params.firebase_screen ||
@@ -63,7 +57,6 @@ const AnalyticsDetail = ({ event, }) => {
63
57
  event.screenClass ||
64
58
  params.firebase_screen_class);
65
59
  }, [event.screenName, event.screenClass, params]);
66
- // Filtered parameter entries
67
60
  const filteredParamEntries = useMemo(() => {
68
61
  const entries = Object.entries(params);
69
62
  if (!paramSearch.trim())
@@ -74,7 +67,6 @@ const AnalyticsDetail = ({ event, }) => {
74
67
  return k.toLowerCase().includes(q) || valStr.toLowerCase().includes(q);
75
68
  });
76
69
  }, [params, paramSearch]);
77
- // Category Theme Meta
78
70
  const catMeta = useMemo(() => {
79
71
  switch (category) {
80
72
  case 'ecommerce':
@@ -130,12 +122,12 @@ const AnalyticsDetail = ({ event, }) => {
130
122
  ];
131
123
  return (<ScrollView style={detailStyles.scroll} contentContainerStyle={detailStyles.content} showsVerticalScrollIndicator contentInsetAdjustmentBehavior="never" automaticallyAdjustContentInsets={false}>
132
124
 
133
- {/* ── 1. Hero Event Header Card ────────────────────────────────────── */}
125
+
134
126
  <View style={detailStyles.heroCard}>
135
- {/* Top Badges Row */}
127
+
136
128
  <View style={detailStyles.heroTopRow}>
137
129
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flexWrap: 'wrap', flex: 1 }}>
138
- {/* Source Badge */}
130
+
139
131
  <View style={[
140
132
  detailStyles.sourceBadge,
141
133
  event.source === 'firebase'
@@ -162,7 +154,7 @@ const AnalyticsDetail = ({ event, }) => {
162
154
  </Text>
163
155
  </View>
164
156
 
165
- {/* Category Badge */}
157
+
166
158
  <View style={[
167
159
  detailStyles.catBadge,
168
160
  { backgroundColor: catMeta.bg, borderColor: catMeta.border },
@@ -174,18 +166,18 @@ const AnalyticsDetail = ({ event, }) => {
174
166
  </View>
175
167
  </View>
176
168
 
177
- {/* Copy Full Event JSON Button */}
169
+
178
170
  <CopyButton value={JSON.stringify(fullJsonData, null, 2)} label={t('analytics.eventDetails')}/>
179
171
  </View>
180
172
 
181
- {/* Event Name Heading */}
173
+
182
174
  <View style={detailStyles.titleRow}>
183
175
  <Text style={detailStyles.eventTitle} selectable numberOfLines={2}>
184
176
  {event.name}
185
177
  </Text>
186
178
  </View>
187
179
 
188
- {/* Sub Details Row: Timestamp & Screen Location */}
180
+
189
181
  <View style={detailStyles.metaRow}>
190
182
  <View style={detailStyles.timePill}>
191
183
  <ClockIcon color={AppColors.purple} size={11}/>
@@ -202,7 +194,7 @@ const AnalyticsDetail = ({ event, }) => {
202
194
  </View>)}
203
195
  </View>
204
196
 
205
- {/* ── 2. Metric Pills Summary ──────────────────────────────────────── */}
197
+
206
198
  <View style={detailStyles.metricsBar}>
207
199
  <View style={detailStyles.metricPill}>
208
200
  <Text style={detailStyles.metricLabel}>Params:</Text>
@@ -235,14 +227,14 @@ const AnalyticsDetail = ({ event, }) => {
235
227
  </View>
236
228
  </View>
237
229
 
238
- {/* ── 3. View Switcher Tabs (Overview, Tree, Raw) ───────────────────── */}
230
+
239
231
  <View style={detailStyles.tabsWrap}>
240
232
  <SegmentedTabs tabs={viewTabs} activeKey={activeViewTab} onChange={key => setActiveViewTab(key)}/>
241
233
  </View>
242
234
 
243
- {/* ── 4. Main Tab Body Content ───────────────────────────────────────── */}
235
+
244
236
  {activeViewTab === 'overview' && (<View style={detailStyles.tabContent}>
245
- {/* Metadata Card (Session, User ID, Client ID) */}
237
+
246
238
  {(event.userId || event.sessionId || event.trackingId) && (<View style={detailStyles.sectionCard}>
247
239
  <View style={detailStyles.sectionHeader}>
248
240
  <LayersIcon color={AppColors.purple} size={12}/>
@@ -264,7 +256,7 @@ const AnalyticsDetail = ({ event, }) => {
264
256
  </View>
265
257
  </View>)}
266
258
 
267
- {/* Parameters Table Section */}
259
+
268
260
  <View style={detailStyles.sectionCard}>
269
261
  <View style={detailStyles.sectionHeaderBetween}>
270
262
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
@@ -278,7 +270,7 @@ const AnalyticsDetail = ({ event, }) => {
278
270
  </Text>
279
271
  </View>
280
272
 
281
- {/* Search filter within parameters (if > 4 params) */}
273
+
282
274
  {paramKeys.length > 4 && (<View style={detailStyles.searchBar}>
283
275
  <SearchIcon color={AppColors.grayTextWeak} size={13}/>
284
276
  <TextInput placeholder="Filter parameters by key or value..." placeholderTextColor={AppColors.grayTextWeak} value={paramSearch} onChangeText={setParamSearch} style={detailStyles.searchInput} autoCorrect={false} autoCapitalize="none"/>
@@ -308,7 +300,6 @@ const AnalyticsDetail = ({ event, }) => {
308
300
  else if (isObject)
309
301
  typeStr = 'object';
310
302
  const valString = isObject ? JSON.stringify(val, null, 2) : String(val);
311
- // Highlight standard GA4 ecom/screen keys
312
303
  const isKeyHighlighted = key === 'value' ||
313
304
  key === 'price' ||
314
305
  key === 'currency' ||
@@ -317,7 +308,7 @@ const AnalyticsDetail = ({ event, }) => {
317
308
  key === 'item_name';
318
309
  return (<AnimatedEntrance key={key} index={pIdx} distance={4}>
319
310
  <View style={detailStyles.paramCard}>
320
- {/* Param Top Row: Key + Type + Copy */}
311
+
321
312
  <View style={detailStyles.paramCardHeader}>
322
313
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flex: 1, minWidth: 0 }}>
323
314
  <HighlightText text={key} search={paramSearch} style={[
@@ -334,7 +325,7 @@ const AnalyticsDetail = ({ event, }) => {
334
325
  <CopyButton value={valString} label={key}/>
335
326
  </View>
336
327
 
337
- {/* Param Value Display */}
328
+
338
329
  <View style={detailStyles.paramValBox}>
339
330
  {isObject ? (<JsonViewer data={val} search={paramSearch} hideTabs wrap/>) : (<HighlightText text={valString} search={paramSearch} style={detailStyles.paramValText} highlightStyle={detailStyles.highlight} selectable/>)}
340
331
  </View>
@@ -344,7 +335,7 @@ const AnalyticsDetail = ({ event, }) => {
344
335
  </View>)}
345
336
  </View>
346
337
 
347
- {/* User Properties Section (if any) */}
338
+
348
339
  {userPropKeys.length > 0 && (<View style={detailStyles.sectionCard}>
349
340
  <View style={detailStyles.sectionHeader}>
350
341
  <SparkleIcon color={AppColors.purple} size={12}/>
@@ -363,12 +354,12 @@ const AnalyticsDetail = ({ event, }) => {
363
354
  </View>)}
364
355
  </View>)}
365
356
 
366
- {/* ── JSON Tree View ────────────────────────────────────────────────── */}
357
+
367
358
  {activeViewTab === 'tree' && (<View style={detailStyles.jsonContainer}>
368
359
  <JsonViewer data={fullJsonData} defaultExpandDepth={1} mode="pretty" fullHeight/>
369
360
  </View>)}
370
361
 
371
- {/* ── Raw Payload View ──────────────────────────────────────────────── */}
362
+
372
363
  {activeViewTab === 'raw' && (<View style={detailStyles.jsonContainer}>
373
364
  <JsonViewer data={fullJsonData} mode="raw" fullHeight/>
374
365
  </View>)}
@@ -7,7 +7,6 @@ import { useTranslation } from '../i18n';
7
7
  import HighlightText from './HighlightText';
8
8
  import TouchableScale from './TouchableScale';
9
9
  import { CartIcon, MoneyIcon, GlobeIcon, BoltIcon, SparkleIcon, ClockIcon, } from './NetworkIcons';
10
- // ─── Component ────────────────────────────────────────────────────────────────
11
10
  const AnalyticsEventCard = React.memo(function AnalyticsEventCard({ event, onPress, isNew = false, searchStr = '', msSincePrev, computedScreenName, }) {
12
11
  const { t } = useTranslation();
13
12
  const color = getEventColor(event.name);
@@ -17,7 +16,6 @@ const AnalyticsEventCard = React.memo(function AnalyticsEventCard({ event, onPre
17
16
  : 0;
18
17
  const catKey = getEventCategory(event.name);
19
18
  const tagColors = getCategoryColors(catKey);
20
- // Flash animation for newly logged events
21
19
  const flashOpacity = useRef(new Animated.Value(isNew ? 1 : 0)).current;
22
20
  useEffect(() => {
23
21
  if (isNew) {
@@ -37,7 +35,7 @@ const AnalyticsEventCard = React.memo(function AnalyticsEventCard({ event, onPre
37
35
  ? t('analytics.systemCategory')
38
36
  : t('analytics.customCategory');
39
37
  return (<View style={cardStyles.container}>
40
- {/* ── Gap Indicator ─────────────────────────────────────────────────── */}
38
+
41
39
  {showGap && (<View style={cardStyles.gapContainer}>
42
40
  <View style={cardStyles.gapLine}/>
43
41
  <Text style={[cardStyles.gapText, { color: AppColors.grayTextWeak }]}>
@@ -46,7 +44,7 @@ const AnalyticsEventCard = React.memo(function AnalyticsEventCard({ event, onPre
46
44
  <View style={cardStyles.gapLine}/>
47
45
  </View>)}
48
46
 
49
- {/* ── Main Card ─────────────────────────────────────────────────────── */}
47
+
50
48
  <TouchableScale onPress={onPress} style={[
51
49
  cardStyles.modernCard,
52
50
  {
@@ -65,10 +63,10 @@ const AnalyticsEventCard = React.memo(function AnalyticsEventCard({ event, onPre
65
63
  },
66
64
  ]}/>
67
65
 
68
- {/* Top Row: Icon Badge, Event Name, Category Badge & Timestamp */}
66
+
69
67
  <View style={cardStyles.cardHeader}>
70
68
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 7, flex: 1 }}>
71
- {/* Category Icon Badge */}
69
+
72
70
  <View style={[
73
71
  cardStyles.iconBadge,
74
72
  { backgroundColor: tagColors.bg, borderColor: tagColors.border },
@@ -76,10 +74,10 @@ const AnalyticsEventCard = React.memo(function AnalyticsEventCard({ event, onPre
76
74
  {catKey === 'ecommerce' ? (<CartIcon color={tagColors.text} size={12}/>) : catKey === 'page_view' ? (<GlobeIcon color={tagColors.text} size={12}/>) : catKey === 'system' ? (<BoltIcon color={tagColors.text} size={12}/>) : (<SparkleIcon color={tagColors.text} size={12}/>)}
77
75
  </View>
78
76
 
79
- {/* Event Name */}
77
+
80
78
  <HighlightText text={event.name} search={searchStr} style={[cardStyles.eventName, { color: AppColors.primaryBlack }]} highlightStyle={cardStyles.highlight} numberOfLines={1}/>
81
79
 
82
- {/* Category Pill Tag */}
80
+
83
81
  <View style={[
84
82
  cardStyles.categoryBadge,
85
83
  { backgroundColor: tagColors.bg, borderColor: tagColors.border },
@@ -89,7 +87,7 @@ const AnalyticsEventCard = React.memo(function AnalyticsEventCard({ event, onPre
89
87
  </Text>
90
88
  </View>
91
89
 
92
- {/* Duplicate Multiplier */}
90
+
93
91
  {event.count !== undefined && event.count > 0 ? (<View style={[
94
92
  cardStyles.duplicateBadge,
95
93
  event.count === 1 && {
@@ -106,7 +104,7 @@ const AnalyticsEventCard = React.memo(function AnalyticsEventCard({ event, onPre
106
104
  </View>) : null}
107
105
  </View>
108
106
 
109
- {/* Timestamp */}
107
+
110
108
  <View style={{ flexDirection: 'row', alignItems: 'center', gap: 3 }}>
111
109
  <ClockIcon color={AppColors.grayTextWeak} size={10}/>
112
110
  <Text style={[cardStyles.timestamp, { color: AppColors.grayTextWeak }]}>
@@ -115,7 +113,7 @@ const AnalyticsEventCard = React.memo(function AnalyticsEventCard({ event, onPre
115
113
  </View>
116
114
  </View>
117
115
 
118
- {/* Bottom Row: Metadata Chips (Screen, Params, Value) */}
116
+
119
117
  <View style={cardStyles.cardBody}>
120
118
  <View style={cardStyles.chipsRow}>
121
119
  {(() => {
@@ -230,7 +228,6 @@ const AnalyticsEventCard = React.memo(function AnalyticsEventCard({ event, onPre
230
228
  </TouchableScale>
231
229
  </View>);
232
230
  });
233
- // ─── Styles ───────────────────────────────────────────────────────────────────
234
231
  const cardStyles = StyleSheet.create({
235
232
  container: {
236
233
  paddingHorizontal: 10,
@@ -7,10 +7,8 @@ const BAR_HEIGHT = 24;
7
7
  const PADDING_Y = 12;
8
8
  const AnalyticsGraph = ({ event, accentColor }) => {
9
9
  const params = event.params || {};
10
- // 1. Check for E-commerce items array
11
10
  const itemsArray = Array.isArray(params.items) ? params.items : null;
12
11
  const filteredItems = itemsArray?.filter((item) => typeof item.price === 'number') || [];
13
- // 2. Discover root-level numeric fields (exclude ids)
14
12
  const rootNumericKeys = [];
15
13
  Object.entries(params).forEach(([k, v]) => {
16
14
  if (typeof v === 'number' &&
@@ -19,7 +17,6 @@ const AnalyticsGraph = ({ event, accentColor }) => {
19
17
  rootNumericKeys.push({ key: k, value: v });
20
18
  }
21
19
  });
22
- // 3. Discover dates (YYYY-MM-DD format commonly used in booking/flights)
23
20
  const dateKeys = [];
24
21
  Object.entries(params).forEach(([k, v]) => {
25
22
  if (typeof v === 'string' &&
@@ -31,7 +28,6 @@ const AnalyticsGraph = ({ event, accentColor }) => {
31
28
  }
32
29
  }
33
30
  });
34
- // 4. Calculate parameter types
35
31
  const paramTypes = { string: 0, number: 0, boolean: 0, object: 0 };
36
32
  const strings = [];
37
33
  Object.entries(params).forEach(([k, v]) => {
@@ -53,7 +49,7 @@ const AnalyticsGraph = ({ event, accentColor }) => {
53
49
  const typeData = [
54
50
  { label: 'Strings', value: paramTypes.string, color: AppColors.purple },
55
51
  { label: 'Numbers', value: paramTypes.number, color: AppColors.skyBlue },
56
- { label: 'Booleans', value: paramTypes.boolean, color: AppColors.amber500 }, // Amber
52
+ { label: 'Booleans', value: paramTypes.boolean, color: AppColors.amber500 },
57
53
  { label: 'Objects', value: paramTypes.object, color: AppColors.greenColor },
58
54
  ].filter(d => d.value > 0);
59
55
  strings.sort((a, b) => b.value - a.value);
@@ -63,8 +59,8 @@ const AnalyticsGraph = ({ event, accentColor }) => {
63
59
  const hasDatesChart = dateKeys.length > 0;
64
60
  const hasStringsChart = topStrings.length > 0;
65
61
  const hasTypeData = typeData.length > 0;
66
- const screenWidth = Dimensions.get('window').width - 60; // Padding adjustments
67
- const rightMargin = 40; // Space for labels at the end of the bar
62
+ const screenWidth = Dimensions.get('window').width - 60;
63
+ const rightMargin = 40;
68
64
  const maxBarWidth = screenWidth - rightMargin;
69
65
  return (<View style={graphStyles.container}>
70
66
  <Text style={graphStyles.headerTitle}>Data Visualization</Text>
@@ -98,7 +94,6 @@ const AnalyticsGraph = ({ event, accentColor }) => {
98
94
  </View>)}
99
95
  </View>);
100
96
  };
101
- // --- Donut Chart Helpers ---
102
97
  const polarToCartesian = (centerX, centerY, radius, angleInDegrees) => {
103
98
  const angleInRadians = ((angleInDegrees - 90) * Math.PI) / 180.0;
104
99
  return {
@@ -183,7 +178,7 @@ const GaugeChart = ({ data, accentColor, }) => {
183
178
  }}>
184
179
  {data.map(d => {
185
180
  const fillPct = Math.min(Math.abs(d.value) / maxVal, 1);
186
- const strokeDashoffset = Math.max(circumference - fillPct * circumference, 0.001); // avoid exact 0
181
+ const strokeDashoffset = Math.max(circumference - fillPct * circumference, 0.001);
187
182
  return (<View key={d.label} style={{ alignItems: 'center', width: 70 }}>
188
183
  <Svg width="60" height="60" viewBox="0 0 60 60">
189
184
  <Circle cx="30" cy="30" r={radius} stroke={AppColors.grayBorderSecondary} strokeWidth={stroke} fill="none"/>
@@ -259,7 +254,7 @@ const CalendarChart = ({ data, accentColor, }) => {
259
254
  shadowOffset: { width: 0, height: 2 },
260
255
  elevation: 2,
261
256
  }}>
262
- {/* Calendar Header with Accent Color */}
257
+
263
258
  <View style={{
264
259
  backgroundColor: accentColor,
265
260
  height: 18,
@@ -276,7 +271,7 @@ const CalendarChart = ({ data, accentColor, }) => {
276
271
  {monthText} {yearText}
277
272
  </Text>
278
273
  </View>
279
- {/* Calendar Body */}
274
+
280
275
  <View style={{
281
276
  flex: 1,
282
277
  justifyContent: 'center',
@@ -321,18 +316,18 @@ const BarChart = ({ data, accentColor, maxBarWidth, isGradient = false, }) => {
321
316
  const y = i * (BAR_HEIGHT + PADDING_Y);
322
317
  const barWidth = Math.max((d.value / maxVal) * maxBarWidth, 2);
323
318
  return (<React.Fragment key={d.label}>
324
- {/* Label above bar */}
319
+
325
320
  <SvgText x={0} y={y + 12} fill={AppColors.grayTextStrong} fontSize="11" fontFamily={AppFonts.interMedium}>
326
321
  {d.label}
327
322
  </SvgText>
328
323
 
329
- {/* Background trace line */}
324
+
330
325
  <Line x1={0} y1={y + 24} x2={maxBarWidth} y2={y + 24} stroke={AppColors.grayBorderSecondary} strokeDasharray="4"/>
331
326
 
332
- {/* The actual Bar */}
327
+
333
328
  <Rect x={0} y={y + 16} width={barWidth} height={14} fill={isGradient ? 'url(#barGrad)' : accentColor} rx={4} opacity={0.85}/>
334
329
 
335
- {/* Value Text at the end of the bar */}
330
+
336
331
  <SvgText x={barWidth + 6} y={y + 26} fill={AppColors.primaryBlack} fontSize="11" fontFamily={AppFonts.interBold}>
337
332
  {d.value}
338
333
  </SvgText>
@@ -3,7 +3,6 @@ import { Image, Platform, StyleSheet, View, } from 'react-native';
3
3
  import BrandSquareIcon from './BrandSquareIcon';
4
4
  export const AppHeaderLogo = ({ size = 46, customIcon, }) => {
5
5
  const [loadError, setLoadError] = useState(false);
6
- // 1. If customIcon is explicitly provided, render it directly edge-to-edge
7
6
  if (customIcon) {
8
7
  if (React.isValidElement(customIcon)) {
9
8
  const clonedIcon = React.cloneElement(customIcon, {
@@ -33,7 +32,6 @@ export const AppHeaderLogo = ({ size = 46, customIcon, }) => {
33
32
  <Image source={customIcon} style={logoStyles.image} resizeMode="cover"/>
34
33
  </View>);
35
34
  }
36
- // 2. Dynamically query installed native app icon (AppIcon on iOS, ic_launcher on Android)
37
35
  if (!loadError && Platform.OS !== 'web') {
38
36
  const nativeSource = Platform.select({
39
37
  ios: { uri: 'AppIcon' },
@@ -51,7 +49,6 @@ export const AppHeaderLogo = ({ size = 46, customIcon, }) => {
51
49
  <Image source={nativeSource} style={logoStyles.image} resizeMode="cover" onError={() => setLoadError(true)}/>
52
50
  </View>);
53
51
  }
54
- // 3. Fallback: Inspector's Signature Owl Brand Logo
55
52
  return (<View style={[
56
53
  logoStyles.svgContainer,
57
54
  {
@@ -59,18 +59,18 @@ export const BrandCircleIcon = ({ size = 56 }) => {
59
59
  <Circle cx="128" cy="128" r="121.4" fill="none" stroke="url(#edge)" strokeOpacity={0.7} strokeWidth={1.4}/>
60
60
  <Circle cx="128" cy="128" r="100" fill="url(#halo)"/>
61
61
  <G transform="translate(128 132) scale(1.05) translate(-128 -134)">
62
- {/* wing 1 */}
62
+
63
63
  <Path d="M74 124 C58 154 60 190 86 204 C79 176 77 148 88 126 Z" fill="url(#wing)" stroke="url(#beam)" strokeWidth={2.5} strokeOpacity={0.45}/>
64
- {/* wing 2 */}
64
+
65
65
  <Path d="M182 124 C198 154 196 190 170 204 C177 176 179 148 168 126 Z" fill="url(#wing)" stroke="url(#beam)" strokeWidth={2.5} strokeOpacity={0.45}/>
66
- {/* body */}
66
+
67
67
  <Path d="M62 150 C58 104 70 70 90 58 L98 42 L116 62 Q128 57 140 62 L158 42 L166 58 C186 70 198 104 194 150 C198 180 184 204 152 212 C140 216 116 216 104 212 C72 204 58 180 62 150 Z" fill="url(#owlbody)" stroke="url(#beam)" strokeWidth={4} strokeLinejoin="round"/>
68
68
 
69
- {/* inner-ear shadows */}
69
+
70
70
  <Path d="M99 48 L114 62 L104 63 L98 55 Z" fill="#080F22" opacity={0.5}/>
71
71
  <Path d="M157 48 L142 62 L152 63 L158 55 Z" fill="#080F22" opacity={0.5}/>
72
72
 
73
- {/* wing feather lines */}
73
+
74
74
  <G stroke="#22325A" strokeWidth={2.2} fill="none" strokeLinecap="round" opacity={0.75}>
75
75
  <Path d="M80 138 q-5 26 3 50"/>
76
76
  <Path d="M90 134 q-4 26 3 48"/>
@@ -78,10 +78,10 @@ export const BrandCircleIcon = ({ size = 56 }) => {
78
78
  <Path d="M166 134 q4 26 -3 48"/>
79
79
  </G>
80
80
 
81
- {/* belly plate */}
81
+
82
82
  <Path d="M128 126 C151 126 164 148 162 174 C160 198 146 212 128 212 C110 212 96 198 94 174 C92 148 105 126 128 126 Z" fill="url(#belly)"/>
83
83
 
84
- {/* belly feather scallops */}
84
+
85
85
  <G stroke="#3E588C" strokeWidth={2.3} fill="none" strokeLinecap="round" opacity={0.4}>
86
86
  <Path d="M110 154 Q118 162 126 154"/>
87
87
  <Path d="M126 154 Q134 162 142 154"/>
@@ -92,7 +92,7 @@ export const BrandCircleIcon = ({ size = 56 }) => {
92
92
  <Path d="M128 190 Q136 198 144 190"/>
93
93
  </G>
94
94
 
95
- {/* developer chest screen + code emblem */}
95
+
96
96
  <Rect x={107} y={161} width={42} height={32} rx={9} fill="#0C1426" stroke="url(#beam)" strokeWidth={2} strokeOpacity={0.7}/>
97
97
  <G stroke="#8FD0EC" strokeWidth={3} strokeLinecap="round" strokeLinejoin="round" fill="none">
98
98
  <Path d="M122 170 L115 177 L122 184"/>
@@ -100,27 +100,27 @@ export const BrandCircleIcon = ({ size = 56 }) => {
100
100
  <Path d="M130 168 L126 186"/>
101
101
  </G>
102
102
 
103
- {/* facial disc */}
103
+
104
104
  <Path d="M128 92 C148 70 186 78 186 108 C186 134 160 152 128 152 C96 152 70 134 70 108 C70 78 108 70 128 92 Z" fill="url(#faceplate)" stroke="#52709E" strokeWidth={2.6} strokeOpacity={0.7}/>
105
- {/* facial-disc centre ridge */}
105
+
106
106
  <Path d="M128 96 L128 120" stroke="#52709E" strokeWidth={2} strokeLinecap="round" strokeOpacity={0.45}/>
107
107
 
108
- {/* feet */}
108
+
109
109
  <G stroke="url(#beak)" strokeWidth={5} strokeLinecap="round" fill="none">
110
110
  <Path d="M111 209 L105 224 M111 209 L111 226 M111 209 L117 224"/>
111
111
  <Path d="M145 209 L139 224 M145 209 L145 226 M145 209 L151 224"/>
112
112
  </G>
113
113
 
114
- {/* normal eye: big cute yellow iris, dark pupil, sparkles */}
114
+
115
115
  <Circle cx={153} cy={107} r={17} fill="url(#iris)" stroke="#1A1205" strokeWidth={2.2}/>
116
116
  <Circle cx={153} cy={108} r={8.2} fill="#0A0E18"/>
117
117
  <Circle cx={156.2} cy={104} r={3.1} fill="#ffffff" opacity={0.95}/>
118
118
  <Circle cx={149.6} cy={111} r={1.6} fill="#ffffff" opacity={0.7}/>
119
119
 
120
- {/* beak */}
120
+
121
121
  <Path d="M123.5 123 Q128 121 132.5 123 Q131 132 128 134.5 Q125 132 123.5 123 Z" fill="url(#beak)"/>
122
122
 
123
- {/* magnifier held to the big (debug) eye */}
123
+
124
124
  <Circle cx={95} cy={103} r={20} fill="url(#iris)" stroke="#1A1205" strokeWidth={2.6}/>
125
125
  <Circle cx={95} cy={104} r={10} fill="#0A0E18"/>
126
126
  <Circle cx={98.6} cy={100} r={3.4} fill="#ffffff" opacity={0.95}/>
@@ -131,7 +131,7 @@ export const BrandCircleIcon = ({ size = 56 }) => {
131
131
  <Line x1={75} y1={123} x2={54} y2={147} stroke="url(#beam)" strokeWidth={8.5} strokeLinecap="round"/>
132
132
  <Circle cx={95} cy={103} r={28} fill="none" stroke="url(#beam)" strokeWidth={7}/>
133
133
 
134
- {/* rosy cheeks */}
134
+
135
135
  <Ellipse cx={83} cy={127} rx={9} ry={6} fill="url(#blush)"/>
136
136
  <Ellipse cx={167} cy={122} rx={9} ry={6} fill="url(#blush)"/>
137
137
  </G>