lynx-console 0.2.0 → 0.2.2
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 -112
- package/dist/index.css +0 -388
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +616 -113
- package/dist/index.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 +159 -29
- package/src/components/Tabs.css +0 -9
- package/src/components/Tabs.tsx +21 -3
- package/src/index.tsx +29 -22
- 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,11 +960,41 @@ 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"}
|
|
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>
|
|
586
998
|
<view bindtap={() => {
|
|
587
999
|
console.log("[PerformancePanel] performances", performances);
|
|
588
1000
|
}} style={{
|
|
@@ -591,21 +1003,39 @@ const PerformancePanel = ({ performances, clearPerformances }) => {
|
|
|
591
1003
|
}}>
|
|
592
1004
|
<text>Log</text>
|
|
593
1005
|
</view>
|
|
594
|
-
<view bindtap={clearPerformances} className={"pp-clearButton"}>
|
|
595
|
-
<text className={"pp-clearButtonText"}
|
|
1006
|
+
<view bindtap={clearPerformances} className={"pp-clearButton"} style={{ backgroundColor: colors.bg.neutralWeak }}>
|
|
1007
|
+
<text className={"pp-clearButtonText"} style={{
|
|
1008
|
+
fontWeight: fontWeight.medium,
|
|
1009
|
+
color: colors.fg.neutralMuted
|
|
1010
|
+
}}>
|
|
1011
|
+
🗑
|
|
1012
|
+
</text>
|
|
596
1013
|
</view>
|
|
597
1014
|
</view>
|
|
598
1015
|
<view className={"pp-placeholder"}>
|
|
599
|
-
<text className={"pp-placeholderText"}
|
|
1016
|
+
<text className={"pp-placeholderText"} style={{
|
|
1017
|
+
fontWeight: fontWeight.regular,
|
|
1018
|
+
color: colors.fg.disabled
|
|
1019
|
+
}}>
|
|
600
1020
|
No performance data yet...
|
|
601
1021
|
</text>
|
|
602
1022
|
</view>
|
|
603
1023
|
</view>;
|
|
604
1024
|
return <view className={"pp-container"}>
|
|
605
|
-
<view className={"pp-header"}>
|
|
606
|
-
<text className={"pp-count"}
|
|
607
|
-
|
|
608
|
-
|
|
1025
|
+
<view className={"pp-header"} style={{ borderBottomColor: colors.stroke.neutralSubtle }}>
|
|
1026
|
+
<text className={"pp-count"} style={{
|
|
1027
|
+
fontWeight: fontWeight.regular,
|
|
1028
|
+
color: colors.fg.neutralSubtle
|
|
1029
|
+
}}>
|
|
1030
|
+
{performances.length} entries
|
|
1031
|
+
</text>
|
|
1032
|
+
<view bindtap={clearPerformances} className={"pp-clearButton"} style={{ backgroundColor: colors.bg.neutralWeak }}>
|
|
1033
|
+
<text className={"pp-clearButtonText"} style={{
|
|
1034
|
+
fontWeight: fontWeight.medium,
|
|
1035
|
+
color: colors.fg.neutralMuted
|
|
1036
|
+
}}>
|
|
1037
|
+
🗑
|
|
1038
|
+
</text>
|
|
609
1039
|
</view>
|
|
610
1040
|
</view>
|
|
611
1041
|
|
|
@@ -616,68 +1046,122 @@ const PerformancePanel = ({ performances, clearPerformances }) => {
|
|
|
616
1046
|
const primaryFcp = getPrimaryFcpLabel(perf);
|
|
617
1047
|
const { totalFcp, lynxFcp, fcp } = fcpMetrics ?? {};
|
|
618
1048
|
return <list-item key={perf.id} item-key={perf.id}>
|
|
619
|
-
<view className={"pp-item"}>
|
|
1049
|
+
<view className={"pp-item"} style={{ borderBottomColor: colors.stroke.neutralWeak }}>
|
|
620
1050
|
<view className={"pp-itemHeader"} bindtap={() => setSelectedId(selectedId === perf.id ? null : perf.id)}>
|
|
621
|
-
<text className={
|
|
1051
|
+
<text className={"pp-entryType"} style={{
|
|
1052
|
+
fontWeight: fontWeight.bold,
|
|
1053
|
+
...getEntryTypeColors(colors, perf.entryType)
|
|
1054
|
+
}}>
|
|
622
1055
|
{perf.entryType}
|
|
623
1056
|
</text>
|
|
624
|
-
<text className={"pp-entryName"}
|
|
625
|
-
|
|
1057
|
+
<text className={"pp-entryName"} style={{
|
|
1058
|
+
fontWeight: fontWeight.medium,
|
|
1059
|
+
color: colors.fg.neutral
|
|
1060
|
+
}}>
|
|
1061
|
+
{perf.name}
|
|
1062
|
+
</text>
|
|
1063
|
+
<text className={"pp-timestamp"} style={{
|
|
1064
|
+
fontWeight: fontWeight.regular,
|
|
1065
|
+
color: colors.fg.neutralSubtle
|
|
1066
|
+
}}>
|
|
626
1067
|
{new Date(perf.timestamp).toISOString()}
|
|
627
1068
|
</text>
|
|
628
1069
|
</view>
|
|
629
1070
|
|
|
630
1071
|
<view bindtap={() => setSelectedId(selectedId === perf.id ? null : perf.id)}>
|
|
631
|
-
{isMetricFcp && primaryFcp && <text className={"pp-fcpHighlight"}
|
|
1072
|
+
{isMetricFcp && primaryFcp && <text className={"pp-fcpHighlight"} style={{
|
|
1073
|
+
fontWeight: fontWeight.bold,
|
|
1074
|
+
color: colors.palette.blue600,
|
|
1075
|
+
backgroundColor: colors.palette.blue100
|
|
1076
|
+
}}>
|
|
1077
|
+
{primaryFcp}
|
|
1078
|
+
</text>}
|
|
632
1079
|
</view>
|
|
633
1080
|
|
|
634
1081
|
{selectedId === perf.id && <view className={"pp-detailsContainer"}>
|
|
635
1082
|
{isMetricFcp && fcpMetrics && <view className={"pp-fcpSection"}>
|
|
636
|
-
{totalFcp !== void 0 && <view className={"pp-fcpMetric"}>
|
|
1083
|
+
{totalFcp !== void 0 && <view className={"pp-fcpMetric"} style={{ backgroundColor: colors.bg.layerDefault }}>
|
|
637
1084
|
<view className={"pp-fcpMetricHeader"}>
|
|
638
|
-
<text className={"pp-fcpMetricName"}
|
|
1085
|
+
<text className={"pp-fcpMetricName"} style={{
|
|
1086
|
+
fontWeight: fontWeight.bold,
|
|
1087
|
+
color: colors.fg.neutral
|
|
1088
|
+
}}>
|
|
639
1089
|
전체 FCP
|
|
640
1090
|
</text>
|
|
641
|
-
<text className={"pp-fcpMetricValue"}
|
|
1091
|
+
<text className={"pp-fcpMetricValue"} style={{
|
|
1092
|
+
fontWeight: fontWeight.bold,
|
|
1093
|
+
color: colors.palette.blue600
|
|
1094
|
+
}}>
|
|
642
1095
|
{formatDuration(totalFcp.duration)}
|
|
643
1096
|
</text>
|
|
644
1097
|
</view>
|
|
645
|
-
<text className={"pp-fcpMetricDescription"}
|
|
1098
|
+
<text className={"pp-fcpMetricDescription"} style={{
|
|
1099
|
+
fontWeight: fontWeight.regular,
|
|
1100
|
+
color: colors.fg.neutralSubtle
|
|
1101
|
+
}}>
|
|
646
1102
|
PrepareTemplate Start부터 Paint End 까지 걸리는
|
|
647
1103
|
시간
|
|
648
1104
|
</text>
|
|
649
1105
|
</view>}
|
|
650
1106
|
|
|
651
|
-
{lynxFcp !== void 0 && <view className={"pp-fcpMetric"}>
|
|
1107
|
+
{lynxFcp !== void 0 && <view className={"pp-fcpMetric"} style={{ backgroundColor: colors.bg.layerDefault }}>
|
|
652
1108
|
<view className={"pp-fcpMetricHeader"}>
|
|
653
|
-
<text className={"pp-fcpMetricName"}
|
|
654
|
-
|
|
1109
|
+
<text className={"pp-fcpMetricName"} style={{
|
|
1110
|
+
fontWeight: fontWeight.bold,
|
|
1111
|
+
color: colors.fg.neutral
|
|
1112
|
+
}}>
|
|
1113
|
+
LynxFCP
|
|
1114
|
+
</text>
|
|
1115
|
+
<text className={"pp-fcpMetricValue"} style={{
|
|
1116
|
+
fontWeight: fontWeight.bold,
|
|
1117
|
+
color: colors.palette.blue600
|
|
1118
|
+
}}>
|
|
655
1119
|
{formatDuration(lynxFcp.duration)}
|
|
656
1120
|
</text>
|
|
657
1121
|
</view>
|
|
658
|
-
<text className={"pp-fcpMetricDescription"}
|
|
1122
|
+
<text className={"pp-fcpMetricDescription"} style={{
|
|
1123
|
+
fontWeight: fontWeight.regular,
|
|
1124
|
+
color: colors.fg.neutralSubtle
|
|
1125
|
+
}}>
|
|
659
1126
|
Bundle Load 시작부터 Paint End 까지 걸리는 시간
|
|
660
1127
|
</text>
|
|
661
1128
|
</view>}
|
|
662
1129
|
|
|
663
|
-
{fcp !== void 0 && <view className={"pp-fcpMetric"}>
|
|
1130
|
+
{fcp !== void 0 && <view className={"pp-fcpMetric"} style={{ backgroundColor: colors.bg.layerDefault }}>
|
|
664
1131
|
<view className={"pp-fcpMetricHeader"}>
|
|
665
|
-
<text className={"pp-fcpMetricName"}
|
|
1132
|
+
<text className={"pp-fcpMetricName"} style={{
|
|
1133
|
+
fontWeight: fontWeight.bold,
|
|
1134
|
+
color: colors.fg.neutral
|
|
1135
|
+
}}>
|
|
666
1136
|
렌더링 FCP
|
|
667
1137
|
</text>
|
|
668
|
-
<text className={"pp-fcpMetricValue"}
|
|
1138
|
+
<text className={"pp-fcpMetricValue"} style={{
|
|
1139
|
+
fontWeight: fontWeight.bold,
|
|
1140
|
+
color: colors.palette.blue600
|
|
1141
|
+
}}>
|
|
669
1142
|
{formatDuration(fcp.duration)}
|
|
670
1143
|
</text>
|
|
671
1144
|
</view>
|
|
672
|
-
<text className={"pp-fcpMetricDescription"}
|
|
1145
|
+
<text className={"pp-fcpMetricDescription"} style={{
|
|
1146
|
+
fontWeight: fontWeight.regular,
|
|
1147
|
+
color: colors.fg.neutralSubtle
|
|
1148
|
+
}}>
|
|
673
1149
|
TemplateBundle 준비부터 Paint End 까지 걸리는 시간
|
|
674
1150
|
</text>
|
|
675
1151
|
</view>}
|
|
676
1152
|
</view>}
|
|
677
1153
|
|
|
678
|
-
{!!perf.rawEntry && <view className={"pp-rawEntrySection"}>
|
|
679
|
-
<text className={"pp-detailTitle"}
|
|
680
|
-
|
|
1154
|
+
{!!perf.rawEntry && <view className={"pp-rawEntrySection"} style={{ backgroundColor: colors.bg.neutralWeak }}>
|
|
1155
|
+
<text className={"pp-detailTitle"} style={{
|
|
1156
|
+
fontWeight: fontWeight.bold,
|
|
1157
|
+
color: colors.fg.neutral
|
|
1158
|
+
}}>
|
|
1159
|
+
Raw Entry
|
|
1160
|
+
</text>
|
|
1161
|
+
<text className={"pp-rawEntry"} style={{
|
|
1162
|
+
fontWeight: fontWeight.regular,
|
|
1163
|
+
color: colors.fg.neutralSubtle
|
|
1164
|
+
}}>
|
|
681
1165
|
{String(stringify(perf.rawEntry, null, 2, { references: true }))}
|
|
682
1166
|
</text>
|
|
683
1167
|
</view>}
|
|
@@ -692,11 +1176,12 @@ const PerformancePanel = ({ performances, clearPerformances }) => {
|
|
|
692
1176
|
//#endregion
|
|
693
1177
|
//#region src/components/Tabs.tsx
|
|
694
1178
|
function Tabs(props) {
|
|
1179
|
+
const colors = useThemeColors();
|
|
695
1180
|
const tabContentsRef = useRef(null);
|
|
696
1181
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
697
1182
|
const tabSize = props.items.length < 4 ? void 0 : `t${Math.max(1, 5 - (props.items.length - 3))}`;
|
|
698
1183
|
return <view className={"tabs-root"}>
|
|
699
|
-
<view className={"tabs-header"}>
|
|
1184
|
+
<view className={"tabs-header"} style={{ boxShadow: `inset 0 -1px 0 0 ${colors.stroke.neutralSubtle}` }}>
|
|
700
1185
|
{props.items.map((item, i) => <view key={item.key} className={"tabs-triggerButton"} bindtap={() => {
|
|
701
1186
|
setActiveIndex(i);
|
|
702
1187
|
props.onTabChange?.();
|
|
@@ -708,11 +1193,14 @@ function Tabs(props) {
|
|
|
708
1193
|
}
|
|
709
1194
|
}).exec();
|
|
710
1195
|
}}>
|
|
711
|
-
<text className={`tabs-triggerButtonText${
|
|
1196
|
+
<text className={`tabs-triggerButtonText${tabSize ? ` tabs-triggerButtonText--${tabSize}` : ""}`} style={{
|
|
1197
|
+
fontWeight: fontWeight.bold,
|
|
1198
|
+
color: i === activeIndex ? colors.fg.neutral : colors.fg.neutralSubtle
|
|
1199
|
+
}}>
|
|
712
1200
|
{item.label}
|
|
713
1201
|
</text>
|
|
714
1202
|
{i === 0 && <view className={"tabs-triggerIndicator"} style={{ transform: `translateX(${activeIndex * 100}%)` }}>
|
|
715
|
-
<view className={"tabs-triggerIndicatorLine"} />
|
|
1203
|
+
<view className={"tabs-triggerIndicatorLine"} style={{ backgroundColor: colors.fg.neutral }} />
|
|
716
1204
|
</view>}
|
|
717
1205
|
</view>)}
|
|
718
1206
|
</view>
|
|
@@ -860,6 +1348,7 @@ const SHINE_STYLES = {
|
|
|
860
1348
|
}
|
|
861
1349
|
};
|
|
862
1350
|
const FloatingButton = ({ bindtap, children }) => {
|
|
1351
|
+
const colors = useThemeColors();
|
|
863
1352
|
const { phase, right, bottom, clearTimer, handlers } = useLongPressDrag(bindtap);
|
|
864
1353
|
const handleReload = () => {
|
|
865
1354
|
try {
|
|
@@ -875,14 +1364,17 @@ const FloatingButton = ({ bindtap, children }) => {
|
|
|
875
1364
|
<view className={"fb-wrapper"} consume-slide-event={[[-180, 180]]} style={{
|
|
876
1365
|
right: `${right}px`,
|
|
877
1366
|
bottom: `${bottom}px`,
|
|
878
|
-
transform: isDragging ? "scale(1.05)" : "scale(1)"
|
|
1367
|
+
transform: isDragging ? "scale(1.05)" : "scale(1)",
|
|
1368
|
+
transition: `transform ${duration.d4} cubic-bezier(0.4, 0, 0.2, 1)`
|
|
879
1369
|
}} {...handlers}>
|
|
880
|
-
<view className={"fb-button"}>
|
|
1370
|
+
<view className={"fb-button"} style={{ backgroundColor: colors.palette.green600 }}>
|
|
881
1371
|
{children}
|
|
882
1372
|
<view className={"fb-shineOverlay"} style={SHINE_STYLES[phase]} />
|
|
883
1373
|
</view>
|
|
884
|
-
<view className={"fb-reloadButton"} catchtouchstart={() => clearTimer()} bindtap={handleReload}>
|
|
885
|
-
<text className={"fb-reloadIcon"}
|
|
1374
|
+
<view className={"fb-reloadButton"} style={{ backgroundColor: colors.palette.green600 }} catchtouchstart={() => clearTimer()} bindtap={handleReload}>
|
|
1375
|
+
<text className={"fb-reloadIcon"} style={{ color: colors.palette.staticWhite }}>
|
|
1376
|
+
{"↻"}
|
|
1377
|
+
</text>
|
|
886
1378
|
</view>
|
|
887
1379
|
</view>
|
|
888
1380
|
</>;
|
|
@@ -894,6 +1386,7 @@ const LynxConsole = forwardRef(({ theme = "light", safeAreaInsetBottom = "50px",
|
|
|
894
1386
|
const [isOpen, setIsOpen] = useState(false);
|
|
895
1387
|
const [shouldClose, setShouldClose] = useState(false);
|
|
896
1388
|
const { performances } = usePerformance();
|
|
1389
|
+
const colors = useMemo(() => getColors(theme), [theme]);
|
|
897
1390
|
const latestFcp = useMemo(() => {
|
|
898
1391
|
for (let i = performances.length - 1; i >= 0; i--) {
|
|
899
1392
|
const perf = performances[i];
|
|
@@ -922,18 +1415,28 @@ const LynxConsole = forwardRef(({ theme = "light", safeAreaInsetBottom = "50px",
|
|
|
922
1415
|
setIsOpen(false);
|
|
923
1416
|
setShouldClose(false);
|
|
924
1417
|
};
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1418
|
+
return <ThemeProvider value={colors}>
|
|
1419
|
+
<view style={{
|
|
1420
|
+
backgroundColor: colors.bg.layerDefault,
|
|
1421
|
+
color: colors.fg.neutral
|
|
1422
|
+
}}>
|
|
1423
|
+
<FloatingButton bindtap={handleOpenBottomSheet}>
|
|
1424
|
+
<text className="fb-title" style={{
|
|
1425
|
+
fontWeight: "400",
|
|
1426
|
+
color: colors.palette.staticWhite
|
|
1427
|
+
}}>LynxConsole</text>
|
|
1428
|
+
<text className="fb-subtitle" style={{
|
|
1429
|
+
fontWeight: "400",
|
|
1430
|
+
color: colors.palette.staticWhite
|
|
1431
|
+
}}>
|
|
1432
|
+
{`${latestFcp?.name ?? "FCP"}: ${latestFcp?.duration ? latestFcp.duration.toFixed(2) : "--"}ms`}
|
|
1433
|
+
</text>
|
|
1434
|
+
</FloatingButton>
|
|
1435
|
+
{isOpen && <BottomSheet isOpen={isOpen} shouldClose={shouldClose} onClose={handleCloseBottomSheet} title="Lynx Console" safeAreaInsetBottom={safeAreaInsetBottom}>
|
|
1436
|
+
<ConsolePanel customTabs={customTabs} />
|
|
1437
|
+
</BottomSheet>}
|
|
1438
|
+
</view>
|
|
1439
|
+
</ThemeProvider>;
|
|
937
1440
|
});
|
|
938
1441
|
|
|
939
1442
|
//#endregion
|