lynx-console 0.2.1 → 0.2.3
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/dist/index.cjs +615 -120
- package/dist/index.css +0 -397
- package/dist/index.css.map +1 -1
- package/dist/index.mjs +616 -121
- package/dist/index.mjs.map +1 -1
- package/dist/setup.cjs +0 -1
- package/dist/setup.d.cts +0 -1
- package/dist/setup.d.cts.map +1 -1
- package/dist/setup.d.mts +0 -1
- package/dist/setup.d.mts.map +1 -1
- package/dist/setup.mjs +0 -1
- package/dist/setup.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/BottomSheet.css +0 -7
- package/src/components/BottomSheet.tsx +24 -3
- package/src/components/ConsolePanel.css +0 -141
- package/src/components/FloatingButton.css +0 -8
- package/src/components/FloatingButton.tsx +15 -2
- package/src/components/LogPanel.tsx +214 -26
- package/src/components/NetworkDetailSection.tsx +71 -9
- package/src/components/NetworkPanel.css +0 -91
- package/src/components/NetworkPanel.tsx +168 -20
- package/src/components/PerformancePanel.css +0 -60
- package/src/components/PerformancePanel.tsx +157 -35
- package/src/components/Tabs.css +0 -9
- package/src/components/Tabs.tsx +21 -3
- package/src/index.tsx +29 -23
- package/src/styles/ThemeContext.ts +10 -0
- package/src/styles/theme.ts +111 -0
- package/src/styles/global.css +0 -8
- package/src/styles/vars/color.ts +0 -41
- package/src/styles/vars/dimension.ts +0 -10
- package/src/styles/vars/index.css +0 -71
- package/src/styles/vars/index.ts +0 -18
- package/src/styles/vars/radius.ts +0 -2
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,104 @@
|
|
|
1
1
|
import "./index.css";
|
|
2
|
-
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "@lynx-js/react";
|
|
2
|
+
import { createContext, forwardRef, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from "@lynx-js/react";
|
|
3
3
|
import { stringify } from "javascript-stringify";
|
|
4
4
|
|
|
5
|
+
//#region src/styles/theme.ts
|
|
6
|
+
const colorMap = {
|
|
7
|
+
light: {
|
|
8
|
+
palette: {
|
|
9
|
+
blue100: "#eff6ff",
|
|
10
|
+
blue600: "#5e98fe",
|
|
11
|
+
gray100: "#f7f8f9",
|
|
12
|
+
gray400: "#dcdee3",
|
|
13
|
+
green100: "#edfaf6",
|
|
14
|
+
green600: "#10ab7d",
|
|
15
|
+
purple100: "#f5f3fe",
|
|
16
|
+
purple600: "#9f84fb",
|
|
17
|
+
red100: "#fdf0f0",
|
|
18
|
+
red600: "#fc6a66",
|
|
19
|
+
red900: "#921708",
|
|
20
|
+
staticWhite: "#ffffff",
|
|
21
|
+
yellow100: "#fff7de",
|
|
22
|
+
yellow600: "#c49725",
|
|
23
|
+
yellow900: "#4f3e1f"
|
|
24
|
+
},
|
|
25
|
+
fg: {
|
|
26
|
+
neutral: "#1a1c20",
|
|
27
|
+
placeholder: "#b0b3ba",
|
|
28
|
+
disabled: "#d1d3d8",
|
|
29
|
+
neutralMuted: "#555d6d",
|
|
30
|
+
neutralSubtle: "#868b94"
|
|
31
|
+
},
|
|
32
|
+
bg: {
|
|
33
|
+
overlay: "#00000074",
|
|
34
|
+
layerDefault: "#ffffff",
|
|
35
|
+
layerFloating: "#ffffff",
|
|
36
|
+
neutralWeak: "#f3f4f5"
|
|
37
|
+
},
|
|
38
|
+
stroke: {
|
|
39
|
+
neutralSubtle: "#0000000c",
|
|
40
|
+
neutralWeak: "#dcdee3"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
dark: {
|
|
44
|
+
palette: {
|
|
45
|
+
blue100: "#202742",
|
|
46
|
+
blue600: "#1e82eb",
|
|
47
|
+
gray100: "#16171b",
|
|
48
|
+
gray400: "#393d46",
|
|
49
|
+
green100: "#202926",
|
|
50
|
+
green600: "#1b946d",
|
|
51
|
+
purple100: "#28213b",
|
|
52
|
+
purple600: "#8e6bee",
|
|
53
|
+
red100: "#322323",
|
|
54
|
+
red600: "#f73526",
|
|
55
|
+
red900: "#f8c5c3",
|
|
56
|
+
staticWhite: "#ffffff",
|
|
57
|
+
yellow100: "#302819",
|
|
58
|
+
yellow600: "#b6720d",
|
|
59
|
+
yellow900: "#e5d49b"
|
|
60
|
+
},
|
|
61
|
+
fg: {
|
|
62
|
+
neutral: "#f3f4f5",
|
|
63
|
+
placeholder: "#868b94",
|
|
64
|
+
disabled: "#5b606a",
|
|
65
|
+
neutralMuted: "#dcdee3",
|
|
66
|
+
neutralSubtle: "#b0b3ba"
|
|
67
|
+
},
|
|
68
|
+
bg: {
|
|
69
|
+
overlay: "#00000074",
|
|
70
|
+
layerDefault: "#16171b",
|
|
71
|
+
layerFloating: "#1d2025",
|
|
72
|
+
neutralWeak: "#2b2e35"
|
|
73
|
+
},
|
|
74
|
+
stroke: {
|
|
75
|
+
neutralSubtle: "#ffffff0d",
|
|
76
|
+
neutralWeak: "#393d46"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const fontWeight = {
|
|
81
|
+
regular: "400",
|
|
82
|
+
medium: "500",
|
|
83
|
+
bold: "700"
|
|
84
|
+
};
|
|
85
|
+
const duration = {
|
|
86
|
+
d4: "200ms",
|
|
87
|
+
d6: "300ms"
|
|
88
|
+
};
|
|
89
|
+
function getColors(theme) {
|
|
90
|
+
return colorMap[theme];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/styles/ThemeContext.ts
|
|
95
|
+
const ThemeContext = createContext(getColors("light"));
|
|
96
|
+
const ThemeProvider = ThemeContext.Provider;
|
|
97
|
+
function useThemeColors() {
|
|
98
|
+
return useContext(ThemeContext);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
5
102
|
//#region src/components/BottomSheet.tsx
|
|
6
103
|
const MIN_HEIGHT = 200;
|
|
7
104
|
const MAX_HEIGHT = 700;
|
|
@@ -9,6 +106,7 @@ const DEFAULT_HEIGHT = 500;
|
|
|
9
106
|
const CLOSE_DRAG_THRESHOLD = 30;
|
|
10
107
|
let savedHeight = null;
|
|
11
108
|
function BottomSheet({ children, title, footer, onClose, isOpen, shouldClose = false, safeAreaInsetBottom = "25px" }) {
|
|
109
|
+
const colors = useThemeColors();
|
|
12
110
|
const [sheetHeight, setSheetHeight] = useState(savedHeight ?? DEFAULT_HEIGHT);
|
|
13
111
|
const [tempHeight, setTempHeight] = useState(savedHeight ?? DEFAULT_HEIGHT);
|
|
14
112
|
const [isDragging, setIsDragging] = useState(false);
|
|
@@ -51,19 +149,29 @@ function BottomSheet({ children, title, footer, onClose, isOpen, shouldClose = f
|
|
|
51
149
|
setSheetHeight(tempHeight);
|
|
52
150
|
if (dragDistance > CLOSE_DRAG_THRESHOLD) handleClose();
|
|
53
151
|
};
|
|
54
|
-
return <scroll-view className="bs-backdrop" style={{
|
|
152
|
+
return <scroll-view className="bs-backdrop" style={{
|
|
153
|
+
background: colors.bg.overlay,
|
|
154
|
+
opacity: isOpening || isClosing ? 0 : 1,
|
|
155
|
+
transition: `opacity ${duration.d6} cubic-bezier(0.4, 0, 0.2, 1)`
|
|
156
|
+
}}>
|
|
55
157
|
<view className="bs-overlay" bindtap={handleClose}>
|
|
56
158
|
<view className="bs-content" catchtap={() => {}} style={{
|
|
159
|
+
background: colors.bg.layerFloating,
|
|
57
160
|
height: `${isDragging ? tempHeight : sheetHeight}px`,
|
|
58
161
|
transform: isOpening || isClosing ? "translateY(100%)" : "translateY(0)",
|
|
59
|
-
transition: isDragging ? "none" :
|
|
162
|
+
transition: isDragging ? "none" : `transform ${duration.d6} cubic-bezier(0.4, 0, 0.2, 1)`
|
|
60
163
|
}}>
|
|
61
164
|
{}
|
|
62
165
|
<view className="bs-handleContainer" bindtouchstart={handleTouchStart} bindtouchmove={handleTouchMove} bindtouchend={handleTouchEnd}>
|
|
63
|
-
<view className="bs-handle" />
|
|
166
|
+
<view className="bs-handle" style={{ backgroundColor: colors.palette.gray400 }} />
|
|
64
167
|
</view>
|
|
65
168
|
<view className="bs-header">
|
|
66
|
-
{title && <text className="bs-title"
|
|
169
|
+
{title && <text className="bs-title" style={{
|
|
170
|
+
fontWeight: fontWeight.bold,
|
|
171
|
+
color: colors.fg.neutral
|
|
172
|
+
}}>
|
|
173
|
+
{title}
|
|
174
|
+
</text>}
|
|
67
175
|
</view>
|
|
68
176
|
<view className="bs-body" style={{ paddingBottom: safeAreaInsetBottom }}>
|
|
69
177
|
{children}
|
|
@@ -193,7 +301,37 @@ const runCode = (code) => {
|
|
|
193
301
|
console.error(e);
|
|
194
302
|
}
|
|
195
303
|
};
|
|
304
|
+
function getLevelColor(colors, level) {
|
|
305
|
+
switch (level) {
|
|
306
|
+
case "log": return colors.palette.green600;
|
|
307
|
+
case "info": return colors.palette.blue600;
|
|
308
|
+
case "warn": return colors.palette.yellow600;
|
|
309
|
+
case "error": return colors.palette.red600;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function getLogItemBg(colors, level) {
|
|
313
|
+
switch (level) {
|
|
314
|
+
case "warn": return colors.palette.yellow100;
|
|
315
|
+
case "error": return colors.palette.red100;
|
|
316
|
+
default: return;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function getStringColor(colors, level) {
|
|
320
|
+
switch (level) {
|
|
321
|
+
case "warn": return colors.palette.yellow900;
|
|
322
|
+
case "error": return colors.palette.red900;
|
|
323
|
+
default: return colors.fg.neutral;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function getPrimitiveColor(colors, level) {
|
|
327
|
+
switch (level) {
|
|
328
|
+
case "warn": return colors.palette.yellow900;
|
|
329
|
+
case "error": return colors.palette.red900;
|
|
330
|
+
default: return colors.palette.blue600;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
196
333
|
const LogPanel = ({ logs, clearLogs }) => {
|
|
334
|
+
const colors = useThemeColors();
|
|
197
335
|
const [expandedArgs, setExpandedArgs] = useState(/* @__PURE__ */ new Set());
|
|
198
336
|
const [code, setCode] = useState("");
|
|
199
337
|
const [enabledLevels, setEnabledLevels] = useState(() => savedEnabledLevels ?? new Set(LOG_LEVELS));
|
|
@@ -277,23 +415,51 @@ const LogPanel = ({ logs, clearLogs }) => {
|
|
|
277
415
|
const renderArg = (arg, parentKey, level) => {
|
|
278
416
|
const key = parentKey;
|
|
279
417
|
const isExpanded = expandedArgs.has(key);
|
|
280
|
-
if (arg === null) return <text
|
|
281
|
-
|
|
418
|
+
if (arg === null) return <text style={{
|
|
419
|
+
color: colors.fg.neutralSubtle,
|
|
420
|
+
fontWeight: fontWeight.regular
|
|
421
|
+
}}>
|
|
422
|
+
null
|
|
423
|
+
</text>;
|
|
424
|
+
if (arg === void 0) return <text style={{
|
|
425
|
+
color: colors.fg.neutralSubtle,
|
|
426
|
+
fontWeight: fontWeight.regular
|
|
427
|
+
}}>
|
|
428
|
+
undefined
|
|
429
|
+
</text>;
|
|
282
430
|
if (typeof arg === "string") {
|
|
283
431
|
const MAX_LENGTH = 80;
|
|
284
|
-
|
|
432
|
+
const shouldTruncate = arg.length > MAX_LENGTH;
|
|
433
|
+
const strColor = getStringColor(colors, level);
|
|
434
|
+
if (!shouldTruncate) return <text className={"cp-argString"} style={{
|
|
435
|
+
color: strColor,
|
|
436
|
+
fontWeight: fontWeight.regular
|
|
437
|
+
}}>
|
|
438
|
+
{arg}
|
|
439
|
+
</text>;
|
|
285
440
|
return <view className={"cp-argObject"}>
|
|
286
441
|
<view className={"cp-argObjectHeader"} bindtap={() => toggleArg(key)}>
|
|
287
|
-
<text className={"cp-toggleIndicator"}
|
|
442
|
+
<text className={"cp-toggleIndicator"} style={{
|
|
443
|
+
color: colors.fg.neutralSubtle,
|
|
444
|
+
fontWeight: fontWeight.regular
|
|
445
|
+
}}>
|
|
288
446
|
{isExpanded ? "▼" : "▶"}
|
|
289
447
|
</text>
|
|
290
|
-
<text className={
|
|
448
|
+
<text className={"cp-argString"} style={{
|
|
449
|
+
color: strColor,
|
|
450
|
+
fontWeight: fontWeight.regular
|
|
451
|
+
}}>
|
|
291
452
|
{isExpanded ? arg : `${arg.slice(0, MAX_LENGTH)}...`}
|
|
292
453
|
</text>
|
|
293
454
|
</view>
|
|
294
455
|
</view>;
|
|
295
456
|
}
|
|
296
|
-
if (typeof arg === "number" || typeof arg === "boolean") return <text className={
|
|
457
|
+
if (typeof arg === "number" || typeof arg === "boolean") return <text className={"cp-argPrimitive"} style={{
|
|
458
|
+
color: getPrimitiveColor(colors, level),
|
|
459
|
+
fontWeight: fontWeight.regular
|
|
460
|
+
}}>
|
|
461
|
+
{String(arg)}
|
|
462
|
+
</text>;
|
|
297
463
|
if (typeof arg === "object") {
|
|
298
464
|
let preview = "Object";
|
|
299
465
|
if (Array.isArray(arg)) preview = `Array(${arg.length})`;
|
|
@@ -309,40 +475,81 @@ const LogPanel = ({ logs, clearLogs }) => {
|
|
|
309
475
|
else jsonString = stringify(arg, null, 2, { references: true }) ?? String(arg);
|
|
310
476
|
return <view className={"cp-argObject"}>
|
|
311
477
|
<view className={"cp-argObjectHeader"} bindtap={() => toggleArg(key)}>
|
|
312
|
-
<text className={"cp-toggleIndicator"}
|
|
478
|
+
<text className={"cp-toggleIndicator"} style={{
|
|
479
|
+
color: colors.fg.neutralSubtle,
|
|
480
|
+
fontWeight: fontWeight.regular
|
|
481
|
+
}}>
|
|
313
482
|
{isExpanded ? "▼" : "▶"}
|
|
314
483
|
</text>
|
|
315
|
-
<text className={"cp-argObjectPreview"}
|
|
484
|
+
<text className={"cp-argObjectPreview"} style={{
|
|
485
|
+
fontWeight: fontWeight.medium,
|
|
486
|
+
color: colors.fg.neutral
|
|
487
|
+
}}>
|
|
488
|
+
{preview}
|
|
489
|
+
</text>
|
|
316
490
|
</view>
|
|
317
491
|
{isExpanded && <view className={"cp-argObjectContent"}>
|
|
318
|
-
<text className={"cp-argObjectJson"}
|
|
492
|
+
<text className={"cp-argObjectJson"} style={{
|
|
493
|
+
fontWeight: fontWeight.regular,
|
|
494
|
+
color: colors.fg.neutral
|
|
495
|
+
}}>
|
|
496
|
+
{jsonString}
|
|
497
|
+
</text>
|
|
319
498
|
</view>}
|
|
320
499
|
</view>;
|
|
321
500
|
}
|
|
322
|
-
return <text className={
|
|
501
|
+
return <text className={"cp-argPrimitive"} style={{
|
|
502
|
+
color: getPrimitiveColor(colors, level),
|
|
503
|
+
fontWeight: fontWeight.regular
|
|
504
|
+
}}>
|
|
505
|
+
{String(arg)}
|
|
506
|
+
</text>;
|
|
323
507
|
};
|
|
324
508
|
return <view className={"cp-logContainer"} bindtap={() => {
|
|
325
509
|
if (filterOpen) setFilterOpen(false);
|
|
326
510
|
}}>
|
|
327
511
|
<view className={"cp-logHeader"}>
|
|
328
512
|
<view className={"cp-filterWrapper"}>
|
|
329
|
-
<view className={"cp-filterButton"} catchtap={() => setFilterOpen((v) => !v)}>
|
|
330
|
-
<text className={"cp-filterButtonText"}
|
|
513
|
+
<view className={"cp-filterButton"} style={{ backgroundColor: colors.bg.neutralWeak }} catchtap={() => setFilterOpen((v) => !v)}>
|
|
514
|
+
<text className={"cp-filterButtonText"} style={{
|
|
515
|
+
fontWeight: fontWeight.medium,
|
|
516
|
+
color: colors.fg.neutralMuted
|
|
517
|
+
}}>
|
|
518
|
+
Filter ▼
|
|
519
|
+
</text>
|
|
331
520
|
</view>
|
|
332
|
-
{filterOpen && <view className={"cp-filterDropdown"}
|
|
521
|
+
{filterOpen && <view className={"cp-filterDropdown"} style={{
|
|
522
|
+
backgroundColor: colors.bg.layerFloating,
|
|
523
|
+
borderColor: colors.stroke.neutralSubtle
|
|
524
|
+
}} catchtap={() => {}}>
|
|
333
525
|
{LOG_LEVELS.map((level) => <view key={level} className={"cp-filterOption"} bindtap={() => toggleLevel(level)}>
|
|
334
|
-
<text className={
|
|
526
|
+
<text className={"cp-filterCheckbox"} style={{
|
|
527
|
+
fontWeight: fontWeight.medium,
|
|
528
|
+
color: getLevelColor(colors, level)
|
|
529
|
+
}}>
|
|
335
530
|
{enabledLevels.has(level) ? "✅" : "⬜"}
|
|
336
531
|
</text>
|
|
337
|
-
<text className={
|
|
532
|
+
<text className={"cp-filterLabel"} style={{
|
|
533
|
+
fontWeight: fontWeight.medium,
|
|
534
|
+
color: getLevelColor(colors, level)
|
|
535
|
+
}}>
|
|
338
536
|
{level.toUpperCase()}
|
|
339
537
|
</text>
|
|
340
538
|
</view>)}
|
|
341
539
|
</view>}
|
|
342
540
|
</view>
|
|
343
|
-
<view className={"cp-searchWrapper"}>
|
|
344
|
-
<text className={"cp-searchPrompt"}
|
|
345
|
-
|
|
541
|
+
<view className={"cp-searchWrapper"} style={{ borderBottomColor: colors.stroke.neutralSubtle }}>
|
|
542
|
+
<text className={"cp-searchPrompt"} style={{
|
|
543
|
+
fontWeight: fontWeight.medium,
|
|
544
|
+
color: colors.fg.placeholder
|
|
545
|
+
}}>
|
|
546
|
+
{"›"}
|
|
547
|
+
</text>
|
|
548
|
+
<input ref={searchInputRef} className={"cp-searchInput"} style={{
|
|
549
|
+
fontWeight: fontWeight.regular,
|
|
550
|
+
color: colors.fg.neutral,
|
|
551
|
+
caretColor: colors.palette.green600
|
|
552
|
+
}} placeholder="Search logs..." bindinput={(e) => setSearchQuery(e.detail.value)} />
|
|
346
553
|
{searchQuery.length > 0 && <view className={"cp-searchClear"} bindtap={() => {
|
|
347
554
|
setSearchQuery("");
|
|
348
555
|
searchInputRef.current?.invoke({
|
|
@@ -350,7 +557,12 @@ const LogPanel = ({ logs, clearLogs }) => {
|
|
|
350
557
|
params: { value: "" }
|
|
351
558
|
}).exec();
|
|
352
559
|
}}>
|
|
353
|
-
<text className={"cp-searchClearText"}
|
|
560
|
+
<text className={"cp-searchClearText"} style={{
|
|
561
|
+
fontWeight: fontWeight.medium,
|
|
562
|
+
color: colors.fg.placeholder
|
|
563
|
+
}}>
|
|
564
|
+
✕
|
|
565
|
+
</text>
|
|
354
566
|
</view>}
|
|
355
567
|
</view>
|
|
356
568
|
<view style={{
|
|
@@ -358,31 +570,48 @@ const LogPanel = ({ logs, clearLogs }) => {
|
|
|
358
570
|
flexDirection: "row",
|
|
359
571
|
gap: 8
|
|
360
572
|
}}>
|
|
361
|
-
<view className={"cp-clearButton"} bindtap={clearLogs}>
|
|
362
|
-
<text className={"cp-clearButtonText"}
|
|
573
|
+
<view className={"cp-clearButton"} style={{ backgroundColor: colors.bg.neutralWeak }} bindtap={clearLogs}>
|
|
574
|
+
<text className={"cp-clearButtonText"} style={{
|
|
575
|
+
fontWeight: fontWeight.medium,
|
|
576
|
+
color: colors.fg.neutralMuted
|
|
577
|
+
}}>
|
|
578
|
+
🗑
|
|
579
|
+
</text>
|
|
363
580
|
</view>
|
|
364
581
|
</view>
|
|
365
582
|
</view>
|
|
366
583
|
<FadeList listRef={listRef} className={"cp-logList"} preload-buffer-count={10} initial-scroll-index={Math.max(0, filteredLogs.length - 1)}>
|
|
367
584
|
{filteredLogs.length === 0 ? <list-item item-key="empty-state">
|
|
368
585
|
<view className={"cp-placeholder"}>
|
|
369
|
-
<text className={"cp-placeholderText"}
|
|
586
|
+
<text className={"cp-placeholderText"} style={{
|
|
587
|
+
fontWeight: fontWeight.regular,
|
|
588
|
+
color: colors.fg.disabled
|
|
589
|
+
}}>
|
|
370
590
|
No logs yet. Try console.log("Hello!")
|
|
371
591
|
</text>
|
|
372
592
|
</view>
|
|
373
593
|
</list-item> : filteredLogs.map((log) => {
|
|
374
594
|
return <list-item key={log.id} item-key={log.id}>
|
|
375
|
-
<view className={
|
|
595
|
+
<view className={"cp-logItem"} style={{
|
|
596
|
+
backgroundColor: getLogItemBg(colors, log.level),
|
|
597
|
+
borderBottomColor: colors.stroke.neutralWeak
|
|
598
|
+
}}>
|
|
376
599
|
<view className={"cp-logItemHeader"}>
|
|
377
|
-
<text className={
|
|
600
|
+
<text className={"cp-logLevel"} style={{
|
|
601
|
+
fontWeight: fontWeight.bold,
|
|
602
|
+
color: getLevelColor(colors, log.level)
|
|
603
|
+
}}>
|
|
378
604
|
{log.level.toUpperCase()}
|
|
379
605
|
</text>
|
|
380
|
-
<text className={"cp-logTime"}
|
|
606
|
+
<text className={"cp-logTime"} style={{
|
|
607
|
+
fontWeight: fontWeight.regular,
|
|
608
|
+
color: colors.fg.neutralSubtle
|
|
609
|
+
}}>
|
|
381
610
|
{new Date(log.timestamp).toISOString()}
|
|
382
611
|
</text>
|
|
383
612
|
</view>
|
|
384
613
|
<view className={"cp-logArgsContainer"}>
|
|
385
|
-
{log.args.map((arg, index) => <view key={`${log.id}-${index.toString()}`} className={"cp-logArgItem"}>
|
|
614
|
+
{log.args.map((arg, index) => <view key={`${log.id}-${index.toString()}`} className={"cp-logArgItem"} style={{ fontWeight: fontWeight.regular }}>
|
|
386
615
|
{renderArg(arg, `${log.id}-${index.toString()}`, log.level)}
|
|
387
616
|
</view>)}
|
|
388
617
|
</view>
|
|
@@ -391,10 +620,24 @@ const LogPanel = ({ logs, clearLogs }) => {
|
|
|
391
620
|
})}
|
|
392
621
|
</FadeList>
|
|
393
622
|
<view className={"cp-replInputRow"}>
|
|
394
|
-
<text className={"cp-replPrompt"}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
623
|
+
<text className={"cp-replPrompt"} style={{
|
|
624
|
+
fontWeight: fontWeight.medium,
|
|
625
|
+
color: colors.fg.placeholder
|
|
626
|
+
}}>
|
|
627
|
+
{"›"}
|
|
628
|
+
</text>
|
|
629
|
+
<input ref={inputRef} className={"cp-replInput"} style={{
|
|
630
|
+
fontWeight: fontWeight.regular,
|
|
631
|
+
color: colors.fg.neutral,
|
|
632
|
+
caretColor: colors.palette.green600
|
|
633
|
+
}} placeholder="enter code..." bindinput={(e) => setCode(e.detail.value)} bindconfirm={handleRun} />
|
|
634
|
+
<view className={"cp-replRunButton"} style={{ backgroundColor: colors.palette.green100 }} bindtap={handleRun}>
|
|
635
|
+
<text className={"cp-replRunButtonText"} style={{
|
|
636
|
+
fontWeight: fontWeight.medium,
|
|
637
|
+
color: colors.palette.green600
|
|
638
|
+
}}>
|
|
639
|
+
Run
|
|
640
|
+
</text>
|
|
398
641
|
</view>
|
|
399
642
|
</view>
|
|
400
643
|
</view>;
|
|
@@ -403,31 +646,117 @@ const LogPanel = ({ logs, clearLogs }) => {
|
|
|
403
646
|
//#endregion
|
|
404
647
|
//#region src/components/NetworkDetailSection.tsx
|
|
405
648
|
const NetworkDetailSection = ({ headers = {}, body = "", error = "" }) => {
|
|
649
|
+
const colors = useThemeColors();
|
|
406
650
|
return <>
|
|
407
651
|
{}
|
|
408
652
|
<view className={"np-detailSection"}>
|
|
409
|
-
<text className={"np-detailSectionTitle"}
|
|
653
|
+
<text className={"np-detailSectionTitle"} style={{
|
|
654
|
+
fontWeight: fontWeight.bold,
|
|
655
|
+
color: colors.fg.neutral
|
|
656
|
+
}}>
|
|
657
|
+
Headers
|
|
658
|
+
</text>
|
|
410
659
|
{headers && Object.keys(headers).length > 0 ? <view className={"np-table"}>
|
|
411
|
-
{Object.entries(headers).map(([key, value]) => <view key={key} className={"np-tableRow"}>
|
|
412
|
-
<text className={"np-tableKey"}
|
|
413
|
-
|
|
660
|
+
{Object.entries(headers).map(([key, value]) => <view key={key} className={"np-tableRow"} style={{ backgroundColor: colors.bg.neutralWeak }}>
|
|
661
|
+
<text className={"np-tableKey"} style={{
|
|
662
|
+
fontWeight: fontWeight.bold,
|
|
663
|
+
color: colors.fg.neutralSubtle
|
|
664
|
+
}}>
|
|
665
|
+
{key}
|
|
666
|
+
</text>
|
|
667
|
+
<text className={"np-tableValue"} style={{
|
|
668
|
+
fontWeight: fontWeight.regular,
|
|
669
|
+
color: colors.fg.neutral
|
|
670
|
+
}}>
|
|
671
|
+
{value}
|
|
672
|
+
</text>
|
|
414
673
|
</view>)}
|
|
415
|
-
</view> : <text className={"np-emptyText"}
|
|
674
|
+
</view> : <text className={"np-emptyText"} style={{
|
|
675
|
+
fontWeight: fontWeight.regular,
|
|
676
|
+
color: colors.fg.disabled
|
|
677
|
+
}}>
|
|
678
|
+
No headers
|
|
679
|
+
</text>}
|
|
416
680
|
</view>
|
|
417
681
|
|
|
418
682
|
{}
|
|
419
683
|
<view className={"np-detailSection"}>
|
|
420
|
-
<text className={"np-detailSectionTitle"}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
684
|
+
<text className={"np-detailSectionTitle"} style={{
|
|
685
|
+
fontWeight: fontWeight.bold,
|
|
686
|
+
color: colors.fg.neutral
|
|
687
|
+
}}>
|
|
688
|
+
Body
|
|
689
|
+
</text>
|
|
690
|
+
{error && <text className={"np-errorText"} style={{
|
|
691
|
+
fontWeight: fontWeight.regular,
|
|
692
|
+
color: colors.palette.red600,
|
|
693
|
+
backgroundColor: colors.palette.red100
|
|
694
|
+
}}>
|
|
695
|
+
{error}
|
|
696
|
+
</text>}
|
|
697
|
+
{body && <text className={"np-bodyText"} style={{
|
|
698
|
+
fontWeight: fontWeight.regular,
|
|
699
|
+
color: colors.fg.neutral,
|
|
700
|
+
backgroundColor: colors.bg.neutralWeak
|
|
701
|
+
}}>
|
|
702
|
+
{body}
|
|
703
|
+
</text>}
|
|
704
|
+
{!error && !body && <text className={"np-emptyText"} style={{
|
|
705
|
+
fontWeight: fontWeight.regular,
|
|
706
|
+
color: colors.fg.disabled
|
|
707
|
+
}}>
|
|
708
|
+
No body
|
|
709
|
+
</text>}
|
|
424
710
|
</view>
|
|
425
711
|
</>;
|
|
426
712
|
};
|
|
427
713
|
|
|
428
714
|
//#endregion
|
|
429
715
|
//#region src/components/NetworkPanel.tsx
|
|
716
|
+
function getMethodColors(colors, method) {
|
|
717
|
+
switch (method) {
|
|
718
|
+
case "GET": return {
|
|
719
|
+
color: colors.palette.blue600,
|
|
720
|
+
backgroundColor: colors.palette.blue100
|
|
721
|
+
};
|
|
722
|
+
case "POST": return {
|
|
723
|
+
color: colors.palette.green600,
|
|
724
|
+
backgroundColor: colors.palette.green100
|
|
725
|
+
};
|
|
726
|
+
case "PUT": return {
|
|
727
|
+
color: colors.palette.yellow600,
|
|
728
|
+
backgroundColor: colors.palette.yellow100
|
|
729
|
+
};
|
|
730
|
+
case "PATCH": return {
|
|
731
|
+
color: colors.palette.purple600,
|
|
732
|
+
backgroundColor: colors.palette.purple100
|
|
733
|
+
};
|
|
734
|
+
case "DELETE": return {
|
|
735
|
+
color: colors.palette.red600,
|
|
736
|
+
backgroundColor: colors.palette.red100
|
|
737
|
+
};
|
|
738
|
+
default: return {
|
|
739
|
+
color: colors.fg.neutral,
|
|
740
|
+
backgroundColor: colors.bg.neutralWeak
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
function getStatusCodeColor(colors, variant) {
|
|
745
|
+
switch (variant) {
|
|
746
|
+
case "success": return colors.palette.green600;
|
|
747
|
+
case "error": return colors.palette.red600;
|
|
748
|
+
case "pending": return colors.fg.neutralSubtle;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
function getItemBg(colors, status) {
|
|
752
|
+
switch (status) {
|
|
753
|
+
case "pending": return colors.palette.gray100;
|
|
754
|
+
case "error": return colors.palette.red100;
|
|
755
|
+
default: return;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
430
758
|
const NetworkPanel = ({ networks, clearNetworks }) => {
|
|
759
|
+
const colors = useThemeColors();
|
|
431
760
|
const [selectedId, setSelectedId] = useState(null);
|
|
432
761
|
const [activeTab, setActiveTab] = useState("general");
|
|
433
762
|
const formatDuration = (duration) => {
|
|
@@ -476,54 +805,99 @@ const NetworkPanel = ({ networks, clearNetworks }) => {
|
|
|
476
805
|
};
|
|
477
806
|
return <view className={"np-container"}>
|
|
478
807
|
<view className={"np-header"}>
|
|
479
|
-
<text className={"np-count"}
|
|
480
|
-
|
|
481
|
-
|
|
808
|
+
<text className={"np-count"} style={{
|
|
809
|
+
fontWeight: fontWeight.regular,
|
|
810
|
+
color: colors.fg.neutralSubtle
|
|
811
|
+
}}>
|
|
812
|
+
Total: {networks.length} requests
|
|
813
|
+
</text>
|
|
814
|
+
<view className={"np-clearButton"} style={{ backgroundColor: colors.bg.neutralWeak }} bindtap={clearNetworks}>
|
|
815
|
+
<text className={"np-clearButtonText"} style={{
|
|
816
|
+
fontWeight: fontWeight.medium,
|
|
817
|
+
color: colors.fg.neutralMuted
|
|
818
|
+
}}>
|
|
819
|
+
🗑
|
|
820
|
+
</text>
|
|
482
821
|
</view>
|
|
483
822
|
</view>
|
|
484
823
|
|
|
485
824
|
{networks.length === 0 ? <view className={"np-placeholder"}>
|
|
486
|
-
<text className={"np-placeholderText"}
|
|
825
|
+
<text className={"np-placeholderText"} style={{
|
|
826
|
+
fontWeight: fontWeight.regular,
|
|
827
|
+
color: colors.fg.disabled
|
|
828
|
+
}}>
|
|
829
|
+
No network requests yet
|
|
830
|
+
</text>
|
|
487
831
|
</view> : <FadeList className={"np-list"}>
|
|
488
832
|
{networks.map((network) => <list-item key={network.id} item-key={network.id}>
|
|
489
|
-
<view className={
|
|
833
|
+
<view className={"np-item"} style={{
|
|
834
|
+
backgroundColor: getItemBg(colors, network.status),
|
|
835
|
+
borderBottomColor: colors.stroke.neutralWeak
|
|
836
|
+
}}>
|
|
490
837
|
<view className={"np-itemHeader"} bindtap={() => setSelectedId(selectedId === network.id ? null : network.id)}>
|
|
491
|
-
<text className={
|
|
838
|
+
<text className={"np-method"} style={{
|
|
839
|
+
fontWeight: fontWeight.bold,
|
|
840
|
+
...getMethodColors(colors, network.method)
|
|
841
|
+
}}>
|
|
492
842
|
{network.method}
|
|
493
843
|
</text>
|
|
494
|
-
{network.statusCode && <text className={
|
|
844
|
+
{network.statusCode && <text className={"np-statusCode"} style={{
|
|
845
|
+
fontWeight: fontWeight.bold,
|
|
846
|
+
color: getStatusCodeColor(colors, getStatusCodeVariant(network.status, network.statusCode))
|
|
847
|
+
}}>
|
|
495
848
|
{network.statusCode}
|
|
496
849
|
</text>}
|
|
497
|
-
{network.status === "pending" && <text className={"np-statusCode
|
|
850
|
+
{network.status === "pending" && <text className={"np-statusCode"} style={{
|
|
851
|
+
fontWeight: fontWeight.bold,
|
|
852
|
+
color: colors.fg.neutralSubtle
|
|
853
|
+
}}>
|
|
498
854
|
Pending...
|
|
499
855
|
</text>}
|
|
500
|
-
<text className={"np-time"}
|
|
856
|
+
<text className={"np-time"} style={{
|
|
857
|
+
fontWeight: fontWeight.regular,
|
|
858
|
+
color: colors.fg.neutralSubtle
|
|
859
|
+
}}>
|
|
501
860
|
{formatDuration(network.duration)}
|
|
502
861
|
</text>
|
|
503
|
-
<text className={"np-time"}
|
|
862
|
+
<text className={"np-time"} style={{
|
|
863
|
+
fontWeight: fontWeight.regular,
|
|
864
|
+
color: colors.fg.neutralSubtle
|
|
865
|
+
}}>
|
|
504
866
|
{new Date(network.startTime).toISOString()}
|
|
505
867
|
</text>
|
|
506
868
|
</view>
|
|
507
869
|
|
|
508
|
-
<text className={"np-path"}
|
|
870
|
+
<text className={"np-path"} style={{
|
|
871
|
+
fontWeight: fontWeight.regular,
|
|
872
|
+
color: colors.fg.neutral
|
|
873
|
+
}} bindtap={() => setSelectedId(selectedId === network.id ? null : network.id)}>
|
|
509
874
|
{extractPath(network.url)}
|
|
510
875
|
</text>
|
|
511
876
|
|
|
512
|
-
{selectedId === network.id && <view className={"np-detailsContainer"}>
|
|
877
|
+
{selectedId === network.id && <view className={"np-detailsContainer"} style={{ borderTopColor: colors.stroke.neutralSubtle }}>
|
|
513
878
|
{}
|
|
514
879
|
<view className={"np-tabs"}>
|
|
515
|
-
<view className={
|
|
516
|
-
<text className={
|
|
880
|
+
<view className={"np-tab"} style={{ backgroundColor: activeTab === "general" ? colors.bg.neutralWeak : void 0 }} bindtap={() => setActiveTab("general")}>
|
|
881
|
+
<text className={"np-tabText"} style={{
|
|
882
|
+
fontWeight: fontWeight.medium,
|
|
883
|
+
color: activeTab === "general" ? colors.fg.neutral : colors.fg.neutralSubtle
|
|
884
|
+
}}>
|
|
517
885
|
General
|
|
518
886
|
</text>
|
|
519
887
|
</view>
|
|
520
|
-
<view className={
|
|
521
|
-
<text className={
|
|
888
|
+
<view className={"np-tab"} style={{ backgroundColor: activeTab === "request" ? colors.bg.neutralWeak : void 0 }} bindtap={() => setActiveTab("request")}>
|
|
889
|
+
<text className={"np-tabText"} style={{
|
|
890
|
+
fontWeight: fontWeight.medium,
|
|
891
|
+
color: activeTab === "request" ? colors.fg.neutral : colors.fg.neutralSubtle
|
|
892
|
+
}}>
|
|
522
893
|
Request
|
|
523
894
|
</text>
|
|
524
895
|
</view>
|
|
525
|
-
<view className={
|
|
526
|
-
<text className={
|
|
896
|
+
<view className={"np-tab"} style={{ backgroundColor: activeTab === "response" ? colors.bg.neutralWeak : void 0 }} bindtap={() => setActiveTab("response")}>
|
|
897
|
+
<text className={"np-tabText"} style={{
|
|
898
|
+
fontWeight: fontWeight.medium,
|
|
899
|
+
color: activeTab === "response" ? colors.fg.neutral : colors.fg.neutralSubtle
|
|
900
|
+
}}>
|
|
527
901
|
Response
|
|
528
902
|
</text>
|
|
529
903
|
</view>
|
|
@@ -532,9 +906,17 @@ const NetworkPanel = ({ networks, clearNetworks }) => {
|
|
|
532
906
|
{}
|
|
533
907
|
<view className={"np-tabContent"}>
|
|
534
908
|
{activeTab === "general" && <view className={"np-table"}>
|
|
535
|
-
{getGeneralInfo(network).map((item) => <view key={item.key} className={"np-tableRow"}>
|
|
536
|
-
<text className={"np-tableKey"}
|
|
537
|
-
|
|
909
|
+
{getGeneralInfo(network).map((item) => <view key={item.key} className={"np-tableRow"} style={{ backgroundColor: colors.bg.neutralWeak }}>
|
|
910
|
+
<text className={"np-tableKey"} style={{
|
|
911
|
+
fontWeight: fontWeight.bold,
|
|
912
|
+
color: colors.fg.neutralSubtle
|
|
913
|
+
}}>
|
|
914
|
+
{item.key}
|
|
915
|
+
</text>
|
|
916
|
+
<text className={"np-tableValue"} style={{
|
|
917
|
+
fontWeight: fontWeight.regular,
|
|
918
|
+
color: colors.fg.neutral
|
|
919
|
+
}}>
|
|
538
920
|
{item.value}
|
|
539
921
|
</text>
|
|
540
922
|
</view>)}
|
|
@@ -578,34 +960,74 @@ const getPrimaryFcpLabel = (entry) => {
|
|
|
578
960
|
if (fcp?.duration !== void 0) return `fcp: ${formatDuration(fcp.duration)}`;
|
|
579
961
|
return "";
|
|
580
962
|
};
|
|
963
|
+
function getEntryTypeColors(colors, entryType) {
|
|
964
|
+
switch (entryType) {
|
|
965
|
+
case "init": return {
|
|
966
|
+
color: colors.palette.blue600,
|
|
967
|
+
backgroundColor: colors.palette.blue100
|
|
968
|
+
};
|
|
969
|
+
case "metric": return {
|
|
970
|
+
color: colors.palette.green600,
|
|
971
|
+
backgroundColor: colors.palette.green100
|
|
972
|
+
};
|
|
973
|
+
case "pipeline": return {
|
|
974
|
+
color: colors.palette.purple600,
|
|
975
|
+
backgroundColor: colors.palette.purple100
|
|
976
|
+
};
|
|
977
|
+
case "resource": return {
|
|
978
|
+
color: colors.palette.yellow600,
|
|
979
|
+
backgroundColor: colors.palette.yellow100
|
|
980
|
+
};
|
|
981
|
+
default: return {
|
|
982
|
+
color: colors.fg.neutral,
|
|
983
|
+
backgroundColor: colors.bg.neutralWeak
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
}
|
|
581
987
|
const PerformancePanel = ({ performances, clearPerformances }) => {
|
|
988
|
+
const colors = useThemeColors();
|
|
582
989
|
const [selectedId, setSelectedId] = useState(null);
|
|
583
990
|
if (performances.length === 0) return <view className={"pp-container"}>
|
|
584
|
-
<view className={"pp-header"}>
|
|
585
|
-
<text className={"pp-count"}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
}}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
<text
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
991
|
+
<view className={"pp-header"} style={{ borderBottomColor: colors.stroke.neutralSubtle }}>
|
|
992
|
+
<text className={"pp-count"} style={{
|
|
993
|
+
fontWeight: fontWeight.regular,
|
|
994
|
+
color: colors.fg.neutralSubtle
|
|
995
|
+
}}>
|
|
996
|
+
0 entries
|
|
997
|
+
</text>
|
|
998
|
+
<view bindtap={clearPerformances} className={"pp-clearButton"} style={{ backgroundColor: colors.bg.neutralWeak }}>
|
|
999
|
+
<text className={"pp-clearButtonText"} style={{
|
|
1000
|
+
fontWeight: fontWeight.medium,
|
|
1001
|
+
color: colors.fg.neutralMuted
|
|
1002
|
+
}}>
|
|
1003
|
+
🗑
|
|
1004
|
+
</text>
|
|
596
1005
|
</view>
|
|
597
1006
|
</view>
|
|
598
1007
|
<view className={"pp-placeholder"}>
|
|
599
|
-
<text className={"pp-placeholderText"}
|
|
1008
|
+
<text className={"pp-placeholderText"} style={{
|
|
1009
|
+
fontWeight: fontWeight.regular,
|
|
1010
|
+
color: colors.fg.disabled
|
|
1011
|
+
}}>
|
|
600
1012
|
No performance data yet...
|
|
601
1013
|
</text>
|
|
602
1014
|
</view>
|
|
603
1015
|
</view>;
|
|
604
1016
|
return <view className={"pp-container"}>
|
|
605
|
-
<view className={"pp-header"}>
|
|
606
|
-
<text className={"pp-count"}
|
|
607
|
-
|
|
608
|
-
|
|
1017
|
+
<view className={"pp-header"} style={{ borderBottomColor: colors.stroke.neutralSubtle }}>
|
|
1018
|
+
<text className={"pp-count"} style={{
|
|
1019
|
+
fontWeight: fontWeight.regular,
|
|
1020
|
+
color: colors.fg.neutralSubtle
|
|
1021
|
+
}}>
|
|
1022
|
+
{performances.length} entries
|
|
1023
|
+
</text>
|
|
1024
|
+
<view bindtap={clearPerformances} className={"pp-clearButton"} style={{ backgroundColor: colors.bg.neutralWeak }}>
|
|
1025
|
+
<text className={"pp-clearButtonText"} style={{
|
|
1026
|
+
fontWeight: fontWeight.medium,
|
|
1027
|
+
color: colors.fg.neutralMuted
|
|
1028
|
+
}}>
|
|
1029
|
+
🗑
|
|
1030
|
+
</text>
|
|
609
1031
|
</view>
|
|
610
1032
|
</view>
|
|
611
1033
|
|
|
@@ -616,68 +1038,122 @@ const PerformancePanel = ({ performances, clearPerformances }) => {
|
|
|
616
1038
|
const primaryFcp = getPrimaryFcpLabel(perf);
|
|
617
1039
|
const { totalFcp, lynxFcp, fcp } = fcpMetrics ?? {};
|
|
618
1040
|
return <list-item key={perf.id} item-key={perf.id}>
|
|
619
|
-
<view className={"pp-item"}>
|
|
1041
|
+
<view className={"pp-item"} style={{ borderBottomColor: colors.stroke.neutralWeak }}>
|
|
620
1042
|
<view className={"pp-itemHeader"} bindtap={() => setSelectedId(selectedId === perf.id ? null : perf.id)}>
|
|
621
|
-
<text className={
|
|
1043
|
+
<text className={"pp-entryType"} style={{
|
|
1044
|
+
fontWeight: fontWeight.bold,
|
|
1045
|
+
...getEntryTypeColors(colors, perf.entryType)
|
|
1046
|
+
}}>
|
|
622
1047
|
{perf.entryType}
|
|
623
1048
|
</text>
|
|
624
|
-
<text className={"pp-entryName"}
|
|
625
|
-
|
|
1049
|
+
<text className={"pp-entryName"} style={{
|
|
1050
|
+
fontWeight: fontWeight.medium,
|
|
1051
|
+
color: colors.fg.neutral
|
|
1052
|
+
}}>
|
|
1053
|
+
{perf.name}
|
|
1054
|
+
</text>
|
|
1055
|
+
<text className={"pp-timestamp"} style={{
|
|
1056
|
+
fontWeight: fontWeight.regular,
|
|
1057
|
+
color: colors.fg.neutralSubtle
|
|
1058
|
+
}}>
|
|
626
1059
|
{new Date(perf.timestamp).toISOString()}
|
|
627
1060
|
</text>
|
|
628
1061
|
</view>
|
|
629
1062
|
|
|
630
1063
|
<view bindtap={() => setSelectedId(selectedId === perf.id ? null : perf.id)}>
|
|
631
|
-
{isMetricFcp && primaryFcp && <text className={"pp-fcpHighlight"}
|
|
1064
|
+
{isMetricFcp && primaryFcp && <text className={"pp-fcpHighlight"} style={{
|
|
1065
|
+
fontWeight: fontWeight.bold,
|
|
1066
|
+
color: colors.palette.blue600,
|
|
1067
|
+
backgroundColor: colors.palette.blue100
|
|
1068
|
+
}}>
|
|
1069
|
+
{primaryFcp}
|
|
1070
|
+
</text>}
|
|
632
1071
|
</view>
|
|
633
1072
|
|
|
634
1073
|
{selectedId === perf.id && <view className={"pp-detailsContainer"}>
|
|
635
1074
|
{isMetricFcp && fcpMetrics && <view className={"pp-fcpSection"}>
|
|
636
|
-
{totalFcp !== void 0 && <view className={"pp-fcpMetric"}>
|
|
1075
|
+
{totalFcp !== void 0 && <view className={"pp-fcpMetric"} style={{ backgroundColor: colors.bg.layerDefault }}>
|
|
637
1076
|
<view className={"pp-fcpMetricHeader"}>
|
|
638
|
-
<text className={"pp-fcpMetricName"}
|
|
1077
|
+
<text className={"pp-fcpMetricName"} style={{
|
|
1078
|
+
fontWeight: fontWeight.bold,
|
|
1079
|
+
color: colors.fg.neutral
|
|
1080
|
+
}}>
|
|
639
1081
|
전체 FCP
|
|
640
1082
|
</text>
|
|
641
|
-
<text className={"pp-fcpMetricValue"}
|
|
1083
|
+
<text className={"pp-fcpMetricValue"} style={{
|
|
1084
|
+
fontWeight: fontWeight.bold,
|
|
1085
|
+
color: colors.palette.blue600
|
|
1086
|
+
}}>
|
|
642
1087
|
{formatDuration(totalFcp.duration)}
|
|
643
1088
|
</text>
|
|
644
1089
|
</view>
|
|
645
|
-
<text className={"pp-fcpMetricDescription"}
|
|
1090
|
+
<text className={"pp-fcpMetricDescription"} style={{
|
|
1091
|
+
fontWeight: fontWeight.regular,
|
|
1092
|
+
color: colors.fg.neutralSubtle
|
|
1093
|
+
}}>
|
|
646
1094
|
PrepareTemplate Start부터 Paint End 까지 걸리는
|
|
647
1095
|
시간
|
|
648
1096
|
</text>
|
|
649
1097
|
</view>}
|
|
650
1098
|
|
|
651
|
-
{lynxFcp !== void 0 && <view className={"pp-fcpMetric"}>
|
|
1099
|
+
{lynxFcp !== void 0 && <view className={"pp-fcpMetric"} style={{ backgroundColor: colors.bg.layerDefault }}>
|
|
652
1100
|
<view className={"pp-fcpMetricHeader"}>
|
|
653
|
-
<text className={"pp-fcpMetricName"}
|
|
654
|
-
|
|
1101
|
+
<text className={"pp-fcpMetricName"} style={{
|
|
1102
|
+
fontWeight: fontWeight.bold,
|
|
1103
|
+
color: colors.fg.neutral
|
|
1104
|
+
}}>
|
|
1105
|
+
LynxFCP
|
|
1106
|
+
</text>
|
|
1107
|
+
<text className={"pp-fcpMetricValue"} style={{
|
|
1108
|
+
fontWeight: fontWeight.bold,
|
|
1109
|
+
color: colors.palette.blue600
|
|
1110
|
+
}}>
|
|
655
1111
|
{formatDuration(lynxFcp.duration)}
|
|
656
1112
|
</text>
|
|
657
1113
|
</view>
|
|
658
|
-
<text className={"pp-fcpMetricDescription"}
|
|
1114
|
+
<text className={"pp-fcpMetricDescription"} style={{
|
|
1115
|
+
fontWeight: fontWeight.regular,
|
|
1116
|
+
color: colors.fg.neutralSubtle
|
|
1117
|
+
}}>
|
|
659
1118
|
Bundle Load 시작부터 Paint End 까지 걸리는 시간
|
|
660
1119
|
</text>
|
|
661
1120
|
</view>}
|
|
662
1121
|
|
|
663
|
-
{fcp !== void 0 && <view className={"pp-fcpMetric"}>
|
|
1122
|
+
{fcp !== void 0 && <view className={"pp-fcpMetric"} style={{ backgroundColor: colors.bg.layerDefault }}>
|
|
664
1123
|
<view className={"pp-fcpMetricHeader"}>
|
|
665
|
-
<text className={"pp-fcpMetricName"}
|
|
1124
|
+
<text className={"pp-fcpMetricName"} style={{
|
|
1125
|
+
fontWeight: fontWeight.bold,
|
|
1126
|
+
color: colors.fg.neutral
|
|
1127
|
+
}}>
|
|
666
1128
|
렌더링 FCP
|
|
667
1129
|
</text>
|
|
668
|
-
<text className={"pp-fcpMetricValue"}
|
|
1130
|
+
<text className={"pp-fcpMetricValue"} style={{
|
|
1131
|
+
fontWeight: fontWeight.bold,
|
|
1132
|
+
color: colors.palette.blue600
|
|
1133
|
+
}}>
|
|
669
1134
|
{formatDuration(fcp.duration)}
|
|
670
1135
|
</text>
|
|
671
1136
|
</view>
|
|
672
|
-
<text className={"pp-fcpMetricDescription"}
|
|
1137
|
+
<text className={"pp-fcpMetricDescription"} style={{
|
|
1138
|
+
fontWeight: fontWeight.regular,
|
|
1139
|
+
color: colors.fg.neutralSubtle
|
|
1140
|
+
}}>
|
|
673
1141
|
TemplateBundle 준비부터 Paint End 까지 걸리는 시간
|
|
674
1142
|
</text>
|
|
675
1143
|
</view>}
|
|
676
1144
|
</view>}
|
|
677
1145
|
|
|
678
|
-
{!!perf.rawEntry && <view className={"pp-rawEntrySection"}>
|
|
679
|
-
<text className={"pp-detailTitle"}
|
|
680
|
-
|
|
1146
|
+
{!!perf.rawEntry && <view className={"pp-rawEntrySection"} style={{ backgroundColor: colors.bg.neutralWeak }}>
|
|
1147
|
+
<text className={"pp-detailTitle"} style={{
|
|
1148
|
+
fontWeight: fontWeight.bold,
|
|
1149
|
+
color: colors.fg.neutral
|
|
1150
|
+
}}>
|
|
1151
|
+
Raw Entry
|
|
1152
|
+
</text>
|
|
1153
|
+
<text className={"pp-rawEntry"} style={{
|
|
1154
|
+
fontWeight: fontWeight.regular,
|
|
1155
|
+
color: colors.fg.neutralSubtle
|
|
1156
|
+
}}>
|
|
681
1157
|
{String(stringify(perf.rawEntry, null, 2, { references: true }))}
|
|
682
1158
|
</text>
|
|
683
1159
|
</view>}
|
|
@@ -692,11 +1168,12 @@ const PerformancePanel = ({ performances, clearPerformances }) => {
|
|
|
692
1168
|
//#endregion
|
|
693
1169
|
//#region src/components/Tabs.tsx
|
|
694
1170
|
function Tabs(props) {
|
|
1171
|
+
const colors = useThemeColors();
|
|
695
1172
|
const tabContentsRef = useRef(null);
|
|
696
1173
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
697
1174
|
const tabSize = props.items.length < 4 ? void 0 : `t${Math.max(1, 5 - (props.items.length - 3))}`;
|
|
698
1175
|
return <view className={"tabs-root"}>
|
|
699
|
-
<view className={"tabs-header"}>
|
|
1176
|
+
<view className={"tabs-header"} style={{ boxShadow: `inset 0 -1px 0 0 ${colors.stroke.neutralSubtle}` }}>
|
|
700
1177
|
{props.items.map((item, i) => <view key={item.key} className={"tabs-triggerButton"} bindtap={() => {
|
|
701
1178
|
setActiveIndex(i);
|
|
702
1179
|
props.onTabChange?.();
|
|
@@ -708,11 +1185,14 @@ function Tabs(props) {
|
|
|
708
1185
|
}
|
|
709
1186
|
}).exec();
|
|
710
1187
|
}}>
|
|
711
|
-
<text className={`tabs-triggerButtonText${
|
|
1188
|
+
<text className={`tabs-triggerButtonText${tabSize ? ` tabs-triggerButtonText--${tabSize}` : ""}`} style={{
|
|
1189
|
+
fontWeight: fontWeight.bold,
|
|
1190
|
+
color: i === activeIndex ? colors.fg.neutral : colors.fg.neutralSubtle
|
|
1191
|
+
}}>
|
|
712
1192
|
{item.label}
|
|
713
1193
|
</text>
|
|
714
1194
|
{i === 0 && <view className={"tabs-triggerIndicator"} style={{ transform: `translateX(${activeIndex * 100}%)` }}>
|
|
715
|
-
<view className={"tabs-triggerIndicatorLine"} />
|
|
1195
|
+
<view className={"tabs-triggerIndicatorLine"} style={{ backgroundColor: colors.fg.neutral }} />
|
|
716
1196
|
</view>}
|
|
717
1197
|
</view>)}
|
|
718
1198
|
</view>
|
|
@@ -860,6 +1340,7 @@ const SHINE_STYLES = {
|
|
|
860
1340
|
}
|
|
861
1341
|
};
|
|
862
1342
|
const FloatingButton = ({ bindtap, children }) => {
|
|
1343
|
+
const colors = useThemeColors();
|
|
863
1344
|
const { phase, right, bottom, clearTimer, handlers } = useLongPressDrag(bindtap);
|
|
864
1345
|
const handleReload = () => {
|
|
865
1346
|
try {
|
|
@@ -875,14 +1356,17 @@ const FloatingButton = ({ bindtap, children }) => {
|
|
|
875
1356
|
<view className={"fb-wrapper"} consume-slide-event={[[-180, 180]]} style={{
|
|
876
1357
|
right: `${right}px`,
|
|
877
1358
|
bottom: `${bottom}px`,
|
|
878
|
-
transform: isDragging ? "scale(1.05)" : "scale(1)"
|
|
1359
|
+
transform: isDragging ? "scale(1.05)" : "scale(1)",
|
|
1360
|
+
transition: `transform ${duration.d4} cubic-bezier(0.4, 0, 0.2, 1)`
|
|
879
1361
|
}} {...handlers}>
|
|
880
|
-
<view className={"fb-button"}>
|
|
1362
|
+
<view className={"fb-button"} style={{ backgroundColor: colors.palette.green600 }}>
|
|
881
1363
|
{children}
|
|
882
1364
|
<view className={"fb-shineOverlay"} style={SHINE_STYLES[phase]} />
|
|
883
1365
|
</view>
|
|
884
|
-
<view className={"fb-reloadButton"} catchtouchstart={() => clearTimer()} bindtap={handleReload}>
|
|
885
|
-
<text className={"fb-reloadIcon"}
|
|
1366
|
+
<view className={"fb-reloadButton"} style={{ backgroundColor: colors.palette.green600 }} catchtouchstart={() => clearTimer()} bindtap={handleReload}>
|
|
1367
|
+
<text className={"fb-reloadIcon"} style={{ color: colors.palette.staticWhite }}>
|
|
1368
|
+
{"↻"}
|
|
1369
|
+
</text>
|
|
886
1370
|
</view>
|
|
887
1371
|
</view>
|
|
888
1372
|
</>;
|
|
@@ -894,6 +1378,7 @@ const LynxConsole = forwardRef(({ theme = "light", safeAreaInsetBottom = "50px",
|
|
|
894
1378
|
const [isOpen, setIsOpen] = useState(false);
|
|
895
1379
|
const [shouldClose, setShouldClose] = useState(false);
|
|
896
1380
|
const { performances } = usePerformance();
|
|
1381
|
+
const colors = useMemo(() => getColors(theme), [theme]);
|
|
897
1382
|
const latestFcp = useMemo(() => {
|
|
898
1383
|
for (let i = performances.length - 1; i >= 0; i--) {
|
|
899
1384
|
const perf = performances[i];
|
|
@@ -922,18 +1407,28 @@ const LynxConsole = forwardRef(({ theme = "light", safeAreaInsetBottom = "50px",
|
|
|
922
1407
|
setIsOpen(false);
|
|
923
1408
|
setShouldClose(false);
|
|
924
1409
|
};
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1410
|
+
return <ThemeProvider value={colors}>
|
|
1411
|
+
<view style={{
|
|
1412
|
+
backgroundColor: colors.bg.layerDefault,
|
|
1413
|
+
color: colors.fg.neutral
|
|
1414
|
+
}}>
|
|
1415
|
+
<FloatingButton bindtap={handleOpenBottomSheet}>
|
|
1416
|
+
<text className="fb-title" style={{
|
|
1417
|
+
fontWeight: "400",
|
|
1418
|
+
color: colors.palette.staticWhite
|
|
1419
|
+
}}>LynxConsole</text>
|
|
1420
|
+
<text className="fb-subtitle" style={{
|
|
1421
|
+
fontWeight: "400",
|
|
1422
|
+
color: colors.palette.staticWhite
|
|
1423
|
+
}}>
|
|
1424
|
+
{`${latestFcp?.name ?? "FCP"}: ${latestFcp?.duration ? latestFcp.duration.toFixed(2) : "--"}ms`}
|
|
1425
|
+
</text>
|
|
1426
|
+
</FloatingButton>
|
|
1427
|
+
{isOpen && <BottomSheet isOpen={isOpen} shouldClose={shouldClose} onClose={handleCloseBottomSheet} title="Lynx Console" safeAreaInsetBottom={safeAreaInsetBottom}>
|
|
1428
|
+
<ConsolePanel customTabs={customTabs} />
|
|
1429
|
+
</BottomSheet>}
|
|
1430
|
+
</view>
|
|
1431
|
+
</ThemeProvider>;
|
|
937
1432
|
});
|
|
938
1433
|
|
|
939
1434
|
//#endregion
|