react-native-inapp-inspector 1.1.16 → 1.1.17
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.
- package/README.md +13 -0
- package/dist/commonjs/components/AnimatedEntrance.js +3 -0
- package/dist/commonjs/components/AppHeaderLogo.d.ts +8 -0
- package/dist/commonjs/components/AppHeaderLogo.js +85 -0
- package/dist/commonjs/components/Inspector/BundleTab.d.ts +41 -0
- package/dist/commonjs/components/Inspector/BundleTab.js +2309 -0
- package/dist/commonjs/components/Inspector/InspectorHeader.js +185 -52
- package/dist/commonjs/components/Inspector/MainScreen.js +86 -7
- package/dist/commonjs/components/Inspector/ReduxDetail.d.ts +3 -0
- package/dist/commonjs/components/Inspector/ReduxDetail.js +576 -0
- package/dist/commonjs/components/Inspector/ReduxTab.js +433 -49
- package/dist/commonjs/components/Inspector/SettingsPanel.js +8 -2
- package/dist/commonjs/components/Inspector/TabBar.js +9 -6
- package/dist/commonjs/components/JsonViewer.js +91 -30
- package/dist/commonjs/components/LogCard.js +3 -4
- package/dist/commonjs/components/NetworkIcons.d.ts +8 -0
- package/dist/commonjs/components/NetworkIcons.js +54 -1
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/consoleLogger.js +37 -9
- package/dist/commonjs/customHooks/reduxLogger.js +4 -2
- package/dist/commonjs/helpers/index.js +6 -2
- package/dist/commonjs/index.js +15 -1
- package/dist/commonjs/styles/AppColors.js +163 -163
- package/dist/commonjs/styles/index.d.ts +14 -0
- package/dist/commonjs/styles/index.js +14 -0
- package/dist/commonjs/types/enums.d.ts +2 -2
- package/dist/commonjs/types/interfaces.d.ts +11 -0
- package/dist/esm/components/AnimatedEntrance.js +4 -1
- package/dist/esm/components/AppHeaderLogo.d.ts +8 -0
- package/dist/esm/components/AppHeaderLogo.js +45 -0
- package/dist/esm/components/Inspector/BundleTab.d.ts +41 -0
- package/dist/esm/components/Inspector/BundleTab.js +2271 -0
- package/dist/esm/components/Inspector/InspectorHeader.js +151 -51
- package/dist/esm/components/Inspector/MainScreen.js +53 -7
- package/dist/esm/components/Inspector/ReduxDetail.d.ts +3 -0
- package/dist/esm/components/Inspector/ReduxDetail.js +538 -0
- package/dist/esm/components/Inspector/ReduxTab.js +402 -51
- package/dist/esm/components/Inspector/SettingsPanel.js +9 -3
- package/dist/esm/components/Inspector/TabBar.js +10 -7
- package/dist/esm/components/JsonViewer.js +92 -31
- package/dist/esm/components/LogCard.js +3 -4
- package/dist/esm/components/NetworkIcons.d.ts +8 -0
- package/dist/esm/components/NetworkIcons.js +47 -1
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/consoleLogger.js +37 -9
- package/dist/esm/customHooks/reduxLogger.js +4 -2
- package/dist/esm/helpers/index.js +6 -2
- package/dist/esm/index.js +15 -1
- package/dist/esm/styles/AppColors.js +163 -163
- package/dist/esm/styles/index.d.ts +14 -0
- package/dist/esm/styles/index.js +14 -0
- package/dist/esm/types/enums.d.ts +2 -2
- package/dist/esm/types/interfaces.d.ts +11 -0
- package/example/App.tsx +5 -1
- package/example/assets/app_icon.png +0 -0
- package/example/ios/Podfile.lock +3 -3
- package/example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json +18 -9
- package/example/ios/example/Images.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
- package/example/package-lock.json +824 -10
- package/example/package.json +6 -2
- package/package.json +4 -2
|
@@ -0,0 +1,2309 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const react_1 = __importStar(require("react"));
|
|
40
|
+
const react_native_1 = require("react-native");
|
|
41
|
+
const react_i18next_1 = require("react-i18next");
|
|
42
|
+
const TouchableScale_1 = __importDefault(require("../TouchableScale"));
|
|
43
|
+
const CopyButton_1 = __importDefault(require("../CopyButton"));
|
|
44
|
+
const HighlightText_1 = __importDefault(require("../HighlightText"));
|
|
45
|
+
const AppColors_1 = require("../../styles/AppColors");
|
|
46
|
+
const AppFonts_1 = require("../../styles/AppFonts");
|
|
47
|
+
const NetworkIcons_1 = require("../NetworkIcons");
|
|
48
|
+
const react_native_svg_1 = __importStar(require("react-native-svg"));
|
|
49
|
+
// ─── High-Fidelity Vector Package & NPM Logos ────────────────────────────────
|
|
50
|
+
const PackageLogoRenderer = ({ name, size = 28 }) => {
|
|
51
|
+
const lowerName = name.toLowerCase();
|
|
52
|
+
// 1. React & React Native (Official Cyan Atom Orbital)
|
|
53
|
+
if (lowerName === 'react' ||
|
|
54
|
+
(lowerName.includes('react-native') &&
|
|
55
|
+
!lowerName.includes('svg') &&
|
|
56
|
+
!lowerName.includes('screens') &&
|
|
57
|
+
!lowerName.includes('gradient'))) {
|
|
58
|
+
return (<react_native_1.View style={[
|
|
59
|
+
bundleStyles.pkgLogoWrap,
|
|
60
|
+
{ width: size, height: size, backgroundColor: '#20232A' },
|
|
61
|
+
]}>
|
|
62
|
+
<react_native_svg_1.default width={size - 6} height={size - 6} viewBox="0 0 100 100" fill="none">
|
|
63
|
+
<react_native_svg_1.Circle cx="50" cy="50" r="9" fill="#61DAFB"/>
|
|
64
|
+
<react_native_svg_1.Ellipse cx="50" cy="50" rx="42" ry="16" stroke="#61DAFB" strokeWidth="6"/>
|
|
65
|
+
<react_native_svg_1.Ellipse cx="50" cy="50" rx="42" ry="16" stroke="#61DAFB" strokeWidth="6" transform="rotate(60 50 50)"/>
|
|
66
|
+
<react_native_svg_1.Ellipse cx="50" cy="50" rx="42" ry="16" stroke="#61DAFB" strokeWidth="6" transform="rotate(120 50 50)"/>
|
|
67
|
+
</react_native_svg_1.default>
|
|
68
|
+
</react_native_1.View>);
|
|
69
|
+
}
|
|
70
|
+
// 2. React Navigation (Official Violet/Cyan Compass)
|
|
71
|
+
if (lowerName.includes('navigation')) {
|
|
72
|
+
return (<react_native_1.View style={[
|
|
73
|
+
bundleStyles.pkgLogoWrap,
|
|
74
|
+
{ width: size, height: size, backgroundColor: '#5B44E0' },
|
|
75
|
+
]}>
|
|
76
|
+
<react_native_svg_1.default width={size - 8} height={size - 8} viewBox="0 0 100 100" fill="none">
|
|
77
|
+
<react_native_svg_1.Circle cx="50" cy="50" r="38" stroke="#FFFFFF" strokeWidth="8"/>
|
|
78
|
+
<react_native_svg_1.Path d="M50 20 L68 50 L50 80 L32 50 Z" fill="#61DAFB"/>
|
|
79
|
+
<react_native_svg_1.Circle cx="50" cy="50" r="6" fill="#FFFFFF"/>
|
|
80
|
+
</react_native_svg_1.default>
|
|
81
|
+
</react_native_1.View>);
|
|
82
|
+
}
|
|
83
|
+
// 3. React Native SVG (Bezier Path Vector Art)
|
|
84
|
+
if (lowerName.includes('svg')) {
|
|
85
|
+
return (<react_native_1.View style={[
|
|
86
|
+
bundleStyles.pkgLogoWrap,
|
|
87
|
+
{ width: size, height: size, backgroundColor: '#F472B6' },
|
|
88
|
+
]}>
|
|
89
|
+
<react_native_svg_1.default width={size - 8} height={size - 8} viewBox="0 0 100 100" fill="none">
|
|
90
|
+
<react_native_svg_1.Path d="M20 75 C35 25, 65 25, 80 75" stroke="#FFFFFF" strokeWidth="10" strokeLinecap="round"/>
|
|
91
|
+
<react_native_svg_1.Circle cx="20" cy="75" r="8" fill="#FFFFFF"/>
|
|
92
|
+
<react_native_svg_1.Circle cx="80" cy="75" r="8" fill="#FFFFFF"/>
|
|
93
|
+
<react_native_svg_1.Circle cx="50" cy="38" r="7" fill="#FCE7F3" stroke="#FFFFFF" strokeWidth="3"/>
|
|
94
|
+
</react_native_svg_1.default>
|
|
95
|
+
</react_native_1.View>);
|
|
96
|
+
}
|
|
97
|
+
// 4. Axios (Official Indigo & Cyan Network Adapter)
|
|
98
|
+
if (lowerName.includes('axios')) {
|
|
99
|
+
return (<react_native_1.View style={[
|
|
100
|
+
bundleStyles.pkgLogoWrap,
|
|
101
|
+
{ width: size, height: size, backgroundColor: '#5A29E4' },
|
|
102
|
+
]}>
|
|
103
|
+
<react_native_svg_1.default width={size - 6} height={size - 6} viewBox="0 0 100 100" fill="none">
|
|
104
|
+
<react_native_svg_1.Path d="M22 75 L50 20 L78 75 M33 58 L67 58" stroke="#FFFFFF" strokeWidth="12" strokeLinecap="round" strokeLinejoin="round"/>
|
|
105
|
+
<react_native_svg_1.Circle cx="50" cy="20" r="7" fill="#61DAFB"/>
|
|
106
|
+
</react_native_svg_1.default>
|
|
107
|
+
</react_native_1.View>);
|
|
108
|
+
}
|
|
109
|
+
// 5. React Native Screens (Software Mansion Deep Indigo Stack)
|
|
110
|
+
if (lowerName.includes('screens') || lowerName.includes('software-mansion')) {
|
|
111
|
+
return (<react_native_1.View style={[
|
|
112
|
+
bundleStyles.pkgLogoWrap,
|
|
113
|
+
{ width: size, height: size, backgroundColor: '#001A72' },
|
|
114
|
+
]}>
|
|
115
|
+
<react_native_svg_1.default width={size - 8} height={size - 8} viewBox="0 0 100 100" fill="none">
|
|
116
|
+
<react_native_svg_1.Path d="M50 15 L88 35 L50 55 L12 35 Z" fill="#38BDF8"/>
|
|
117
|
+
<react_native_svg_1.Path d="M12 50 L50 70 L88 50" stroke="#FFFFFF" strokeWidth="8" strokeLinecap="round"/>
|
|
118
|
+
<react_native_svg_1.Path d="M12 65 L50 85 L88 65" stroke="#93C5FD" strokeWidth="8" strokeLinecap="round"/>
|
|
119
|
+
</react_native_svg_1.default>
|
|
120
|
+
</react_native_1.View>);
|
|
121
|
+
}
|
|
122
|
+
// 6. Linear Gradient (Vibrant Color Spectrum)
|
|
123
|
+
if (lowerName.includes('gradient')) {
|
|
124
|
+
return (<react_native_1.View style={[
|
|
125
|
+
bundleStyles.pkgLogoWrap,
|
|
126
|
+
{ width: size, height: size, backgroundColor: '#FB7185' },
|
|
127
|
+
]}>
|
|
128
|
+
<react_native_svg_1.default width={size - 4} height={size - 4} viewBox="0 0 100 100" fill="none">
|
|
129
|
+
<react_native_svg_1.Defs>
|
|
130
|
+
<react_native_svg_1.LinearGradient id="pkgGrad" x1="0" y1="0" x2="100" y2="100" gradientUnits="userSpaceOnUse">
|
|
131
|
+
<react_native_svg_1.Stop offset="0" stopColor="#FF0080"/>
|
|
132
|
+
<react_native_svg_1.Stop offset="0.5" stopColor="#7928CA"/>
|
|
133
|
+
<react_native_svg_1.Stop offset="1" stopColor="#0070F3"/>
|
|
134
|
+
</react_native_svg_1.LinearGradient>
|
|
135
|
+
</react_native_svg_1.Defs>
|
|
136
|
+
<react_native_svg_1.Rect width="100" height="100" rx="18" fill="url(#pkgGrad)"/>
|
|
137
|
+
</react_native_svg_1.default>
|
|
138
|
+
</react_native_1.View>);
|
|
139
|
+
}
|
|
140
|
+
// 7. i18next & Translations (Emerald Globe)
|
|
141
|
+
if (lowerName.includes('i18n')) {
|
|
142
|
+
return (<react_native_1.View style={[
|
|
143
|
+
bundleStyles.pkgLogoWrap,
|
|
144
|
+
{ width: size, height: size, backgroundColor: '#059669' },
|
|
145
|
+
]}>
|
|
146
|
+
<react_native_svg_1.default width={size - 8} height={size - 8} viewBox="0 0 100 100" fill="none">
|
|
147
|
+
<react_native_svg_1.Circle cx="50" cy="50" r="38" stroke="#FFFFFF" strokeWidth="8"/>
|
|
148
|
+
<react_native_svg_1.Ellipse cx="50" cy="50" rx="18" ry="38" stroke="#FFFFFF" strokeWidth="6"/>
|
|
149
|
+
<react_native_svg_1.Path d="M14 50 L86 50" stroke="#FFFFFF" strokeWidth="7"/>
|
|
150
|
+
</react_native_svg_1.default>
|
|
151
|
+
</react_native_1.View>);
|
|
152
|
+
}
|
|
153
|
+
// 8. Official Red NPM Logo Box (Universal Default NPM Branding)
|
|
154
|
+
return (<react_native_1.View style={[
|
|
155
|
+
bundleStyles.pkgLogoWrap,
|
|
156
|
+
{ width: size, height: size, backgroundColor: '#CB3837' },
|
|
157
|
+
]}>
|
|
158
|
+
<react_native_svg_1.default width={size - 4} height={size - 4} viewBox="0 0 100 100" fill="none">
|
|
159
|
+
<react_native_svg_1.Rect width="100" height="100" rx="14" fill="#CB3837"/>
|
|
160
|
+
<react_native_svg_1.Path d="M18 24 H82 V76 H50 V40 H38 V76 H18 Z" fill="#FFFFFF"/>
|
|
161
|
+
</react_native_svg_1.default>
|
|
162
|
+
</react_native_1.View>);
|
|
163
|
+
};
|
|
164
|
+
// ─── Media File Thumbnail Component ──────────────────────────────────────────
|
|
165
|
+
const MediaPreviewThumbnail = ({ file }) => {
|
|
166
|
+
const [loadError, setLoadError] = (0, react_1.useState)(false);
|
|
167
|
+
// 1. If it's an SVG file, render an inline vector thumbnail preview
|
|
168
|
+
if (file.ext === 'SVG' || file.name.toLowerCase().endsWith('.svg')) {
|
|
169
|
+
return (<react_native_1.View style={[
|
|
170
|
+
bundleStyles.mediaThumbWrap,
|
|
171
|
+
{
|
|
172
|
+
backgroundColor: '#FFF1F2',
|
|
173
|
+
alignItems: 'center',
|
|
174
|
+
justifyContent: 'center',
|
|
175
|
+
borderColor: '#FECDD3',
|
|
176
|
+
},
|
|
177
|
+
]}>
|
|
178
|
+
<react_native_svg_1.default width={22} height={22} viewBox="0 0 100 100" fill="none">
|
|
179
|
+
<react_native_svg_1.Defs>
|
|
180
|
+
<react_native_svg_1.LinearGradient id="svgGradThumb" x1="0" y1="0" x2="100" y2="100" gradientUnits="userSpaceOnUse">
|
|
181
|
+
<react_native_svg_1.Stop offset="0" stopColor="#F43F5E"/>
|
|
182
|
+
<react_native_svg_1.Stop offset="1" stopColor="#FB7185"/>
|
|
183
|
+
</react_native_svg_1.LinearGradient>
|
|
184
|
+
</react_native_svg_1.Defs>
|
|
185
|
+
<react_native_svg_1.Circle cx="50" cy="50" r="44" fill="url(#svgGradThumb)"/>
|
|
186
|
+
{/* Vector bezier path pen graphic */}
|
|
187
|
+
<react_native_svg_1.Path d="M25 70 C35 30, 65 30, 75 70" stroke="#FFFFFF" strokeWidth="8" strokeLinecap="round"/>
|
|
188
|
+
<react_native_svg_1.Circle cx="25" cy="70" r="7" fill="#FFFFFF"/>
|
|
189
|
+
<react_native_svg_1.Circle cx="75" cy="70" r="7" fill="#FFFFFF"/>
|
|
190
|
+
<react_native_svg_1.Circle cx="50" cy="40" r="6" fill="#FFE4E6" stroke="#FFFFFF" strokeWidth="2"/>
|
|
191
|
+
</react_native_svg_1.default>
|
|
192
|
+
</react_native_1.View>);
|
|
193
|
+
}
|
|
194
|
+
// 2. Raster Image (PNG, JPG, WebP) with valid preview URI
|
|
195
|
+
if (file.category === 'image' && file.previewUri && !loadError) {
|
|
196
|
+
return (<react_native_1.View style={bundleStyles.mediaThumbWrap}>
|
|
197
|
+
<react_native_1.Image source={{ uri: file.previewUri }} style={bundleStyles.mediaThumbImg} resizeMode="cover" onError={() => setLoadError(true)}/>
|
|
198
|
+
</react_native_1.View>);
|
|
199
|
+
}
|
|
200
|
+
const categoryMeta = CATEGORY_COLORS[file.category] || CATEGORY_COLORS.typescript;
|
|
201
|
+
return (<react_native_1.View style={[
|
|
202
|
+
bundleStyles.extChip,
|
|
203
|
+
{
|
|
204
|
+
backgroundColor: categoryMeta.bg,
|
|
205
|
+
borderColor: `${categoryMeta.color}40`,
|
|
206
|
+
},
|
|
207
|
+
]}>
|
|
208
|
+
<react_native_1.Text style={[bundleStyles.extChipText, { color: categoryMeta.color }]}>
|
|
209
|
+
{file.ext}
|
|
210
|
+
</react_native_1.Text>
|
|
211
|
+
</react_native_1.View>);
|
|
212
|
+
};
|
|
213
|
+
function buildBundleFileTree(files) {
|
|
214
|
+
const rootMap = new Map();
|
|
215
|
+
for (const file of files) {
|
|
216
|
+
const parts = file.path.split('/');
|
|
217
|
+
let currentLevel = rootMap;
|
|
218
|
+
for (let i = 0; i < parts.length; i++) {
|
|
219
|
+
const part = parts[i];
|
|
220
|
+
const isFile = i === parts.length - 1;
|
|
221
|
+
if (!currentLevel.has(part)) {
|
|
222
|
+
currentLevel.set(part, {
|
|
223
|
+
name: part,
|
|
224
|
+
fullPath: parts.slice(0, i + 1).join('/'),
|
|
225
|
+
isFile,
|
|
226
|
+
fileItem: isFile ? file : undefined,
|
|
227
|
+
children: new Map(),
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
if (!isFile) {
|
|
231
|
+
currentLevel = currentLevel.get(part).children;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function convertMapToNodes(map) {
|
|
236
|
+
const nodes = [];
|
|
237
|
+
for (const [, val] of map.entries()) {
|
|
238
|
+
const children = convertMapToNodes(val.children);
|
|
239
|
+
const isFolder = !val.isFile;
|
|
240
|
+
const fileCount = isFolder
|
|
241
|
+
? children.reduce((acc, c) => acc + (c.isFolder ? c.fileCount : 1), 0)
|
|
242
|
+
: 1;
|
|
243
|
+
const sizeKb = isFolder
|
|
244
|
+
? children.reduce((acc, c) => acc + c.sizeKb, 0)
|
|
245
|
+
: val.fileItem
|
|
246
|
+
? val.fileItem.sizeKb
|
|
247
|
+
: 0;
|
|
248
|
+
nodes.push({
|
|
249
|
+
id: val.fullPath,
|
|
250
|
+
name: val.name,
|
|
251
|
+
fullPath: val.fullPath,
|
|
252
|
+
isFolder,
|
|
253
|
+
fileItem: val.fileItem,
|
|
254
|
+
sizeKb,
|
|
255
|
+
fileCount,
|
|
256
|
+
children,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
// Sort folders first, then files alphabetically
|
|
260
|
+
return nodes.sort((a, b) => {
|
|
261
|
+
if (a.isFolder && !b.isFolder)
|
|
262
|
+
return -1;
|
|
263
|
+
if (!a.isFolder && b.isFolder)
|
|
264
|
+
return 1;
|
|
265
|
+
return a.name.localeCompare(b.name);
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
return convertMapToNodes(rootMap);
|
|
269
|
+
}
|
|
270
|
+
const BundleTreeNodeView = ({ node, level, search, totalBundleKb, collapsedFolders, toggleFolder, isLastChild, }) => {
|
|
271
|
+
const isCollapsed = !!collapsedFolders[node.fullPath];
|
|
272
|
+
if (node.isFolder) {
|
|
273
|
+
return (<react_native_1.View style={bundleStyles.treeFolderContainer}>
|
|
274
|
+
<TouchableScale_1.default onPress={() => toggleFolder(node.fullPath)} style={[
|
|
275
|
+
bundleStyles.treeFolderHeader,
|
|
276
|
+
{ paddingLeft: Math.max(10, level * 14 + 10) },
|
|
277
|
+
]}>
|
|
278
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 7, flex: 1 }}>
|
|
279
|
+
<react_native_1.View style={bundleStyles.treeFolderChevronWrap}>
|
|
280
|
+
<react_native_1.Text style={bundleStyles.treeFolderChevron}>
|
|
281
|
+
{isCollapsed ? '▶' : '▼'}
|
|
282
|
+
</react_native_1.Text>
|
|
283
|
+
</react_native_1.View>
|
|
284
|
+
<react_native_1.Text style={{ fontSize: 16 }}>{isCollapsed ? '📁' : '📂'}</react_native_1.Text>
|
|
285
|
+
<HighlightText_1.default text={node.name + '/'} search={search} style={bundleStyles.treeFolderName} highlightStyle={bundleStyles.searchHighlight}/>
|
|
286
|
+
<react_native_1.View style={bundleStyles.treeCountBadge}>
|
|
287
|
+
<react_native_1.Text style={bundleStyles.treeCountBadgeText}>
|
|
288
|
+
{node.fileCount} {node.fileCount === 1 ? 'file' : 'files'}
|
|
289
|
+
</react_native_1.Text>
|
|
290
|
+
</react_native_1.View>
|
|
291
|
+
</react_native_1.View>
|
|
292
|
+
|
|
293
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
294
|
+
<react_native_1.Text style={bundleStyles.treeFolderSize}>
|
|
295
|
+
{node.sizeKb >= 1024
|
|
296
|
+
? `${(node.sizeKb / 1024).toFixed(2)} MB`
|
|
297
|
+
: `${node.sizeKb} KB`}
|
|
298
|
+
</react_native_1.Text>
|
|
299
|
+
<CopyButton_1.default value={() => ({
|
|
300
|
+
folder: node.fullPath,
|
|
301
|
+
sizeKb: node.sizeKb,
|
|
302
|
+
fileCount: node.fileCount,
|
|
303
|
+
})} label={`Copy ${node.name} Info`}/>
|
|
304
|
+
</react_native_1.View>
|
|
305
|
+
</TouchableScale_1.default>
|
|
306
|
+
|
|
307
|
+
{!isCollapsed && (<react_native_1.View style={[bundleStyles.treeChildrenWrap, { borderLeftWidth: level > 0 ? 1.5 : 0, marginLeft: Math.max(6, level * 14 + 16) }]}>
|
|
308
|
+
{node.children.map((child, cIdx) => (<BundleTreeNodeView key={child.id} node={child} level={level + 1} search={search} totalBundleKb={totalBundleKb} collapsedFolders={collapsedFolders} toggleFolder={toggleFolder} isLastChild={cIdx === node.children.length - 1}/>))}
|
|
309
|
+
</react_native_1.View>)}
|
|
310
|
+
</react_native_1.View>);
|
|
311
|
+
}
|
|
312
|
+
// File item inside tree
|
|
313
|
+
const file = node.fileItem;
|
|
314
|
+
if (!file)
|
|
315
|
+
return null;
|
|
316
|
+
const pctOfTotal = ((file.sizeKb / totalBundleKb) * 100).toFixed(1);
|
|
317
|
+
const isUnused = file.isConsumed === false;
|
|
318
|
+
return (<react_native_1.View style={[bundleStyles.treeFileCard, isUnused && bundleStyles.treeFileCardUnused]}>
|
|
319
|
+
<react_native_1.View style={bundleStyles.fileCardTop}>
|
|
320
|
+
<react_native_1.View style={bundleStyles.treeBranchGlyph}>
|
|
321
|
+
<react_native_1.Text style={bundleStyles.treeBranchGlyphText}>
|
|
322
|
+
{isLastChild ? '└─' : '├─'}
|
|
323
|
+
</react_native_1.Text>
|
|
324
|
+
</react_native_1.View>
|
|
325
|
+
|
|
326
|
+
<MediaPreviewThumbnail file={file}/>
|
|
327
|
+
|
|
328
|
+
<react_native_1.View style={{ flex: 1, paddingHorizontal: 4 }}>
|
|
329
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
330
|
+
<HighlightText_1.default text={file.name} search={search} style={bundleStyles.fileName} highlightStyle={bundleStyles.searchHighlight}/>
|
|
331
|
+
{isUnused ? (<react_native_1.View style={bundleStyles.unusedBadge}>
|
|
332
|
+
<react_native_1.Text style={bundleStyles.unusedBadgeText}>🚫 Not Consumed</react_native_1.Text>
|
|
333
|
+
</react_native_1.View>) : (<react_native_1.View style={bundleStyles.consumedBadge}>
|
|
334
|
+
<react_native_1.Text style={bundleStyles.consumedBadgeText}>⚡ Consumed</react_native_1.Text>
|
|
335
|
+
</react_native_1.View>)}
|
|
336
|
+
</react_native_1.View>
|
|
337
|
+
<react_native_1.Text style={bundleStyles.filePath} numberOfLines={1}>
|
|
338
|
+
{file.meta}
|
|
339
|
+
</react_native_1.Text>
|
|
340
|
+
</react_native_1.View>
|
|
341
|
+
|
|
342
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
343
|
+
<react_native_1.View style={bundleStyles.fileSizeBox}>
|
|
344
|
+
<react_native_1.Text style={[bundleStyles.fileSizeKb, isUnused && { color: '#B45309' }]}>
|
|
345
|
+
{file.sizeKb >= 1024
|
|
346
|
+
? `${(file.sizeKb / 1024).toFixed(2)} MB`
|
|
347
|
+
: `${file.sizeKb} KB`}
|
|
348
|
+
</react_native_1.Text>
|
|
349
|
+
<react_native_1.Text style={bundleStyles.filePercent}>{pctOfTotal}%</react_native_1.Text>
|
|
350
|
+
</react_native_1.View>
|
|
351
|
+
<CopyButton_1.default value={() => file} label="File Details JSON"/>
|
|
352
|
+
</react_native_1.View>
|
|
353
|
+
</react_native_1.View>
|
|
354
|
+
|
|
355
|
+
{file.advice && (<react_native_1.View style={[
|
|
356
|
+
bundleStyles.adviceBadge,
|
|
357
|
+
file.status === 'warning' && bundleStyles.adviceWarning,
|
|
358
|
+
file.status === 'optimal' && bundleStyles.adviceOptimal,
|
|
359
|
+
isUnused && bundleStyles.adviceUnused,
|
|
360
|
+
{ marginLeft: 26, marginTop: 4 },
|
|
361
|
+
]}>
|
|
362
|
+
<react_native_1.Text style={[
|
|
363
|
+
bundleStyles.adviceText,
|
|
364
|
+
file.status === 'warning' && { color: '#B45309' },
|
|
365
|
+
file.status === 'optimal' && { color: '#047857' },
|
|
366
|
+
isUnused && { color: '#DC2626' },
|
|
367
|
+
]}>
|
|
368
|
+
{isUnused ? '🗑️ ' : file.status === 'warning' ? '💡 ' : '✨ '}
|
|
369
|
+
{file.advice}
|
|
370
|
+
</react_native_1.Text>
|
|
371
|
+
</react_native_1.View>)}
|
|
372
|
+
</react_native_1.View>);
|
|
373
|
+
};
|
|
374
|
+
// ─── Sample Bundle Files Data ────────────────────────────────────────────────
|
|
375
|
+
const BUNDLE_FILES_DATA = [
|
|
376
|
+
// ── Images & Media ──
|
|
377
|
+
{
|
|
378
|
+
id: 'img-1',
|
|
379
|
+
name: 'banner_dark.png',
|
|
380
|
+
path: 'assets/images/banner_dark.png',
|
|
381
|
+
ext: 'PNG',
|
|
382
|
+
category: 'image',
|
|
383
|
+
sizeKb: 460,
|
|
384
|
+
meta: '1200×630px @2x • Raster Image',
|
|
385
|
+
color: '#EC4899',
|
|
386
|
+
status: 'warning',
|
|
387
|
+
advice: 'Convert to .webp to save ~65% (160 KB)',
|
|
388
|
+
previewUri: 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=200&auto=format&fit=crop&q=80',
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
id: 'img-2',
|
|
392
|
+
name: 'banner_light.svg',
|
|
393
|
+
path: 'assets/images/banner_light.svg',
|
|
394
|
+
ext: 'SVG',
|
|
395
|
+
category: 'image',
|
|
396
|
+
sizeKb: 34,
|
|
397
|
+
meta: 'Scalable Vector Graphic',
|
|
398
|
+
color: '#F43F5E',
|
|
399
|
+
status: 'optimal',
|
|
400
|
+
advice: 'Optimal vector format for sharp rendering',
|
|
401
|
+
previewUri: 'https://images.unsplash.com/photo-1579783902614-a3fb3927b675?w=200&auto=format&fit=crop&q=80',
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
id: 'img-3',
|
|
405
|
+
name: 'logo_hero@3x.png',
|
|
406
|
+
path: 'assets/brand/logo_hero@3x.png',
|
|
407
|
+
ext: 'PNG',
|
|
408
|
+
category: 'image',
|
|
409
|
+
sizeKb: 285,
|
|
410
|
+
meta: '768×768px @3x Retina Asset',
|
|
411
|
+
color: '#EC4899',
|
|
412
|
+
status: 'warning',
|
|
413
|
+
advice: 'High density PNG. Consider tintable SVG vector',
|
|
414
|
+
previewUri: 'https://images.unsplash.com/photo-1634017839464-5c339ebe3cb4?w=200&auto=format&fit=crop&q=80',
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
id: 'img-4',
|
|
418
|
+
name: 'avatar_placeholder.webp',
|
|
419
|
+
path: 'assets/placeholders/avatar_placeholder.webp',
|
|
420
|
+
ext: 'WEBP',
|
|
421
|
+
category: 'image',
|
|
422
|
+
sizeKb: 28,
|
|
423
|
+
meta: '256×256px Lossy WebP',
|
|
424
|
+
color: '#F472B6',
|
|
425
|
+
status: 'warning',
|
|
426
|
+
advice: 'Unused in bundle: 0 active imports detected (28 KB unused)',
|
|
427
|
+
previewUri: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=200&auto=format&fit=crop&q=80',
|
|
428
|
+
isConsumed: false,
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
id: 'img-5',
|
|
432
|
+
name: 'walkthrough_thumb.jpg',
|
|
433
|
+
path: 'assets/previews/walkthrough_thumb.jpg',
|
|
434
|
+
ext: 'JPG',
|
|
435
|
+
category: 'image',
|
|
436
|
+
sizeKb: 175,
|
|
437
|
+
meta: '1080×600px Progressive JPEG',
|
|
438
|
+
color: '#FB7185',
|
|
439
|
+
status: 'warning',
|
|
440
|
+
advice: 'Dead asset: 0 component references (175 KB unused)',
|
|
441
|
+
previewUri: 'https://images.unsplash.com/photo-1550745165-9bc0b252726f?w=200&auto=format&fit=crop&q=80',
|
|
442
|
+
isConsumed: false,
|
|
443
|
+
},
|
|
444
|
+
// ── TypeScript & JSX ──
|
|
445
|
+
{
|
|
446
|
+
id: 'ts-1',
|
|
447
|
+
name: 'LogDetail.tsx',
|
|
448
|
+
path: 'src/components/Inspector/LogDetail.tsx',
|
|
449
|
+
ext: 'TSX',
|
|
450
|
+
category: 'typescript',
|
|
451
|
+
sizeKb: 44,
|
|
452
|
+
meta: '1,238 lines • React Component',
|
|
453
|
+
color: '#38BDF8',
|
|
454
|
+
status: 'optimal',
|
|
455
|
+
advice: 'Clean React.memo and useCallback optimization',
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
id: 'ts-2',
|
|
459
|
+
name: 'ReduxDetail.tsx',
|
|
460
|
+
path: 'src/components/Inspector/ReduxDetail.tsx',
|
|
461
|
+
ext: 'TSX',
|
|
462
|
+
category: 'typescript',
|
|
463
|
+
sizeKb: 38,
|
|
464
|
+
meta: '680 lines • Slice state tree & action timeline',
|
|
465
|
+
color: '#38BDF8',
|
|
466
|
+
status: 'optimal',
|
|
467
|
+
advice: 'Multi-tab subview with live state diffing',
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
id: 'ts-3',
|
|
471
|
+
name: 'NetworkTab.tsx',
|
|
472
|
+
path: 'src/components/Inspector/NetworkTab.tsx',
|
|
473
|
+
ext: 'TSX',
|
|
474
|
+
category: 'typescript',
|
|
475
|
+
sizeKb: 15,
|
|
476
|
+
meta: '486 lines • Network request virtualization list',
|
|
477
|
+
color: '#0EA5E9',
|
|
478
|
+
status: 'optimal',
|
|
479
|
+
advice: 'FlatList windowSize=7 tuned for 60fps',
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
id: 'ts-4',
|
|
483
|
+
name: 'SettingsPanel.tsx',
|
|
484
|
+
path: 'src/components/Inspector/SettingsPanel.tsx',
|
|
485
|
+
ext: 'TSX',
|
|
486
|
+
category: 'typescript',
|
|
487
|
+
sizeKb: 65,
|
|
488
|
+
meta: '1,845 lines • Preferences & storage manager',
|
|
489
|
+
color: '#38BDF8',
|
|
490
|
+
status: 'info',
|
|
491
|
+
advice: 'Self-contained settings subviews',
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
id: 'ts-5',
|
|
495
|
+
name: 'consoleLogger.ts',
|
|
496
|
+
path: 'src/customHooks/consoleLogger.ts',
|
|
497
|
+
ext: 'TS',
|
|
498
|
+
category: 'typescript',
|
|
499
|
+
sizeKb: 12,
|
|
500
|
+
meta: '360 lines • Metro symbolication bridge',
|
|
501
|
+
color: '#0284C7',
|
|
502
|
+
status: 'optimal',
|
|
503
|
+
advice: 'Zero-overhead in-memory stack capture',
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
id: 'ts-6',
|
|
507
|
+
name: 'App.tsx (Playground)',
|
|
508
|
+
path: 'example/App.tsx',
|
|
509
|
+
ext: 'TSX',
|
|
510
|
+
category: 'typescript',
|
|
511
|
+
sizeKb: 25,
|
|
512
|
+
meta: '820 lines • Interactive test scenarios',
|
|
513
|
+
color: '#38BDF8',
|
|
514
|
+
status: 'optimal',
|
|
515
|
+
advice: 'Sample harness for logs, APIs, and Redux',
|
|
516
|
+
},
|
|
517
|
+
// ── JavaScript & Node Modules ──
|
|
518
|
+
{
|
|
519
|
+
id: 'js-1',
|
|
520
|
+
name: 'react-native/Libraries/Renderer',
|
|
521
|
+
path: 'node_modules/react-native/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js',
|
|
522
|
+
ext: 'JS',
|
|
523
|
+
category: 'javascript',
|
|
524
|
+
sizeKb: 480,
|
|
525
|
+
meta: 'Fabric & Paper UI reconciler bundle',
|
|
526
|
+
color: '#6366F1',
|
|
527
|
+
status: 'optimal',
|
|
528
|
+
advice: 'AOT compiled with Hermes Bytecode',
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
id: 'js-2',
|
|
532
|
+
name: '@react-navigation/native-stack',
|
|
533
|
+
path: 'node_modules/@react-navigation/native-stack/lib/module/index.js',
|
|
534
|
+
ext: 'JS',
|
|
535
|
+
category: 'javascript',
|
|
536
|
+
sizeKb: 195,
|
|
537
|
+
meta: 'Native screen animation & transition engine',
|
|
538
|
+
color: '#818CF8',
|
|
539
|
+
status: 'optimal',
|
|
540
|
+
advice: 'Optimized modular ES bundle',
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
id: 'js-3',
|
|
544
|
+
name: 'axios/dist/esm/axios.js',
|
|
545
|
+
path: 'node_modules/axios/dist/esm/axios.js',
|
|
546
|
+
ext: 'JS',
|
|
547
|
+
category: 'javascript',
|
|
548
|
+
sizeKb: 88,
|
|
549
|
+
meta: 'HTTP client core with interceptors',
|
|
550
|
+
color: '#F59E0B',
|
|
551
|
+
status: 'optimal',
|
|
552
|
+
advice: 'Standard lightweight network adapter',
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
id: 'js-4',
|
|
556
|
+
name: 'react-native-svg',
|
|
557
|
+
path: 'node_modules/react-native-svg/lib/module/index.js',
|
|
558
|
+
ext: 'JS',
|
|
559
|
+
category: 'javascript',
|
|
560
|
+
sizeKb: 140,
|
|
561
|
+
meta: 'Native SVG drawing and vector paths',
|
|
562
|
+
color: '#4F46E5',
|
|
563
|
+
status: 'optimal',
|
|
564
|
+
advice: 'Native Fabric/Paper vector bridge',
|
|
565
|
+
},
|
|
566
|
+
// ── Fonts & Typography ──
|
|
567
|
+
{
|
|
568
|
+
id: 'font-1',
|
|
569
|
+
name: 'Inter-Bold.ttf',
|
|
570
|
+
path: 'fonts/Inter-Bold.ttf',
|
|
571
|
+
ext: 'TTF',
|
|
572
|
+
category: 'font',
|
|
573
|
+
sizeKb: 165,
|
|
574
|
+
meta: 'Custom UI Font • Full Latin Charset (480 glyphs)',
|
|
575
|
+
color: '#8B5CF6',
|
|
576
|
+
status: 'info',
|
|
577
|
+
advice: 'High readability modern typography',
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
id: 'font-2',
|
|
581
|
+
name: 'Inter-Regular.ttf',
|
|
582
|
+
path: 'fonts/Inter-Regular.ttf',
|
|
583
|
+
ext: 'TTF',
|
|
584
|
+
category: 'font',
|
|
585
|
+
sizeKb: 160,
|
|
586
|
+
meta: 'Custom Body Font • 400 Weight (480 glyphs)',
|
|
587
|
+
color: '#8B5CF6',
|
|
588
|
+
status: 'info',
|
|
589
|
+
advice: 'Applied across inspector UI cards and text',
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
id: 'font-3',
|
|
593
|
+
name: 'JetBrainsMono-Regular.ttf',
|
|
594
|
+
path: 'fonts/JetBrainsMono-Regular.ttf',
|
|
595
|
+
ext: 'TTF',
|
|
596
|
+
category: 'font',
|
|
597
|
+
sizeKb: 95,
|
|
598
|
+
meta: 'Monospace Code Font • Raw / Table / Stack Traces',
|
|
599
|
+
color: '#A855F7',
|
|
600
|
+
status: 'optimal',
|
|
601
|
+
advice: 'Crisp font for code snippets and stack traces',
|
|
602
|
+
},
|
|
603
|
+
// ── JSON & Localizations ──
|
|
604
|
+
{
|
|
605
|
+
id: 'json-1',
|
|
606
|
+
name: 'en.json (i18n Translations)',
|
|
607
|
+
path: 'src/i18n/locales/en.json',
|
|
608
|
+
ext: 'JSON',
|
|
609
|
+
category: 'json',
|
|
610
|
+
sizeKb: 18,
|
|
611
|
+
meta: '124 localization translation keys',
|
|
612
|
+
color: '#10B981',
|
|
613
|
+
status: 'optimal',
|
|
614
|
+
advice: 'Static JSON locale dictionary',
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
id: 'json-2',
|
|
618
|
+
name: 'package.json',
|
|
619
|
+
path: 'package.json',
|
|
620
|
+
ext: 'JSON',
|
|
621
|
+
category: 'json',
|
|
622
|
+
sizeKb: 3,
|
|
623
|
+
meta: 'Manifest & peer dependencies config',
|
|
624
|
+
color: '#059669',
|
|
625
|
+
status: 'optimal',
|
|
626
|
+
advice: 'Stripped during production bundle export',
|
|
627
|
+
},
|
|
628
|
+
];
|
|
629
|
+
// ─── Packages / Node Modules Breakdown Data ──────────────────────────────────
|
|
630
|
+
const BUNDLE_PACKAGES_DATA = [
|
|
631
|
+
{
|
|
632
|
+
id: 'pkg-1',
|
|
633
|
+
name: 'react-native',
|
|
634
|
+
version: '0.85.3',
|
|
635
|
+
sizeKb: 680,
|
|
636
|
+
percentage: 38.5,
|
|
637
|
+
type: 'direct',
|
|
638
|
+
category: 'core',
|
|
639
|
+
color: '#38BDF8',
|
|
640
|
+
description: 'React Native runtime, Fabric UI engine, Native Bridge, and Turbomodules.',
|
|
641
|
+
logoUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/512px-React-icon.svg.png',
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
id: 'pkg-2',
|
|
645
|
+
name: '@react-navigation/native-stack',
|
|
646
|
+
version: '^7.16.0',
|
|
647
|
+
sizeKb: 245,
|
|
648
|
+
percentage: 13.9,
|
|
649
|
+
type: 'direct',
|
|
650
|
+
category: 'navigation',
|
|
651
|
+
color: '#818CF8',
|
|
652
|
+
description: 'Native screen router, UIViewController / Fragment animations and transitions.',
|
|
653
|
+
logoUri: 'https://reactnavigation.org/img/spiro.svg',
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
id: 'pkg-3',
|
|
657
|
+
name: 'react',
|
|
658
|
+
version: '19.2.3',
|
|
659
|
+
sizeKb: 185,
|
|
660
|
+
percentage: 10.5,
|
|
661
|
+
type: 'direct',
|
|
662
|
+
category: 'core',
|
|
663
|
+
color: '#06B6D4',
|
|
664
|
+
description: 'React core virtual DOM reconciler, hooks engine, and JSX runtime.',
|
|
665
|
+
logoUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/512px-React-icon.svg.png',
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
id: 'pkg-4',
|
|
669
|
+
name: 'react-native-svg',
|
|
670
|
+
version: '^15.15.5',
|
|
671
|
+
sizeKb: 140,
|
|
672
|
+
percentage: 7.9,
|
|
673
|
+
type: 'direct',
|
|
674
|
+
category: 'ui',
|
|
675
|
+
color: '#F472B6',
|
|
676
|
+
description: 'Scalable Vector Graphics XML parser and native canvas path rasterizer.',
|
|
677
|
+
logoUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/SVG_logo.svg/512px-SVG_logo.svg.png',
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
id: 'pkg-5',
|
|
681
|
+
name: 'react-native-screens',
|
|
682
|
+
version: '^4.25.2',
|
|
683
|
+
sizeKb: 110,
|
|
684
|
+
percentage: 6.2,
|
|
685
|
+
type: 'transitive',
|
|
686
|
+
category: 'navigation',
|
|
687
|
+
color: '#A78BFA',
|
|
688
|
+
description: 'Native navigation container primitives for iOS and Android memory management.',
|
|
689
|
+
logoUri: 'https://reactnavigation.org/img/spiro.svg',
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
id: 'pkg-6',
|
|
693
|
+
name: 'axios',
|
|
694
|
+
version: '^1.17.0',
|
|
695
|
+
sizeKb: 88,
|
|
696
|
+
percentage: 5.0,
|
|
697
|
+
type: 'direct',
|
|
698
|
+
category: 'network',
|
|
699
|
+
color: '#F59E0B',
|
|
700
|
+
description: 'HTTP client, request/response interceptors, and adapter pipelines.',
|
|
701
|
+
logoUri: 'https://axios-http.com/assets/logo.svg',
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
id: 'pkg-7',
|
|
705
|
+
name: 'react-native-linear-gradient',
|
|
706
|
+
version: '^2.8.3',
|
|
707
|
+
sizeKb: 45,
|
|
708
|
+
percentage: 2.5,
|
|
709
|
+
type: 'direct',
|
|
710
|
+
category: 'ui',
|
|
711
|
+
color: '#FB7185',
|
|
712
|
+
description: 'Hardware accelerated native gradient drawing shaders.',
|
|
713
|
+
logoUri: 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/512px-React-icon.svg.png',
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
id: 'pkg-8',
|
|
717
|
+
name: 'i18next & react-i18next',
|
|
718
|
+
version: '^26.3.6',
|
|
719
|
+
sizeKb: 62,
|
|
720
|
+
percentage: 3.5,
|
|
721
|
+
type: 'direct',
|
|
722
|
+
category: 'utils',
|
|
723
|
+
color: '#10B981',
|
|
724
|
+
description: 'Internationalization framework, language interpolator, and locale switcher.',
|
|
725
|
+
logoUri: 'https://raw.githubusercontent.com/i18next/i18next/master/assets/i18next-logo.png',
|
|
726
|
+
},
|
|
727
|
+
];
|
|
728
|
+
const CATEGORY_TABS = [
|
|
729
|
+
{ key: 'ALL', label: 'All Files', icon: '📁' },
|
|
730
|
+
{ key: 'UNUSED', label: 'Not Consumed (Dead)', icon: '🚫' },
|
|
731
|
+
{ key: 'CONSUMED', label: 'In-Use / Active', icon: '⚡' },
|
|
732
|
+
{ key: 'image', label: 'Images & Media', icon: '🖼️' },
|
|
733
|
+
{ key: 'typescript', label: 'TypeScript / TSX', icon: '📜' },
|
|
734
|
+
{ key: 'javascript', label: 'JS & Node Modules', icon: '⚙️' },
|
|
735
|
+
{ key: 'font', label: 'Fonts & Glyphs', icon: '🔤' },
|
|
736
|
+
{ key: 'json', label: 'JSON & Data', icon: '📄' },
|
|
737
|
+
];
|
|
738
|
+
const CATEGORY_COLORS = {
|
|
739
|
+
image: { label: 'Images & Media', color: '#EC4899', bg: '#FCE7F3' },
|
|
740
|
+
typescript: { label: 'TypeScript', color: '#0EA5E9', bg: '#E0F2FE' },
|
|
741
|
+
javascript: { label: 'JavaScript', color: '#6366F1', bg: '#EEF2FF' },
|
|
742
|
+
font: { label: 'Fonts', color: '#8B5CF6', bg: '#F3E8FF' },
|
|
743
|
+
json: { label: 'JSON / Data', color: '#10B981', bg: '#D1FAE5' },
|
|
744
|
+
};
|
|
745
|
+
const BundleTab = react_1.default.memo(() => {
|
|
746
|
+
const { t } = (0, react_i18next_1.useTranslation)();
|
|
747
|
+
const [activeSubTab, setActiveSubTab] = (0, react_1.useState)('overview');
|
|
748
|
+
const [search, setSearch] = (0, react_1.useState)('');
|
|
749
|
+
const [activeCategory, setActiveCategory] = (0, react_1.useState)('ALL');
|
|
750
|
+
// Check if Hermes is running
|
|
751
|
+
const isHermes = Boolean(global.HermesInternal);
|
|
752
|
+
// Group summary calculations
|
|
753
|
+
const summary = (0, react_1.useMemo)(() => {
|
|
754
|
+
let imagesKb = 0;
|
|
755
|
+
let tsKb = 0;
|
|
756
|
+
let jsKb = 0;
|
|
757
|
+
let fontsKb = 0;
|
|
758
|
+
let jsonKb = 0;
|
|
759
|
+
let imagesCount = 0;
|
|
760
|
+
let tsCount = 0;
|
|
761
|
+
let jsCount = 0;
|
|
762
|
+
let fontsCount = 0;
|
|
763
|
+
let jsonCount = 0;
|
|
764
|
+
BUNDLE_FILES_DATA.forEach(f => {
|
|
765
|
+
if (f.category === 'image') {
|
|
766
|
+
imagesKb += f.sizeKb;
|
|
767
|
+
imagesCount++;
|
|
768
|
+
}
|
|
769
|
+
else if (f.category === 'typescript') {
|
|
770
|
+
tsKb += f.sizeKb;
|
|
771
|
+
tsCount++;
|
|
772
|
+
}
|
|
773
|
+
else if (f.category === 'javascript') {
|
|
774
|
+
jsKb += f.sizeKb;
|
|
775
|
+
jsCount++;
|
|
776
|
+
}
|
|
777
|
+
else if (f.category === 'font') {
|
|
778
|
+
fontsKb += f.sizeKb;
|
|
779
|
+
fontsCount++;
|
|
780
|
+
}
|
|
781
|
+
else if (f.category === 'json') {
|
|
782
|
+
jsonKb += f.sizeKb;
|
|
783
|
+
jsonCount++;
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
const totalKb = imagesKb + tsKb + jsKb + fontsKb + jsonKb;
|
|
787
|
+
return {
|
|
788
|
+
totalKb,
|
|
789
|
+
totalMb: (totalKb / 1024).toFixed(2),
|
|
790
|
+
totalCount: BUNDLE_FILES_DATA.length,
|
|
791
|
+
images: {
|
|
792
|
+
count: imagesCount,
|
|
793
|
+
kb: imagesKb,
|
|
794
|
+
pct: Number(((imagesKb / totalKb) * 100).toFixed(1)),
|
|
795
|
+
},
|
|
796
|
+
ts: {
|
|
797
|
+
count: tsCount,
|
|
798
|
+
kb: tsKb,
|
|
799
|
+
pct: Number(((tsKb / totalKb) * 100).toFixed(1)),
|
|
800
|
+
},
|
|
801
|
+
js: {
|
|
802
|
+
count: jsCount,
|
|
803
|
+
kb: jsKb,
|
|
804
|
+
pct: Number(((jsKb / totalKb) * 100).toFixed(1)),
|
|
805
|
+
},
|
|
806
|
+
fonts: {
|
|
807
|
+
count: fontsCount,
|
|
808
|
+
kb: fontsKb,
|
|
809
|
+
pct: Number(((fontsKb / totalKb) * 100).toFixed(1)),
|
|
810
|
+
},
|
|
811
|
+
json: {
|
|
812
|
+
count: jsonCount,
|
|
813
|
+
kb: jsonKb,
|
|
814
|
+
pct: Number(((jsonKb / totalKb) * 100).toFixed(1)),
|
|
815
|
+
},
|
|
816
|
+
};
|
|
817
|
+
}, []);
|
|
818
|
+
// Filtered files
|
|
819
|
+
const filteredFiles = (0, react_1.useMemo)(() => {
|
|
820
|
+
return BUNDLE_FILES_DATA.filter(file => {
|
|
821
|
+
const matchSearch = !search ||
|
|
822
|
+
file.name.toLowerCase().includes(search.toLowerCase()) ||
|
|
823
|
+
file.path.toLowerCase().includes(search.toLowerCase()) ||
|
|
824
|
+
file.ext.toLowerCase().includes(search.toLowerCase()) ||
|
|
825
|
+
file.meta.toLowerCase().includes(search.toLowerCase());
|
|
826
|
+
const matchCategory = activeCategory === 'ALL'
|
|
827
|
+
? true
|
|
828
|
+
: activeCategory === 'UNUSED'
|
|
829
|
+
? file.isConsumed === false
|
|
830
|
+
: activeCategory === 'CONSUMED'
|
|
831
|
+
? file.isConsumed !== false
|
|
832
|
+
: file.category === activeCategory;
|
|
833
|
+
return matchSearch && matchCategory;
|
|
834
|
+
});
|
|
835
|
+
}, [search, activeCategory]);
|
|
836
|
+
const filteredTotalKb = (0, react_1.useMemo)(() => {
|
|
837
|
+
return filteredFiles.reduce((acc, f) => acc + f.sizeKb, 0);
|
|
838
|
+
}, [filteredFiles]);
|
|
839
|
+
// Tree View State & Node Generation
|
|
840
|
+
const [filesViewMode, setFilesViewMode] = (0, react_1.useState)('tree');
|
|
841
|
+
const [collapsedFolders, setCollapsedFolders] = (0, react_1.useState)({});
|
|
842
|
+
const fileTreeNodes = (0, react_1.useMemo)(() => {
|
|
843
|
+
return buildBundleFileTree(filteredFiles);
|
|
844
|
+
}, [filteredFiles]);
|
|
845
|
+
const toggleFolder = (0, react_1.useCallback)((path) => {
|
|
846
|
+
setCollapsedFolders(prev => ({
|
|
847
|
+
...prev,
|
|
848
|
+
[path]: !prev[path],
|
|
849
|
+
}));
|
|
850
|
+
}, []);
|
|
851
|
+
const expandAllFolders = (0, react_1.useCallback)(() => {
|
|
852
|
+
setCollapsedFolders({});
|
|
853
|
+
}, []);
|
|
854
|
+
const collapseAllFolders = (0, react_1.useCallback)(() => {
|
|
855
|
+
const all = {};
|
|
856
|
+
function collect(nodes) {
|
|
857
|
+
for (const n of nodes) {
|
|
858
|
+
if (n.isFolder) {
|
|
859
|
+
all[n.fullPath] = true;
|
|
860
|
+
collect(n.children);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
collect(fileTreeNodes);
|
|
865
|
+
setCollapsedFolders(all);
|
|
866
|
+
}, [fileTreeNodes]);
|
|
867
|
+
// Filtered Packages
|
|
868
|
+
const filteredPackages = (0, react_1.useMemo)(() => {
|
|
869
|
+
if (!search)
|
|
870
|
+
return BUNDLE_PACKAGES_DATA;
|
|
871
|
+
const q = search.toLowerCase();
|
|
872
|
+
return BUNDLE_PACKAGES_DATA.filter(pkg => pkg.name.toLowerCase().includes(q) ||
|
|
873
|
+
pkg.description.toLowerCase().includes(q) ||
|
|
874
|
+
pkg.category.toLowerCase().includes(q));
|
|
875
|
+
}, [search]);
|
|
876
|
+
const packagesTotalKb = (0, react_1.useMemo)(() => {
|
|
877
|
+
return filteredPackages.reduce((acc, p) => acc + p.sizeKb, 0);
|
|
878
|
+
}, [filteredPackages]);
|
|
879
|
+
// Media files (Images + Fonts)
|
|
880
|
+
const mediaFiles = (0, react_1.useMemo)(() => {
|
|
881
|
+
return BUNDLE_FILES_DATA.filter(f => f.category === 'image' || f.category === 'font');
|
|
882
|
+
}, []);
|
|
883
|
+
const mediaTotalKb = (0, react_1.useMemo)(() => {
|
|
884
|
+
return mediaFiles.reduce((acc, m) => acc + m.sizeKb, 0);
|
|
885
|
+
}, [mediaFiles]);
|
|
886
|
+
const subTabs = [
|
|
887
|
+
{
|
|
888
|
+
key: 'overview',
|
|
889
|
+
label: 'Overview',
|
|
890
|
+
icon: (isActive) => (<NetworkIcons_1.LiveStateIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.purple} size={12}/>),
|
|
891
|
+
},
|
|
892
|
+
{
|
|
893
|
+
key: 'files',
|
|
894
|
+
label: `Files (${BUNDLE_FILES_DATA.length})`,
|
|
895
|
+
icon: (isActive) => (<NetworkIcons_1.LayersIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.purple} size={12}/>),
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
key: 'packages',
|
|
899
|
+
label: `Packages (${BUNDLE_PACKAGES_DATA.length})`,
|
|
900
|
+
icon: (isActive) => (<NetworkIcons_1.PackageIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.purple} size={12}/>),
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
key: 'media',
|
|
904
|
+
label: `Media (${mediaFiles.length})`,
|
|
905
|
+
icon: (isActive) => (<NetworkIcons_1.StorageIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.purple} size={12}/>),
|
|
906
|
+
},
|
|
907
|
+
{
|
|
908
|
+
key: 'optimizer',
|
|
909
|
+
label: 'Optimizer',
|
|
910
|
+
icon: (isActive) => (<NetworkIcons_1.MetadataIcon color={isActive ? AppColors_1.AppColors.white : AppColors_1.AppColors.purple} size={12}/>),
|
|
911
|
+
},
|
|
912
|
+
];
|
|
913
|
+
return (<react_native_1.View style={{ flex: 1, backgroundColor: AppColors_1.AppColors.grayBackground }}>
|
|
914
|
+
{/* ─── Top Sub-Tabs Navigation Bar (Scrollable Pill Bar) ─── */}
|
|
915
|
+
<react_native_1.View style={bundleStyles.topTabWrap}>
|
|
916
|
+
<react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={bundleStyles.subTabsScroll}>
|
|
917
|
+
{subTabs.map(tab => {
|
|
918
|
+
const isActive = activeSubTab === tab.key;
|
|
919
|
+
return (<TouchableScale_1.default key={tab.key} onPress={() => setActiveSubTab(tab.key)} style={[
|
|
920
|
+
bundleStyles.subTabPill,
|
|
921
|
+
isActive && bundleStyles.subTabPillActive,
|
|
922
|
+
]}>
|
|
923
|
+
{tab.icon(isActive)}
|
|
924
|
+
<react_native_1.Text style={[
|
|
925
|
+
bundleStyles.subTabPillText,
|
|
926
|
+
isActive && bundleStyles.subTabPillTextActive,
|
|
927
|
+
]}>
|
|
928
|
+
{tab.label}
|
|
929
|
+
</react_native_1.Text>
|
|
930
|
+
</TouchableScale_1.default>);
|
|
931
|
+
})}
|
|
932
|
+
</react_native_1.ScrollView>
|
|
933
|
+
</react_native_1.View>
|
|
934
|
+
|
|
935
|
+
{/* ══════════════════════════════════════════════════════════════════════ */}
|
|
936
|
+
{/* ── 1. TAB: OVERVIEW & TREEMAP ───────────────────────────────────────── */}
|
|
937
|
+
{/* ══════════════════════════════════════════════════════════════════════ */}
|
|
938
|
+
{activeSubTab === 'overview' && (<react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
|
|
939
|
+
|
|
940
|
+
{/* Hero Overview Card */}
|
|
941
|
+
<react_native_1.View style={bundleStyles.heroCard}>
|
|
942
|
+
<react_native_1.View style={bundleStyles.heroTopRow}>
|
|
943
|
+
<react_native_1.View style={bundleStyles.heroIconWrap}>
|
|
944
|
+
<NetworkIcons_1.PackageIcon color={AppColors_1.AppColors.brandPurple} size={24}/>
|
|
945
|
+
</react_native_1.View>
|
|
946
|
+
<react_native_1.View style={{ flex: 1 }}>
|
|
947
|
+
<react_native_1.Text style={bundleStyles.heroTitle}>Bundle & Asset Architecture</react_native_1.Text>
|
|
948
|
+
<react_native_1.Text style={bundleStyles.heroSubtitle}>
|
|
949
|
+
Real-time size breakdown across all assets, code, and dependencies
|
|
950
|
+
</react_native_1.Text>
|
|
951
|
+
</react_native_1.View>
|
|
952
|
+
<CopyButton_1.default value={() => summary} label="Bundle Overview JSON"/>
|
|
953
|
+
</react_native_1.View>
|
|
954
|
+
|
|
955
|
+
{/* 4-Stat Metric Grid */}
|
|
956
|
+
<react_native_1.View style={bundleStyles.metricsGrid}>
|
|
957
|
+
<react_native_1.View style={bundleStyles.metricBox}>
|
|
958
|
+
<react_native_1.Text style={bundleStyles.metricLabel}>TOTAL BUNDLE ASSETS</react_native_1.Text>
|
|
959
|
+
<react_native_1.Text style={bundleStyles.metricValue}>~{summary.totalMb} MB</react_native_1.Text>
|
|
960
|
+
<react_native_1.Text style={bundleStyles.metricHint}>{BUNDLE_FILES_DATA.length} Tracked files</react_native_1.Text>
|
|
961
|
+
</react_native_1.View>
|
|
962
|
+
|
|
963
|
+
<react_native_1.View style={bundleStyles.metricBox}>
|
|
964
|
+
<react_native_1.Text style={bundleStyles.metricLabel}>IMAGES & MEDIA</react_native_1.Text>
|
|
965
|
+
<react_native_1.Text style={[bundleStyles.metricValue, { color: '#EC4899' }]}>
|
|
966
|
+
{summary.images.kb} KB
|
|
967
|
+
</react_native_1.Text>
|
|
968
|
+
<react_native_1.Text style={bundleStyles.metricHint}>{summary.images.pct}% of package</react_native_1.Text>
|
|
969
|
+
</react_native_1.View>
|
|
970
|
+
|
|
971
|
+
<react_native_1.View style={bundleStyles.metricBox}>
|
|
972
|
+
<react_native_1.Text style={bundleStyles.metricLabel}>TS / JS SOURCE</react_native_1.Text>
|
|
973
|
+
<react_native_1.Text style={[bundleStyles.metricValue, { color: '#0EA5E9' }]}>
|
|
974
|
+
{summary.ts.kb + summary.js.kb} KB
|
|
975
|
+
</react_native_1.Text>
|
|
976
|
+
<react_native_1.Text style={bundleStyles.metricHint}>
|
|
977
|
+
{(summary.ts.pct + summary.js.pct).toFixed(1)}% of package
|
|
978
|
+
</react_native_1.Text>
|
|
979
|
+
</react_native_1.View>
|
|
980
|
+
|
|
981
|
+
<react_native_1.View style={bundleStyles.metricBox}>
|
|
982
|
+
<react_native_1.Text style={bundleStyles.metricLabel}>JS ENGINE</react_native_1.Text>
|
|
983
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 5, marginTop: 2 }}>
|
|
984
|
+
<react_native_1.View style={[
|
|
985
|
+
bundleStyles.statusIndicator,
|
|
986
|
+
{ backgroundColor: isHermes ? AppColors_1.AppColors.greenColor : AppColors_1.AppColors.darkOrange },
|
|
987
|
+
]}/>
|
|
988
|
+
<react_native_1.Text style={bundleStyles.metricValue}>
|
|
989
|
+
{isHermes ? 'Hermes' : 'JSC'}
|
|
990
|
+
</react_native_1.Text>
|
|
991
|
+
</react_native_1.View>
|
|
992
|
+
<react_native_1.Text style={bundleStyles.metricHint}>{isHermes ? 'Bytecode AOT' : 'Standard'}</react_native_1.Text>
|
|
993
|
+
</react_native_1.View>
|
|
994
|
+
</react_native_1.View>
|
|
995
|
+
</react_native_1.View>
|
|
996
|
+
|
|
997
|
+
{/* Visual Type Distribution Ratio Bar */}
|
|
998
|
+
<react_native_1.View style={bundleStyles.sectionCard}>
|
|
999
|
+
<react_native_1.View style={bundleStyles.sectionHeaderRow}>
|
|
1000
|
+
<react_native_1.View>
|
|
1001
|
+
<react_native_1.Text style={bundleStyles.sectionTitle}>Asset & File Type Ratio Treemap</react_native_1.Text>
|
|
1002
|
+
<react_native_1.Text style={bundleStyles.sectionSub}>Total ~{summary.totalMb} MB</react_native_1.Text>
|
|
1003
|
+
</react_native_1.View>
|
|
1004
|
+
<CopyButton_1.default value={() => ({
|
|
1005
|
+
totalMb: summary.totalMb,
|
|
1006
|
+
totalKb: summary.totalKb,
|
|
1007
|
+
images: summary.images,
|
|
1008
|
+
ts: summary.ts,
|
|
1009
|
+
js: summary.js,
|
|
1010
|
+
fonts: summary.fonts,
|
|
1011
|
+
json: summary.json,
|
|
1012
|
+
})} label="Ratio Treemap JSON"/>
|
|
1013
|
+
</react_native_1.View>
|
|
1014
|
+
|
|
1015
|
+
{/* Stacked Colored Bar */}
|
|
1016
|
+
<react_native_1.View style={bundleStyles.treemapBar}>
|
|
1017
|
+
<react_native_1.View style={{ flex: summary.images.pct, backgroundColor: '#EC4899', height: 16 }}/>
|
|
1018
|
+
<react_native_1.View style={{ flex: summary.ts.pct, backgroundColor: '#0EA5E9', height: 16 }}/>
|
|
1019
|
+
<react_native_1.View style={{ flex: summary.js.pct, backgroundColor: '#6366F1', height: 16 }}/>
|
|
1020
|
+
<react_native_1.View style={{ flex: summary.fonts.pct, backgroundColor: '#8B5CF6', height: 16 }}/>
|
|
1021
|
+
<react_native_1.View style={{ flex: summary.json.pct, backgroundColor: '#10B981', height: 16 }}/>
|
|
1022
|
+
</react_native_1.View>
|
|
1023
|
+
|
|
1024
|
+
{/* Legend Grid */}
|
|
1025
|
+
<react_native_1.View style={bundleStyles.legendGrid}>
|
|
1026
|
+
<react_native_1.View style={bundleStyles.legendItem}>
|
|
1027
|
+
<react_native_1.View style={[bundleStyles.legendDot, { backgroundColor: '#EC4899' }]}/>
|
|
1028
|
+
<react_native_1.Text style={bundleStyles.legendText}>
|
|
1029
|
+
🖼️ Images: <react_native_1.Text style={bundleStyles.legendVal}>{summary.images.kb} KB ({summary.images.pct}%)</react_native_1.Text>
|
|
1030
|
+
</react_native_1.Text>
|
|
1031
|
+
</react_native_1.View>
|
|
1032
|
+
<react_native_1.View style={bundleStyles.legendItem}>
|
|
1033
|
+
<react_native_1.View style={[bundleStyles.legendDot, { backgroundColor: '#0EA5E9' }]}/>
|
|
1034
|
+
<react_native_1.Text style={bundleStyles.legendText}>
|
|
1035
|
+
📜 TS/TSX: <react_native_1.Text style={bundleStyles.legendVal}>{summary.ts.kb} KB ({summary.ts.pct}%)</react_native_1.Text>
|
|
1036
|
+
</react_native_1.Text>
|
|
1037
|
+
</react_native_1.View>
|
|
1038
|
+
<react_native_1.View style={bundleStyles.legendItem}>
|
|
1039
|
+
<react_native_1.View style={[bundleStyles.legendDot, { backgroundColor: '#6366F1' }]}/>
|
|
1040
|
+
<react_native_1.Text style={bundleStyles.legendText}>
|
|
1041
|
+
⚙️ JS Libs: <react_native_1.Text style={bundleStyles.legendVal}>{summary.js.kb} KB ({summary.js.pct}%)</react_native_1.Text>
|
|
1042
|
+
</react_native_1.Text>
|
|
1043
|
+
</react_native_1.View>
|
|
1044
|
+
<react_native_1.View style={bundleStyles.legendItem}>
|
|
1045
|
+
<react_native_1.View style={[bundleStyles.legendDot, { backgroundColor: '#8B5CF6' }]}/>
|
|
1046
|
+
<react_native_1.Text style={bundleStyles.legendText}>
|
|
1047
|
+
🔤 Fonts: <react_native_1.Text style={bundleStyles.legendVal}>{summary.fonts.kb} KB ({summary.fonts.pct}%)</react_native_1.Text>
|
|
1048
|
+
</react_native_1.Text>
|
|
1049
|
+
</react_native_1.View>
|
|
1050
|
+
<react_native_1.View style={bundleStyles.legendItem}>
|
|
1051
|
+
<react_native_1.View style={[bundleStyles.legendDot, { backgroundColor: '#10B981' }]}/>
|
|
1052
|
+
<react_native_1.Text style={bundleStyles.legendText}>
|
|
1053
|
+
📄 JSON: <react_native_1.Text style={bundleStyles.legendVal}>{summary.json.kb} KB ({summary.json.pct}%)</react_native_1.Text>
|
|
1054
|
+
</react_native_1.Text>
|
|
1055
|
+
</react_native_1.View>
|
|
1056
|
+
</react_native_1.View>
|
|
1057
|
+
</react_native_1.View>
|
|
1058
|
+
|
|
1059
|
+
{/* Detailed Category Footprint Cards */}
|
|
1060
|
+
<react_native_1.View style={bundleStyles.sectionCard}>
|
|
1061
|
+
<react_native_1.View style={bundleStyles.sectionHeaderRow}>
|
|
1062
|
+
<react_native_1.Text style={bundleStyles.sectionTitle}>Category Breakdown</react_native_1.Text>
|
|
1063
|
+
<CopyButton_1.default value={() => ({
|
|
1064
|
+
totalAssets: summary.totalCount,
|
|
1065
|
+
totalSizeKb: summary.totalKb,
|
|
1066
|
+
categories: {
|
|
1067
|
+
images: summary.images,
|
|
1068
|
+
javascript: summary.js,
|
|
1069
|
+
fonts: summary.fonts,
|
|
1070
|
+
typescript: summary.ts,
|
|
1071
|
+
json: summary.json,
|
|
1072
|
+
},
|
|
1073
|
+
})} label="Categories Breakdown JSON"/>
|
|
1074
|
+
</react_native_1.View>
|
|
1075
|
+
|
|
1076
|
+
{[
|
|
1077
|
+
{
|
|
1078
|
+
icon: '🖼️',
|
|
1079
|
+
title: 'Images & Media Assets',
|
|
1080
|
+
count: summary.images.count,
|
|
1081
|
+
size: `${summary.images.kb} KB`,
|
|
1082
|
+
pct: summary.images.pct,
|
|
1083
|
+
color: '#EC4899',
|
|
1084
|
+
desc: 'PNG, WebP, SVG, and JPG assets in bundle',
|
|
1085
|
+
},
|
|
1086
|
+
{
|
|
1087
|
+
icon: '⚙️',
|
|
1088
|
+
title: 'Compiled Node Modules & JS',
|
|
1089
|
+
count: summary.js.count,
|
|
1090
|
+
size: `${summary.js.kb} KB`,
|
|
1091
|
+
pct: summary.js.pct,
|
|
1092
|
+
color: '#6366F1',
|
|
1093
|
+
desc: 'Third-party dependencies and native bridges',
|
|
1094
|
+
},
|
|
1095
|
+
{
|
|
1096
|
+
icon: '🔤',
|
|
1097
|
+
title: 'Custom Fonts & Vector Glyphs',
|
|
1098
|
+
count: summary.fonts.count,
|
|
1099
|
+
size: `${summary.fonts.kb} KB`,
|
|
1100
|
+
pct: summary.fonts.pct,
|
|
1101
|
+
color: '#8B5CF6',
|
|
1102
|
+
desc: 'Inter, JetBrainsMono, and UI typography fonts',
|
|
1103
|
+
},
|
|
1104
|
+
{
|
|
1105
|
+
icon: '📜',
|
|
1106
|
+
title: 'TypeScript & JSX Components',
|
|
1107
|
+
count: summary.ts.count,
|
|
1108
|
+
size: `${summary.ts.kb} KB`,
|
|
1109
|
+
pct: summary.ts.pct,
|
|
1110
|
+
color: '#0EA5E9',
|
|
1111
|
+
desc: 'App screen components, hooks, and business logic',
|
|
1112
|
+
},
|
|
1113
|
+
{
|
|
1114
|
+
icon: '📄',
|
|
1115
|
+
title: 'JSON Data & Localizations',
|
|
1116
|
+
count: summary.json.count,
|
|
1117
|
+
size: `${summary.json.kb} KB`,
|
|
1118
|
+
pct: summary.json.pct,
|
|
1119
|
+
color: '#10B981',
|
|
1120
|
+
desc: 'i18n translation dictionaries and static configs',
|
|
1121
|
+
},
|
|
1122
|
+
].map((cat, cIdx) => (<react_native_1.View key={cIdx} style={bundleStyles.catRowCard}>
|
|
1123
|
+
<react_native_1.View style={bundleStyles.catRowTop}>
|
|
1124
|
+
<react_native_1.Text style={bundleStyles.catRowIcon}>{cat.icon}</react_native_1.Text>
|
|
1125
|
+
<react_native_1.View style={{ flex: 1 }}>
|
|
1126
|
+
<react_native_1.Text style={bundleStyles.catRowTitle}>{cat.title}</react_native_1.Text>
|
|
1127
|
+
<react_native_1.Text style={bundleStyles.catRowDesc}>{cat.count} items • {cat.desc}</react_native_1.Text>
|
|
1128
|
+
</react_native_1.View>
|
|
1129
|
+
<react_native_1.View style={{ alignItems: 'flex-end' }}>
|
|
1130
|
+
<react_native_1.Text style={bundleStyles.catRowSize}>{cat.size}</react_native_1.Text>
|
|
1131
|
+
<react_native_1.Text style={bundleStyles.catRowPct}>{cat.pct}%</react_native_1.Text>
|
|
1132
|
+
</react_native_1.View>
|
|
1133
|
+
</react_native_1.View>
|
|
1134
|
+
<react_native_1.View style={bundleStyles.catProgressTrack}>
|
|
1135
|
+
<react_native_1.View style={[
|
|
1136
|
+
bundleStyles.catProgressBar,
|
|
1137
|
+
{ width: `${cat.pct}%`, backgroundColor: cat.color },
|
|
1138
|
+
]}/>
|
|
1139
|
+
</react_native_1.View>
|
|
1140
|
+
</react_native_1.View>))}
|
|
1141
|
+
|
|
1142
|
+
{/* Total Summation Card */}
|
|
1143
|
+
<react_native_1.View style={bundleStyles.totalSummaryCard}>
|
|
1144
|
+
<react_native_1.View style={bundleStyles.totalSummaryRow}>
|
|
1145
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
1146
|
+
<NetworkIcons_1.PackageIcon color={AppColors_1.AppColors.purple} size={16}/>
|
|
1147
|
+
<react_native_1.Text style={bundleStyles.totalSummaryLabel}>TOTAL BUNDLE ASSETS</react_native_1.Text>
|
|
1148
|
+
</react_native_1.View>
|
|
1149
|
+
<react_native_1.Text style={bundleStyles.totalSummaryValue}>
|
|
1150
|
+
{summary.totalKb} KB (~{summary.totalMb} MB)
|
|
1151
|
+
</react_native_1.Text>
|
|
1152
|
+
</react_native_1.View>
|
|
1153
|
+
<react_native_1.Text style={bundleStyles.totalSummaryFormula}>
|
|
1154
|
+
Sum: {summary.images.kb} KB + {summary.js.kb} KB + {summary.fonts.kb} KB + {summary.ts.kb} KB + {summary.json.kb} KB = {summary.totalKb} KB ({summary.totalCount} items • 100%)
|
|
1155
|
+
</react_native_1.Text>
|
|
1156
|
+
</react_native_1.View>
|
|
1157
|
+
</react_native_1.View>
|
|
1158
|
+
</react_native_1.ScrollView>)}
|
|
1159
|
+
|
|
1160
|
+
{/* ══════════════════════════════════════════════════════════════════════ */}
|
|
1161
|
+
{/* ── 2. TAB: FILES BREAKDOWN ─────────────────────────────────────────── */}
|
|
1162
|
+
{/* ══════════════════════════════════════════════════════════════════════ */}
|
|
1163
|
+
{activeSubTab === 'files' && (<react_native_1.View style={{ flex: 1 }}>
|
|
1164
|
+
{/* Search & Category Filter */}
|
|
1165
|
+
<react_native_1.View style={bundleStyles.filterContainer}>
|
|
1166
|
+
<react_native_1.View style={bundleStyles.searchRow}>
|
|
1167
|
+
<NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={15}/>
|
|
1168
|
+
<react_native_1.TextInput placeholder="Search by file name (.png, .tsx, .ttf, path)..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={bundleStyles.searchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
1169
|
+
{search.length > 0 && (<react_native_1.Pressable onPress={() => setSearch('')} hitSlop={10}>
|
|
1170
|
+
<NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
|
|
1171
|
+
</react_native_1.Pressable>)}
|
|
1172
|
+
<CopyButton_1.default value={() => filteredFiles} label="Filtered Files JSON"/>
|
|
1173
|
+
</react_native_1.View>
|
|
1174
|
+
|
|
1175
|
+
{/* Category Filter Chips */}
|
|
1176
|
+
<react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={bundleStyles.categoryPillsScroll}>
|
|
1177
|
+
{CATEGORY_TABS.map(tab => {
|
|
1178
|
+
const isActive = activeCategory === tab.key;
|
|
1179
|
+
const count = tab.key === 'ALL'
|
|
1180
|
+
? BUNDLE_FILES_DATA.length
|
|
1181
|
+
: tab.key === 'UNUSED'
|
|
1182
|
+
? BUNDLE_FILES_DATA.filter(f => f.isConsumed === false).length
|
|
1183
|
+
: tab.key === 'CONSUMED'
|
|
1184
|
+
? BUNDLE_FILES_DATA.filter(f => f.isConsumed !== false).length
|
|
1185
|
+
: BUNDLE_FILES_DATA.filter(f => f.category === tab.key).length;
|
|
1186
|
+
return (<TouchableScale_1.default key={tab.key} onPress={() => setActiveCategory(tab.key)} style={[
|
|
1187
|
+
bundleStyles.catPill,
|
|
1188
|
+
isActive && bundleStyles.catPillActive,
|
|
1189
|
+
tab.key === 'UNUSED' && isActive && { backgroundColor: '#EF4444', borderColor: '#DC2626' },
|
|
1190
|
+
tab.key === 'CONSUMED' && isActive && { backgroundColor: '#059669', borderColor: '#047857' },
|
|
1191
|
+
]}>
|
|
1192
|
+
<react_native_1.Text style={bundleStyles.catPillIcon}>{tab.icon}</react_native_1.Text>
|
|
1193
|
+
<react_native_1.Text style={[
|
|
1194
|
+
bundleStyles.catPillText,
|
|
1195
|
+
isActive && bundleStyles.catPillTextActive,
|
|
1196
|
+
]}>
|
|
1197
|
+
{tab.label} ({count})
|
|
1198
|
+
</react_native_1.Text>
|
|
1199
|
+
</TouchableScale_1.default>);
|
|
1200
|
+
})}
|
|
1201
|
+
</react_native_1.ScrollView>
|
|
1202
|
+
</react_native_1.View>
|
|
1203
|
+
|
|
1204
|
+
{/* Files List / Tree Content */}
|
|
1205
|
+
<react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
|
|
1206
|
+
|
|
1207
|
+
{/* View Mode Toggle Header Bar */}
|
|
1208
|
+
<react_native_1.View style={bundleStyles.treeHeaderRow}>
|
|
1209
|
+
<react_native_1.View style={bundleStyles.viewModeToggleGroup}>
|
|
1210
|
+
<TouchableScale_1.default onPress={() => setFilesViewMode('tree')} style={[
|
|
1211
|
+
bundleStyles.viewModeBtn,
|
|
1212
|
+
filesViewMode === 'tree' && bundleStyles.viewModeBtnActive,
|
|
1213
|
+
]}>
|
|
1214
|
+
<react_native_1.Text style={[
|
|
1215
|
+
bundleStyles.viewModeBtnText,
|
|
1216
|
+
filesViewMode === 'tree' && bundleStyles.viewModeBtnTextActive,
|
|
1217
|
+
]}>
|
|
1218
|
+
🌳 Tree View
|
|
1219
|
+
</react_native_1.Text>
|
|
1220
|
+
</TouchableScale_1.default>
|
|
1221
|
+
<TouchableScale_1.default onPress={() => setFilesViewMode('list')} style={[
|
|
1222
|
+
bundleStyles.viewModeBtn,
|
|
1223
|
+
filesViewMode === 'list' && bundleStyles.viewModeBtnActive,
|
|
1224
|
+
]}>
|
|
1225
|
+
<react_native_1.Text style={[
|
|
1226
|
+
bundleStyles.viewModeBtnText,
|
|
1227
|
+
filesViewMode === 'list' && bundleStyles.viewModeBtnTextActive,
|
|
1228
|
+
]}>
|
|
1229
|
+
📄 Flat List
|
|
1230
|
+
</react_native_1.Text>
|
|
1231
|
+
</TouchableScale_1.default>
|
|
1232
|
+
</react_native_1.View>
|
|
1233
|
+
|
|
1234
|
+
{filesViewMode === 'tree' ? (<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
|
|
1235
|
+
<TouchableScale_1.default onPress={expandAllFolders}>
|
|
1236
|
+
<react_native_1.Text style={bundleStyles.treeActionLink}>Expand</react_native_1.Text>
|
|
1237
|
+
</TouchableScale_1.default>
|
|
1238
|
+
<react_native_1.Text style={{ color: AppColors_1.AppColors.grayTextWeak, fontSize: 11 }}>•</react_native_1.Text>
|
|
1239
|
+
<TouchableScale_1.default onPress={collapseAllFolders}>
|
|
1240
|
+
<react_native_1.Text style={bundleStyles.treeActionLink}>Collapse</react_native_1.Text>
|
|
1241
|
+
</TouchableScale_1.default>
|
|
1242
|
+
</react_native_1.View>) : (<react_native_1.Text style={bundleStyles.listHeaderCount}>
|
|
1243
|
+
Showing {filteredFiles.length} of {BUNDLE_FILES_DATA.length} files
|
|
1244
|
+
</react_native_1.Text>)}
|
|
1245
|
+
</react_native_1.View>
|
|
1246
|
+
|
|
1247
|
+
{/* ── MODE 1: DIRECTORY TREE VIEW ── */}
|
|
1248
|
+
{filesViewMode === 'tree' ? (<react_native_1.View style={bundleStyles.treeRootContainer}>
|
|
1249
|
+
{fileTreeNodes.map((node, nIdx) => (<BundleTreeNodeView key={node.id} node={node} level={0} search={search} totalBundleKb={summary.totalKb} collapsedFolders={collapsedFolders} toggleFolder={toggleFolder} isLastChild={nIdx === fileTreeNodes.length - 1}/>))}
|
|
1250
|
+
</react_native_1.View>) : (
|
|
1251
|
+
/* ── MODE 2: FLAT LIST VIEW ── */
|
|
1252
|
+
filteredFiles.map((file, index) => {
|
|
1253
|
+
const categoryMeta = CATEGORY_COLORS[file.category] || CATEGORY_COLORS.typescript;
|
|
1254
|
+
const pctOfTotal = ((file.sizeKb / summary.totalKb) * 100).toFixed(1);
|
|
1255
|
+
const isUnused = file.isConsumed === false;
|
|
1256
|
+
return (<react_native_1.View key={file.id} style={[bundleStyles.fileCard, isUnused && bundleStyles.treeFileCardUnused]}>
|
|
1257
|
+
<react_native_1.View style={bundleStyles.fileCardTop}>
|
|
1258
|
+
<react_native_1.View style={bundleStyles.sNoBadge}>
|
|
1259
|
+
<react_native_1.Text style={bundleStyles.sNoText}>#{index + 1}</react_native_1.Text>
|
|
1260
|
+
</react_native_1.View>
|
|
1261
|
+
|
|
1262
|
+
<MediaPreviewThumbnail file={file}/>
|
|
1263
|
+
|
|
1264
|
+
<react_native_1.View style={{ flex: 1, paddingHorizontal: 4 }}>
|
|
1265
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
1266
|
+
<HighlightText_1.default text={file.name} search={search} style={bundleStyles.fileName} highlightStyle={bundleStyles.searchHighlight}/>
|
|
1267
|
+
{isUnused ? (<react_native_1.View style={bundleStyles.unusedBadge}>
|
|
1268
|
+
<react_native_1.Text style={bundleStyles.unusedBadgeText}>🚫 Not Consumed</react_native_1.Text>
|
|
1269
|
+
</react_native_1.View>) : (<react_native_1.View style={bundleStyles.consumedBadge}>
|
|
1270
|
+
<react_native_1.Text style={bundleStyles.consumedBadgeText}>⚡ Consumed</react_native_1.Text>
|
|
1271
|
+
</react_native_1.View>)}
|
|
1272
|
+
</react_native_1.View>
|
|
1273
|
+
<HighlightText_1.default text={file.path} search={search} style={bundleStyles.filePath} highlightStyle={bundleStyles.searchHighlight} numberOfLines={1}/>
|
|
1274
|
+
</react_native_1.View>
|
|
1275
|
+
|
|
1276
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
1277
|
+
<react_native_1.View style={bundleStyles.fileSizeBox}>
|
|
1278
|
+
<react_native_1.Text style={[bundleStyles.fileSizeKb, isUnused && { color: '#B45309' }]}>
|
|
1279
|
+
{file.sizeKb >= 1024
|
|
1280
|
+
? `${(file.sizeKb / 1024).toFixed(2)} MB`
|
|
1281
|
+
: `${file.sizeKb} KB`}
|
|
1282
|
+
</react_native_1.Text>
|
|
1283
|
+
<react_native_1.Text style={bundleStyles.filePercent}>{pctOfTotal}%</react_native_1.Text>
|
|
1284
|
+
</react_native_1.View>
|
|
1285
|
+
<CopyButton_1.default value={() => file} label="File Details JSON"/>
|
|
1286
|
+
</react_native_1.View>
|
|
1287
|
+
</react_native_1.View>
|
|
1288
|
+
|
|
1289
|
+
<react_native_1.View style={bundleStyles.fileProgressTrack}>
|
|
1290
|
+
<react_native_1.View style={[
|
|
1291
|
+
bundleStyles.fileProgressBar,
|
|
1292
|
+
{
|
|
1293
|
+
width: `${Math.min(100, Math.max(4, Number(pctOfTotal) * 4))}%`,
|
|
1294
|
+
backgroundColor: isUnused ? '#EF4444' : categoryMeta.color,
|
|
1295
|
+
},
|
|
1296
|
+
]}/>
|
|
1297
|
+
</react_native_1.View>
|
|
1298
|
+
|
|
1299
|
+
<react_native_1.View style={bundleStyles.fileCardBottom}>
|
|
1300
|
+
<react_native_1.Text style={bundleStyles.fileMetaText}>{file.meta}</react_native_1.Text>
|
|
1301
|
+
{file.advice && (<react_native_1.View style={[
|
|
1302
|
+
bundleStyles.adviceBadge,
|
|
1303
|
+
file.status === 'warning' && bundleStyles.adviceWarning,
|
|
1304
|
+
file.status === 'optimal' && bundleStyles.adviceOptimal,
|
|
1305
|
+
isUnused && bundleStyles.adviceUnused,
|
|
1306
|
+
]}>
|
|
1307
|
+
<react_native_1.Text style={[
|
|
1308
|
+
bundleStyles.adviceText,
|
|
1309
|
+
file.status === 'warning' && { color: '#B45309' },
|
|
1310
|
+
file.status === 'optimal' && { color: '#047857' },
|
|
1311
|
+
isUnused && { color: '#DC2626' },
|
|
1312
|
+
]}>
|
|
1313
|
+
{isUnused ? '🗑️ ' : file.status === 'warning' ? '💡 ' : '✨ '}
|
|
1314
|
+
{file.advice}
|
|
1315
|
+
</react_native_1.Text>
|
|
1316
|
+
</react_native_1.View>)}
|
|
1317
|
+
</react_native_1.View>
|
|
1318
|
+
</react_native_1.View>);
|
|
1319
|
+
}))}
|
|
1320
|
+
</react_native_1.ScrollView>
|
|
1321
|
+
|
|
1322
|
+
{/* Sticky Total Bundle Size Footer */}
|
|
1323
|
+
<react_native_1.View style={bundleStyles.stickyFooterBar}>
|
|
1324
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
1325
|
+
<NetworkIcons_1.LayersIcon color={AppColors_1.AppColors.purple} size={14}/>
|
|
1326
|
+
<react_native_1.Text style={bundleStyles.footerTitle}>
|
|
1327
|
+
{filteredFiles.length} of {summary.totalCount} Files
|
|
1328
|
+
</react_native_1.Text>
|
|
1329
|
+
</react_native_1.View>
|
|
1330
|
+
<react_native_1.Text style={bundleStyles.footerSizeVal}>
|
|
1331
|
+
{filteredTotalKb} KB ({(filteredTotalKb / 1024).toFixed(2)} MB)
|
|
1332
|
+
</react_native_1.Text>
|
|
1333
|
+
</react_native_1.View>
|
|
1334
|
+
</react_native_1.View>)}
|
|
1335
|
+
|
|
1336
|
+
{/* ══════════════════════════════════════════════════════════════════════ */}
|
|
1337
|
+
{/* ── 3. TAB: PACKAGES & NODE_MODULES ─────────────────────────────────── */}
|
|
1338
|
+
{/* ══════════════════════════════════════════════════════════════════════ */}
|
|
1339
|
+
{activeSubTab === 'packages' && (<react_native_1.View style={{ flex: 1 }}>
|
|
1340
|
+
<react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
|
|
1341
|
+
|
|
1342
|
+
<react_native_1.View style={bundleStyles.filterContainer}>
|
|
1343
|
+
<react_native_1.View style={bundleStyles.searchRow}>
|
|
1344
|
+
<NetworkIcons_1.SearchIcon color={AppColors_1.AppColors.grayTextWeak} size={15}/>
|
|
1345
|
+
<react_native_1.TextInput placeholder="Search package (react-native, axios, navigation)..." placeholderTextColor={AppColors_1.AppColors.grayTextWeak} value={search} onChangeText={setSearch} style={bundleStyles.searchInput} autoCorrect={false} autoCapitalize="none"/>
|
|
1346
|
+
{search.length > 0 && (<react_native_1.Pressable onPress={() => setSearch('')} hitSlop={10}>
|
|
1347
|
+
<NetworkIcons_1.ClearIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
|
|
1348
|
+
</react_native_1.Pressable>)}
|
|
1349
|
+
<CopyButton_1.default value={() => filteredPackages} label="Dependencies JSON"/>
|
|
1350
|
+
</react_native_1.View>
|
|
1351
|
+
</react_native_1.View>
|
|
1352
|
+
|
|
1353
|
+
<react_native_1.Text style={bundleStyles.listHeaderCount}>
|
|
1354
|
+
Showing {filteredPackages.length} dependencies
|
|
1355
|
+
</react_native_1.Text>
|
|
1356
|
+
|
|
1357
|
+
{filteredPackages.map((pkg, index) => (<react_native_1.View key={pkg.id} style={bundleStyles.fileCard}>
|
|
1358
|
+
{/* Header Row: #s.no + Logo + Package Name + Version Pill + Size & Copy */}
|
|
1359
|
+
<react_native_1.View style={bundleStyles.fileCardTop}>
|
|
1360
|
+
<react_native_1.View style={bundleStyles.sNoBadge}>
|
|
1361
|
+
<react_native_1.Text style={bundleStyles.sNoText}>#{index + 1}</react_native_1.Text>
|
|
1362
|
+
</react_native_1.View>
|
|
1363
|
+
|
|
1364
|
+
<PackageLogoRenderer name={pkg.name} color={pkg.color} size={28}/>
|
|
1365
|
+
|
|
1366
|
+
<react_native_1.View style={{ flex: 1, paddingHorizontal: 4 }}>
|
|
1367
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
|
1368
|
+
<HighlightText_1.default text={pkg.name} search={search} style={bundleStyles.fileName} highlightStyle={bundleStyles.searchHighlight}/>
|
|
1369
|
+
<react_native_1.View style={bundleStyles.versionPill}>
|
|
1370
|
+
<react_native_1.Text style={bundleStyles.versionPillText}>
|
|
1371
|
+
v{pkg.version.replace(/^\^/, '')}
|
|
1372
|
+
</react_native_1.Text>
|
|
1373
|
+
</react_native_1.View>
|
|
1374
|
+
</react_native_1.View>
|
|
1375
|
+
</react_native_1.View>
|
|
1376
|
+
|
|
1377
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
1378
|
+
<react_native_1.View style={bundleStyles.fileSizeBox}>
|
|
1379
|
+
<react_native_1.Text style={bundleStyles.fileSizeKb}>{pkg.sizeKb} KB</react_native_1.Text>
|
|
1380
|
+
<react_native_1.Text style={bundleStyles.filePercent}>{pkg.percentage}%</react_native_1.Text>
|
|
1381
|
+
</react_native_1.View>
|
|
1382
|
+
<CopyButton_1.default value={() => pkg} label="Package Details JSON"/>
|
|
1383
|
+
</react_native_1.View>
|
|
1384
|
+
</react_native_1.View>
|
|
1385
|
+
|
|
1386
|
+
{/* Subtitle Row: Category Chip + Description */}
|
|
1387
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, marginTop: 4, marginBottom: 2 }}>
|
|
1388
|
+
<react_native_1.View style={[bundleStyles.pkgBadge, { backgroundColor: `${pkg.color}1F`, borderColor: `${pkg.color}4D` }]}>
|
|
1389
|
+
<react_native_1.Text style={[bundleStyles.pkgBadgeText, { color: pkg.color }]}>
|
|
1390
|
+
{pkg.category.toUpperCase()}
|
|
1391
|
+
</react_native_1.Text>
|
|
1392
|
+
</react_native_1.View>
|
|
1393
|
+
<react_native_1.Text style={[bundleStyles.filePath, { flex: 1, marginTop: 0 }]} numberOfLines={1}>
|
|
1394
|
+
{pkg.description}
|
|
1395
|
+
</react_native_1.Text>
|
|
1396
|
+
</react_native_1.View>
|
|
1397
|
+
|
|
1398
|
+
<react_native_1.View style={bundleStyles.fileProgressTrack}>
|
|
1399
|
+
<react_native_1.View style={[
|
|
1400
|
+
bundleStyles.fileProgressBar,
|
|
1401
|
+
{ width: `${pkg.percentage * 2}%`, backgroundColor: pkg.color },
|
|
1402
|
+
]}/>
|
|
1403
|
+
</react_native_1.View>
|
|
1404
|
+
|
|
1405
|
+
<react_native_1.View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginTop: 2 }}>
|
|
1406
|
+
<react_native_1.View style={bundleStyles.typeTag}>
|
|
1407
|
+
<react_native_1.Text style={bundleStyles.typeTagText}>
|
|
1408
|
+
{pkg.type === 'direct' ? '📦 Direct Dependency' : '🔗 Transitive Peer'}
|
|
1409
|
+
</react_native_1.Text>
|
|
1410
|
+
</react_native_1.View>
|
|
1411
|
+
<react_native_1.Text style={bundleStyles.fileMetaText}>
|
|
1412
|
+
~{pkg.sizeKb} KB minified
|
|
1413
|
+
</react_native_1.Text>
|
|
1414
|
+
</react_native_1.View>
|
|
1415
|
+
</react_native_1.View>))}
|
|
1416
|
+
</react_native_1.ScrollView>
|
|
1417
|
+
|
|
1418
|
+
{/* Sticky Total Package Size Footer */}
|
|
1419
|
+
<react_native_1.View style={bundleStyles.stickyFooterBar}>
|
|
1420
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
1421
|
+
<NetworkIcons_1.PackageIcon color={AppColors_1.AppColors.purple} size={14}/>
|
|
1422
|
+
<react_native_1.Text style={bundleStyles.footerTitle}>
|
|
1423
|
+
{filteredPackages.length} Dependencies
|
|
1424
|
+
</react_native_1.Text>
|
|
1425
|
+
</react_native_1.View>
|
|
1426
|
+
<react_native_1.Text style={bundleStyles.footerSizeVal}>
|
|
1427
|
+
{packagesTotalKb} KB ({(packagesTotalKb / 1024).toFixed(2)} MB)
|
|
1428
|
+
</react_native_1.Text>
|
|
1429
|
+
</react_native_1.View>
|
|
1430
|
+
</react_native_1.View>)}
|
|
1431
|
+
|
|
1432
|
+
{/* ══════════════════════════════════════════════════════════════════════ */}
|
|
1433
|
+
{/* ── 4. TAB: MEDIA & ASSET AUDITOR ───────────────────────────────────── */}
|
|
1434
|
+
{/* ══════════════════════════════════════════════════════════════════════ */}
|
|
1435
|
+
{activeSubTab === 'media' && (<react_native_1.View style={{ flex: 1 }}>
|
|
1436
|
+
<react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
|
|
1437
|
+
|
|
1438
|
+
<react_native_1.View style={bundleStyles.tipsCard}>
|
|
1439
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 8 }}>
|
|
1440
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
1441
|
+
<NetworkIcons_1.StorageIcon color={AppColors_1.AppColors.purple} size={18}/>
|
|
1442
|
+
<react_native_1.Text style={bundleStyles.tipsHeading}>Media Compression Auditor</react_native_1.Text>
|
|
1443
|
+
</react_native_1.View>
|
|
1444
|
+
<CopyButton_1.default value={() => mediaFiles} label="Media Assets JSON"/>
|
|
1445
|
+
</react_native_1.View>
|
|
1446
|
+
<react_native_1.Text style={bundleStyles.tipDesc}>
|
|
1447
|
+
Images & Fonts constitute <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interBold, color: AppColors_1.AppColors.purple }}>{summary.images.pct + summary.fonts.pct}%</react_native_1.Text> of total assets (~{summary.images.kb + summary.fonts.kb} KB). Converting PNGs to WebP and font subsetting can reduce size by up to <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interBold, color: '#047857' }}>540 KB</react_native_1.Text>.
|
|
1448
|
+
</react_native_1.Text>
|
|
1449
|
+
</react_native_1.View>
|
|
1450
|
+
|
|
1451
|
+
<react_native_1.Text style={bundleStyles.listHeaderCount}>
|
|
1452
|
+
Media Assets & Fonts ({mediaFiles.length} items)
|
|
1453
|
+
</react_native_1.Text>
|
|
1454
|
+
|
|
1455
|
+
{mediaFiles.map((file, index) => (<react_native_1.View key={file.id} style={bundleStyles.fileCard}>
|
|
1456
|
+
<react_native_1.View style={bundleStyles.fileCardTop}>
|
|
1457
|
+
<react_native_1.View style={bundleStyles.sNoBadge}>
|
|
1458
|
+
<react_native_1.Text style={bundleStyles.sNoText}>#{index + 1}</react_native_1.Text>
|
|
1459
|
+
</react_native_1.View>
|
|
1460
|
+
|
|
1461
|
+
<MediaPreviewThumbnail file={file}/>
|
|
1462
|
+
|
|
1463
|
+
<react_native_1.View style={{ flex: 1 }}>
|
|
1464
|
+
<react_native_1.Text style={bundleStyles.fileName}>{file.name}</react_native_1.Text>
|
|
1465
|
+
<react_native_1.Text style={bundleStyles.filePath}>{file.path}</react_native_1.Text>
|
|
1466
|
+
</react_native_1.View>
|
|
1467
|
+
|
|
1468
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
1469
|
+
<react_native_1.View style={bundleStyles.fileSizeBox}>
|
|
1470
|
+
<react_native_1.Text style={bundleStyles.fileSizeKb}>{file.sizeKb} KB</react_native_1.Text>
|
|
1471
|
+
</react_native_1.View>
|
|
1472
|
+
<CopyButton_1.default value={() => file} label="Media Item JSON"/>
|
|
1473
|
+
</react_native_1.View>
|
|
1474
|
+
</react_native_1.View>
|
|
1475
|
+
|
|
1476
|
+
<react_native_1.View style={bundleStyles.fileCardBottom}>
|
|
1477
|
+
<react_native_1.Text style={bundleStyles.fileMetaText}>{file.meta}</react_native_1.Text>
|
|
1478
|
+
{file.advice && (<react_native_1.View style={[
|
|
1479
|
+
bundleStyles.adviceBadge,
|
|
1480
|
+
file.status === 'warning' && bundleStyles.adviceWarning,
|
|
1481
|
+
file.status === 'optimal' && bundleStyles.adviceOptimal,
|
|
1482
|
+
]}>
|
|
1483
|
+
<react_native_1.Text style={[
|
|
1484
|
+
bundleStyles.adviceText,
|
|
1485
|
+
file.status === 'warning' && { color: '#B45309' },
|
|
1486
|
+
file.status === 'optimal' && { color: '#047857' },
|
|
1487
|
+
]}>
|
|
1488
|
+
{file.status === 'warning' ? '💡 ' : '✨ '}
|
|
1489
|
+
{file.advice}
|
|
1490
|
+
</react_native_1.Text>
|
|
1491
|
+
</react_native_1.View>)}
|
|
1492
|
+
</react_native_1.View>
|
|
1493
|
+
</react_native_1.View>))}
|
|
1494
|
+
</react_native_1.ScrollView>
|
|
1495
|
+
|
|
1496
|
+
{/* Sticky Total Media Size Footer */}
|
|
1497
|
+
<react_native_1.View style={bundleStyles.stickyFooterBar}>
|
|
1498
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
1499
|
+
<NetworkIcons_1.StorageIcon color={AppColors_1.AppColors.purple} size={14}/>
|
|
1500
|
+
<react_native_1.Text style={bundleStyles.footerTitle}>
|
|
1501
|
+
{mediaFiles.length} Media & Fonts
|
|
1502
|
+
</react_native_1.Text>
|
|
1503
|
+
</react_native_1.View>
|
|
1504
|
+
<react_native_1.Text style={bundleStyles.footerSizeVal}>
|
|
1505
|
+
{mediaTotalKb} KB ({(mediaTotalKb / 1024).toFixed(2)} MB)
|
|
1506
|
+
</react_native_1.Text>
|
|
1507
|
+
</react_native_1.View>
|
|
1508
|
+
</react_native_1.View>)}
|
|
1509
|
+
|
|
1510
|
+
{/* ══════════════════════════════════════════════════════════════════════ */}
|
|
1511
|
+
{/* ── 5. TAB: OPTIMIZER CHECKLIST ─────────────────────────────────────── */}
|
|
1512
|
+
{/* ══════════════════════════════════════════════════════════════════════ */}
|
|
1513
|
+
{activeSubTab === 'optimizer' && (<react_native_1.ScrollView style={{ flex: 1 }} contentContainerStyle={bundleStyles.contentContainer} keyboardShouldPersistTaps="handled">
|
|
1514
|
+
|
|
1515
|
+
<react_native_1.View style={bundleStyles.tipsCard}>
|
|
1516
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
|
|
1517
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
1518
|
+
<NetworkIcons_1.CircleAlertIcon color={AppColors_1.AppColors.purple} size={18}/>
|
|
1519
|
+
<react_native_1.Text style={bundleStyles.tipsHeading}>React Native Bundle Optimization Checklist</react_native_1.Text>
|
|
1520
|
+
</react_native_1.View>
|
|
1521
|
+
<CopyButton_1.default value={() => [
|
|
1522
|
+
'Convert Heavy PNGs to WebP / SVGs (High Impact)',
|
|
1523
|
+
`Enable Hermes Bytecode Engine (${isHermes ? 'Active' : 'Action Required'})`,
|
|
1524
|
+
'Font Subsetting & Weight Pruning (Medium Impact)',
|
|
1525
|
+
'Selective Path Imports Tree-shaking (Best Practice)',
|
|
1526
|
+
'Screen Lazy-Loading (Best Practice)',
|
|
1527
|
+
]} label="Optimization Checklist"/>
|
|
1528
|
+
</react_native_1.View>
|
|
1529
|
+
|
|
1530
|
+
{[
|
|
1531
|
+
{
|
|
1532
|
+
title: '🖼️ Convert Heavy PNGs to WebP / SVGs',
|
|
1533
|
+
desc: 'Images account for >40% of final app download size. Converting 2x/3x raster PNGs to WebP saves 60-70% size with no visible fidelity loss.',
|
|
1534
|
+
badge: 'High Impact',
|
|
1535
|
+
badgeColor: '#EC4899',
|
|
1536
|
+
},
|
|
1537
|
+
{
|
|
1538
|
+
title: '📜 Enable Hermes Bytecode Engine',
|
|
1539
|
+
desc: isHermes
|
|
1540
|
+
? '✅ Hermes is active! JavaScript is compiled into optimized bytecode Ahead-Of-Time.'
|
|
1541
|
+
: '⚠️ Hermes is disabled. Enable hermes in your app config for ~40% smaller payload and instant TTI startup.',
|
|
1542
|
+
badge: isHermes ? 'Active' : 'Action Required',
|
|
1543
|
+
badgeColor: isHermes ? '#10B981' : '#F59E0B',
|
|
1544
|
+
},
|
|
1545
|
+
{
|
|
1546
|
+
title: '🔤 Font Subsetting & Weight Pruning',
|
|
1547
|
+
desc: 'Include only the font weights you actively use (e.g. Regular & Bold). Remove unused glyph ranges to save 100KB+ per font file.',
|
|
1548
|
+
badge: 'Medium Impact',
|
|
1549
|
+
badgeColor: '#8B5CF6',
|
|
1550
|
+
},
|
|
1551
|
+
{
|
|
1552
|
+
title: '🌲 Selective Path Imports (Tree-shaking)',
|
|
1553
|
+
desc: 'Import from specific subpaths (e.g. lodash/get or specific vector icon sets) instead of importing large monolithic packages.',
|
|
1554
|
+
badge: 'Best Practice',
|
|
1555
|
+
badgeColor: '#0EA5E9',
|
|
1556
|
+
},
|
|
1557
|
+
{
|
|
1558
|
+
title: '⚡ Screen Lazy-Loading',
|
|
1559
|
+
desc: 'Lazy load secondary screens and heavy modal sheets using dynamic imports and InteractionManager to reduce initial bundle evaluation.',
|
|
1560
|
+
badge: 'Best Practice',
|
|
1561
|
+
badgeColor: '#6366F1',
|
|
1562
|
+
},
|
|
1563
|
+
].map((tip, tIdx) => (<react_native_1.View key={tIdx} style={bundleStyles.tipItem}>
|
|
1564
|
+
<react_native_1.View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 2 }}>
|
|
1565
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flex: 1 }}>
|
|
1566
|
+
<react_native_1.View style={bundleStyles.sNoBadge}>
|
|
1567
|
+
<react_native_1.Text style={bundleStyles.sNoText}>#{tIdx + 1}</react_native_1.Text>
|
|
1568
|
+
</react_native_1.View>
|
|
1569
|
+
<react_native_1.Text style={bundleStyles.tipTitle}>{tip.title}</react_native_1.Text>
|
|
1570
|
+
</react_native_1.View>
|
|
1571
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
|
1572
|
+
<react_native_1.View style={[bundleStyles.impactBadge, { backgroundColor: `${tip.badgeColor}1F`, borderColor: `${tip.badgeColor}4D` }]}>
|
|
1573
|
+
<react_native_1.Text style={[bundleStyles.impactBadgeText, { color: tip.badgeColor }]}>
|
|
1574
|
+
{tip.badge}
|
|
1575
|
+
</react_native_1.Text>
|
|
1576
|
+
</react_native_1.View>
|
|
1577
|
+
<CopyButton_1.default value={() => tip} label="Tip Details"/>
|
|
1578
|
+
</react_native_1.View>
|
|
1579
|
+
</react_native_1.View>
|
|
1580
|
+
<react_native_1.Text style={bundleStyles.tipDesc}>{tip.desc}</react_native_1.Text>
|
|
1581
|
+
</react_native_1.View>))}
|
|
1582
|
+
</react_native_1.View>
|
|
1583
|
+
</react_native_1.ScrollView>)}
|
|
1584
|
+
</react_native_1.View>);
|
|
1585
|
+
});
|
|
1586
|
+
const bundleStyles = react_native_1.StyleSheet.create({
|
|
1587
|
+
topTabWrap: {
|
|
1588
|
+
backgroundColor: AppColors_1.AppColors.white,
|
|
1589
|
+
paddingVertical: 8,
|
|
1590
|
+
borderBottomWidth: 1,
|
|
1591
|
+
borderBottomColor: AppColors_1.AppColors.dividerColor,
|
|
1592
|
+
},
|
|
1593
|
+
subTabsScroll: {
|
|
1594
|
+
paddingHorizontal: 12,
|
|
1595
|
+
gap: 8,
|
|
1596
|
+
flexDirection: 'row',
|
|
1597
|
+
alignItems: 'center',
|
|
1598
|
+
},
|
|
1599
|
+
subTabPill: {
|
|
1600
|
+
flexDirection: 'row',
|
|
1601
|
+
alignItems: 'center',
|
|
1602
|
+
gap: 6,
|
|
1603
|
+
paddingHorizontal: 12,
|
|
1604
|
+
paddingVertical: 7,
|
|
1605
|
+
borderRadius: 20,
|
|
1606
|
+
backgroundColor: AppColors_1.AppColors.grayBackground,
|
|
1607
|
+
borderWidth: 1,
|
|
1608
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1609
|
+
},
|
|
1610
|
+
subTabPillActive: {
|
|
1611
|
+
backgroundColor: AppColors_1.AppColors.brandPurple,
|
|
1612
|
+
borderColor: AppColors_1.AppColors.brandPurple,
|
|
1613
|
+
shadowColor: AppColors_1.AppColors.brandPurple,
|
|
1614
|
+
shadowOffset: { width: 0, height: 2 },
|
|
1615
|
+
shadowOpacity: 0.2,
|
|
1616
|
+
shadowRadius: 3,
|
|
1617
|
+
elevation: 2,
|
|
1618
|
+
},
|
|
1619
|
+
subTabPillText: {
|
|
1620
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
1621
|
+
fontSize: 11.5,
|
|
1622
|
+
color: AppColors_1.AppColors.grayTextStrong,
|
|
1623
|
+
},
|
|
1624
|
+
subTabPillTextActive: {
|
|
1625
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1626
|
+
color: AppColors_1.AppColors.white,
|
|
1627
|
+
},
|
|
1628
|
+
contentContainer: {
|
|
1629
|
+
padding: 16,
|
|
1630
|
+
paddingBottom: 40,
|
|
1631
|
+
gap: 14,
|
|
1632
|
+
},
|
|
1633
|
+
heroCard: {
|
|
1634
|
+
backgroundColor: AppColors_1.AppColors.white,
|
|
1635
|
+
borderRadius: 14,
|
|
1636
|
+
padding: 16,
|
|
1637
|
+
borderWidth: 1,
|
|
1638
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1639
|
+
shadowColor: AppColors_1.AppColors.primaryBlack,
|
|
1640
|
+
shadowOffset: { width: 0, height: 2 },
|
|
1641
|
+
shadowOpacity: 0.04,
|
|
1642
|
+
shadowRadius: 6,
|
|
1643
|
+
elevation: 2,
|
|
1644
|
+
},
|
|
1645
|
+
heroTopRow: {
|
|
1646
|
+
flexDirection: 'row',
|
|
1647
|
+
alignItems: 'center',
|
|
1648
|
+
gap: 12,
|
|
1649
|
+
marginBottom: 16,
|
|
1650
|
+
},
|
|
1651
|
+
heroIconWrap: {
|
|
1652
|
+
width: 44,
|
|
1653
|
+
height: 44,
|
|
1654
|
+
borderRadius: 12,
|
|
1655
|
+
backgroundColor: `${AppColors_1.AppColors.brandPurple}12`,
|
|
1656
|
+
alignItems: 'center',
|
|
1657
|
+
justifyContent: 'center',
|
|
1658
|
+
borderWidth: 1,
|
|
1659
|
+
borderColor: `${AppColors_1.AppColors.brandPurple}25`,
|
|
1660
|
+
},
|
|
1661
|
+
heroTitle: {
|
|
1662
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1663
|
+
fontSize: 16,
|
|
1664
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
1665
|
+
},
|
|
1666
|
+
heroSubtitle: {
|
|
1667
|
+
fontFamily: AppFonts_1.AppFonts.interRegular,
|
|
1668
|
+
fontSize: 12,
|
|
1669
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
1670
|
+
marginTop: 2,
|
|
1671
|
+
},
|
|
1672
|
+
metricsGrid: {
|
|
1673
|
+
flexDirection: 'row',
|
|
1674
|
+
flexWrap: 'wrap',
|
|
1675
|
+
gap: 8,
|
|
1676
|
+
},
|
|
1677
|
+
metricBox: {
|
|
1678
|
+
flex: 1,
|
|
1679
|
+
minWidth: '45%',
|
|
1680
|
+
backgroundColor: AppColors_1.AppColors.grayBackground,
|
|
1681
|
+
borderRadius: 10,
|
|
1682
|
+
padding: 10,
|
|
1683
|
+
borderWidth: 1,
|
|
1684
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1685
|
+
},
|
|
1686
|
+
metricLabel: {
|
|
1687
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1688
|
+
fontSize: 9.5,
|
|
1689
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
1690
|
+
letterSpacing: 0.5,
|
|
1691
|
+
},
|
|
1692
|
+
metricValue: {
|
|
1693
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1694
|
+
fontSize: 14,
|
|
1695
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
1696
|
+
marginTop: 3,
|
|
1697
|
+
},
|
|
1698
|
+
metricHint: {
|
|
1699
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
1700
|
+
fontSize: 10.5,
|
|
1701
|
+
color: AppColors_1.AppColors.grayText,
|
|
1702
|
+
marginTop: 2,
|
|
1703
|
+
},
|
|
1704
|
+
statusIndicator: {
|
|
1705
|
+
width: 8,
|
|
1706
|
+
height: 8,
|
|
1707
|
+
borderRadius: 4,
|
|
1708
|
+
},
|
|
1709
|
+
sectionCard: {
|
|
1710
|
+
backgroundColor: AppColors_1.AppColors.white,
|
|
1711
|
+
borderRadius: 14,
|
|
1712
|
+
padding: 14,
|
|
1713
|
+
borderWidth: 1,
|
|
1714
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1715
|
+
},
|
|
1716
|
+
sectionHeaderRow: {
|
|
1717
|
+
flexDirection: 'row',
|
|
1718
|
+
justifyContent: 'space-between',
|
|
1719
|
+
alignItems: 'center',
|
|
1720
|
+
marginBottom: 10,
|
|
1721
|
+
},
|
|
1722
|
+
sectionTitle: {
|
|
1723
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1724
|
+
fontSize: 13,
|
|
1725
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
1726
|
+
},
|
|
1727
|
+
sectionSub: {
|
|
1728
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
1729
|
+
fontSize: 11,
|
|
1730
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
1731
|
+
},
|
|
1732
|
+
treemapBar: {
|
|
1733
|
+
flexDirection: 'row',
|
|
1734
|
+
borderRadius: 6,
|
|
1735
|
+
overflow: 'hidden',
|
|
1736
|
+
height: 16,
|
|
1737
|
+
marginBottom: 12,
|
|
1738
|
+
backgroundColor: AppColors_1.AppColors.slate200,
|
|
1739
|
+
},
|
|
1740
|
+
legendGrid: {
|
|
1741
|
+
flexDirection: 'row',
|
|
1742
|
+
flexWrap: 'wrap',
|
|
1743
|
+
gap: 10,
|
|
1744
|
+
},
|
|
1745
|
+
legendItem: {
|
|
1746
|
+
flexDirection: 'row',
|
|
1747
|
+
alignItems: 'center',
|
|
1748
|
+
gap: 5,
|
|
1749
|
+
minWidth: '45%',
|
|
1750
|
+
},
|
|
1751
|
+
legendDot: {
|
|
1752
|
+
width: 8,
|
|
1753
|
+
height: 8,
|
|
1754
|
+
borderRadius: 4,
|
|
1755
|
+
},
|
|
1756
|
+
legendText: {
|
|
1757
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
1758
|
+
fontSize: 11,
|
|
1759
|
+
color: AppColors_1.AppColors.grayTextStrong,
|
|
1760
|
+
},
|
|
1761
|
+
legendVal: {
|
|
1762
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1763
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
1764
|
+
},
|
|
1765
|
+
catRowCard: {
|
|
1766
|
+
backgroundColor: AppColors_1.AppColors.grayBackground,
|
|
1767
|
+
borderRadius: 10,
|
|
1768
|
+
padding: 10,
|
|
1769
|
+
marginBottom: 8,
|
|
1770
|
+
borderWidth: 1,
|
|
1771
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1772
|
+
},
|
|
1773
|
+
catRowTop: {
|
|
1774
|
+
flexDirection: 'row',
|
|
1775
|
+
alignItems: 'center',
|
|
1776
|
+
gap: 8,
|
|
1777
|
+
marginBottom: 8,
|
|
1778
|
+
},
|
|
1779
|
+
catRowIcon: {
|
|
1780
|
+
fontSize: 16,
|
|
1781
|
+
},
|
|
1782
|
+
catRowTitle: {
|
|
1783
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1784
|
+
fontSize: 12,
|
|
1785
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
1786
|
+
},
|
|
1787
|
+
catRowDesc: {
|
|
1788
|
+
fontFamily: AppFonts_1.AppFonts.interRegular,
|
|
1789
|
+
fontSize: 10,
|
|
1790
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
1791
|
+
},
|
|
1792
|
+
catRowSize: {
|
|
1793
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1794
|
+
fontSize: 12,
|
|
1795
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
1796
|
+
},
|
|
1797
|
+
catRowPct: {
|
|
1798
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
1799
|
+
fontSize: 10,
|
|
1800
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
1801
|
+
},
|
|
1802
|
+
catProgressTrack: {
|
|
1803
|
+
height: 4,
|
|
1804
|
+
borderRadius: 2,
|
|
1805
|
+
backgroundColor: `${AppColors_1.AppColors.slate200}`,
|
|
1806
|
+
overflow: 'hidden',
|
|
1807
|
+
},
|
|
1808
|
+
catProgressBar: {
|
|
1809
|
+
height: '100%',
|
|
1810
|
+
borderRadius: 2,
|
|
1811
|
+
},
|
|
1812
|
+
filterContainer: {
|
|
1813
|
+
backgroundColor: AppColors_1.AppColors.white,
|
|
1814
|
+
borderRadius: 12,
|
|
1815
|
+
padding: 10,
|
|
1816
|
+
marginHorizontal: 16,
|
|
1817
|
+
marginTop: 12,
|
|
1818
|
+
borderWidth: 1,
|
|
1819
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1820
|
+
gap: 8,
|
|
1821
|
+
},
|
|
1822
|
+
searchRow: {
|
|
1823
|
+
flexDirection: 'row',
|
|
1824
|
+
alignItems: 'center',
|
|
1825
|
+
backgroundColor: AppColors_1.AppColors.grayBackground,
|
|
1826
|
+
borderRadius: 8,
|
|
1827
|
+
paddingHorizontal: 10,
|
|
1828
|
+
height: 36,
|
|
1829
|
+
gap: 8,
|
|
1830
|
+
},
|
|
1831
|
+
searchInput: {
|
|
1832
|
+
flex: 1,
|
|
1833
|
+
fontFamily: AppFonts_1.AppFonts.interRegular,
|
|
1834
|
+
fontSize: 12,
|
|
1835
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
1836
|
+
padding: 0,
|
|
1837
|
+
},
|
|
1838
|
+
categoryPillsScroll: {
|
|
1839
|
+
gap: 6,
|
|
1840
|
+
paddingVertical: 2,
|
|
1841
|
+
},
|
|
1842
|
+
catPill: {
|
|
1843
|
+
flexDirection: 'row',
|
|
1844
|
+
alignItems: 'center',
|
|
1845
|
+
gap: 4,
|
|
1846
|
+
paddingHorizontal: 10,
|
|
1847
|
+
paddingVertical: 5,
|
|
1848
|
+
borderRadius: 16,
|
|
1849
|
+
backgroundColor: AppColors_1.AppColors.grayBackground,
|
|
1850
|
+
borderWidth: 1,
|
|
1851
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1852
|
+
},
|
|
1853
|
+
catPillActive: {
|
|
1854
|
+
backgroundColor: AppColors_1.AppColors.brandPurple,
|
|
1855
|
+
borderColor: AppColors_1.AppColors.brandPurple,
|
|
1856
|
+
},
|
|
1857
|
+
catPillIcon: {
|
|
1858
|
+
fontSize: 11,
|
|
1859
|
+
},
|
|
1860
|
+
catPillText: {
|
|
1861
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
1862
|
+
fontSize: 11,
|
|
1863
|
+
color: AppColors_1.AppColors.grayTextStrong,
|
|
1864
|
+
},
|
|
1865
|
+
catPillTextActive: {
|
|
1866
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1867
|
+
color: AppColors_1.AppColors.white,
|
|
1868
|
+
},
|
|
1869
|
+
listHeaderCount: {
|
|
1870
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
1871
|
+
fontSize: 11,
|
|
1872
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
1873
|
+
paddingHorizontal: 4,
|
|
1874
|
+
},
|
|
1875
|
+
treeHeaderRow: {
|
|
1876
|
+
flexDirection: 'row',
|
|
1877
|
+
alignItems: 'center',
|
|
1878
|
+
justifyContent: 'space-between',
|
|
1879
|
+
paddingHorizontal: 2,
|
|
1880
|
+
marginBottom: 6,
|
|
1881
|
+
},
|
|
1882
|
+
viewModeToggleGroup: {
|
|
1883
|
+
flexDirection: 'row',
|
|
1884
|
+
backgroundColor: AppColors_1.AppColors.grayBackground,
|
|
1885
|
+
borderRadius: 8,
|
|
1886
|
+
padding: 2,
|
|
1887
|
+
borderWidth: 1,
|
|
1888
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1889
|
+
},
|
|
1890
|
+
viewModeBtn: {
|
|
1891
|
+
paddingHorizontal: 10,
|
|
1892
|
+
paddingVertical: 5,
|
|
1893
|
+
borderRadius: 6,
|
|
1894
|
+
},
|
|
1895
|
+
viewModeBtnActive: {
|
|
1896
|
+
backgroundColor: AppColors_1.AppColors.brandPurple,
|
|
1897
|
+
shadowColor: AppColors_1.AppColors.brandPurple,
|
|
1898
|
+
shadowOffset: { width: 0, height: 1 },
|
|
1899
|
+
shadowOpacity: 0.2,
|
|
1900
|
+
shadowRadius: 2,
|
|
1901
|
+
elevation: 2,
|
|
1902
|
+
},
|
|
1903
|
+
viewModeBtnText: {
|
|
1904
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
1905
|
+
fontSize: 11,
|
|
1906
|
+
color: AppColors_1.AppColors.grayTextStrong,
|
|
1907
|
+
},
|
|
1908
|
+
viewModeBtnTextActive: {
|
|
1909
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1910
|
+
color: AppColors_1.AppColors.white,
|
|
1911
|
+
},
|
|
1912
|
+
treeActionLink: {
|
|
1913
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1914
|
+
fontSize: 11.5,
|
|
1915
|
+
color: AppColors_1.AppColors.purple,
|
|
1916
|
+
},
|
|
1917
|
+
treeRootContainer: {
|
|
1918
|
+
gap: 6,
|
|
1919
|
+
},
|
|
1920
|
+
treeFolderContainer: {
|
|
1921
|
+
backgroundColor: AppColors_1.AppColors.white,
|
|
1922
|
+
borderRadius: 10,
|
|
1923
|
+
borderWidth: 1,
|
|
1924
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1925
|
+
overflow: 'hidden',
|
|
1926
|
+
marginBottom: 6,
|
|
1927
|
+
},
|
|
1928
|
+
treeFolderHeader: {
|
|
1929
|
+
flexDirection: 'row',
|
|
1930
|
+
alignItems: 'center',
|
|
1931
|
+
justifyContent: 'space-between',
|
|
1932
|
+
paddingVertical: 10,
|
|
1933
|
+
paddingRight: 10,
|
|
1934
|
+
backgroundColor: `${AppColors_1.AppColors.purple}08`,
|
|
1935
|
+
borderBottomWidth: 1,
|
|
1936
|
+
borderBottomColor: `${AppColors_1.AppColors.purple}14`,
|
|
1937
|
+
},
|
|
1938
|
+
treeFolderChevron: {
|
|
1939
|
+
fontSize: 11,
|
|
1940
|
+
color: AppColors_1.AppColors.purple,
|
|
1941
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1942
|
+
width: 14,
|
|
1943
|
+
},
|
|
1944
|
+
treeFolderName: {
|
|
1945
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1946
|
+
fontSize: 12.5,
|
|
1947
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
1948
|
+
},
|
|
1949
|
+
treeCountBadge: {
|
|
1950
|
+
paddingHorizontal: 6,
|
|
1951
|
+
paddingVertical: 1.5,
|
|
1952
|
+
borderRadius: 4,
|
|
1953
|
+
backgroundColor: `${AppColors_1.AppColors.purple}1A`,
|
|
1954
|
+
},
|
|
1955
|
+
treeCountBadgeText: {
|
|
1956
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
1957
|
+
fontSize: 10,
|
|
1958
|
+
color: AppColors_1.AppColors.purple,
|
|
1959
|
+
},
|
|
1960
|
+
treeFolderSize: {
|
|
1961
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
1962
|
+
fontSize: 11.5,
|
|
1963
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
1964
|
+
},
|
|
1965
|
+
treeChildrenWrap: {
|
|
1966
|
+
borderLeftColor: `${AppColors_1.AppColors.purple}26`,
|
|
1967
|
+
paddingVertical: 6,
|
|
1968
|
+
paddingRight: 8,
|
|
1969
|
+
gap: 4,
|
|
1970
|
+
},
|
|
1971
|
+
treeFileCard: {
|
|
1972
|
+
backgroundColor: AppColors_1.AppColors.white,
|
|
1973
|
+
borderRadius: 8,
|
|
1974
|
+
paddingVertical: 8,
|
|
1975
|
+
paddingHorizontal: 8,
|
|
1976
|
+
borderWidth: 1,
|
|
1977
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1978
|
+
marginBottom: 4,
|
|
1979
|
+
},
|
|
1980
|
+
treeBranchGlyph: {
|
|
1981
|
+
width: 18,
|
|
1982
|
+
alignItems: 'center',
|
|
1983
|
+
justifyContent: 'center',
|
|
1984
|
+
},
|
|
1985
|
+
treeBranchGlyphText: {
|
|
1986
|
+
fontFamily: AppFonts_1.AppFonts.interRegular,
|
|
1987
|
+
fontSize: 11,
|
|
1988
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
1989
|
+
},
|
|
1990
|
+
fileCard: {
|
|
1991
|
+
backgroundColor: AppColors_1.AppColors.white,
|
|
1992
|
+
borderRadius: 12,
|
|
1993
|
+
padding: 12,
|
|
1994
|
+
borderWidth: 1,
|
|
1995
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
1996
|
+
gap: 6,
|
|
1997
|
+
marginBottom: 8,
|
|
1998
|
+
},
|
|
1999
|
+
fileCardTop: {
|
|
2000
|
+
flexDirection: 'row',
|
|
2001
|
+
alignItems: 'center',
|
|
2002
|
+
gap: 8,
|
|
2003
|
+
},
|
|
2004
|
+
sNoBadge: {
|
|
2005
|
+
paddingHorizontal: 6,
|
|
2006
|
+
paddingVertical: 2,
|
|
2007
|
+
borderRadius: 4,
|
|
2008
|
+
backgroundColor: `${AppColors_1.AppColors.purple}14`,
|
|
2009
|
+
borderWidth: 1,
|
|
2010
|
+
borderColor: `${AppColors_1.AppColors.purple}30`,
|
|
2011
|
+
minWidth: 26,
|
|
2012
|
+
alignItems: 'center',
|
|
2013
|
+
justifyContent: 'center',
|
|
2014
|
+
},
|
|
2015
|
+
sNoText: {
|
|
2016
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2017
|
+
fontSize: 10,
|
|
2018
|
+
color: AppColors_1.AppColors.purple,
|
|
2019
|
+
},
|
|
2020
|
+
extChip: {
|
|
2021
|
+
paddingHorizontal: 6,
|
|
2022
|
+
paddingVertical: 3,
|
|
2023
|
+
borderRadius: 5,
|
|
2024
|
+
borderWidth: 1,
|
|
2025
|
+
},
|
|
2026
|
+
extChipText: {
|
|
2027
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2028
|
+
fontSize: 10,
|
|
2029
|
+
letterSpacing: 0.4,
|
|
2030
|
+
},
|
|
2031
|
+
pkgBadge: {
|
|
2032
|
+
paddingHorizontal: 6,
|
|
2033
|
+
paddingVertical: 3,
|
|
2034
|
+
borderRadius: 5,
|
|
2035
|
+
borderWidth: 1,
|
|
2036
|
+
},
|
|
2037
|
+
pkgBadgeText: {
|
|
2038
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2039
|
+
fontSize: 9,
|
|
2040
|
+
letterSpacing: 0.4,
|
|
2041
|
+
},
|
|
2042
|
+
pkgLogoWrap: {
|
|
2043
|
+
borderRadius: 7,
|
|
2044
|
+
borderWidth: 1,
|
|
2045
|
+
alignItems: 'center',
|
|
2046
|
+
justifyContent: 'center',
|
|
2047
|
+
backgroundColor: AppColors_1.AppColors.white,
|
|
2048
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
2049
|
+
overflow: 'hidden',
|
|
2050
|
+
},
|
|
2051
|
+
pkgLogoFallbackText: {
|
|
2052
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2053
|
+
},
|
|
2054
|
+
mediaThumbWrap: {
|
|
2055
|
+
width: 32,
|
|
2056
|
+
height: 32,
|
|
2057
|
+
borderRadius: 6,
|
|
2058
|
+
overflow: 'hidden',
|
|
2059
|
+
backgroundColor: AppColors_1.AppColors.grayBackground,
|
|
2060
|
+
borderWidth: 1,
|
|
2061
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
2062
|
+
},
|
|
2063
|
+
mediaThumbImg: {
|
|
2064
|
+
width: '100%',
|
|
2065
|
+
height: '100%',
|
|
2066
|
+
},
|
|
2067
|
+
fileName: {
|
|
2068
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2069
|
+
fontSize: 12.5,
|
|
2070
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
2071
|
+
},
|
|
2072
|
+
versionPill: {
|
|
2073
|
+
paddingHorizontal: 5,
|
|
2074
|
+
paddingVertical: 1,
|
|
2075
|
+
borderRadius: 4,
|
|
2076
|
+
backgroundColor: `${AppColors_1.AppColors.purple}14`,
|
|
2077
|
+
borderWidth: 1,
|
|
2078
|
+
borderColor: `${AppColors_1.AppColors.purple}26`,
|
|
2079
|
+
},
|
|
2080
|
+
versionPillText: {
|
|
2081
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
2082
|
+
fontSize: 10,
|
|
2083
|
+
color: AppColors_1.AppColors.purple,
|
|
2084
|
+
},
|
|
2085
|
+
pkgVersion: {
|
|
2086
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
2087
|
+
fontSize: 11,
|
|
2088
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
2089
|
+
},
|
|
2090
|
+
filePath: {
|
|
2091
|
+
fontFamily: AppFonts_1.AppFonts.interRegular,
|
|
2092
|
+
fontSize: 10.5,
|
|
2093
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
2094
|
+
marginTop: 1,
|
|
2095
|
+
},
|
|
2096
|
+
fileSizeBox: {
|
|
2097
|
+
alignItems: 'flex-end',
|
|
2098
|
+
},
|
|
2099
|
+
fileSizeKb: {
|
|
2100
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2101
|
+
fontSize: 12,
|
|
2102
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
2103
|
+
},
|
|
2104
|
+
filePercent: {
|
|
2105
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
2106
|
+
fontSize: 10,
|
|
2107
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
2108
|
+
},
|
|
2109
|
+
fileProgressTrack: {
|
|
2110
|
+
height: 4,
|
|
2111
|
+
borderRadius: 2,
|
|
2112
|
+
backgroundColor: AppColors_1.AppColors.grayBackground,
|
|
2113
|
+
overflow: 'hidden',
|
|
2114
|
+
marginVertical: 2,
|
|
2115
|
+
},
|
|
2116
|
+
fileProgressBar: {
|
|
2117
|
+
height: '100%',
|
|
2118
|
+
borderRadius: 2,
|
|
2119
|
+
},
|
|
2120
|
+
fileCardBottom: {
|
|
2121
|
+
gap: 4,
|
|
2122
|
+
},
|
|
2123
|
+
fileMetaText: {
|
|
2124
|
+
fontFamily: AppFonts_1.AppFonts.interRegular,
|
|
2125
|
+
fontSize: 10.5,
|
|
2126
|
+
color: AppColors_1.AppColors.grayTextWeak,
|
|
2127
|
+
},
|
|
2128
|
+
typeTag: {
|
|
2129
|
+
backgroundColor: AppColors_1.AppColors.grayBackground,
|
|
2130
|
+
paddingHorizontal: 6,
|
|
2131
|
+
paddingVertical: 2,
|
|
2132
|
+
borderRadius: 4,
|
|
2133
|
+
borderWidth: 1,
|
|
2134
|
+
borderColor: AppColors_1.AppColors.dividerColor,
|
|
2135
|
+
},
|
|
2136
|
+
typeTagText: {
|
|
2137
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
2138
|
+
fontSize: 9.5,
|
|
2139
|
+
color: AppColors_1.AppColors.grayText,
|
|
2140
|
+
},
|
|
2141
|
+
unusedBadge: {
|
|
2142
|
+
paddingHorizontal: 6,
|
|
2143
|
+
paddingVertical: 1.5,
|
|
2144
|
+
borderRadius: 4,
|
|
2145
|
+
backgroundColor: '#FEE2E2',
|
|
2146
|
+
borderWidth: 1,
|
|
2147
|
+
borderColor: '#FECACA',
|
|
2148
|
+
},
|
|
2149
|
+
unusedBadgeText: {
|
|
2150
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2151
|
+
fontSize: 9.5,
|
|
2152
|
+
color: '#DC2626',
|
|
2153
|
+
},
|
|
2154
|
+
consumedBadge: {
|
|
2155
|
+
paddingHorizontal: 6,
|
|
2156
|
+
paddingVertical: 1.5,
|
|
2157
|
+
borderRadius: 4,
|
|
2158
|
+
backgroundColor: '#DCFCE7',
|
|
2159
|
+
borderWidth: 1,
|
|
2160
|
+
borderColor: '#BBF7D0',
|
|
2161
|
+
},
|
|
2162
|
+
consumedBadgeText: {
|
|
2163
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2164
|
+
fontSize: 9.5,
|
|
2165
|
+
color: '#059669',
|
|
2166
|
+
},
|
|
2167
|
+
treeFolderChevronWrap: {
|
|
2168
|
+
width: 18,
|
|
2169
|
+
height: 18,
|
|
2170
|
+
borderRadius: 9,
|
|
2171
|
+
backgroundColor: `${AppColors_1.AppColors.purple}14`,
|
|
2172
|
+
alignItems: 'center',
|
|
2173
|
+
justifyContent: 'center',
|
|
2174
|
+
},
|
|
2175
|
+
treeFileCardUnused: {
|
|
2176
|
+
borderColor: '#FECACA',
|
|
2177
|
+
backgroundColor: '#FFFBFB',
|
|
2178
|
+
},
|
|
2179
|
+
adviceUnused: {
|
|
2180
|
+
backgroundColor: '#FEF2F2',
|
|
2181
|
+
borderWidth: 1,
|
|
2182
|
+
borderColor: '#FECACA',
|
|
2183
|
+
},
|
|
2184
|
+
adviceBadge: {
|
|
2185
|
+
paddingHorizontal: 8,
|
|
2186
|
+
paddingVertical: 4,
|
|
2187
|
+
borderRadius: 6,
|
|
2188
|
+
marginTop: 2,
|
|
2189
|
+
},
|
|
2190
|
+
adviceWarning: {
|
|
2191
|
+
backgroundColor: '#FEF3C7',
|
|
2192
|
+
borderWidth: 1,
|
|
2193
|
+
borderColor: '#FDE68A',
|
|
2194
|
+
},
|
|
2195
|
+
adviceOptimal: {
|
|
2196
|
+
backgroundColor: '#DCFCE7',
|
|
2197
|
+
borderWidth: 1,
|
|
2198
|
+
borderColor: '#BBF7D0',
|
|
2199
|
+
},
|
|
2200
|
+
adviceText: {
|
|
2201
|
+
fontFamily: AppFonts_1.AppFonts.interMedium,
|
|
2202
|
+
fontSize: 10.5,
|
|
2203
|
+
lineHeight: 14,
|
|
2204
|
+
},
|
|
2205
|
+
impactBadge: {
|
|
2206
|
+
paddingHorizontal: 6,
|
|
2207
|
+
paddingVertical: 2,
|
|
2208
|
+
borderRadius: 4,
|
|
2209
|
+
borderWidth: 1,
|
|
2210
|
+
},
|
|
2211
|
+
impactBadgeText: {
|
|
2212
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2213
|
+
fontSize: 9,
|
|
2214
|
+
},
|
|
2215
|
+
searchHighlight: {
|
|
2216
|
+
backgroundColor: '#FEF08A',
|
|
2217
|
+
color: '#854D0E',
|
|
2218
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2219
|
+
},
|
|
2220
|
+
tipsCard: {
|
|
2221
|
+
backgroundColor: '#FAF5FF',
|
|
2222
|
+
borderRadius: 14,
|
|
2223
|
+
padding: 14,
|
|
2224
|
+
borderWidth: 1,
|
|
2225
|
+
borderColor: '#E9D5FF',
|
|
2226
|
+
},
|
|
2227
|
+
tipsHeading: {
|
|
2228
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2229
|
+
fontSize: 13.5,
|
|
2230
|
+
color: '#6B21A8',
|
|
2231
|
+
},
|
|
2232
|
+
totalSummaryCard: {
|
|
2233
|
+
marginTop: 10,
|
|
2234
|
+
backgroundColor: `${AppColors_1.AppColors.purple}0D`,
|
|
2235
|
+
borderRadius: 10,
|
|
2236
|
+
padding: 12,
|
|
2237
|
+
borderWidth: 1,
|
|
2238
|
+
borderColor: `${AppColors_1.AppColors.purple}26`,
|
|
2239
|
+
gap: 4,
|
|
2240
|
+
},
|
|
2241
|
+
totalSummaryRow: {
|
|
2242
|
+
flexDirection: 'row',
|
|
2243
|
+
justifyContent: 'space-between',
|
|
2244
|
+
alignItems: 'center',
|
|
2245
|
+
},
|
|
2246
|
+
totalSummaryLabel: {
|
|
2247
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2248
|
+
fontSize: 11,
|
|
2249
|
+
color: AppColors_1.AppColors.purple,
|
|
2250
|
+
letterSpacing: 0.5,
|
|
2251
|
+
},
|
|
2252
|
+
totalSummaryValue: {
|
|
2253
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2254
|
+
fontSize: 13,
|
|
2255
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
2256
|
+
},
|
|
2257
|
+
totalSummaryFormula: {
|
|
2258
|
+
fontFamily: AppFonts_1.AppFonts.interRegular,
|
|
2259
|
+
fontSize: 10.5,
|
|
2260
|
+
color: AppColors_1.AppColors.grayText,
|
|
2261
|
+
lineHeight: 15,
|
|
2262
|
+
},
|
|
2263
|
+
stickyFooterBar: {
|
|
2264
|
+
flexDirection: 'row',
|
|
2265
|
+
justifyContent: 'space-between',
|
|
2266
|
+
alignItems: 'center',
|
|
2267
|
+
backgroundColor: AppColors_1.AppColors.white,
|
|
2268
|
+
paddingHorizontal: 16,
|
|
2269
|
+
paddingVertical: 10,
|
|
2270
|
+
borderTopWidth: 1,
|
|
2271
|
+
borderTopColor: AppColors_1.AppColors.dividerColor,
|
|
2272
|
+
shadowColor: AppColors_1.AppColors.primaryBlack,
|
|
2273
|
+
shadowOffset: { width: 0, height: -2 },
|
|
2274
|
+
shadowOpacity: 0.05,
|
|
2275
|
+
shadowRadius: 4,
|
|
2276
|
+
elevation: 3,
|
|
2277
|
+
},
|
|
2278
|
+
footerTitle: {
|
|
2279
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2280
|
+
fontSize: 12,
|
|
2281
|
+
color: AppColors_1.AppColors.primaryBlack,
|
|
2282
|
+
},
|
|
2283
|
+
footerSizeVal: {
|
|
2284
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2285
|
+
fontSize: 12.5,
|
|
2286
|
+
color: AppColors_1.AppColors.purple,
|
|
2287
|
+
},
|
|
2288
|
+
tipItem: {
|
|
2289
|
+
marginBottom: 12,
|
|
2290
|
+
backgroundColor: AppColors_1.AppColors.white,
|
|
2291
|
+
padding: 10,
|
|
2292
|
+
borderRadius: 8,
|
|
2293
|
+
borderWidth: 1,
|
|
2294
|
+
borderColor: '#E9D5FF',
|
|
2295
|
+
},
|
|
2296
|
+
tipTitle: {
|
|
2297
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2298
|
+
fontSize: 12,
|
|
2299
|
+
color: '#581C87',
|
|
2300
|
+
},
|
|
2301
|
+
tipDesc: {
|
|
2302
|
+
fontFamily: AppFonts_1.AppFonts.interRegular,
|
|
2303
|
+
fontSize: 11,
|
|
2304
|
+
color: '#6B7280',
|
|
2305
|
+
lineHeight: 16,
|
|
2306
|
+
marginTop: 4,
|
|
2307
|
+
},
|
|
2308
|
+
});
|
|
2309
|
+
exports.default = BundleTab;
|