lynx-console 0.0.0
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/assets/src/components/BottomSheet.css.ts.vanilla-D-1A77Ik.css +83 -0
- package/dist/assets/src/components/ConsolePanel.css.ts.vanilla-B3avfSlI.css +246 -0
- package/dist/assets/src/components/FloatingButton.css.ts.vanilla-rPj35oLW.css +55 -0
- package/dist/assets/src/components/NetworkPanel.css.ts.vanilla-DFMduT0T.css +247 -0
- package/dist/assets/src/components/PerformancePanel.css.ts.vanilla-D35LuXlW.css +216 -0
- package/dist/assets/src/components/Tabs.css.ts.vanilla-DD7L2oXt.css +50 -0
- package/dist/index.cjs +1058 -0
- package/dist/index.css +466 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +17 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +17 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +1059 -0
- package/dist/index.mjs.map +1 -0
- package/dist/setup.cjs +377 -0
- package/dist/setup.d.cts +15 -0
- package/dist/setup.d.cts.map +1 -0
- package/dist/setup.d.mts +15 -0
- package/dist/setup.d.mts.map +1 -0
- package/dist/setup.mjs +374 -0
- package/dist/setup.mjs.map +1 -0
- package/package.json +51 -0
- package/src/components/BottomSheet.css.ts +93 -0
- package/src/components/BottomSheet.tsx +142 -0
- package/src/components/ConsolePanel.css.ts +261 -0
- package/src/components/ConsolePanel.tsx +41 -0
- package/src/components/FloatingButton.css.ts +62 -0
- package/src/components/FloatingButton.tsx +37 -0
- package/src/components/LogPanel.tsx +241 -0
- package/src/components/NetworkDetailSection.tsx +42 -0
- package/src/components/NetworkPanel.css.ts +280 -0
- package/src/components/NetworkPanel.tsx +222 -0
- package/src/components/PerformancePanel.css.ts +224 -0
- package/src/components/PerformancePanel.tsx +209 -0
- package/src/components/Tabs.css.ts +66 -0
- package/src/components/Tabs.tsx +81 -0
- package/src/globals.d.ts +9 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useConsole.ts +35 -0
- package/src/hooks/useNetwork.ts +36 -0
- package/src/hooks/usePerformance.ts +39 -0
- package/src/index.tsx +110 -0
- package/src/setup/_setupMainThreadConsole.ts +80 -0
- package/src/setup/index.ts +4 -0
- package/src/setup/setupLogMonitor.ts +78 -0
- package/src/setup/setupMainThreadConsole.ts +34 -0
- package/src/setup/setupNetworkMonitor.ts +247 -0
- package/src/setup/setupPerformanceMonitor.ts +70 -0
- package/src/shared/ensureConsoleStructure.ts +20 -0
- package/src/styles/getDimensionValue.ts +7 -0
- package/src/styles/global.css.ts +10 -0
- package/src/styles/tokens.json +80 -0
- package/src/styles/typography.ts +25 -0
- package/src/styles/vars/color.ts +228 -0
- package/src/styles/vars/dimension.ts +79 -0
- package/src/styles/vars/index.css +463 -0
- package/src/styles/vars/index.ts +22 -0
- package/src/styles/vars/radius.ts +12 -0
- package/src/types.ts +96 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1058 @@
|
|
|
1
|
+
import "./index.css";
|
|
2
|
+
let _lynx_js_react = require("@lynx-js/react");
|
|
3
|
+
require("./assets/src/components/BottomSheet.css.ts.vanilla-D-1A77Ik.css");
|
|
4
|
+
require("./assets/src/components/ConsolePanel.css.ts.vanilla-B3avfSlI.css");
|
|
5
|
+
let javascript_stringify = require("javascript-stringify");
|
|
6
|
+
require("./assets/src/components/NetworkPanel.css.ts.vanilla-DFMduT0T.css");
|
|
7
|
+
require("./assets/src/components/PerformancePanel.css.ts.vanilla-D35LuXlW.css");
|
|
8
|
+
require("./assets/src/components/Tabs.css.ts.vanilla-DD7L2oXt.css");
|
|
9
|
+
require("./assets/src/components/FloatingButton.css.ts.vanilla-rPj35oLW.css");
|
|
10
|
+
|
|
11
|
+
//#region src/components/BottomSheet.css.ts
|
|
12
|
+
var backdrop = "BottomSheet_backdrop__5pjw6y1";
|
|
13
|
+
var body = "BottomSheet_body__5pjw6y7";
|
|
14
|
+
var content = "BottomSheet_content__5pjw6y2";
|
|
15
|
+
var footer = "BottomSheet_footer__5pjw6y8";
|
|
16
|
+
var handle = "BottomSheet_handle__5pjw6y4";
|
|
17
|
+
var handleContainer = "BottomSheet_handleContainer__5pjw6y3";
|
|
18
|
+
var header$2 = "BottomSheet_header__5pjw6y5";
|
|
19
|
+
var overlay = "BottomSheet_overlay__5pjw6y0";
|
|
20
|
+
var title$1 = "BottomSheet_title__5pjw6y6";
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/components/BottomSheet.tsx
|
|
24
|
+
const MIN_HEIGHT = 200;
|
|
25
|
+
const MAX_HEIGHT = 700;
|
|
26
|
+
const DEFAULT_HEIGHT = 500;
|
|
27
|
+
const CLOSE_DRAG_THRESHOLD = 30;
|
|
28
|
+
let savedHeight = null;
|
|
29
|
+
function BottomSheet({ children, title, footer: footer$1, onClose, isOpen, shouldClose = false, safeAreaInsetBottom = "25px" }) {
|
|
30
|
+
const [sheetHeight, setSheetHeight] = (0, _lynx_js_react.useState)(savedHeight ?? DEFAULT_HEIGHT);
|
|
31
|
+
const [tempHeight, setTempHeight] = (0, _lynx_js_react.useState)(savedHeight ?? DEFAULT_HEIGHT);
|
|
32
|
+
const [isDragging, setIsDragging] = (0, _lynx_js_react.useState)(false);
|
|
33
|
+
const [dragStartY, setDragStartY] = (0, _lynx_js_react.useState)(0);
|
|
34
|
+
const [dragStartHeight, setDragStartHeight] = (0, _lynx_js_react.useState)(savedHeight ?? DEFAULT_HEIGHT);
|
|
35
|
+
const [isOpening, setIsOpening] = (0, _lynx_js_react.useState)(true);
|
|
36
|
+
const [isClosing, setIsClosing] = (0, _lynx_js_react.useState)(false);
|
|
37
|
+
const handleClose = () => {
|
|
38
|
+
setIsClosing(true);
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
onClose();
|
|
41
|
+
}, 300);
|
|
42
|
+
};
|
|
43
|
+
(0, _lynx_js_react.useEffect)(() => {
|
|
44
|
+
requestAnimationFrame(() => {
|
|
45
|
+
setIsOpening(false);
|
|
46
|
+
});
|
|
47
|
+
}, []);
|
|
48
|
+
(0, _lynx_js_react.useEffect)(() => {
|
|
49
|
+
if (shouldClose && !isClosing) handleClose();
|
|
50
|
+
}, [shouldClose, isClosing]);
|
|
51
|
+
(0, _lynx_js_react.useEffect)(() => {
|
|
52
|
+
savedHeight = sheetHeight;
|
|
53
|
+
}, [sheetHeight]);
|
|
54
|
+
if (!isOpen) return null;
|
|
55
|
+
const handleTouchStart = (e) => {
|
|
56
|
+
setIsDragging(true);
|
|
57
|
+
setDragStartY(e.detail.y);
|
|
58
|
+
setDragStartHeight(sheetHeight);
|
|
59
|
+
setTempHeight(sheetHeight);
|
|
60
|
+
};
|
|
61
|
+
const handleTouchMove = (e) => {
|
|
62
|
+
if (!isDragging) return;
|
|
63
|
+
const deltaY = dragStartY - e.detail.y;
|
|
64
|
+
setTempHeight(Math.min(Math.max(dragStartHeight + deltaY, MIN_HEIGHT), MAX_HEIGHT));
|
|
65
|
+
};
|
|
66
|
+
const handleTouchEnd = () => {
|
|
67
|
+
setIsDragging(false);
|
|
68
|
+
const dragDistance = dragStartHeight - tempHeight;
|
|
69
|
+
setSheetHeight(tempHeight);
|
|
70
|
+
if (dragDistance > CLOSE_DRAG_THRESHOLD) handleClose();
|
|
71
|
+
};
|
|
72
|
+
return <scroll-view className={backdrop} style={{ opacity: isOpening || isClosing ? 0 : 1 }}>
|
|
73
|
+
<view className={overlay} bindtap={handleClose}>
|
|
74
|
+
<view className={content} catchtap={() => {}} style={{
|
|
75
|
+
height: `${isDragging ? tempHeight : sheetHeight}px`,
|
|
76
|
+
transform: isOpening || isClosing ? "translateY(100%)" : "translateY(0)",
|
|
77
|
+
transition: isDragging ? "none" : void 0
|
|
78
|
+
}}>
|
|
79
|
+
{}
|
|
80
|
+
<view className={handleContainer} bindtouchstart={handleTouchStart} bindtouchmove={handleTouchMove} bindtouchend={handleTouchEnd}>
|
|
81
|
+
<view className={handle} />
|
|
82
|
+
</view>
|
|
83
|
+
<view className={header$2}>
|
|
84
|
+
{title && <text className={title$1}>{title}</text>}
|
|
85
|
+
</view>
|
|
86
|
+
<view className={body} style={{ paddingBottom: safeAreaInsetBottom }}>
|
|
87
|
+
{children}
|
|
88
|
+
</view>
|
|
89
|
+
{footer$1 && <view className={footer}>{footer$1}</view>}
|
|
90
|
+
</view>
|
|
91
|
+
</view>
|
|
92
|
+
</scroll-view>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/hooks/useConsole.ts
|
|
97
|
+
const useConsole = () => {
|
|
98
|
+
const [logs, setLogs] = (0, _lynx_js_react.useState)([]);
|
|
99
|
+
(0, _lynx_js_react.useEffect)(() => {
|
|
100
|
+
if (typeof globalThis.__LYNX_CONSOLE__?.state?.logs === "undefined") {
|
|
101
|
+
console.warn("[LynxConsole] Log monitoring not initialized");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const state = globalThis.__LYNX_CONSOLE__.state;
|
|
105
|
+
setLogs([...state.logs ?? []]);
|
|
106
|
+
const updateLogs = (_entry) => {
|
|
107
|
+
setLogs([...state.logs ?? []]);
|
|
108
|
+
};
|
|
109
|
+
return state.logSubscribe?.(updateLogs);
|
|
110
|
+
}, []);
|
|
111
|
+
const clearLogs = () => {
|
|
112
|
+
if (typeof globalThis.__LYNX_CONSOLE__?.state?.logs !== "undefined") {
|
|
113
|
+
const state = globalThis.__LYNX_CONSOLE__.state;
|
|
114
|
+
state.logs = [];
|
|
115
|
+
setLogs([]);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
return {
|
|
119
|
+
logs,
|
|
120
|
+
clearLogs
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/hooks/useNetwork.ts
|
|
126
|
+
const useNetwork = () => {
|
|
127
|
+
const [networks, setNetworks] = (0, _lynx_js_react.useState)([]);
|
|
128
|
+
(0, _lynx_js_react.useEffect)(() => {
|
|
129
|
+
if (typeof globalThis.__LYNX_CONSOLE__?.state?.networks === "undefined") {
|
|
130
|
+
console.warn("[LynxConsole] Network monitoring not initialized");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const state = globalThis.__LYNX_CONSOLE__.state;
|
|
134
|
+
setNetworks([...state.networks ?? []]);
|
|
135
|
+
const updateNetworks = (_entry) => {
|
|
136
|
+
setNetworks([...state.networks ?? []]);
|
|
137
|
+
};
|
|
138
|
+
return state.subscribeNetwork?.(updateNetworks);
|
|
139
|
+
}, []);
|
|
140
|
+
const clearNetworks = () => {
|
|
141
|
+
if (typeof globalThis.__LYNX_CONSOLE__?.state?.networks !== "undefined") {
|
|
142
|
+
const state = globalThis.__LYNX_CONSOLE__.state;
|
|
143
|
+
state.networks = [];
|
|
144
|
+
state.networksMap?.clear();
|
|
145
|
+
setNetworks([]);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
return {
|
|
149
|
+
networks,
|
|
150
|
+
clearNetworks
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region src/hooks/usePerformance.ts
|
|
156
|
+
const usePerformance = () => {
|
|
157
|
+
const [performances, setPerformances] = (0, _lynx_js_react.useState)([]);
|
|
158
|
+
(0, _lynx_js_react.useEffect)(() => {
|
|
159
|
+
if (typeof globalThis.__LYNX_CONSOLE__?.state?.performances === "undefined") {
|
|
160
|
+
console.warn("[LynxConsole] Performance monitoring not initialized");
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const state = globalThis.__LYNX_CONSOLE__.state;
|
|
164
|
+
setPerformances([...state.performances ?? []]);
|
|
165
|
+
const updatePerformances = (_entry) => {
|
|
166
|
+
setPerformances([...state.performances ?? []]);
|
|
167
|
+
};
|
|
168
|
+
return state.subscribePerformance?.(updatePerformances);
|
|
169
|
+
}, []);
|
|
170
|
+
const clearPerformances = () => {
|
|
171
|
+
if (typeof globalThis.__LYNX_CONSOLE__?.state?.performances !== "undefined") {
|
|
172
|
+
const state = globalThis.__LYNX_CONSOLE__.state;
|
|
173
|
+
state.performances = [];
|
|
174
|
+
setPerformances([]);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
return {
|
|
178
|
+
performances,
|
|
179
|
+
clearPerformances
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region ../node_modules/@vanilla-extract/recipes/dist/createRuntimeFn-62c9670f.esm.js
|
|
185
|
+
function toPrimitive(t, r) {
|
|
186
|
+
if ("object" != typeof t || !t) return t;
|
|
187
|
+
var e = t[Symbol.toPrimitive];
|
|
188
|
+
if (void 0 !== e) {
|
|
189
|
+
var i = e.call(t, r || "default");
|
|
190
|
+
if ("object" != typeof i) return i;
|
|
191
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
192
|
+
}
|
|
193
|
+
return ("string" === r ? String : Number)(t);
|
|
194
|
+
}
|
|
195
|
+
function toPropertyKey(t) {
|
|
196
|
+
var i = toPrimitive(t, "string");
|
|
197
|
+
return "symbol" == typeof i ? i : String(i);
|
|
198
|
+
}
|
|
199
|
+
function _defineProperty(obj, key, value) {
|
|
200
|
+
key = toPropertyKey(key);
|
|
201
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
202
|
+
value,
|
|
203
|
+
enumerable: true,
|
|
204
|
+
configurable: true,
|
|
205
|
+
writable: true
|
|
206
|
+
});
|
|
207
|
+
else obj[key] = value;
|
|
208
|
+
return obj;
|
|
209
|
+
}
|
|
210
|
+
function ownKeys(e, r) {
|
|
211
|
+
var t = Object.keys(e);
|
|
212
|
+
if (Object.getOwnPropertySymbols) {
|
|
213
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
214
|
+
r && (o = o.filter(function(r) {
|
|
215
|
+
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
|
216
|
+
})), t.push.apply(t, o);
|
|
217
|
+
}
|
|
218
|
+
return t;
|
|
219
|
+
}
|
|
220
|
+
function _objectSpread2(e) {
|
|
221
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
222
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
|
223
|
+
r % 2 ? ownKeys(Object(t), !0).forEach(function(r) {
|
|
224
|
+
_defineProperty(e, r, t[r]);
|
|
225
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r) {
|
|
226
|
+
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
return e;
|
|
230
|
+
}
|
|
231
|
+
function mapValues(input, fn) {
|
|
232
|
+
var result = {};
|
|
233
|
+
for (var _key in input) result[_key] = fn(input[_key], _key);
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
var shouldApplyCompound = (compoundCheck, selections, defaultVariants) => {
|
|
237
|
+
for (var key of Object.keys(compoundCheck)) {
|
|
238
|
+
var _selections$key;
|
|
239
|
+
if (compoundCheck[key] !== ((_selections$key = selections[key]) !== null && _selections$key !== void 0 ? _selections$key : defaultVariants[key])) return false;
|
|
240
|
+
}
|
|
241
|
+
return true;
|
|
242
|
+
};
|
|
243
|
+
var createRuntimeFn = (config) => {
|
|
244
|
+
var runtimeFn = (options) => {
|
|
245
|
+
var className = config.defaultClassName;
|
|
246
|
+
var selections = _objectSpread2(_objectSpread2({}, config.defaultVariants), options);
|
|
247
|
+
for (var variantName in selections) {
|
|
248
|
+
var _selections$variantNa;
|
|
249
|
+
var variantSelection = (_selections$variantNa = selections[variantName]) !== null && _selections$variantNa !== void 0 ? _selections$variantNa : config.defaultVariants[variantName];
|
|
250
|
+
if (variantSelection != null) {
|
|
251
|
+
var selection = variantSelection;
|
|
252
|
+
if (typeof selection === "boolean") selection = selection === true ? "true" : "false";
|
|
253
|
+
var selectionClassName = config.variantClassNames[variantName][selection];
|
|
254
|
+
if (selectionClassName) className += " " + selectionClassName;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
for (var [compoundCheck, compoundClassName] of config.compoundVariants) if (shouldApplyCompound(compoundCheck, selections, config.defaultVariants)) className += " " + compoundClassName;
|
|
258
|
+
return className;
|
|
259
|
+
};
|
|
260
|
+
runtimeFn.variants = () => Object.keys(config.variantClassNames);
|
|
261
|
+
runtimeFn.classNames = {
|
|
262
|
+
get base() {
|
|
263
|
+
return config.defaultClassName.split(" ")[0];
|
|
264
|
+
},
|
|
265
|
+
get variants() {
|
|
266
|
+
return mapValues(config.variantClassNames, (classNames) => mapValues(classNames, (className) => className.split(" ")[0]));
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
return runtimeFn;
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
//#endregion
|
|
273
|
+
//#region src/components/ConsolePanel.css.ts
|
|
274
|
+
var argNull = "ConsolePanel_argNull__db6kuup";
|
|
275
|
+
var argObject = "ConsolePanel_argObject__db6kuu11";
|
|
276
|
+
var argObjectContent = "ConsolePanel_argObjectContent__db6kuu14";
|
|
277
|
+
var argObjectHeader = "ConsolePanel_argObjectHeader__db6kuu12";
|
|
278
|
+
var argObjectJson = "ConsolePanel_argObjectJson__db6kuu17";
|
|
279
|
+
var argObjectPreview = "ConsolePanel_argObjectPreview__db6kuu13";
|
|
280
|
+
var argPrimitive = createRuntimeFn({
|
|
281
|
+
defaultClassName: "ConsolePanel_argPrimitive__db6kuuw",
|
|
282
|
+
variantClassNames: { level: {
|
|
283
|
+
log: "ConsolePanel_argPrimitive_level_log__db6kuux",
|
|
284
|
+
info: "ConsolePanel_argPrimitive_level_info__db6kuuy",
|
|
285
|
+
warn: "ConsolePanel_argPrimitive_level_warn__db6kuuz",
|
|
286
|
+
error: "ConsolePanel_argPrimitive_level_error__db6kuu10"
|
|
287
|
+
} },
|
|
288
|
+
defaultVariants: {},
|
|
289
|
+
compoundVariants: []
|
|
290
|
+
});
|
|
291
|
+
var argString = createRuntimeFn({
|
|
292
|
+
defaultClassName: "ConsolePanel_argString__db6kuur",
|
|
293
|
+
variantClassNames: { level: {
|
|
294
|
+
log: "ConsolePanel_argString_level_log__db6kuus",
|
|
295
|
+
info: "ConsolePanel_argString_level_info__db6kuut",
|
|
296
|
+
warn: "ConsolePanel_argString_level_warn__db6kuuu",
|
|
297
|
+
error: "ConsolePanel_argString_level_error__db6kuuv"
|
|
298
|
+
} },
|
|
299
|
+
defaultVariants: {},
|
|
300
|
+
compoundVariants: []
|
|
301
|
+
});
|
|
302
|
+
var argUndefined = "ConsolePanel_argUndefined__db6kuuq";
|
|
303
|
+
var clearButton$2 = "ConsolePanel_clearButton__db6kuu6";
|
|
304
|
+
var clearButtonText$2 = "ConsolePanel_clearButtonText__db6kuu7";
|
|
305
|
+
var container$3 = "ConsolePanel_container__db6kuu0";
|
|
306
|
+
var logArgItem = "ConsolePanel_logArgItem__db6kuuo";
|
|
307
|
+
var logArgsContainer = "ConsolePanel_logArgsContainer__db6kuun";
|
|
308
|
+
var logContainer = "ConsolePanel_logContainer__db6kuu3";
|
|
309
|
+
var logCount = "ConsolePanel_logCount__db6kuu5";
|
|
310
|
+
var logHeader = "ConsolePanel_logHeader__db6kuu4";
|
|
311
|
+
var logItem = createRuntimeFn({
|
|
312
|
+
defaultClassName: "ConsolePanel_logItem__db6kuu9",
|
|
313
|
+
variantClassNames: { level: {
|
|
314
|
+
log: "ConsolePanel_logItem_level_log__db6kuua",
|
|
315
|
+
info: "ConsolePanel_logItem_level_info__db6kuub",
|
|
316
|
+
warn: "ConsolePanel_logItem_level_warn__db6kuuc",
|
|
317
|
+
error: "ConsolePanel_logItem_level_error__db6kuud"
|
|
318
|
+
} },
|
|
319
|
+
defaultVariants: {},
|
|
320
|
+
compoundVariants: []
|
|
321
|
+
});
|
|
322
|
+
var logItemHeader = "ConsolePanel_logItemHeader__db6kuue";
|
|
323
|
+
var logLevel = createRuntimeFn({
|
|
324
|
+
defaultClassName: "ConsolePanel_logLevel__db6kuuf",
|
|
325
|
+
variantClassNames: { level: {
|
|
326
|
+
log: "ConsolePanel_logLevel_level_log__db6kuug",
|
|
327
|
+
info: "ConsolePanel_logLevel_level_info__db6kuuh",
|
|
328
|
+
warn: "ConsolePanel_logLevel_level_warn__db6kuui",
|
|
329
|
+
error: "ConsolePanel_logLevel_level_error__db6kuuj"
|
|
330
|
+
} },
|
|
331
|
+
defaultVariants: {},
|
|
332
|
+
compoundVariants: []
|
|
333
|
+
});
|
|
334
|
+
var logList = "ConsolePanel_logList__db6kuu8";
|
|
335
|
+
var logTime = "ConsolePanel_logTime__db6kuuk";
|
|
336
|
+
var placeholder$2 = "ConsolePanel_placeholder__db6kuu1";
|
|
337
|
+
var placeholderText$2 = "ConsolePanel_placeholderText__db6kuu2";
|
|
338
|
+
var replInput = "ConsolePanel_replInput__db6kuu1a";
|
|
339
|
+
var replInputRow = "ConsolePanel_replInputRow__db6kuu18";
|
|
340
|
+
var replPrompt = "ConsolePanel_replPrompt__db6kuu19";
|
|
341
|
+
var replRunButton = "ConsolePanel_replRunButton__db6kuu1b";
|
|
342
|
+
var replRunButtonText = "ConsolePanel_replRunButtonText__db6kuu1c";
|
|
343
|
+
var toggleIndicator = "ConsolePanel_toggleIndicator__db6kuul";
|
|
344
|
+
|
|
345
|
+
//#endregion
|
|
346
|
+
//#region src/components/LogPanel.tsx
|
|
347
|
+
const runCode = (code) => {
|
|
348
|
+
try {
|
|
349
|
+
const result = eval(code);
|
|
350
|
+
if (result instanceof Promise) result.then((r) => console.log(r)).catch((e) => console.error(e));
|
|
351
|
+
else console.log(result);
|
|
352
|
+
} catch (e) {
|
|
353
|
+
console.error(e);
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
const LogPanel = ({ logs, clearLogs }) => {
|
|
357
|
+
const [expandedArgs, setExpandedArgs] = (0, _lynx_js_react.useState)(/* @__PURE__ */ new Set());
|
|
358
|
+
const [code, setCode] = (0, _lynx_js_react.useState)("");
|
|
359
|
+
const inputRef = (0, _lynx_js_react.useRef)(null);
|
|
360
|
+
const listRef = (0, _lynx_js_react.useRef)(null);
|
|
361
|
+
const logsRef = (0, _lynx_js_react.useRef)(logs);
|
|
362
|
+
logsRef.current = logs;
|
|
363
|
+
const scrollToBottom = (smooth) => {
|
|
364
|
+
if (logsRef.current.length === 0) return;
|
|
365
|
+
listRef.current?.invoke({
|
|
366
|
+
method: "scrollToPosition",
|
|
367
|
+
params: {
|
|
368
|
+
position: logsRef.current.length - 1,
|
|
369
|
+
smooth
|
|
370
|
+
}
|
|
371
|
+
}).exec();
|
|
372
|
+
};
|
|
373
|
+
(0, _lynx_js_react.useEffect)(() => {
|
|
374
|
+
scrollToBottom(true);
|
|
375
|
+
}, [logs]);
|
|
376
|
+
const toggleArg = (key) => {
|
|
377
|
+
setExpandedArgs((prev) => {
|
|
378
|
+
const next = new Set(prev);
|
|
379
|
+
if (next.has(key)) next.delete(key);
|
|
380
|
+
else next.add(key);
|
|
381
|
+
return next;
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
const handleRun = () => {
|
|
385
|
+
const trimmed = code.trim();
|
|
386
|
+
if (!trimmed) return;
|
|
387
|
+
setCode("");
|
|
388
|
+
inputRef.current?.invoke({
|
|
389
|
+
method: "setValue",
|
|
390
|
+
params: { value: "" }
|
|
391
|
+
}).exec();
|
|
392
|
+
runCode(trimmed);
|
|
393
|
+
setTimeout(() => scrollToBottom(false), 100);
|
|
394
|
+
};
|
|
395
|
+
const renderArg = (arg, parentKey, level) => {
|
|
396
|
+
const key = parentKey;
|
|
397
|
+
const isExpanded = expandedArgs.has(key);
|
|
398
|
+
if (arg === null) return <text className={argNull}>null</text>;
|
|
399
|
+
if (arg === void 0) return <text className={argUndefined}>undefined</text>;
|
|
400
|
+
if (typeof arg === "string") {
|
|
401
|
+
const MAX_LENGTH = 80;
|
|
402
|
+
if (!(arg.length > MAX_LENGTH)) return <text className={argString({ level })}>{arg}</text>;
|
|
403
|
+
return <view className={argObject}>
|
|
404
|
+
<view className={argObjectHeader} bindtap={() => toggleArg(key)}>
|
|
405
|
+
<text className={toggleIndicator}>
|
|
406
|
+
{isExpanded ? "▼" : "▶"}
|
|
407
|
+
</text>
|
|
408
|
+
<text className={argString({ level })}>
|
|
409
|
+
{isExpanded ? arg : `${arg.slice(0, MAX_LENGTH)}...`}
|
|
410
|
+
</text>
|
|
411
|
+
</view>
|
|
412
|
+
</view>;
|
|
413
|
+
}
|
|
414
|
+
if (typeof arg === "number" || typeof arg === "boolean") return <text className={argPrimitive({ level })}>{String(arg)}</text>;
|
|
415
|
+
if (typeof arg === "object") {
|
|
416
|
+
let preview = "Object";
|
|
417
|
+
if (Array.isArray(arg)) preview = `Array(${arg.length})`;
|
|
418
|
+
else if (arg instanceof Map) preview = `Map(${arg.size})`;
|
|
419
|
+
else if (arg instanceof Set) preview = `Set(${arg.size})`;
|
|
420
|
+
else if (arg instanceof Date) preview = `Date`;
|
|
421
|
+
else if (arg instanceof RegExp) preview = `RegExp`;
|
|
422
|
+
else if (arg instanceof Error) preview = `${arg.constructor.name}`;
|
|
423
|
+
else if (arg?.constructor?.name && arg.constructor.name !== "Object") preview = arg.constructor.name;
|
|
424
|
+
let jsonString;
|
|
425
|
+
if (arg instanceof Map) jsonString = `{\n${Array.from(arg.entries()).map(([k, v]) => ` [${(0, javascript_stringify.stringify)(k)}, ${(0, javascript_stringify.stringify)(v)}]`).join(",\n")}\n}`;
|
|
426
|
+
else if (arg instanceof Set) jsonString = `{\n${Array.from(arg.values()).map((v) => (0, javascript_stringify.stringify)(v)).join(", ")}\n}`;
|
|
427
|
+
else jsonString = (0, javascript_stringify.stringify)(arg, null, 2, { references: true }) ?? String(arg);
|
|
428
|
+
return <view className={argObject}>
|
|
429
|
+
<view className={argObjectHeader} bindtap={() => toggleArg(key)}>
|
|
430
|
+
<text className={toggleIndicator}>
|
|
431
|
+
{isExpanded ? "▼" : "▶"}
|
|
432
|
+
</text>
|
|
433
|
+
<text className={argObjectPreview}>{preview}</text>
|
|
434
|
+
</view>
|
|
435
|
+
{isExpanded && <view className={argObjectContent}>
|
|
436
|
+
<text className={argObjectJson}>{jsonString}</text>
|
|
437
|
+
</view>}
|
|
438
|
+
</view>;
|
|
439
|
+
}
|
|
440
|
+
return <text className={argPrimitive({ level })}>{String(arg)}</text>;
|
|
441
|
+
};
|
|
442
|
+
return <view className={logContainer}>
|
|
443
|
+
<view className={logHeader}>
|
|
444
|
+
<text className={logCount}>Total {logs.length} logs</text>
|
|
445
|
+
<view style={{
|
|
446
|
+
display: "flex",
|
|
447
|
+
flexDirection: "row",
|
|
448
|
+
gap: 8
|
|
449
|
+
}}>
|
|
450
|
+
<view className={clearButton$2} bindtap={clearLogs}>
|
|
451
|
+
<text className={clearButtonText$2}>Clear</text>
|
|
452
|
+
</view>
|
|
453
|
+
</view>
|
|
454
|
+
</view>
|
|
455
|
+
<list ref={listRef} scroll-orientation="vertical" className={logList} initial-scroll-index={Math.max(0, logs.length - 1)}>
|
|
456
|
+
{logs.length === 0 ? <list-item item-key="empty-state">
|
|
457
|
+
<view className={placeholder$2}>
|
|
458
|
+
<text className={placeholderText$2}>
|
|
459
|
+
No logs yet. Try console.log("Hello!")
|
|
460
|
+
</text>
|
|
461
|
+
</view>
|
|
462
|
+
</list-item> : logs.map((log) => {
|
|
463
|
+
return <list-item key={log.id} item-key={log.id}>
|
|
464
|
+
<view className={logItem({ level: log.level })}>
|
|
465
|
+
<view className={logItemHeader}>
|
|
466
|
+
<text className={logLevel({ level: log.level })}>
|
|
467
|
+
{log.level.toUpperCase()}
|
|
468
|
+
</text>
|
|
469
|
+
<text className={logTime}>
|
|
470
|
+
{new Date(log.timestamp).toISOString()}
|
|
471
|
+
</text>
|
|
472
|
+
</view>
|
|
473
|
+
<view className={logArgsContainer}>
|
|
474
|
+
{log.args.map((arg, index) => <view key={`${log.id}-${index.toString()}`} className={logArgItem}>
|
|
475
|
+
{renderArg(arg, `${log.id}-${index.toString()}`, log.level)}
|
|
476
|
+
</view>)}
|
|
477
|
+
</view>
|
|
478
|
+
</view>
|
|
479
|
+
</list-item>;
|
|
480
|
+
})}
|
|
481
|
+
</list>
|
|
482
|
+
<view className={replInputRow}>
|
|
483
|
+
<text className={replPrompt}>{"›"}</text>
|
|
484
|
+
<input ref={inputRef} className={replInput} placeholder="enter code..." bindinput={(e) => setCode(e.detail.value)} bindconfirm={handleRun} />
|
|
485
|
+
<view className={replRunButton} bindtap={handleRun}>
|
|
486
|
+
<text className={replRunButtonText}>Run</text>
|
|
487
|
+
</view>
|
|
488
|
+
</view>
|
|
489
|
+
</view>;
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
//#endregion
|
|
493
|
+
//#region src/components/NetworkPanel.css.ts
|
|
494
|
+
var bodyText = "NetworkPanel_bodyText__1kf6i8q16";
|
|
495
|
+
var clearButton$1 = "NetworkPanel_clearButton__1kf6i8q3";
|
|
496
|
+
var clearButtonText$1 = "NetworkPanel_clearButtonText__1kf6i8q4";
|
|
497
|
+
var container$2 = "NetworkPanel_container__1kf6i8q0";
|
|
498
|
+
var count$1 = "NetworkPanel_count__1kf6i8q2";
|
|
499
|
+
var detailSection = "NetworkPanel_detailSection__1kf6i8q10";
|
|
500
|
+
var detailSectionTitle = "NetworkPanel_detailSectionTitle__1kf6i8q11";
|
|
501
|
+
var detailsContainer$1 = "NetworkPanel_detailsContainer__1kf6i8qr";
|
|
502
|
+
var emptyText = "NetworkPanel_emptyText__1kf6i8q18";
|
|
503
|
+
var errorText = "NetworkPanel_errorText__1kf6i8q17";
|
|
504
|
+
var header$1 = "NetworkPanel_header__1kf6i8q1";
|
|
505
|
+
var item$1 = createRuntimeFn({
|
|
506
|
+
defaultClassName: "NetworkPanel_item__1kf6i8q8",
|
|
507
|
+
variantClassNames: { status: {
|
|
508
|
+
pending: "NetworkPanel_item_status_pending__1kf6i8q9",
|
|
509
|
+
success: "NetworkPanel_item_status_success__1kf6i8qa",
|
|
510
|
+
error: "NetworkPanel_item_status_error__1kf6i8qb"
|
|
511
|
+
} },
|
|
512
|
+
defaultVariants: {},
|
|
513
|
+
compoundVariants: []
|
|
514
|
+
});
|
|
515
|
+
var itemHeader$1 = "NetworkPanel_itemHeader__1kf6i8qc";
|
|
516
|
+
var list$1 = "NetworkPanel_list__1kf6i8q5";
|
|
517
|
+
var method = createRuntimeFn({
|
|
518
|
+
defaultClassName: "NetworkPanel_method__1kf6i8qd",
|
|
519
|
+
variantClassNames: { type: {
|
|
520
|
+
GET: "NetworkPanel_method_type_GET__1kf6i8qe",
|
|
521
|
+
POST: "NetworkPanel_method_type_POST__1kf6i8qf",
|
|
522
|
+
PUT: "NetworkPanel_method_type_PUT__1kf6i8qg",
|
|
523
|
+
PATCH: "NetworkPanel_method_type_PATCH__1kf6i8qh",
|
|
524
|
+
DELETE: "NetworkPanel_method_type_DELETE__1kf6i8qi"
|
|
525
|
+
} },
|
|
526
|
+
defaultVariants: {},
|
|
527
|
+
compoundVariants: []
|
|
528
|
+
});
|
|
529
|
+
var path = "NetworkPanel_path__1kf6i8qp";
|
|
530
|
+
var placeholder$1 = "NetworkPanel_placeholder__1kf6i8q6";
|
|
531
|
+
var placeholderText$1 = "NetworkPanel_placeholderText__1kf6i8q7";
|
|
532
|
+
var statusCode = createRuntimeFn({
|
|
533
|
+
defaultClassName: "NetworkPanel_statusCode__1kf6i8qj",
|
|
534
|
+
variantClassNames: { type: {
|
|
535
|
+
success: "NetworkPanel_statusCode_type_success__1kf6i8qk",
|
|
536
|
+
error: "NetworkPanel_statusCode_type_error__1kf6i8ql",
|
|
537
|
+
pending: "NetworkPanel_statusCode_type_pending__1kf6i8qm"
|
|
538
|
+
} },
|
|
539
|
+
defaultVariants: {},
|
|
540
|
+
compoundVariants: []
|
|
541
|
+
});
|
|
542
|
+
var tab = createRuntimeFn({
|
|
543
|
+
defaultClassName: "NetworkPanel_tab__1kf6i8qt",
|
|
544
|
+
variantClassNames: { active: {
|
|
545
|
+
true: "NetworkPanel_tab_active_true__1kf6i8qu",
|
|
546
|
+
false: "NetworkPanel_tab_active_false__1kf6i8qv"
|
|
547
|
+
} },
|
|
548
|
+
defaultVariants: {},
|
|
549
|
+
compoundVariants: []
|
|
550
|
+
});
|
|
551
|
+
var tabContent$1 = "NetworkPanel_tabContent__1kf6i8qz";
|
|
552
|
+
var tabText = createRuntimeFn({
|
|
553
|
+
defaultClassName: "NetworkPanel_tabText__1kf6i8qw",
|
|
554
|
+
variantClassNames: { active: {
|
|
555
|
+
true: "NetworkPanel_tabText_active_true__1kf6i8qx",
|
|
556
|
+
false: "NetworkPanel_tabText_active_false__1kf6i8qy"
|
|
557
|
+
} },
|
|
558
|
+
defaultVariants: {},
|
|
559
|
+
compoundVariants: []
|
|
560
|
+
});
|
|
561
|
+
var table = "NetworkPanel_table__1kf6i8q12";
|
|
562
|
+
var tableKey = "NetworkPanel_tableKey__1kf6i8q14";
|
|
563
|
+
var tableRow = "NetworkPanel_tableRow__1kf6i8q13";
|
|
564
|
+
var tableValue = "NetworkPanel_tableValue__1kf6i8q15";
|
|
565
|
+
var tabs$1 = "NetworkPanel_tabs__1kf6i8qs";
|
|
566
|
+
var time = "NetworkPanel_time__1kf6i8qn";
|
|
567
|
+
|
|
568
|
+
//#endregion
|
|
569
|
+
//#region src/components/NetworkDetailSection.tsx
|
|
570
|
+
const NetworkDetailSection = ({ headers = {}, body = "", error = "" }) => {
|
|
571
|
+
return <>
|
|
572
|
+
{}
|
|
573
|
+
<view className={detailSection}>
|
|
574
|
+
<text className={detailSectionTitle}>Headers</text>
|
|
575
|
+
{headers && Object.keys(headers).length > 0 ? <view className={table}>
|
|
576
|
+
{Object.entries(headers).map(([key, value]) => <view key={key} className={tableRow}>
|
|
577
|
+
<text className={tableKey}>{key}</text>
|
|
578
|
+
<text className={tableValue}>{value}</text>
|
|
579
|
+
</view>)}
|
|
580
|
+
</view> : <text className={emptyText}>No headers</text>}
|
|
581
|
+
</view>
|
|
582
|
+
|
|
583
|
+
{}
|
|
584
|
+
<view className={detailSection}>
|
|
585
|
+
<text className={detailSectionTitle}>Body</text>
|
|
586
|
+
{error && <text className={errorText}>{error}</text>}
|
|
587
|
+
{body && <text className={bodyText}>{body}</text>}
|
|
588
|
+
{!error && !body && <text className={emptyText}>No body</text>}
|
|
589
|
+
</view>
|
|
590
|
+
</>;
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
//#endregion
|
|
594
|
+
//#region src/components/NetworkPanel.tsx
|
|
595
|
+
const NetworkPanel = ({ networks, clearNetworks }) => {
|
|
596
|
+
const [selectedId, setSelectedId] = (0, _lynx_js_react.useState)(null);
|
|
597
|
+
const [activeTab, setActiveTab] = (0, _lynx_js_react.useState)("general");
|
|
598
|
+
const formatDuration = (duration) => {
|
|
599
|
+
if (!duration) return "-";
|
|
600
|
+
if (duration < 1e3) return `${duration}ms`;
|
|
601
|
+
return `${(duration / 1e3).toFixed(2)}s`;
|
|
602
|
+
};
|
|
603
|
+
const extractPath = (url) => {
|
|
604
|
+
const pathMatch = url.match(/^https?:\/\/[^/]+(.*)$/);
|
|
605
|
+
if (pathMatch?.[1]) return pathMatch[1].startsWith("/") ? pathMatch[1].slice(1) : pathMatch[1];
|
|
606
|
+
return url;
|
|
607
|
+
};
|
|
608
|
+
const getGeneralInfo = (network) => {
|
|
609
|
+
return [
|
|
610
|
+
{
|
|
611
|
+
key: "URL",
|
|
612
|
+
value: network.url
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
key: "Method",
|
|
616
|
+
value: network.method
|
|
617
|
+
},
|
|
618
|
+
network.statusCode ? {
|
|
619
|
+
key: "Status",
|
|
620
|
+
value: String(network.statusCode)
|
|
621
|
+
} : null,
|
|
622
|
+
{
|
|
623
|
+
key: "Request Time",
|
|
624
|
+
value: new Date(network.startTime).toISOString()
|
|
625
|
+
},
|
|
626
|
+
network.endTime ? {
|
|
627
|
+
key: "Response Time",
|
|
628
|
+
value: new Date(network.endTime).toISOString()
|
|
629
|
+
} : null,
|
|
630
|
+
network.duration ? {
|
|
631
|
+
key: "Duration",
|
|
632
|
+
value: formatDuration(network.duration)
|
|
633
|
+
} : null
|
|
634
|
+
].filter((item) => item !== null);
|
|
635
|
+
};
|
|
636
|
+
const getStatusCodeVariant = (status, statusCode) => {
|
|
637
|
+
if (status === "pending") return "pending";
|
|
638
|
+
if (status === "error") return "error";
|
|
639
|
+
if (statusCode && statusCode >= 200 && statusCode < 300) return "success";
|
|
640
|
+
return "error";
|
|
641
|
+
};
|
|
642
|
+
return <view className={container$2}>
|
|
643
|
+
<view className={header$1}>
|
|
644
|
+
<text className={count$1}>Total: {networks.length} requests</text>
|
|
645
|
+
<view className={clearButton$1} bindtap={clearNetworks}>
|
|
646
|
+
<text className={clearButtonText$1}>Clear</text>
|
|
647
|
+
</view>
|
|
648
|
+
</view>
|
|
649
|
+
|
|
650
|
+
{networks.length === 0 ? <view className={placeholder$1}>
|
|
651
|
+
<text className={placeholderText$1}>No network requests yet</text>
|
|
652
|
+
</view> : <list className={list$1}>
|
|
653
|
+
{networks.map((network) => <list-item key={network.id} item-key={network.id}>
|
|
654
|
+
<view className={item$1({ status: network.status })}>
|
|
655
|
+
<view className={itemHeader$1} bindtap={() => setSelectedId(selectedId === network.id ? null : network.id)}>
|
|
656
|
+
<text className={method({ type: network.method })}>
|
|
657
|
+
{network.method}
|
|
658
|
+
</text>
|
|
659
|
+
{network.statusCode && <text className={statusCode({ type: getStatusCodeVariant(network.status, network.statusCode) })}>
|
|
660
|
+
{network.statusCode}
|
|
661
|
+
</text>}
|
|
662
|
+
{network.status === "pending" && <text className={statusCode({ type: "pending" })}>
|
|
663
|
+
Pending...
|
|
664
|
+
</text>}
|
|
665
|
+
<text className={time}>
|
|
666
|
+
{formatDuration(network.duration)}
|
|
667
|
+
</text>
|
|
668
|
+
<text className={time}>
|
|
669
|
+
{new Date(network.startTime).toISOString()}
|
|
670
|
+
</text>
|
|
671
|
+
</view>
|
|
672
|
+
|
|
673
|
+
<text className={path} bindtap={() => setSelectedId(selectedId === network.id ? null : network.id)}>
|
|
674
|
+
{extractPath(network.url)}
|
|
675
|
+
</text>
|
|
676
|
+
|
|
677
|
+
{selectedId === network.id && <view className={detailsContainer$1}>
|
|
678
|
+
{}
|
|
679
|
+
<view className={tabs$1}>
|
|
680
|
+
<view className={tab({ active: activeTab === "general" })} bindtap={() => setActiveTab("general")}>
|
|
681
|
+
<text className={tabText({ active: activeTab === "general" })}>
|
|
682
|
+
General
|
|
683
|
+
</text>
|
|
684
|
+
</view>
|
|
685
|
+
<view className={tab({ active: activeTab === "request" })} bindtap={() => setActiveTab("request")}>
|
|
686
|
+
<text className={tabText({ active: activeTab === "request" })}>
|
|
687
|
+
Request
|
|
688
|
+
</text>
|
|
689
|
+
</view>
|
|
690
|
+
<view className={tab({ active: activeTab === "response" })} bindtap={() => setActiveTab("response")}>
|
|
691
|
+
<text className={tabText({ active: activeTab === "response" })}>
|
|
692
|
+
Response
|
|
693
|
+
</text>
|
|
694
|
+
</view>
|
|
695
|
+
</view>
|
|
696
|
+
|
|
697
|
+
{}
|
|
698
|
+
<view className={tabContent$1}>
|
|
699
|
+
{activeTab === "general" && <view className={table}>
|
|
700
|
+
{getGeneralInfo(network).map((item) => <view key={item.key} className={tableRow}>
|
|
701
|
+
<text className={tableKey}>{item.key}</text>
|
|
702
|
+
<text className={tableValue}>
|
|
703
|
+
{item.value}
|
|
704
|
+
</text>
|
|
705
|
+
</view>)}
|
|
706
|
+
</view>}
|
|
707
|
+
|
|
708
|
+
{activeTab === "request" && <NetworkDetailSection headers={network.requestHeaders} body={network.requestBody} />}
|
|
709
|
+
|
|
710
|
+
{activeTab === "response" && <NetworkDetailSection headers={network.responseHeaders} body={network.responseBody} error={network.error} />}
|
|
711
|
+
</view>
|
|
712
|
+
</view>}
|
|
713
|
+
</view>
|
|
714
|
+
</list-item>)}
|
|
715
|
+
</list>}
|
|
716
|
+
</view>;
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
//#endregion
|
|
720
|
+
//#region src/components/PerformancePanel.css.ts
|
|
721
|
+
var clearButton = "PerformancePanel_clearButton__19p8bog3";
|
|
722
|
+
var clearButtonText = "PerformancePanel_clearButtonText__19p8bog4";
|
|
723
|
+
var container$1 = "PerformancePanel_container__19p8bog0";
|
|
724
|
+
var count = "PerformancePanel_count__19p8bog2";
|
|
725
|
+
var detailTitle = "PerformancePanel_detailTitle__19p8bogw";
|
|
726
|
+
var detailsContainer = "PerformancePanel_detailsContainer__19p8bogn";
|
|
727
|
+
var entryName = "PerformancePanel_entryName__19p8bogf";
|
|
728
|
+
var entryType = createRuntimeFn({
|
|
729
|
+
defaultClassName: "PerformancePanel_entryType__19p8boga",
|
|
730
|
+
variantClassNames: { type: {
|
|
731
|
+
init: "PerformancePanel_entryType_type_init__19p8bogb",
|
|
732
|
+
metric: "PerformancePanel_entryType_type_metric__19p8bogc",
|
|
733
|
+
pipeline: "PerformancePanel_entryType_type_pipeline__19p8bogd",
|
|
734
|
+
resource: "PerformancePanel_entryType_type_resource__19p8boge"
|
|
735
|
+
} },
|
|
736
|
+
defaultVariants: {},
|
|
737
|
+
compoundVariants: []
|
|
738
|
+
});
|
|
739
|
+
var fcpHighlight = "PerformancePanel_fcpHighlight__19p8bogi";
|
|
740
|
+
var fcpMetric = "PerformancePanel_fcpMetric__19p8bogq";
|
|
741
|
+
var fcpMetricDescription = "PerformancePanel_fcpMetricDescription__19p8bogt";
|
|
742
|
+
var fcpMetricHeader = "PerformancePanel_fcpMetricHeader__19p8bogh";
|
|
743
|
+
var fcpMetricName = "PerformancePanel_fcpMetricName__19p8bogr";
|
|
744
|
+
var fcpMetricValue = "PerformancePanel_fcpMetricValue__19p8bogs";
|
|
745
|
+
var fcpSection = "PerformancePanel_fcpSection__19p8bogo";
|
|
746
|
+
var header = "PerformancePanel_header__19p8bog1";
|
|
747
|
+
var item = "PerformancePanel_item__19p8bog8";
|
|
748
|
+
var itemHeader = "PerformancePanel_itemHeader__19p8bog9";
|
|
749
|
+
var list = "PerformancePanel_list__19p8bog5";
|
|
750
|
+
var placeholder = "PerformancePanel_placeholder__19p8bog6";
|
|
751
|
+
var placeholderText = "PerformancePanel_placeholderText__19p8bog7";
|
|
752
|
+
var rawEntry = "PerformancePanel_rawEntry__19p8bogx";
|
|
753
|
+
var rawEntrySection = "PerformancePanel_rawEntrySection__19p8bogv";
|
|
754
|
+
var timestamp = "PerformancePanel_timestamp__19p8bogg";
|
|
755
|
+
|
|
756
|
+
//#endregion
|
|
757
|
+
//#region src/components/PerformancePanel.tsx
|
|
758
|
+
const isMetricFcpEntry = (entry) => {
|
|
759
|
+
return entry.entryType === "metric" && entry.name === "fcp";
|
|
760
|
+
};
|
|
761
|
+
const extractFcpMetrics = (entry) => {
|
|
762
|
+
if (!isMetricFcpEntry(entry) || !entry.rawEntry) return null;
|
|
763
|
+
const metricEntry = entry.rawEntry;
|
|
764
|
+
return {
|
|
765
|
+
totalFcp: metricEntry.totalFcp ?? void 0,
|
|
766
|
+
lynxFcp: metricEntry.lynxFcp ?? void 0,
|
|
767
|
+
fcp: metricEntry.fcp ?? void 0
|
|
768
|
+
};
|
|
769
|
+
};
|
|
770
|
+
const formatDuration = (ms) => {
|
|
771
|
+
if (ms === void 0) return "-";
|
|
772
|
+
return `${ms.toFixed(2)}ms`;
|
|
773
|
+
};
|
|
774
|
+
const getPrimaryFcpLabel = (entry) => {
|
|
775
|
+
const fcpMetrics = extractFcpMetrics(entry);
|
|
776
|
+
if (!fcpMetrics) return "";
|
|
777
|
+
const { totalFcp, lynxFcp, fcp } = fcpMetrics;
|
|
778
|
+
if (totalFcp?.duration !== void 0) return `totalFcp: ${formatDuration(totalFcp.duration)}`;
|
|
779
|
+
if (lynxFcp?.duration !== void 0) return `lynxFcp: ${formatDuration(lynxFcp.duration)}`;
|
|
780
|
+
if (fcp?.duration !== void 0) return `fcp: ${formatDuration(fcp.duration)}`;
|
|
781
|
+
return "";
|
|
782
|
+
};
|
|
783
|
+
const PerformancePanel = ({ performances, clearPerformances }) => {
|
|
784
|
+
const [selectedId, setSelectedId] = (0, _lynx_js_react.useState)(null);
|
|
785
|
+
if (performances.length === 0) return <view className={container$1}>
|
|
786
|
+
<view className={header}>
|
|
787
|
+
<text className={count}>0 entries</text>
|
|
788
|
+
<view bindtap={() => {
|
|
789
|
+
console.log("[PerformancePanel] performances", performances);
|
|
790
|
+
}} style={{
|
|
791
|
+
padding: "10px",
|
|
792
|
+
backgroundColor: "red"
|
|
793
|
+
}}>
|
|
794
|
+
<text>Log</text>
|
|
795
|
+
</view>
|
|
796
|
+
<view bindtap={clearPerformances} className={clearButton}>
|
|
797
|
+
<text className={clearButtonText}>Clear</text>
|
|
798
|
+
</view>
|
|
799
|
+
</view>
|
|
800
|
+
<view className={placeholder}>
|
|
801
|
+
<text className={placeholderText}>
|
|
802
|
+
No performance data yet...
|
|
803
|
+
</text>
|
|
804
|
+
</view>
|
|
805
|
+
</view>;
|
|
806
|
+
return <view className={container$1}>
|
|
807
|
+
<view className={header}>
|
|
808
|
+
<text className={count}>{performances.length} entries</text>
|
|
809
|
+
<view bindtap={clearPerformances} className={clearButton}>
|
|
810
|
+
<text className={clearButtonText}>Clear</text>
|
|
811
|
+
</view>
|
|
812
|
+
</view>
|
|
813
|
+
|
|
814
|
+
<list className={list}>
|
|
815
|
+
{performances.map((perf) => {
|
|
816
|
+
const isMetricFcp = isMetricFcpEntry(perf);
|
|
817
|
+
const fcpMetrics = extractFcpMetrics(perf);
|
|
818
|
+
const primaryFcp = getPrimaryFcpLabel(perf);
|
|
819
|
+
const { totalFcp, lynxFcp, fcp } = fcpMetrics ?? {};
|
|
820
|
+
return <list-item key={perf.id} item-key={perf.id}>
|
|
821
|
+
<view className={item}>
|
|
822
|
+
<view className={itemHeader} bindtap={() => setSelectedId(selectedId === perf.id ? null : perf.id)}>
|
|
823
|
+
<text className={entryType({ type: perf.entryType })}>
|
|
824
|
+
{perf.entryType}
|
|
825
|
+
</text>
|
|
826
|
+
<text className={entryName}>{perf.name}</text>
|
|
827
|
+
<text className={timestamp}>
|
|
828
|
+
{new Date(perf.timestamp).toISOString()}
|
|
829
|
+
</text>
|
|
830
|
+
</view>
|
|
831
|
+
|
|
832
|
+
<view bindtap={() => setSelectedId(selectedId === perf.id ? null : perf.id)}>
|
|
833
|
+
{isMetricFcp && primaryFcp && <text className={fcpHighlight}>{primaryFcp}</text>}
|
|
834
|
+
</view>
|
|
835
|
+
|
|
836
|
+
{selectedId === perf.id && <view className={detailsContainer}>
|
|
837
|
+
{isMetricFcp && fcpMetrics && <view className={fcpSection}>
|
|
838
|
+
{totalFcp !== void 0 && <view className={fcpMetric}>
|
|
839
|
+
<view className={fcpMetricHeader}>
|
|
840
|
+
<text className={fcpMetricName}>
|
|
841
|
+
전체 FCP
|
|
842
|
+
</text>
|
|
843
|
+
<text className={fcpMetricValue}>
|
|
844
|
+
{formatDuration(totalFcp.duration)}
|
|
845
|
+
</text>
|
|
846
|
+
</view>
|
|
847
|
+
<text className={fcpMetricDescription}>
|
|
848
|
+
PrepareTemplate Start부터 Paint End 까지 걸리는
|
|
849
|
+
시간
|
|
850
|
+
</text>
|
|
851
|
+
</view>}
|
|
852
|
+
|
|
853
|
+
{lynxFcp !== void 0 && <view className={fcpMetric}>
|
|
854
|
+
<view className={fcpMetricHeader}>
|
|
855
|
+
<text className={fcpMetricName}>LynxFCP</text>
|
|
856
|
+
<text className={fcpMetricValue}>
|
|
857
|
+
{formatDuration(lynxFcp.duration)}
|
|
858
|
+
</text>
|
|
859
|
+
</view>
|
|
860
|
+
<text className={fcpMetricDescription}>
|
|
861
|
+
Bundle Load 시작부터 Paint End 까지 걸리는 시간
|
|
862
|
+
</text>
|
|
863
|
+
</view>}
|
|
864
|
+
|
|
865
|
+
{fcp !== void 0 && <view className={fcpMetric}>
|
|
866
|
+
<view className={fcpMetricHeader}>
|
|
867
|
+
<text className={fcpMetricName}>
|
|
868
|
+
렌더링 FCP
|
|
869
|
+
</text>
|
|
870
|
+
<text className={fcpMetricValue}>
|
|
871
|
+
{formatDuration(fcp.duration)}
|
|
872
|
+
</text>
|
|
873
|
+
</view>
|
|
874
|
+
<text className={fcpMetricDescription}>
|
|
875
|
+
TemplateBundle 준비부터 Paint End 까지 걸리는 시간
|
|
876
|
+
</text>
|
|
877
|
+
</view>}
|
|
878
|
+
</view>}
|
|
879
|
+
|
|
880
|
+
{!!perf.rawEntry && <view className={rawEntrySection}>
|
|
881
|
+
<text className={detailTitle}>Raw Entry</text>
|
|
882
|
+
<text className={rawEntry}>
|
|
883
|
+
{String((0, javascript_stringify.stringify)(perf.rawEntry, null, 2, { references: true }))}
|
|
884
|
+
</text>
|
|
885
|
+
</view>}
|
|
886
|
+
</view>}
|
|
887
|
+
</view>
|
|
888
|
+
</list-item>;
|
|
889
|
+
})}
|
|
890
|
+
</list>
|
|
891
|
+
</view>;
|
|
892
|
+
};
|
|
893
|
+
|
|
894
|
+
//#endregion
|
|
895
|
+
//#region src/components/Tabs.css.ts
|
|
896
|
+
var tabContent = "Tabs_tabContent__ud1j9z8";
|
|
897
|
+
var tabContents = "Tabs_tabContents__ud1j9z7";
|
|
898
|
+
var tabHeader = "Tabs_tabHeader__ud1j9z1";
|
|
899
|
+
var tabTriggerButton = "Tabs_tabTriggerButton__ud1j9z2";
|
|
900
|
+
var tabTriggerButtonText = createRuntimeFn({
|
|
901
|
+
defaultClassName: "Tabs_tabTriggerButtonText__ud1j9z3",
|
|
902
|
+
variantClassNames: { active: { true: "Tabs_tabTriggerButtonText_active_true__ud1j9z4" } },
|
|
903
|
+
defaultVariants: {},
|
|
904
|
+
compoundVariants: []
|
|
905
|
+
});
|
|
906
|
+
var tabTriggerIndicator = "Tabs_tabTriggerIndicator__ud1j9z5";
|
|
907
|
+
var tabTriggerIndicatorLine = "Tabs_tabTriggerIndicatorLine__ud1j9z6";
|
|
908
|
+
var tabs = "Tabs_tabs__ud1j9z0";
|
|
909
|
+
|
|
910
|
+
//#endregion
|
|
911
|
+
//#region src/components/Tabs.tsx
|
|
912
|
+
function Tabs(props) {
|
|
913
|
+
const tabContentsRef = (0, _lynx_js_react.useRef)(null);
|
|
914
|
+
const [activeIndex, setActiveIndex] = (0, _lynx_js_react.useState)(0);
|
|
915
|
+
return <view className={tabs}>
|
|
916
|
+
<view className={tabHeader}>
|
|
917
|
+
{props.items.map((item, i) => <view key={item.key} className={tabTriggerButton} bindtap={() => {
|
|
918
|
+
setActiveIndex(i);
|
|
919
|
+
tabContentsRef.current?.invoke({
|
|
920
|
+
method: "scrollToPosition",
|
|
921
|
+
params: {
|
|
922
|
+
position: i,
|
|
923
|
+
smooth: true
|
|
924
|
+
}
|
|
925
|
+
}).exec();
|
|
926
|
+
}}>
|
|
927
|
+
<text className={tabTriggerButtonText({ active: i === activeIndex })}>
|
|
928
|
+
{item.label}
|
|
929
|
+
</text>
|
|
930
|
+
{i === 0 && <view className={tabTriggerIndicator} style={{ transform: `translateX(${activeIndex * 100}%)` }}>
|
|
931
|
+
<view className={tabTriggerIndicatorLine} />
|
|
932
|
+
</view>}
|
|
933
|
+
</view>)}
|
|
934
|
+
</view>
|
|
935
|
+
|
|
936
|
+
<list ref={tabContentsRef} className={tabContents} scroll-orientation="horizontal" item-snap={{
|
|
937
|
+
factor: 0,
|
|
938
|
+
offset: 0
|
|
939
|
+
}} bindsnap={(e) => {
|
|
940
|
+
setActiveIndex(e.detail.position);
|
|
941
|
+
}} bounces={false} preload-buffer-count={props.items.length}>
|
|
942
|
+
{props.items.map((item) => <list-item key={item.key} item-key={item.key} recyclable={false} className={tabContent}>
|
|
943
|
+
{item.renderContent()}
|
|
944
|
+
</list-item>)}
|
|
945
|
+
</list>
|
|
946
|
+
</view>;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
//#endregion
|
|
950
|
+
//#region src/components/ConsolePanel.tsx
|
|
951
|
+
const ConsolePanel = () => {
|
|
952
|
+
const { logs, clearLogs } = useConsole();
|
|
953
|
+
const { networks, clearNetworks } = useNetwork();
|
|
954
|
+
const { performances, clearPerformances } = usePerformance();
|
|
955
|
+
return <view className={container$3}>
|
|
956
|
+
<Tabs items={[
|
|
957
|
+
{
|
|
958
|
+
key: "log",
|
|
959
|
+
label: "Log",
|
|
960
|
+
renderContent: () => <LogPanel logs={logs} clearLogs={clearLogs} />
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
key: "network",
|
|
964
|
+
label: "Network",
|
|
965
|
+
renderContent: () => <NetworkPanel networks={networks} clearNetworks={clearNetworks} />
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
key: "performance",
|
|
969
|
+
label: "Performance",
|
|
970
|
+
renderContent: () => <PerformancePanel performances={performances} clearPerformances={clearPerformances} />
|
|
971
|
+
}
|
|
972
|
+
]} />
|
|
973
|
+
</view>;
|
|
974
|
+
};
|
|
975
|
+
|
|
976
|
+
//#endregion
|
|
977
|
+
//#region src/components/FloatingButton.css.ts
|
|
978
|
+
var button = "FloatingButton_button__1homwpu2";
|
|
979
|
+
var container = "FloatingButton_container__1homwpu1";
|
|
980
|
+
var reloadButton = "FloatingButton_reloadButton__1homwpu5";
|
|
981
|
+
var reloadIcon = "FloatingButton_reloadIcon__1homwpu6";
|
|
982
|
+
var subtitle = "FloatingButton_subtitle__1homwpu4";
|
|
983
|
+
var title = "FloatingButton_title__1homwpu3";
|
|
984
|
+
var wrapper = "FloatingButton_wrapper__1homwpu0";
|
|
985
|
+
|
|
986
|
+
//#endregion
|
|
987
|
+
//#region src/components/FloatingButton.tsx
|
|
988
|
+
const FloatingButton = ({ bindtap, isVisible, children }) => {
|
|
989
|
+
if (!isVisible) return null;
|
|
990
|
+
const handleReload = () => {
|
|
991
|
+
try {
|
|
992
|
+
lynx.reload({}, () => {
|
|
993
|
+
console.log("reloaded!");
|
|
994
|
+
});
|
|
995
|
+
} catch (e) {
|
|
996
|
+
console.error("[LynxConsole] reload failed:", e);
|
|
997
|
+
}
|
|
998
|
+
};
|
|
999
|
+
return <view className={wrapper}>
|
|
1000
|
+
<view className={container} bindtap={bindtap}>
|
|
1001
|
+
<view className={button}>{children}</view>
|
|
1002
|
+
</view>
|
|
1003
|
+
<view className={reloadButton} bindtap={handleReload}>
|
|
1004
|
+
<text className={reloadIcon}>{"↻"}</text>
|
|
1005
|
+
</view>
|
|
1006
|
+
</view>;
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
//#endregion
|
|
1010
|
+
//#region src/index.tsx
|
|
1011
|
+
const LynxConsole = (0, _lynx_js_react.forwardRef)(({ theme = "light", safeAreaInsetBottom = "50px" }, ref) => {
|
|
1012
|
+
const [isOpen, setIsOpen] = (0, _lynx_js_react.useState)(false);
|
|
1013
|
+
const [shouldClose, setShouldClose] = (0, _lynx_js_react.useState)(false);
|
|
1014
|
+
const { performances } = usePerformance();
|
|
1015
|
+
const latestFcp = (0, _lynx_js_react.useMemo)(() => {
|
|
1016
|
+
for (let i = performances.length - 1; i >= 0; i--) {
|
|
1017
|
+
const perf = performances[i];
|
|
1018
|
+
if (perf && perf.entryType === "metric" && perf.name === "fcp") {
|
|
1019
|
+
const metricEntry = perf.rawEntry;
|
|
1020
|
+
if (metricEntry?.totalFcp?.duration !== void 0) return metricEntry.totalFcp;
|
|
1021
|
+
if (metricEntry?.lynxFcp?.duration !== void 0) return metricEntry.lynxFcp;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}, [performances]);
|
|
1025
|
+
(0, _lynx_js_react.useImperativeHandle)(ref, () => ({
|
|
1026
|
+
open: () => {
|
|
1027
|
+
setIsOpen(true);
|
|
1028
|
+
setShouldClose(false);
|
|
1029
|
+
},
|
|
1030
|
+
close: () => {
|
|
1031
|
+
setShouldClose(true);
|
|
1032
|
+
},
|
|
1033
|
+
isOpen: () => isOpen
|
|
1034
|
+
}));
|
|
1035
|
+
const handleOpenBottomSheet = () => {
|
|
1036
|
+
setIsOpen(true);
|
|
1037
|
+
setShouldClose(false);
|
|
1038
|
+
};
|
|
1039
|
+
const handleCloseBottomSheet = () => {
|
|
1040
|
+
setIsOpen(false);
|
|
1041
|
+
setShouldClose(false);
|
|
1042
|
+
};
|
|
1043
|
+
const themeClass = `data-seed-color-mode__${theme}-only`;
|
|
1044
|
+
return <view className={themeClass}>
|
|
1045
|
+
<FloatingButton bindtap={handleOpenBottomSheet} isVisible={!isOpen}>
|
|
1046
|
+
<text className={title}>LynxConsole</text>
|
|
1047
|
+
<text className={subtitle}>
|
|
1048
|
+
{`${latestFcp?.name ?? "FCP"}: ${latestFcp?.duration ? latestFcp.duration.toFixed(2) : "--"}ms`}
|
|
1049
|
+
</text>
|
|
1050
|
+
</FloatingButton>
|
|
1051
|
+
{isOpen && <BottomSheet isOpen={isOpen} shouldClose={shouldClose} onClose={handleCloseBottomSheet} title="Lynx Console" safeAreaInsetBottom={safeAreaInsetBottom}>
|
|
1052
|
+
<ConsolePanel />
|
|
1053
|
+
</BottomSheet>}
|
|
1054
|
+
</view>;
|
|
1055
|
+
});
|
|
1056
|
+
|
|
1057
|
+
//#endregion
|
|
1058
|
+
module.exports = LynxConsole;
|