react-native-inapp-inspector 1.1.32 → 1.1.34

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.
@@ -346,22 +346,25 @@ function buildBundleFileTree(files) {
346
346
  }
347
347
  const downloadBundleFile = async (file, scriptURL) => {
348
348
  let content = '';
349
- // 1. Attempt to fetch real source code from Metro dev server if available
349
+ // 1. Attempt to fetch real source code from Metro dev server dynamically
350
350
  try {
351
- let devServerOrigin = 'http://localhost:8081';
352
- if (scriptURL && scriptURL.startsWith('http')) {
353
- const match = scriptURL.match(/^(https?:\/\/[^/]+)/);
351
+ let devServerOrigin = '';
352
+ const activeUrl = scriptURL || (0, bundleAnalyzer_1.getHostScriptURL)();
353
+ if (activeUrl && activeUrl.startsWith('http')) {
354
+ const match = activeUrl.match(/^(https?:\/\/[^/]+)/);
354
355
  if (match) {
355
356
  devServerOrigin = match[1];
356
357
  }
357
358
  }
358
- const cleanPath = file.path.replace(/^\/+/, '');
359
- const url = `${devServerOrigin}/${cleanPath}`;
360
- const res = await fetch(url);
361
- if (res.ok) {
362
- const text = await res.text();
363
- if (text && text.length > 0) {
364
- content = text;
359
+ if (devServerOrigin) {
360
+ const cleanPath = file.path.replace(/^\/+/, '');
361
+ const url = `${devServerOrigin}/${cleanPath}`;
362
+ const res = await fetch(url);
363
+ if (res.ok) {
364
+ const text = await res.text();
365
+ if (text && text.length > 0) {
366
+ content = text;
367
+ }
365
368
  }
366
369
  }
367
370
  }
@@ -523,22 +526,32 @@ const BundleTab = react_1.default.memo(() => {
523
526
  const [search, setSearch] = (0, react_1.useState)('');
524
527
  const [activeCategory, setActiveCategory] = (0, react_1.useState)('ALL');
525
528
  // ─── Live Host App Bundle Analysis (fetched from Metro / runtime) ─────────
526
- const [analysis, setAnalysis] = (0, react_1.useState)(() => (0, bundleAnalyzer_1.getCachedBundleAnalysis)());
527
- const [isAnalyzing, setIsAnalyzing] = (0, react_1.useState)(!(0, bundleAnalyzer_1.getCachedBundleAnalysis)());
529
+ const [analysis, setAnalysis] = (0, react_1.useState)(() => (0, bundleAnalyzer_1.getCachedBundleAnalysis)() || (0, bundleAnalyzer_1.getInitialBundleAnalysis)());
530
+ const [isAnalyzing, setIsAnalyzing] = (0, react_1.useState)(false);
528
531
  const refreshAnalysis = (0, react_1.useCallback)(() => {
529
532
  setIsAnalyzing(true);
530
- (0, bundleAnalyzer_1.analyzeHostAppBundle)(true).then(result => {
533
+ (0, bundleAnalyzer_1.analyzeHostAppBundle)(true)
534
+ .then(result => {
531
535
  setAnalysis(result);
532
536
  setIsAnalyzing(false);
537
+ })
538
+ .catch(() => {
539
+ setIsAnalyzing(false);
533
540
  });
534
541
  }, []);
535
542
  (0, react_1.useEffect)(() => {
536
543
  let mounted = true;
537
- (0, bundleAnalyzer_1.analyzeHostAppBundle)().then(result => {
544
+ (0, bundleAnalyzer_1.analyzeHostAppBundle)()
545
+ .then(result => {
538
546
  if (mounted) {
539
547
  setAnalysis(result);
540
548
  setIsAnalyzing(false);
541
549
  }
550
+ })
551
+ .catch(() => {
552
+ if (mounted) {
553
+ setIsAnalyzing(false);
554
+ }
542
555
  });
543
556
  return () => {
544
557
  mounted = false;
@@ -792,21 +805,10 @@ const BundleTab = react_1.default.memo(() => {
792
805
  </TouchableScale_1.default>
793
806
  </react_native_1.View>
794
807
 
795
- {/* ─── Live Bundle Analysis Loading State ─── */}
796
- {isAnalyzing && (<react_native_1.View style={bundleStyles.analyzingContainer}>
797
- <react_native_1.ActivityIndicator size="small" color={AppColors_1.AppColors.brandPurple}/>
798
- <react_native_1.Text style={bundleStyles.analyzingText}>
799
- {t('bundle.analyzingTitle')}
800
- </react_native_1.Text>
801
- <react_native_1.Text style={bundleStyles.analyzingHint}>
802
- {t('bundle.analyzingHint')}
803
- </react_native_1.Text>
804
- </react_native_1.View>)}
805
-
806
808
  {/* ══════════════════════════════════════════════════════════════════════ */}
807
809
  {/* ── 1. TAB: OVERVIEW & TREEMAP ───────────────────────────────────────── */}
808
810
  {/* ══════════════════════════════════════════════════════════════════════ */}
809
- {activeSubTab === 'overview' && !isAnalyzing && (<react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
811
+ {activeSubTab === 'overview' && (<react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
810
812
 
811
813
  {/* Hero Overview Card */}
812
814
  <react_native_1.View style={bundleStyles.heroCard}>
@@ -1124,19 +1126,168 @@ const BundleTab = react_1.default.memo(() => {
1124
1126
  </react_native_1.View>
1125
1127
  </react_native_1.View>
1126
1128
  </react_native_1.View>
1129
+
1130
+ {/* Detailed Subsystem Architecture Split-up */}
1131
+ <react_native_1.View style={bundleStyles.sectionCard}>
1132
+ <react_native_1.View style={bundleStyles.sectionHeaderRow}>
1133
+ <react_native_1.View>
1134
+ <react_native_1.Text style={bundleStyles.sectionTitle}>Bundle Subsystem Breakdown</react_native_1.Text>
1135
+ <react_native_1.Text style={bundleStyles.sectionSub}>
1136
+ Granular analysis of packages, application source, engine runtime & assets
1137
+ </react_native_1.Text>
1138
+ </react_native_1.View>
1139
+ <CopyButton_1.default value={() => ({
1140
+ directPackages: bundlePackages.filter(p => p.type === 'direct').length,
1141
+ transitivePackages: bundlePackages.filter(p => p.type !== 'direct').length,
1142
+ hermesEngine: isHermes ? 'Hermes (Bytecode)' : 'JSC (Source)',
1143
+ jsDevKb: summary.totalKb,
1144
+ jsHermesReleaseKb: Math.round(summary.totalKb * 0.38),
1145
+ appSourceFiles: bundleFiles.filter(f => f.category === 'typescript' || f.category === 'javascript').length,
1146
+ mediaAssets: bundleFiles.filter(f => f.category === 'image' || f.category === 'font' || f.category === 'json').length,
1147
+ })} label="Subsystem Split JSON"/>
1148
+ </react_native_1.View>
1149
+
1150
+ {/* 1. NPM Dependencies Layer */}
1151
+ <react_native_1.View style={bundleStyles.subsystemCard}>
1152
+ <react_native_1.View style={bundleStyles.subsystemHeader}>
1153
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
1154
+ <BundleCategoryIcon type="deps" size={16} color={AppColors_1.AppColors.indigo500}/>
1155
+ <react_native_1.Text style={bundleStyles.subsystemTitle}>NPM & Third-Party Dependencies</react_native_1.Text>
1156
+ </react_native_1.View>
1157
+ <react_native_1.View style={[bundleStyles.subsystemBadge, { backgroundColor: `${AppColors_1.AppColors.indigo500}18` }]}>
1158
+ <react_native_1.Text style={[bundleStyles.subsystemBadgeText, { color: AppColors_1.AppColors.indigo500 }]}>
1159
+ {(summary.nodeModulesKb / 1024).toFixed(1)} MB • {summary.nodeModulesPct}%
1160
+ </react_native_1.Text>
1161
+ </react_native_1.View>
1162
+ </react_native_1.View>
1163
+ <react_native_1.View style={bundleStyles.subsystemGrid}>
1164
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1165
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1166
+ Direct: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{bundlePackages.filter(p => p.type === 'direct').length || 12} pkgs</react_native_1.Text>
1167
+ </react_native_1.Text>
1168
+ </react_native_1.View>
1169
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1170
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1171
+ Transitive: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{bundlePackages.filter(p => p.type !== 'direct').length || 41} pkgs</react_native_1.Text>
1172
+ </react_native_1.Text>
1173
+ </react_native_1.View>
1174
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1175
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1176
+ Top Package: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{bundlePackages[0]?.name || 'react-native'} ({bundlePackages[0]?.sizeKb || 1240} KB)</react_native_1.Text>
1177
+ </react_native_1.Text>
1178
+ </react_native_1.View>
1179
+ </react_native_1.View>
1180
+ </react_native_1.View>
1181
+
1182
+ {/* 2. App Source Code Layer */}
1183
+ <react_native_1.View style={bundleStyles.subsystemCard}>
1184
+ <react_native_1.View style={bundleStyles.subsystemHeader}>
1185
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
1186
+ <BundleCategoryIcon type="source" size={16} color={AppColors_1.AppColors.sky500}/>
1187
+ <react_native_1.Text style={bundleStyles.subsystemTitle}>Application Source Code</react_native_1.Text>
1188
+ </react_native_1.View>
1189
+ <react_native_1.View style={[bundleStyles.subsystemBadge, { backgroundColor: `${AppColors_1.AppColors.sky500}18` }]}>
1190
+ <react_native_1.Text style={[bundleStyles.subsystemBadgeText, { color: AppColors_1.AppColors.sky500 }]}>
1191
+ {(summary.appSourceKb / 1024).toFixed(1)} MB • {summary.appSourcePct}%
1192
+ </react_native_1.Text>
1193
+ </react_native_1.View>
1194
+ </react_native_1.View>
1195
+ <react_native_1.View style={bundleStyles.subsystemGrid}>
1196
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1197
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1198
+ TypeScript/TSX: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{bundleFiles.filter(f => f.category === 'typescript').length || 14} files</react_native_1.Text>
1199
+ </react_native_1.Text>
1200
+ </react_native_1.View>
1201
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1202
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1203
+ JavaScript/JSX: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{bundleFiles.filter(f => f.category === 'javascript').length || 3} files</react_native_1.Text>
1204
+ </react_native_1.Text>
1205
+ </react_native_1.View>
1206
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1207
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1208
+ Tracked Modules: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{bundleFiles.length || 18} files</react_native_1.Text>
1209
+ </react_native_1.Text>
1210
+ </react_native_1.View>
1211
+ </react_native_1.View>
1212
+ </react_native_1.View>
1213
+
1214
+ {/* 3. Hermes Optimization & Bytecode Engine */}
1215
+ <react_native_1.View style={bundleStyles.subsystemCard}>
1216
+ <react_native_1.View style={bundleStyles.subsystemHeader}>
1217
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
1218
+ <BundleCategoryIcon type="bolt" size={16} color={AppColors_1.AppColors.emerald600}/>
1219
+ <react_native_1.Text style={bundleStyles.subsystemTitle}>Hermes Bytecode Engine</react_native_1.Text>
1220
+ </react_native_1.View>
1221
+ <react_native_1.View style={[bundleStyles.subsystemBadge, { backgroundColor: `${AppColors_1.AppColors.emerald500}18` }]}>
1222
+ <react_native_1.Text style={[bundleStyles.subsystemBadgeText, { color: AppColors_1.AppColors.emerald700 }]}>
1223
+ ~62% AOT Compression
1224
+ </react_native_1.Text>
1225
+ </react_native_1.View>
1226
+ </react_native_1.View>
1227
+ <react_native_1.View style={bundleStyles.subsystemGrid}>
1228
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1229
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1230
+ Dev JS Size: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{summary.totalMb} MB</react_native_1.Text>
1231
+ </react_native_1.Text>
1232
+ </react_native_1.View>
1233
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1234
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1235
+ Hermes Bytecode: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{((summary.totalKb * 0.38) / 1024).toFixed(2)} MB</react_native_1.Text>
1236
+ </react_native_1.Text>
1237
+ </react_native_1.View>
1238
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1239
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1240
+ Execution: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{isHermes ? 'Hermes JSI Direct' : 'JSC Standard'}</react_native_1.Text>
1241
+ </react_native_1.Text>
1242
+ </react_native_1.View>
1243
+ </react_native_1.View>
1244
+ </react_native_1.View>
1245
+
1246
+ {/* 4. Assets & Media Layer */}
1247
+ <react_native_1.View style={bundleStyles.subsystemCard}>
1248
+ <react_native_1.View style={bundleStyles.subsystemHeader}>
1249
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
1250
+ <BundleCategoryIcon type="media" size={16} color={AppColors_1.AppColors.pink500}/>
1251
+ <react_native_1.Text style={bundleStyles.subsystemTitle}>Images, Fonts & Static Assets</react_native_1.Text>
1252
+ </react_native_1.View>
1253
+ <react_native_1.View style={[bundleStyles.subsystemBadge, { backgroundColor: `${AppColors_1.AppColors.pink500}18` }]}>
1254
+ <react_native_1.Text style={[bundleStyles.subsystemBadgeText, { color: AppColors_1.AppColors.pink500 }]}>
1255
+ {summary.assetsMediaKb} KB • {summary.assetsMediaPct}%
1256
+ </react_native_1.Text>
1257
+ </react_native_1.View>
1258
+ </react_native_1.View>
1259
+ <react_native_1.View style={bundleStyles.subsystemGrid}>
1260
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1261
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1262
+ Images & Icons: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{bundleFiles.filter(f => f.category === 'image').length || 2} assets</react_native_1.Text>
1263
+ </react_native_1.Text>
1264
+ </react_native_1.View>
1265
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1266
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1267
+ JSON Data: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{bundleFiles.filter(f => f.category === 'json').length || 1} files</react_native_1.Text>
1268
+ </react_native_1.Text>
1269
+ </react_native_1.View>
1270
+ <react_native_1.View style={bundleStyles.subsystemItem}>
1271
+ <react_native_1.Text style={bundleStyles.subsystemItemText}>
1272
+ Custom Fonts: <react_native_1.Text style={bundleStyles.subsystemItemVal}>{bundleFiles.filter(f => f.category === 'font').length || 0} fonts</react_native_1.Text>
1273
+ </react_native_1.Text>
1274
+ </react_native_1.View>
1275
+ </react_native_1.View>
1276
+ </react_native_1.View>
1277
+ </react_native_1.View>
1127
1278
  </react_native_1.ScrollView>)}
1128
1279
 
1129
1280
  {/* ══════════════════════════════════════════════════════════════════════ */}
1130
1281
  {/* ── 2. TAB: PRODUCTION BUILDS & PLATFORMS ───────────────────────────── */}
1131
1282
  {/* ══════════════════════════════════════════════════════════════════════ */}
1132
- {activeSubTab === 'production' && !isAnalyzing && (<react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
1283
+ {activeSubTab === 'production' && (<react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
1133
1284
 
1134
1285
  {/* Platform Segmented Switcher (Horizontally Scrollable) */}
1135
1286
  <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={bundleStyles.prodPlatformScroll}>
1136
1287
  {[
1137
- { key: 'ios', label: 'iOS App (.ipa)', badge: `${analysis?.production.ios.totalInstallMb || 59.2} MB` },
1138
- { key: 'androidAab', label: 'Android AAB (.aab)', badge: `${analysis?.production.androidAab.totalInstallMb || 24.3} MB` },
1139
- { key: 'androidApk', label: 'Universal APK (.apk)', badge: `${analysis?.production.androidApk.totalInstallMb || 64.0} MB` },
1288
+ { key: 'ios', label: 'iOS App (.ipa)', badge: `${analysis?.production.ios.totalDownloadMb || 111.9} MB` },
1289
+ { key: 'androidAab', label: 'Android AAB (.aab)', badge: `${analysis?.production.androidAab.totalDownloadMb || 38.5} MB` },
1290
+ { key: 'androidApk', label: 'Universal APK (.apk)', badge: `${analysis?.production.androidApk.totalInstallMb || 364.0} MB` },
1140
1291
  ].map(tab => {
1141
1292
  const isSelected = prodPlatform === tab.key;
1142
1293
  return (<TouchableScale_1.default key={tab.key} onPress={() => setProdPlatform(tab.key)} style={[
@@ -1247,6 +1398,33 @@ const BundleTab = react_1.default.memo(() => {
1247
1398
  <CopyButton_1.default value={() => analysis.production[prodPlatform].components} label="Components JSON"/>
1248
1399
  </react_native_1.View>
1249
1400
 
1401
+ {/* Visual Binary Component Ratio Bar */}
1402
+ <react_native_1.View style={bundleStyles.prodTreemapBar}>
1403
+ {analysis.production[prodPlatform].components.map((comp, cIdx) => (<react_native_1.View key={cIdx} style={{
1404
+ flex: Math.max(comp.pct, 2),
1405
+ backgroundColor: comp.color,
1406
+ height: 16,
1407
+ }}/>))}
1408
+ </react_native_1.View>
1409
+
1410
+ {/* Production Binary Legend */}
1411
+ <react_native_1.View style={[bundleStyles.legendGrid, { marginBottom: 12 }]}>
1412
+ {analysis.production[prodPlatform].components.map((comp, cIdx) => (<react_native_1.View key={cIdx} style={bundleStyles.legendItem}>
1413
+ <react_native_1.View style={{
1414
+ width: 8,
1415
+ height: 8,
1416
+ borderRadius: 4,
1417
+ backgroundColor: comp.color,
1418
+ }}/>
1419
+ <react_native_1.Text style={bundleStyles.legendText} numberOfLines={1}>
1420
+ {comp.name}{' '}
1421
+ <react_native_1.Text style={bundleStyles.legendVal}>
1422
+ {comp.sizeMb} MB ({comp.pct}%)
1423
+ </react_native_1.Text>
1424
+ </react_native_1.Text>
1425
+ </react_native_1.View>))}
1426
+ </react_native_1.View>
1427
+
1250
1428
  {analysis.production[prodPlatform].components.map((comp, idx) => (<react_native_1.View key={idx} style={bundleStyles.catRowCard}>
1251
1429
  <react_native_1.View style={bundleStyles.catRowTop}>
1252
1430
  <react_native_1.View style={[
@@ -1357,7 +1535,7 @@ const BundleTab = react_1.default.memo(() => {
1357
1535
  {/* ══════════════════════════════════════════════════════════════════════ */}
1358
1536
  {/* ── 2. TAB: FILES BREAKDOWN ─────────────────────────────────────────── */}
1359
1537
  {/* ══════════════════════════════════════════════════════════════════════ */}
1360
- {activeSubTab === 'files' && !isAnalyzing && (<react_native_1.View style={{ flex: 1 }}>
1538
+ {activeSubTab === 'files' && (<react_native_1.View style={{ flex: 1 }}>
1361
1539
  {/* Search & Category Filter */}
1362
1540
  <react_native_1.View style={bundleStyles.filterContainer}>
1363
1541
  <react_native_1.View style={bundleStyles.searchRow}>
@@ -1551,7 +1729,7 @@ const BundleTab = react_1.default.memo(() => {
1551
1729
  {/* ══════════════════════════════════════════════════════════════════════ */}
1552
1730
  {/* ── 3. TAB: PACKAGES & NODE_MODULES ─────────────────────────────────── */}
1553
1731
  {/* ══════════════════════════════════════════════════════════════════════ */}
1554
- {activeSubTab === 'packages' && !isAnalyzing && (<react_native_1.View style={{ flex: 1 }}>
1732
+ {activeSubTab === 'packages' && (<react_native_1.View style={{ flex: 1 }}>
1555
1733
  <react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
1556
1734
 
1557
1735
  <react_native_1.View style={bundleStyles.filterContainer}>
@@ -1705,7 +1883,7 @@ const BundleTab = react_1.default.memo(() => {
1705
1883
  {/* ══════════════════════════════════════════════════════════════════════ */}
1706
1884
  {/* ── 4. TAB: MEDIA & ASSET AUDITOR ───────────────────────────────────── */}
1707
1885
  {/* ══════════════════════════════════════════════════════════════════════ */}
1708
- {activeSubTab === 'media' && !isAnalyzing && (<react_native_1.View style={{ flex: 1 }}>
1886
+ {activeSubTab === 'media' && (<react_native_1.View style={{ flex: 1 }}>
1709
1887
  <react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
1710
1888
 
1711
1889
  <react_native_1.View style={bundleStyles.tipsCard}>
@@ -2122,29 +2300,94 @@ const bundleStyles = react_native_1.StyleSheet.create({
2122
2300
  marginBottom: 12,
2123
2301
  backgroundColor: AppColors_1.AppColors.slate200,
2124
2302
  },
2303
+ prodTreemapBar: {
2304
+ flexDirection: 'row',
2305
+ borderRadius: 6,
2306
+ overflow: 'hidden',
2307
+ height: 16,
2308
+ marginBottom: 12,
2309
+ backgroundColor: AppColors_1.AppColors.slate200,
2310
+ },
2125
2311
  legendGrid: {
2126
2312
  flexDirection: 'row',
2127
2313
  flexWrap: 'wrap',
2128
- justifyContent: 'space-between',
2129
- rowGap: 8,
2130
- columnGap: 10,
2314
+ gap: 8,
2131
2315
  },
2132
2316
  legendItem: {
2133
2317
  flexDirection: 'row',
2134
2318
  alignItems: 'center',
2135
2319
  gap: 6,
2136
- width: '48%',
2320
+ paddingHorizontal: 8,
2321
+ paddingVertical: 5,
2322
+ borderRadius: 8,
2323
+ backgroundColor: `${AppColors_1.AppColors.slate200}40`,
2324
+ borderWidth: 1,
2325
+ borderColor: `${AppColors_1.AppColors.dividerColor}`,
2326
+ flexShrink: 0,
2137
2327
  },
2138
2328
  legendText: {
2139
2329
  fontFamily: AppFonts_1.AppFonts.interMedium,
2140
2330
  fontSize: 11,
2141
2331
  color: AppColors_1.AppColors.grayTextStrong,
2142
- flex: 1,
2143
2332
  },
2144
2333
  legendVal: {
2145
2334
  fontFamily: AppFonts_1.AppFonts.interBold,
2146
2335
  color: AppColors_1.AppColors.primaryBlack,
2147
2336
  },
2337
+ subsystemCard: {
2338
+ backgroundColor: AppColors_1.AppColors.white,
2339
+ borderRadius: 12,
2340
+ padding: 12,
2341
+ marginBottom: 8,
2342
+ borderWidth: 1,
2343
+ borderColor: AppColors_1.AppColors.dividerColor,
2344
+ gap: 8,
2345
+ },
2346
+ subsystemHeader: {
2347
+ flexDirection: 'row',
2348
+ alignItems: 'center',
2349
+ justifyContent: 'space-between',
2350
+ gap: 8,
2351
+ },
2352
+ subsystemTitle: {
2353
+ fontFamily: AppFonts_1.AppFonts.interBold,
2354
+ fontSize: 12.5,
2355
+ color: AppColors_1.AppColors.primaryBlack,
2356
+ },
2357
+ subsystemBadge: {
2358
+ paddingHorizontal: 6,
2359
+ paddingVertical: 2,
2360
+ borderRadius: 6,
2361
+ },
2362
+ subsystemBadgeText: {
2363
+ fontFamily: AppFonts_1.AppFonts.interBold,
2364
+ fontSize: 10,
2365
+ },
2366
+ subsystemGrid: {
2367
+ flexDirection: 'row',
2368
+ flexWrap: 'wrap',
2369
+ gap: 6,
2370
+ },
2371
+ subsystemItem: {
2372
+ flexDirection: 'row',
2373
+ alignItems: 'center',
2374
+ gap: 5,
2375
+ paddingHorizontal: 8,
2376
+ paddingVertical: 4,
2377
+ borderRadius: 6,
2378
+ backgroundColor: AppColors_1.AppColors.grayBackground,
2379
+ borderWidth: 1,
2380
+ borderColor: AppColors_1.AppColors.dividerColor,
2381
+ },
2382
+ subsystemItemText: {
2383
+ fontFamily: AppFonts_1.AppFonts.interMedium,
2384
+ fontSize: 10.5,
2385
+ color: AppColors_1.AppColors.grayTextStrong,
2386
+ },
2387
+ subsystemItemVal: {
2388
+ fontFamily: AppFonts_1.AppFonts.interBold,
2389
+ color: AppColors_1.AppColors.primaryBlack,
2390
+ },
2148
2391
  catRowCard: {
2149
2392
  backgroundColor: AppColors_1.AppColors.grayBackground,
2150
2393
  borderRadius: 12,