lynx-console 0.2.1 → 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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/components/BottomSheet.tsx","../src/hooks/useConsole.ts","../src/hooks/useNetwork.ts","../src/hooks/usePerformance.ts","../src/components/FadeList.tsx","../src/components/LogPanel.tsx","../src/components/NetworkDetailSection.tsx","../src/components/NetworkPanel.tsx","../src/components/PerformancePanel.tsx","../src/components/Tabs.tsx","../src/components/ConsolePanel.tsx","../src/hooks/useLongPressDrag.ts","../src/components/FloatingButton.tsx","../src/index.tsx"],"sourcesContent":["import { type ReactNode, useEffect, useState } from \"@lynx-js/react\";\nimport type { BaseTouchEvent, Target } from \"@lynx-js/types\";\nimport \"./BottomSheet.css\";\n\ninterface BottomSheetProps {\n children: ReactNode;\n title?: string;\n footer?: ReactNode;\n onClose: () => void;\n isOpen: boolean;\n shouldClose?: boolean;\n safeAreaInsetBottom?: string;\n}\n\nconst MIN_HEIGHT = 200;\nconst MAX_HEIGHT = 700;\nconst DEFAULT_HEIGHT = 500;\nconst CLOSE_DRAG_THRESHOLD = 30; // 30px 이상 아래로 드래그하면 닫힘\n\n// 마지막 높이 저장\nlet savedHeight: number | null = null;\n\nexport default function BottomSheet({\n children,\n title,\n footer,\n onClose,\n isOpen,\n shouldClose = false,\n safeAreaInsetBottom = \"25px\",\n}: BottomSheetProps) {\n const [sheetHeight, setSheetHeight] = useState(savedHeight ?? DEFAULT_HEIGHT);\n const [tempHeight, setTempHeight] = useState(savedHeight ?? DEFAULT_HEIGHT);\n const [isDragging, setIsDragging] = useState(false);\n const [dragStartY, setDragStartY] = useState(0);\n const [dragStartHeight, setDragStartHeight] = useState(\n savedHeight ?? DEFAULT_HEIGHT,\n );\n const [isOpening, setIsOpening] = useState(true);\n const [isClosing, setIsClosing] = useState(false);\n\n // 닫기 애니메이션 처리\n const handleClose = () => {\n setIsClosing(true);\n setTimeout(() => {\n onClose();\n }, 300);\n };\n\n // 아래에서 올라오는 애니메이션\n useEffect(() => {\n requestAnimationFrame(() => {\n setIsOpening(false);\n });\n }, []);\n\n // 외부에서 닫기 요청 시 애니메이션 처리\n useEffect(() => {\n if (shouldClose && !isClosing) {\n handleClose();\n }\n }, [shouldClose, isClosing]);\n\n // 높이 변경 시 저장\n useEffect(() => {\n savedHeight = sheetHeight;\n }, [sheetHeight]);\n\n if (!isOpen) return null;\n\n const handleTouchStart = (e: BaseTouchEvent<Target>) => {\n setIsDragging(true);\n setDragStartY(e.detail.y);\n setDragStartHeight(sheetHeight);\n setTempHeight(sheetHeight);\n };\n\n const handleTouchMove = (e: BaseTouchEvent<Target>) => {\n if (!isDragging) return;\n const deltaY = dragStartY - e.detail.y;\n const newHeight = Math.min(\n Math.max(dragStartHeight + deltaY, MIN_HEIGHT),\n MAX_HEIGHT,\n );\n setTempHeight(newHeight);\n };\n\n const handleTouchEnd = () => {\n setIsDragging(false);\n\n // 아래로 일정 30px 이상 드래그하면 닫기\n const dragDistance = dragStartHeight - tempHeight;\n setSheetHeight(tempHeight);\n if (dragDistance > CLOSE_DRAG_THRESHOLD) {\n handleClose();\n }\n };\n\n return (\n <scroll-view\n className=\"bs-backdrop\"\n style={{\n opacity: isOpening || isClosing ? 0 : 1,\n }}\n >\n <view className=\"bs-overlay\" bindtap={handleClose}>\n <view\n className=\"bs-content\"\n catchtap={() => {}}\n style={{\n height: `${isDragging ? tempHeight : sheetHeight}px`,\n transform:\n isOpening || isClosing ? \"translateY(100%)\" : \"translateY(0)\",\n transition: isDragging ? \"none\" : undefined,\n }}\n >\n {/* catchtap: 이벤트 버블링 차단 */}\n <view\n className=\"bs-handleContainer\"\n bindtouchstart={handleTouchStart}\n bindtouchmove={handleTouchMove}\n bindtouchend={handleTouchEnd}\n >\n <view className=\"bs-handle\" />\n </view>\n <view className=\"bs-header\">\n {title && <text className=\"bs-title\">{title}</text>}\n </view>\n <view\n className=\"bs-body\"\n style={{\n paddingBottom: safeAreaInsetBottom,\n }}\n >\n {children}\n </view>\n {footer && <view className=\"bs-footer\">{footer}</view>}\n </view>\n </view>\n </scroll-view>\n );\n}\n","import { useEffect, useState } from \"@lynx-js/react\";\nimport type { LogEntry } from \"../types\";\n\nexport const useConsole = () => {\n const [logs, setLogs] = useState<LogEntry[]>([]);\n\n useEffect(() => {\n if (typeof globalThis.__LYNX_CONSOLE__?.state?.logs === \"undefined\") {\n console.warn(\"[LynxConsole] Log monitoring not initialized\");\n return;\n }\n\n const state = globalThis.__LYNX_CONSOLE__.state;\n\n setLogs([...(state.logs ?? [])]);\n\n const updateLogs = (_entry: LogEntry) => {\n setLogs([...(state.logs ?? [])]);\n };\n\n const unsubscribe = state.logSubscribe?.(updateLogs);\n\n return unsubscribe;\n }, []);\n\n const clearLogs = () => {\n if (typeof globalThis.__LYNX_CONSOLE__?.state?.logs !== \"undefined\") {\n const state = globalThis.__LYNX_CONSOLE__.state;\n state.logs = [];\n setLogs([]);\n }\n };\n\n return { logs, clearLogs };\n};\n","import { useEffect, useState } from \"@lynx-js/react\";\nimport type { NetworkEntry } from \"../types\";\n\nexport const useNetwork = () => {\n const [networks, setNetworks] = useState<NetworkEntry[]>([]);\n\n useEffect(() => {\n if (typeof globalThis.__LYNX_CONSOLE__?.state?.networks === \"undefined\") {\n console.warn(\"[LynxConsole] Network monitoring not initialized\");\n return;\n }\n\n const state = globalThis.__LYNX_CONSOLE__.state;\n\n setNetworks([...(state.networks ?? [])]);\n\n const updateNetworks = (_entry: NetworkEntry) => {\n setNetworks([...(state.networks ?? [])]);\n };\n\n const unsubscribe = state.subscribeNetwork?.(updateNetworks);\n\n return unsubscribe;\n }, []);\n\n const clearNetworks = () => {\n if (typeof globalThis.__LYNX_CONSOLE__?.state?.networks !== \"undefined\") {\n const state = globalThis.__LYNX_CONSOLE__.state;\n state.networks = [];\n state.networksMap?.clear();\n setNetworks([]);\n }\n };\n\n return { networks, clearNetworks };\n};\n","import { useEffect, useState } from \"@lynx-js/react\";\nimport type { PerformanceEntryData } from \"../types\";\n\nexport const usePerformance = () => {\n const [performances, setPerformances] = useState<PerformanceEntryData[]>([]);\n\n useEffect(() => {\n if (\n typeof globalThis.__LYNX_CONSOLE__?.state?.performances === \"undefined\"\n ) {\n console.warn(\"[LynxConsole] Performance monitoring not initialized\");\n return;\n }\n\n const state = globalThis.__LYNX_CONSOLE__.state;\n\n setPerformances([...(state.performances ?? [])]);\n\n const updatePerformances = (_entry: PerformanceEntryData) => {\n setPerformances([...(state.performances ?? [])]);\n };\n\n const unsubscribe = state.subscribePerformance?.(updatePerformances);\n\n return unsubscribe;\n }, []);\n\n const clearPerformances = () => {\n if (\n typeof globalThis.__LYNX_CONSOLE__?.state?.performances !== \"undefined\"\n ) {\n const state = globalThis.__LYNX_CONSOLE__.state;\n state.performances = [];\n setPerformances([]);\n }\n };\n\n return { performances, clearPerformances };\n};\n","import { useRef } from \"@lynx-js/react\";\nimport type { NodesRef } from \"@lynx-js/types\";\n\ninterface FadeListProps {\n className?: string;\n listRef?: React.RefObject<NodesRef>;\n children: React.ReactNode;\n \"preload-buffer-count\"?: number;\n \"initial-scroll-index\"?: number;\n}\n\nexport const FadeList = ({\n className,\n listRef: externalListRef,\n children,\n ...listProps\n}: FadeListProps) => {\n const internalListRef = useRef<NodesRef>(null);\n const listRef = externalListRef ?? internalListRef;\n\n return (\n <list\n ref={listRef}\n scroll-orientation=\"vertical\"\n className={className}\n {...listProps}\n >\n {children}\n </list>\n );\n};\n","import { useEffect, useMemo, useRef, useState } from \"@lynx-js/react\";\nimport type { BaseEvent, InputInputEvent, NodesRef } from \"@lynx-js/types\";\nimport { stringify } from \"javascript-stringify\";\nimport type { LogEntry, LogLevel } from \"../types\";\nimport \"./ConsolePanel.css\";\nimport { FadeList } from \"./FadeList\";\n\nconst LOG_LEVELS: LogLevel[] = [\"log\", \"info\", \"warn\", \"error\"];\n\nlet savedEnabledLevels: Set<LogLevel> | null = null;\nlet savedSearchQuery = \"\";\nlet closeFilterDropdown: (() => void) | null = null;\n\nexport const dismissFilterDropdown = () => closeFilterDropdown?.();\n\ninterface LogPanelProps {\n logs: LogEntry[];\n clearLogs: () => void;\n}\n\nconst runCode = (code: string) => {\n try {\n // biome-ignore lint: intentional REPL tool\n const result = eval(code);\n if (result instanceof Promise) {\n result.then((r) => console.log(r)).catch((e) => console.error(e));\n } else {\n console.log(result);\n }\n } catch (e) {\n console.error(e);\n }\n};\n\nexport const LogPanel = ({ logs, clearLogs }: LogPanelProps) => {\n const [expandedArgs, setExpandedArgs] = useState(new Set());\n const [code, setCode] = useState(\"\");\n const [enabledLevels, setEnabledLevels] = useState<Set<LogLevel>>(\n () => savedEnabledLevels ?? new Set(LOG_LEVELS),\n );\n const [filterOpen, setFilterOpen] = useState(false);\n const [searchQuery, setSearchQuery] = useState(savedSearchQuery);\n const inputRef = useRef<NodesRef>(null);\n const searchInputRef = useRef<NodesRef>(null);\n const listRef = useRef<NodesRef>(null);\n\n useEffect(() => {\n savedEnabledLevels = enabledLevels;\n }, [enabledLevels]);\n\n useEffect(() => {\n savedSearchQuery = searchQuery;\n }, [searchQuery]);\n\n useEffect(() => {\n if (savedSearchQuery) {\n searchInputRef.current\n ?.invoke({ method: \"setValue\", params: { value: savedSearchQuery } })\n .exec();\n }\n }, []);\n\n useEffect(() => {\n closeFilterDropdown = () => setFilterOpen(false);\n return () => { closeFilterDropdown = null; };\n }, []);\n\n const filteredLogs = useMemo(\n () =>\n logs.filter((log) => {\n if (!enabledLevels.has(log.level)) return false;\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n return log.args.some((arg) => String(arg).toLowerCase().includes(query));\n }\n return true;\n }),\n [logs, enabledLevels, searchQuery],\n );\n const logsRef = useRef(filteredLogs);\n logsRef.current = filteredLogs;\n\n const toggleLevel = (level: LogLevel) => {\n setEnabledLevels((prev) => {\n const next = new Set(prev);\n if (next.has(level)) {\n next.delete(level);\n } else {\n next.add(level);\n }\n return next;\n });\n };\n\n const scrollToBottom = (smooth: boolean) => {\n if (logsRef.current.length === 0) return;\n listRef.current\n ?.invoke({\n method: \"scrollToPosition\",\n params: { position: logsRef.current.length - 1, smooth },\n })\n .exec();\n };\n\n useEffect(() => {\n scrollToBottom(true);\n }, [filteredLogs]);\n\n const toggleArg = (key: string) => {\n setExpandedArgs((prev) => {\n const next = new Set(prev);\n if (next.has(key)) {\n next.delete(key);\n } else {\n next.add(key);\n }\n return next;\n });\n };\n\n const handleRun = () => {\n const trimmed = code.trim();\n if (!trimmed) return;\n\n setCode(\"\");\n inputRef.current\n ?.invoke({ method: \"setValue\", params: { value: \"\" } })\n .exec();\n runCode(trimmed);\n setTimeout(() => scrollToBottom(false), 100);\n };\n\n const renderArg = (\n arg: unknown,\n parentKey: string,\n level: \"log\" | \"info\" | \"warn\" | \"error\",\n ): React.ReactNode => {\n const key = parentKey;\n const isExpanded = expandedArgs.has(key);\n\n if (arg === null) {\n return <text className={\"cp-argNull\"}>null</text>;\n }\n\n if (arg === undefined) {\n return <text className={\"cp-argUndefined\"}>undefined</text>;\n }\n\n if (typeof arg === \"string\") {\n const MAX_LENGTH = 80;\n const shouldTruncate = arg.length > MAX_LENGTH;\n\n if (!shouldTruncate) {\n return <text className={`cp-argString cp-argString--${level}`}>{arg}</text>;\n }\n\n return (\n <view className={\"cp-argObject\"}>\n <view className={\"cp-argObjectHeader\"} bindtap={() => toggleArg(key)}>\n <text className={\"cp-toggleIndicator\"}>\n {isExpanded ? \"▼\" : \"▶\"}\n </text>\n <text className={`cp-argString cp-argString--${level}`}>\n {isExpanded ? arg : `${arg.slice(0, MAX_LENGTH)}...`}\n </text>\n </view>\n </view>\n );\n }\n\n if (typeof arg === \"number\" || typeof arg === \"boolean\") {\n return <text className={`cp-argPrimitive cp-argPrimitive--${level}`}>{String(arg)}</text>;\n }\n\n if (typeof arg === \"object\") {\n let preview = \"Object\";\n if (Array.isArray(arg)) {\n preview = `Array(${arg.length})`;\n } else if (arg instanceof Map) {\n preview = `Map(${arg.size})`;\n } else if (arg instanceof Set) {\n preview = `Set(${arg.size})`;\n } else if (arg instanceof Date) {\n preview = `Date`;\n } else if (arg instanceof RegExp) {\n preview = `RegExp`;\n } else if (arg instanceof Error) {\n preview = `${arg.constructor.name}`;\n } else if (arg?.constructor?.name && arg.constructor.name !== \"Object\") {\n preview = arg.constructor.name;\n }\n\n let jsonString: string;\n if (arg instanceof Map) {\n const entries = Array.from(arg.entries()).map(\n ([k, v]) => ` [${stringify(k)}, ${stringify(v)}]`,\n );\n jsonString = `{\\n${entries.join(\",\\n\")}\\n}`;\n } else if (arg instanceof Set) {\n const values = Array.from(arg.values()).map((v) => stringify(v));\n jsonString = `{\\n${values.join(\", \")}\\n}`;\n } else {\n jsonString =\n stringify(arg, null, 2, { references: true }) ?? String(arg);\n }\n\n return (\n <view className={\"cp-argObject\"}>\n <view className={\"cp-argObjectHeader\"} bindtap={() => toggleArg(key)}>\n <text className={\"cp-toggleIndicator\"}>\n {isExpanded ? \"▼\" : \"▶\"}\n </text>\n <text className={\"cp-argObjectPreview\"}>{preview}</text>\n </view>\n {isExpanded && (\n <view className={\"cp-argObjectContent\"}>\n <text className={\"cp-argObjectJson\"}>{jsonString}</text>\n </view>\n )}\n </view>\n );\n }\n\n return <text className={`cp-argPrimitive cp-argPrimitive--${level}`}>{String(arg)}</text>;\n };\n\n return (\n <view\n className={\"cp-logContainer\"}\n bindtap={() => { if (filterOpen) setFilterOpen(false); }}\n >\n <view className={\"cp-logHeader\"}>\n <view className={\"cp-filterWrapper\"}>\n <view\n className={\"cp-filterButton\"}\n catchtap={() => setFilterOpen((v) => !v)}\n >\n <text className={\"cp-filterButtonText\"}>Filter ▼</text>\n </view>\n {filterOpen && (\n <view className={\"cp-filterDropdown\"} catchtap={() => {}}>\n {LOG_LEVELS.map((level) => (\n <view\n key={level}\n className={\"cp-filterOption\"}\n bindtap={() => toggleLevel(level)}\n >\n <text className={`cp-filterCheckbox cp-filterCheckbox--${level}`}>\n {enabledLevels.has(level) ? \"✅\" : \"⬜\"}\n </text>\n <text className={`cp-filterLabel cp-filterLabel--${level}`}>\n {level.toUpperCase()}\n </text>\n </view>\n ))}\n </view>\n )}\n </view>\n <view className={\"cp-searchWrapper\"}>\n <text className={\"cp-searchPrompt\"}>{\"›\"}</text>\n <input\n ref={searchInputRef}\n className={\"cp-searchInput\"}\n placeholder=\"Search logs...\"\n bindinput={(e: BaseEvent<\"bindinput\", InputInputEvent>) =>\n setSearchQuery(e.detail.value)\n }\n />\n {searchQuery.length > 0 && (\n <view\n className={\"cp-searchClear\"}\n bindtap={() => {\n setSearchQuery(\"\");\n searchInputRef.current\n ?.invoke({ method: \"setValue\", params: { value: \"\" } })\n .exec();\n }}\n >\n <text className={\"cp-searchClearText\"}>✕</text>\n </view>\n )}\n </view>\n <view style={{ display: \"flex\", flexDirection: \"row\", gap: 8 }}>\n <view className={\"cp-clearButton\"} bindtap={clearLogs}>\n <text className={\"cp-clearButtonText\"}>🗑</text>\n </view>\n </view>\n </view>\n <FadeList\n listRef={listRef}\n className={\"cp-logList\"}\n preload-buffer-count={10}\n initial-scroll-index={Math.max(0, filteredLogs.length - 1)}\n >\n {filteredLogs.length === 0 ? (\n <list-item item-key=\"empty-state\">\n <view className={\"cp-placeholder\"}>\n <text className={\"cp-placeholderText\"}>\n No logs yet. Try console.log(\"Hello!\")\n </text>\n </view>\n </list-item>\n ) : (\n filteredLogs.map((log) => {\n return (\n <list-item key={log.id} item-key={log.id}>\n <view className={`cp-logItem cp-logItem--${log.level}`}>\n <view className={\"cp-logItemHeader\"}>\n <text className={`cp-logLevel cp-logLevel--${log.level}`}>\n {log.level.toUpperCase()}\n </text>\n <text className={\"cp-logTime\"}>\n {new Date(log.timestamp).toISOString()}\n </text>\n </view>\n <view className={\"cp-logArgsContainer\"}>\n {log.args.map((arg, index) => (\n <view\n key={`${log.id}-${index.toString()}`}\n className={\"cp-logArgItem\"}\n >\n {renderArg(\n arg,\n `${log.id}-${index.toString()}`,\n log.level,\n )}\n </view>\n ))}\n </view>\n </view>\n </list-item>\n );\n })\n )}\n </FadeList>\n <view className={\"cp-replInputRow\"}>\n <text className={\"cp-replPrompt\"}>{\"›\"}</text>\n <input\n ref={inputRef}\n className={\"cp-replInput\"}\n placeholder=\"enter code...\"\n bindinput={(e: BaseEvent<\"bindinput\", InputInputEvent>) =>\n setCode(e.detail.value)\n }\n bindconfirm={handleRun}\n />\n <view className={\"cp-replRunButton\"} bindtap={handleRun}>\n <text className={\"cp-replRunButtonText\"}>Run</text>\n </view>\n </view>\n </view>\n );\n};\n","import \"./NetworkPanel.css\";\n\ninterface NetworkDetailSectionProps {\n headers?: Record<string, string> | undefined;\n body?: string | undefined;\n error?: string | undefined;\n}\n\nexport const NetworkDetailSection = ({\n headers = {},\n body = \"\",\n error = \"\",\n}: NetworkDetailSectionProps) => {\n return (\n <>\n {/* Headers */}\n <view className={\"np-detailSection\"}>\n <text className={\"np-detailSectionTitle\"}>Headers</text>\n {headers && Object.keys(headers).length > 0 ? (\n <view className={\"np-table\"}>\n {Object.entries(headers).map(([key, value]) => (\n <view key={key} className={\"np-tableRow\"}>\n <text className={\"np-tableKey\"}>{key}</text>\n <text className={\"np-tableValue\"}>{value}</text>\n </view>\n ))}\n </view>\n ) : (\n <text className={\"np-emptyText\"}>No headers</text>\n )}\n </view>\n\n {/* Body */}\n <view className={\"np-detailSection\"}>\n <text className={\"np-detailSectionTitle\"}>Body</text>\n {error && <text className={\"np-errorText\"}>{error}</text>}\n {body && <text className={\"np-bodyText\"}>{body}</text>}\n {!error && !body && <text className={\"np-emptyText\"}>No body</text>}\n </view>\n </>\n );\n};\n","import { useState } from \"@lynx-js/react\";\nimport type { NetworkEntry } from \"../types\";\nimport { FadeList } from \"./FadeList\";\nimport { NetworkDetailSection } from \"./NetworkDetailSection\";\nimport \"./NetworkPanel.css\";\n\ninterface NetworkPanelProps {\n networks: NetworkEntry[];\n clearNetworks: () => void;\n}\n\ntype TabType = \"general\" | \"request\" | \"response\";\n\nexport const NetworkPanel = ({\n networks,\n clearNetworks,\n}: NetworkPanelProps) => {\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [activeTab, setActiveTab] = useState<TabType>(\"general\");\n const formatDuration = (duration?: number): string => {\n if (!duration) return \"-\";\n if (duration < 1000) return `${duration}ms`;\n return `${(duration / 1000).toFixed(2)}s`;\n };\n\n const extractPath = (url: string): string => {\n const pathMatch = url.match(/^https?:\\/\\/[^/]+(.*)$/);\n if (pathMatch?.[1]) {\n return pathMatch[1].startsWith(\"/\")\n ? pathMatch[1].slice(1)\n : pathMatch[1];\n }\n return url;\n };\n\n const getGeneralInfo = (network: NetworkEntry) => {\n return [\n { key: \"URL\", value: network.url },\n { key: \"Method\", value: network.method },\n network.statusCode\n ? { key: \"Status\", value: String(network.statusCode) }\n : null,\n {\n key: \"Request Time\",\n value: new Date(network.startTime).toISOString(),\n },\n network.endTime\n ? {\n key: \"Response Time\",\n value: new Date(network.endTime).toISOString(),\n }\n : null,\n network.duration\n ? { key: \"Duration\", value: formatDuration(network.duration) }\n : null,\n ].filter((item) => item !== null);\n };\n\n const getStatusCodeVariant = (\n status: string,\n statusCode?: number,\n ): \"success\" | \"error\" | \"pending\" => {\n if (status === \"pending\") return \"pending\";\n if (status === \"error\") return \"error\";\n if (statusCode && statusCode >= 200 && statusCode < 300) return \"success\";\n return \"error\";\n };\n\n return (\n <view className={\"np-container\"}>\n <view className={\"np-header\"}>\n <text className={\"np-count\"}>Total: {networks.length} requests</text>\n <view className={\"np-clearButton\"} bindtap={clearNetworks}>\n <text className={\"np-clearButtonText\"}>🗑</text>\n </view>\n </view>\n\n {networks.length === 0 ? (\n <view className={\"np-placeholder\"}>\n <text className={\"np-placeholderText\"}>No network requests yet</text>\n </view>\n ) : (\n <FadeList className={\"np-list\"}>\n {networks.map((network) => (\n <list-item key={network.id} item-key={network.id}>\n <view className={`np-item np-item--${network.status}`}>\n <view\n className={\"np-itemHeader\"}\n bindtap={() =>\n setSelectedId(selectedId === network.id ? null : network.id)\n }\n >\n <text\n className={`np-method np-method--${network.method}`}\n >\n {network.method}\n </text>\n {network.statusCode && (\n <text\n className={`np-statusCode np-statusCode--${getStatusCodeVariant(network.status, network.statusCode)}`}\n >\n {network.statusCode}\n </text>\n )}\n {network.status === \"pending\" && (\n <text className={\"np-statusCode np-statusCode--pending\"}>\n Pending...\n </text>\n )}\n <text className={\"np-time\"}>\n {formatDuration(network.duration)}\n </text>\n <text className={\"np-time\"}>\n {new Date(network.startTime).toISOString()}\n </text>\n </view>\n\n <text\n className={\"np-path\"}\n bindtap={() =>\n setSelectedId(selectedId === network.id ? null : network.id)\n }\n >\n {extractPath(network.url)}\n </text>\n\n {selectedId === network.id && (\n <view className={\"np-detailsContainer\"}>\n {/* Tabs */}\n <view className={\"np-tabs\"}>\n <view\n className={`np-tab${activeTab === \"general\" ? \" np-tab--active\" : \"\"}`}\n bindtap={() => setActiveTab(\"general\")}\n >\n <text\n className={`np-tabText${activeTab === \"general\" ? \" np-tabText--active\" : \"\"}`}\n >\n General\n </text>\n </view>\n <view\n className={`np-tab${activeTab === \"request\" ? \" np-tab--active\" : \"\"}`}\n bindtap={() => setActiveTab(\"request\")}\n >\n <text\n className={`np-tabText${activeTab === \"request\" ? \" np-tabText--active\" : \"\"}`}\n >\n Request\n </text>\n </view>\n <view\n className={`np-tab${activeTab === \"response\" ? \" np-tab--active\" : \"\"}`}\n bindtap={() => setActiveTab(\"response\")}\n >\n <text\n className={`np-tabText${activeTab === \"response\" ? \" np-tabText--active\" : \"\"}`}\n >\n Response\n </text>\n </view>\n </view>\n\n {/* Tab Content */}\n <view className={\"np-tabContent\"}>\n {activeTab === \"general\" && (\n <view className={\"np-table\"}>\n {getGeneralInfo(network).map((item) => (\n <view key={item.key} className={\"np-tableRow\"}>\n <text className={\"np-tableKey\"}>{item.key}</text>\n <text className={\"np-tableValue\"}>\n {item.value}\n </text>\n </view>\n ))}\n </view>\n )}\n\n {activeTab === \"request\" && (\n <NetworkDetailSection\n headers={network.requestHeaders}\n body={network.requestBody}\n />\n )}\n\n {activeTab === \"response\" && (\n <NetworkDetailSection\n headers={network.responseHeaders}\n body={network.responseBody}\n error={network.error}\n />\n )}\n </view>\n </view>\n )}\n </view>\n </list-item>\n ))}\n </FadeList>\n )}\n </view>\n );\n};\n","import { useState } from \"@lynx-js/react\";\nimport { stringify } from \"javascript-stringify\";\nimport type { PerformanceEntryData } from \"../types\";\nimport { FadeList } from \"./FadeList\";\nimport \"./PerformancePanel.css\";\n\ninterface PerformancePanelProps {\n performances: PerformanceEntryData[];\n clearPerformances: () => void;\n}\n\ninterface FcpMetric {\n name: string;\n duration: number;\n}\n\ninterface MetricFcpEntry {\n totalFcp?: FcpMetric;\n lynxFcp?: FcpMetric;\n fcp?: FcpMetric;\n}\n\nconst isMetricFcpEntry = (entry: PerformanceEntryData): boolean => {\n return entry.entryType === \"metric\" && entry.name === \"fcp\";\n};\n\nconst extractFcpMetrics = (entry: PerformanceEntryData) => {\n if (!isMetricFcpEntry(entry) || !entry.rawEntry) {\n return null;\n }\n\n const metricEntry = entry.rawEntry as MetricFcpEntry;\n\n return {\n totalFcp: metricEntry.totalFcp ?? undefined,\n lynxFcp: metricEntry.lynxFcp ?? undefined,\n fcp: metricEntry.fcp ?? undefined,\n };\n};\n\nconst formatDuration = (ms?: number): string => {\n if (ms === undefined) return \"-\";\n return `${ms.toFixed(2)}ms`;\n};\n\nconst getPrimaryFcpLabel = (entry: PerformanceEntryData): string => {\n const fcpMetrics = extractFcpMetrics(entry);\n if (!fcpMetrics) return \"\";\n\n const { totalFcp, lynxFcp, fcp } = fcpMetrics;\n\n if (totalFcp?.duration !== undefined) {\n return `totalFcp: ${formatDuration(totalFcp.duration)}`;\n }\n if (lynxFcp?.duration !== undefined) {\n return `lynxFcp: ${formatDuration(lynxFcp.duration)}`;\n }\n if (fcp?.duration !== undefined) {\n return `fcp: ${formatDuration(fcp.duration)}`;\n }\n return \"\";\n};\n\nexport const PerformancePanel = ({\n performances,\n clearPerformances,\n}: PerformancePanelProps) => {\n const [selectedId, setSelectedId] = useState<string | null>(null);\n if (performances.length === 0) {\n return (\n <view className={\"pp-container\"}>\n <view className={\"pp-header\"}>\n <text className={\"pp-count\"}>0 entries</text>\n <view\n bindtap={() => {\n console.log(\"[PerformancePanel] performances\", performances);\n }}\n style={{ padding: \"10px\", backgroundColor: \"red\" }}\n >\n <text>Log</text>\n </view>\n <view bindtap={clearPerformances} className={\"pp-clearButton\"}>\n <text className={\"pp-clearButtonText\"}>🗑</text>\n </view>\n </view>\n <view className={\"pp-placeholder\"}>\n <text className={\"pp-placeholderText\"}>\n No performance data yet...\n </text>\n </view>\n </view>\n );\n }\n\n return (\n <view className={\"pp-container\"}>\n <view className={\"pp-header\"}>\n <text className={\"pp-count\"}>{performances.length} entries</text>\n <view bindtap={clearPerformances} className={\"pp-clearButton\"}>\n <text className={\"pp-clearButtonText\"}>🗑</text>\n </view>\n </view>\n\n <FadeList className={\"pp-list\"}>\n {performances.map((perf) => {\n const isMetricFcp = isMetricFcpEntry(perf);\n const fcpMetrics = extractFcpMetrics(perf);\n const primaryFcp = getPrimaryFcpLabel(perf);\n const { totalFcp, lynxFcp, fcp } = fcpMetrics ?? {};\n\n return (\n <list-item key={perf.id} item-key={perf.id}>\n <view className={\"pp-item\"}>\n <view\n className={\"pp-itemHeader\"}\n bindtap={() =>\n setSelectedId(selectedId === perf.id ? null : perf.id)\n }\n >\n <text className={`pp-entryType pp-entryType--${perf.entryType}`}>\n {perf.entryType}\n </text>\n <text className={\"pp-entryName\"}>{perf.name}</text>\n <text className={\"pp-timestamp\"}>\n {new Date(perf.timestamp).toISOString()}\n </text>\n </view>\n\n <view\n bindtap={() =>\n setSelectedId(selectedId === perf.id ? null : perf.id)\n }\n >\n {isMetricFcp && primaryFcp && (\n <text className={\"pp-fcpHighlight\"}>{primaryFcp}</text>\n )}\n </view>\n\n {selectedId === perf.id && (\n <view className={\"pp-detailsContainer\"}>\n {isMetricFcp && fcpMetrics && (\n <view className={\"pp-fcpSection\"}>\n {totalFcp !== undefined && (\n <view className={\"pp-fcpMetric\"}>\n <view className={\"pp-fcpMetricHeader\"}>\n <text className={\"pp-fcpMetricName\"}>\n 전체 FCP\n </text>\n <text className={\"pp-fcpMetricValue\"}>\n {formatDuration(totalFcp.duration)}\n </text>\n </view>\n <text className={\"pp-fcpMetricDescription\"}>\n PrepareTemplate Start부터 Paint End 까지 걸리는\n 시간\n </text>\n </view>\n )}\n\n {lynxFcp !== undefined && (\n <view className={\"pp-fcpMetric\"}>\n <view className={\"pp-fcpMetricHeader\"}>\n <text className={\"pp-fcpMetricName\"}>LynxFCP</text>\n <text className={\"pp-fcpMetricValue\"}>\n {formatDuration(lynxFcp.duration)}\n </text>\n </view>\n <text className={\"pp-fcpMetricDescription\"}>\n Bundle Load 시작부터 Paint End 까지 걸리는 시간\n </text>\n </view>\n )}\n\n {fcp !== undefined && (\n <view className={\"pp-fcpMetric\"}>\n <view className={\"pp-fcpMetricHeader\"}>\n <text className={\"pp-fcpMetricName\"}>\n 렌더링 FCP\n </text>\n <text className={\"pp-fcpMetricValue\"}>\n {formatDuration(fcp.duration)}\n </text>\n </view>\n <text className={\"pp-fcpMetricDescription\"}>\n TemplateBundle 준비부터 Paint End 까지 걸리는 시간\n </text>\n </view>\n )}\n </view>\n )}\n\n {!!perf.rawEntry && (\n <view className={\"pp-rawEntrySection\"}>\n <text className={\"pp-detailTitle\"}>Raw Entry</text>\n <text className={\"pp-rawEntry\"}>\n {String(stringify(perf.rawEntry, null, 2, { references: true }))}\n </text>\n </view>\n )}\n </view>\n )}\n </view>\n </list-item>\n );\n })}\n </FadeList>\n </view>\n );\n};\n","import { type ReactNode, useRef, useState } from \"@lynx-js/react\";\nimport type { ListSnapEvent, NodesRef } from \"@lynx-js/types\";\nimport \"./Tabs.css\";\n\ntype TabsProps = {\n items: Array<{\n key: string;\n label: string;\n renderContent: () => ReactNode;\n }>;\n onTabChange?: () => void;\n};\n\nexport default function Tabs(props: TabsProps) {\n const tabContentsRef = useRef<NodesRef>(null);\n const [activeIndex, setActiveIndex] = useState(0);\n const tabSize =\n props.items.length < 4\n ? undefined\n : (`t${Math.max(1, 5 - (props.items.length - 3))}`);\n\n return (\n <view className={\"tabs-root\"}>\n <view className={\"tabs-header\"}>\n {props.items.map((item, i) => (\n <view\n key={item.key}\n className={\"tabs-triggerButton\"}\n bindtap={() => {\n setActiveIndex(i);\n props.onTabChange?.();\n\n tabContentsRef.current\n ?.invoke({\n method: \"scrollToPosition\",\n params: {\n position: i,\n smooth: true,\n },\n })\n .exec();\n }}\n >\n <text\n className={`tabs-triggerButtonText${i === activeIndex ? \" tabs-triggerButtonText--active\" : \"\"}${tabSize ? ` tabs-triggerButtonText--${tabSize}` : \"\"}`}\n >\n {item.label}\n </text>\n {i === 0 && (\n <view\n className={\"tabs-triggerIndicator\"}\n style={{ transform: `translateX(${activeIndex * 100}%)` }}\n >\n <view className={\"tabs-triggerIndicatorLine\"} />\n </view>\n )}\n </view>\n ))}\n </view>\n\n <list\n ref={tabContentsRef}\n className={\"tabs-contents\"}\n scroll-orientation=\"horizontal\"\n item-snap={{ factor: 0, offset: 0 }}\n bindscroll={() => props.onTabChange?.()}\n bindsnap={(e: ListSnapEvent) => {\n setActiveIndex(e.detail.position);\n }}\n bounces={false}\n preload-buffer-count={props.items.length}\n >\n {props.items.map((item) => (\n <list-item\n key={item.key}\n item-key={item.key}\n recyclable={false}\n className={\"tabs-content\"}\n >\n {item.renderContent()}\n </list-item>\n ))}\n </list>\n </view>\n );\n}\n","import { useConsole, useNetwork, usePerformance } from \"../hooks\";\nimport type { CustomTab } from \"../types\";\nimport \"./ConsolePanel.css\";\nimport { LogPanel, dismissFilterDropdown } from \"./LogPanel\";\nimport { NetworkPanel } from \"./NetworkPanel\";\nimport { PerformancePanel } from \"./PerformancePanel\";\nimport Tabs from \"./Tabs\";\n\ninterface ConsolePanelProps {\n customTabs?: CustomTab[];\n}\n\nexport const ConsolePanel = ({ customTabs }: ConsolePanelProps) => {\n const { logs, clearLogs } = useConsole();\n const { networks, clearNetworks } = useNetwork();\n const { performances, clearPerformances } = usePerformance();\n\n const state = globalThis.__LYNX_CONSOLE__?.state;\n\n const items: Array<{\n key: string;\n label: string;\n renderContent: () => ReturnType<typeof LogPanel>;\n }> = [];\n\n if (state?.logs) {\n items.push({\n key: \"log\",\n label: \"Log\",\n renderContent: () => <LogPanel logs={logs} clearLogs={clearLogs} />,\n });\n }\n\n if (state?.networks) {\n items.push({\n key: \"network\",\n label: \"Network\",\n renderContent: () => (\n <NetworkPanel networks={networks} clearNetworks={clearNetworks} />\n ),\n });\n }\n\n if (state?.performances) {\n items.push({\n key: \"performance\",\n label: \"Perf\",\n renderContent: () => (\n <PerformancePanel\n performances={performances}\n clearPerformances={clearPerformances}\n />\n ),\n });\n }\n\n if (customTabs) {\n for (const tab of customTabs) {\n items.push({\n key: tab.key,\n label: tab.label,\n renderContent: tab.renderContent,\n });\n }\n }\n\n if (items.length === 0) {\n return null;\n }\n\n return (\n <view className=\"cp-container\">\n <Tabs onTabChange={dismissFilterDropdown} items={items} />\n </view>\n );\n};\n","import { useRef, useState } from \"@lynx-js/react\";\nimport type { BaseTouchEvent, Target } from \"@lynx-js/types\";\n\nconst LONG_PRESS_DURATION = 400;\nconst MOVE_THRESHOLD = 5;\n\nconst DEFAULT_RIGHT = 16;\nconst DEFAULT_BOTTOM = 84;\n\nlet savedRight = DEFAULT_RIGHT;\nlet savedBottom = DEFAULT_BOTTOM;\n\nexport function useLongPressDrag(onTap: () => void) {\n const [right, setRight] = useState(savedRight);\n const [bottom, setBottom] = useState(savedBottom);\n const [phase, setPhase] = useState<\"idle\" | \"dragging\" | \"releasing\">(\"idle\");\n const [tempRight, setTempRight] = useState(savedRight);\n const [tempBottom, setTempBottom] = useState(savedBottom);\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const draggingRef = useRef(false);\n const startRef = useRef({ x: 0, y: 0, r: 0, b: 0 });\n\n const clearTimer = () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const handleTouchStart = (e: BaseTouchEvent<Target>) => {\n startRef.current = {\n x: e.detail.x,\n y: e.detail.y,\n r: right,\n b: bottom,\n };\n draggingRef.current = false;\n\n timerRef.current = setTimeout(() => {\n draggingRef.current = true;\n setPhase(\"dragging\");\n setTempRight(right);\n setTempBottom(bottom);\n }, LONG_PRESS_DURATION);\n };\n\n const handleTouchMove = (e: BaseTouchEvent<Target>) => {\n const dx = e.detail.x - startRef.current.x;\n const dy = e.detail.y - startRef.current.y;\n\n if (\n !draggingRef.current &&\n (Math.abs(dx) > MOVE_THRESHOLD || Math.abs(dy) > MOVE_THRESHOLD)\n ) {\n clearTimer();\n }\n\n if (!draggingRef.current) return;\n\n // right/bottom 기준이므로 방향 반전\n setTempRight(startRef.current.r - dx);\n setTempBottom(startRef.current.b - dy);\n };\n\n const handleTouchEnd = () => {\n clearTimer();\n\n if (draggingRef.current) {\n setRight(tempRight);\n setBottom(tempBottom);\n savedRight = tempRight;\n savedBottom = tempBottom;\n setPhase(\"releasing\");\n draggingRef.current = false;\n setTimeout(() => setPhase(\"idle\"), 300);\n } else {\n onTap();\n }\n };\n\n const isDragging = phase === \"dragging\";\n\n return {\n phase,\n right: isDragging ? tempRight : right,\n bottom: isDragging ? tempBottom : bottom,\n clearTimer,\n handlers: {\n catchtouchstart: handleTouchStart,\n catchtouchmove: handleTouchMove,\n catchtouchend: handleTouchEnd,\n },\n };\n}\n","import type { ReactNode } from \"@lynx-js/react\";\nimport { useLongPressDrag } from \"../hooks/useLongPressDrag\";\nimport \"./FloatingButton.css\";\n\ninterface FloatingButtonProps {\n bindtap: () => void;\n children: ReactNode;\n}\n\nconst SHINE_STYLES = {\n idle: {\n transform: \"scale(0)\",\n opacity: 0,\n },\n dragging: {\n transform: \"scale(1)\",\n opacity: 1,\n transition: \"transform 300ms cubic-bezier(0.4, 0, 0.2, 1)\",\n },\n releasing: {\n transform: \"scale(1)\",\n opacity: 0,\n transition: \"opacity 300ms cubic-bezier(0.4, 0, 0.2, 1)\",\n },\n} as const;\n\nexport const FloatingButton = ({\n bindtap,\n children,\n}: FloatingButtonProps) => {\n const { phase, right, bottom, clearTimer, handlers } =\n useLongPressDrag(bindtap);\n\n\n const handleReload = () => {\n try {\n lynx.reload({}, () => {\n console.log(\"reloaded!\");\n });\n } catch (e) {\n console.error(\"[LynxConsole] reload failed:\", e);\n }\n };\n\n const isDragging = phase === \"dragging\";\n\n return (\n <>\n <view\n className={\"fb-wrapper\"}\n consume-slide-event={[[-180, 180]]}\n style={{\n right: `${right}px`,\n bottom: `${bottom}px`,\n transform: isDragging ? \"scale(1.05)\" : \"scale(1)\",\n }}\n {...handlers}\n >\n <view className={\"fb-button\"}>\n {children}\n <view className={\"fb-shineOverlay\"} style={SHINE_STYLES[phase]} />\n </view>\n <view\n className={\"fb-reloadButton\"}\n catchtouchstart={() => clearTimer()}\n bindtap={handleReload}\n >\n <text className={\"fb-reloadIcon\"}>{\"\\u21BB\"}</text>\n </view>\n </view>\n </>\n );\n};\n","import \"./styles/vars/index.css\";\nimport \"./styles/global.css\";\nimport {\n type ForwardedRef,\n forwardRef,\n useImperativeHandle,\n useMemo,\n useState,\n} from \"@lynx-js/react\";\nimport BottomSheet from \"./components/BottomSheet.jsx\";\nimport { ConsolePanel } from \"./components/ConsolePanel.jsx\";\nimport \"./components/FloatingButton.css\";\nimport { FloatingButton } from \"./components/FloatingButton.jsx\";\nimport { usePerformance } from \"./hooks/usePerformance\";\nimport type { CustomTab } from \"./types\";\n\nexport interface LynxConsoleHandle {\n open: () => void;\n close: () => void;\n isOpen: () => boolean;\n}\n\nexport interface LynxConsoleProps {\n theme?: \"light\" | \"dark\";\n safeAreaInsetBottom?: string;\n customTabs?: CustomTab[];\n}\n\ninterface FcpMetric {\n name: string;\n duration: number;\n}\n\ninterface MetricFcpEntry {\n totalFcp?: FcpMetric;\n lynxFcp?: FcpMetric;\n fcp?: FcpMetric;\n}\n\nconst LynxConsole = forwardRef<LynxConsoleHandle, LynxConsoleProps>(\n (\n { theme = \"light\", safeAreaInsetBottom = \"50px\", customTabs },\n ref: ForwardedRef<LynxConsoleHandle>,\n ) => {\n const [isOpen, setIsOpen] = useState(false);\n const [shouldClose, setShouldClose] = useState(false);\n const { performances } = usePerformance();\n\n const latestFcp = useMemo(() => {\n for (let i = performances.length - 1; i >= 0; i--) {\n const perf = performances[i];\n if (perf && perf.entryType === \"metric\" && perf.name === \"fcp\") {\n const metricEntry = perf.rawEntry as MetricFcpEntry | undefined;\n // totalFcp를 먼저 시도하고, 없으면 lynxFcp 반환\n if (metricEntry?.totalFcp?.duration !== undefined) {\n return metricEntry.totalFcp;\n }\n if (metricEntry?.lynxFcp?.duration !== undefined) {\n return metricEntry.lynxFcp;\n }\n }\n }\n return undefined;\n }, [performances]);\n\n useImperativeHandle(ref, () => ({\n open: () => {\n setIsOpen(true);\n setShouldClose(false);\n },\n close: () => {\n setShouldClose(true);\n },\n isOpen: () => isOpen,\n }));\n\n const handleOpenBottomSheet = () => {\n setIsOpen(true);\n setShouldClose(false);\n };\n\n const handleCloseBottomSheet = () => {\n setIsOpen(false);\n setShouldClose(false);\n };\n\n const themeClass = `data-lynx-console-color-mode__${theme}-only`;\n\n return (\n <view className={themeClass}>\n <FloatingButton bindtap={handleOpenBottomSheet}>\n <text className=\"fb-title\">LynxConsole</text>\n <text className=\"fb-subtitle\">\n {`${latestFcp?.name ?? \"FCP\"}: ${latestFcp?.duration ? latestFcp.duration.toFixed(2) : \"--\"}ms`}\n </text>\n </FloatingButton>\n {isOpen && (\n <BottomSheet\n isOpen={isOpen}\n shouldClose={shouldClose}\n onClose={handleCloseBottomSheet}\n title=\"Lynx Console\"\n safeAreaInsetBottom={safeAreaInsetBottom}\n >\n <ConsolePanel customTabs={customTabs} />\n </BottomSheet>\n )}\n </view>\n );\n },\n);\n\nexport type { CustomTab } from \"./types\";\nexport default LynxConsole;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/styles/theme.ts","../src/styles/ThemeContext.ts","../src/components/BottomSheet.tsx","../src/hooks/useConsole.ts","../src/hooks/useNetwork.ts","../src/hooks/usePerformance.ts","../src/components/FadeList.tsx","../src/components/LogPanel.tsx","../src/components/NetworkDetailSection.tsx","../src/components/NetworkPanel.tsx","../src/components/PerformancePanel.tsx","../src/components/Tabs.tsx","../src/components/ConsolePanel.tsx","../src/hooks/useLongPressDrag.ts","../src/components/FloatingButton.tsx","../src/index.tsx"],"sourcesContent":["export type Theme = \"light\" | \"dark\";\n\nconst lightColors = {\n palette: {\n blue100: \"#eff6ff\",\n blue600: \"#5e98fe\",\n gray100: \"#f7f8f9\",\n gray400: \"#dcdee3\",\n green100: \"#edfaf6\",\n green600: \"#10ab7d\",\n purple100: \"#f5f3fe\",\n purple600: \"#9f84fb\",\n red100: \"#fdf0f0\",\n red600: \"#fc6a66\",\n red900: \"#921708\",\n staticWhite: \"#ffffff\",\n yellow100: \"#fff7de\",\n yellow600: \"#c49725\",\n yellow900: \"#4f3e1f\",\n },\n fg: {\n neutral: \"#1a1c20\",\n placeholder: \"#b0b3ba\",\n disabled: \"#d1d3d8\",\n neutralMuted: \"#555d6d\",\n neutralSubtle: \"#868b94\",\n },\n bg: {\n overlay: \"#00000074\",\n layerDefault: \"#ffffff\",\n layerFloating: \"#ffffff\",\n neutralWeak: \"#f3f4f5\",\n },\n stroke: {\n neutralSubtle: \"#0000000c\",\n neutralWeak: \"#dcdee3\",\n },\n} as const;\n\nconst darkColors = {\n palette: {\n blue100: \"#202742\",\n blue600: \"#1e82eb\",\n gray100: \"#16171b\",\n gray400: \"#393d46\",\n green100: \"#202926\",\n green600: \"#1b946d\",\n purple100: \"#28213b\",\n purple600: \"#8e6bee\",\n red100: \"#322323\",\n red600: \"#f73526\",\n red900: \"#f8c5c3\",\n staticWhite: \"#ffffff\",\n yellow100: \"#302819\",\n yellow600: \"#b6720d\",\n yellow900: \"#e5d49b\",\n },\n fg: {\n neutral: \"#f3f4f5\",\n placeholder: \"#868b94\",\n disabled: \"#5b606a\",\n neutralMuted: \"#dcdee3\",\n neutralSubtle: \"#b0b3ba\",\n },\n bg: {\n overlay: \"#00000074\",\n layerDefault: \"#16171b\",\n layerFloating: \"#1d2025\",\n neutralWeak: \"#2b2e35\",\n },\n stroke: {\n neutralSubtle: \"#ffffff0d\",\n neutralWeak: \"#393d46\",\n },\n} as const;\n\nconst colorMap = {\n light: lightColors,\n dark: darkColors,\n} as const;\n\nexport const fontWeight = {\n regular: \"400\",\n medium: \"500\",\n bold: \"700\",\n} as const;\n\nexport const duration = {\n d4: \"200ms\",\n d6: \"300ms\",\n} as const;\n\nexport const dimension = {\n x2: \"8px\",\n x3: \"12px\",\n x4: \"16px\",\n x6: \"24px\",\n spacingX: {\n globalGutter: \"16px\",\n },\n} as const;\n\nexport const radius = {\n r6: \"24px\",\n} as const;\n\nexport function getColors(theme: Theme) {\n return colorMap[theme];\n}\n\nexport type ThemeColors = ReturnType<typeof getColors>;\n","import { createContext, useContext } from \"@lynx-js/react\";\nimport { type ThemeColors, getColors } from \"./theme\";\n\nconst ThemeContext = createContext<ThemeColors>(getColors(\"light\"));\n\nexport const ThemeProvider = ThemeContext.Provider;\n\nexport function useThemeColors(): ThemeColors {\n return useContext(ThemeContext);\n}\n","import { type ReactNode, useEffect, useState } from \"@lynx-js/react\";\nimport type { BaseTouchEvent, Target } from \"@lynx-js/types\";\nimport { useThemeColors } from \"../styles/ThemeContext\";\nimport { duration, fontWeight } from \"../styles/theme\";\nimport \"./BottomSheet.css\";\n\ninterface BottomSheetProps {\n children: ReactNode;\n title?: string;\n footer?: ReactNode;\n onClose: () => void;\n isOpen: boolean;\n shouldClose?: boolean;\n safeAreaInsetBottom?: string;\n}\n\nconst MIN_HEIGHT = 200;\nconst MAX_HEIGHT = 700;\nconst DEFAULT_HEIGHT = 500;\nconst CLOSE_DRAG_THRESHOLD = 30; // 30px 이상 아래로 드래그하면 닫힘\n\n// 마지막 높이 저장\nlet savedHeight: number | null = null;\n\nexport default function BottomSheet({\n children,\n title,\n footer,\n onClose,\n isOpen,\n shouldClose = false,\n safeAreaInsetBottom = \"25px\",\n}: BottomSheetProps) {\n const colors = useThemeColors();\n const [sheetHeight, setSheetHeight] = useState(savedHeight ?? DEFAULT_HEIGHT);\n const [tempHeight, setTempHeight] = useState(savedHeight ?? DEFAULT_HEIGHT);\n const [isDragging, setIsDragging] = useState(false);\n const [dragStartY, setDragStartY] = useState(0);\n const [dragStartHeight, setDragStartHeight] = useState(\n savedHeight ?? DEFAULT_HEIGHT,\n );\n const [isOpening, setIsOpening] = useState(true);\n const [isClosing, setIsClosing] = useState(false);\n\n // 닫기 애니메이션 처리\n const handleClose = () => {\n setIsClosing(true);\n setTimeout(() => {\n onClose();\n }, 300);\n };\n\n // 아래에서 올라오는 애니메이션\n useEffect(() => {\n requestAnimationFrame(() => {\n setIsOpening(false);\n });\n }, []);\n\n // 외부에서 닫기 요청 시 애니메이션 처리\n useEffect(() => {\n if (shouldClose && !isClosing) {\n handleClose();\n }\n }, [shouldClose, isClosing]);\n\n // 높이 변경 시 저장\n useEffect(() => {\n savedHeight = sheetHeight;\n }, [sheetHeight]);\n\n if (!isOpen) return null;\n\n const handleTouchStart = (e: BaseTouchEvent<Target>) => {\n setIsDragging(true);\n setDragStartY(e.detail.y);\n setDragStartHeight(sheetHeight);\n setTempHeight(sheetHeight);\n };\n\n const handleTouchMove = (e: BaseTouchEvent<Target>) => {\n if (!isDragging) return;\n const deltaY = dragStartY - e.detail.y;\n const newHeight = Math.min(\n Math.max(dragStartHeight + deltaY, MIN_HEIGHT),\n MAX_HEIGHT,\n );\n setTempHeight(newHeight);\n };\n\n const handleTouchEnd = () => {\n setIsDragging(false);\n\n // 아래로 일정 30px 이상 드래그하면 닫기\n const dragDistance = dragStartHeight - tempHeight;\n setSheetHeight(tempHeight);\n if (dragDistance > CLOSE_DRAG_THRESHOLD) {\n handleClose();\n }\n };\n\n return (\n <scroll-view\n className=\"bs-backdrop\"\n style={{\n background: colors.bg.overlay,\n opacity: isOpening || isClosing ? 0 : 1,\n transition: `opacity ${duration.d6} cubic-bezier(0.4, 0, 0.2, 1)`,\n }}\n >\n <view className=\"bs-overlay\" bindtap={handleClose}>\n <view\n className=\"bs-content\"\n catchtap={() => {}}\n style={{\n background: colors.bg.layerFloating,\n height: `${isDragging ? tempHeight : sheetHeight}px`,\n transform:\n isOpening || isClosing ? \"translateY(100%)\" : \"translateY(0)\",\n transition: isDragging\n ? \"none\"\n : `transform ${duration.d6} cubic-bezier(0.4, 0, 0.2, 1)`,\n }}\n >\n {/* catchtap: 이벤트 버블링 차단 */}\n <view\n className=\"bs-handleContainer\"\n bindtouchstart={handleTouchStart}\n bindtouchmove={handleTouchMove}\n bindtouchend={handleTouchEnd}\n >\n <view\n className=\"bs-handle\"\n style={{ backgroundColor: colors.palette.gray400 }}\n />\n </view>\n <view className=\"bs-header\">\n {title && (\n <text\n className=\"bs-title\"\n style={{\n fontWeight: fontWeight.bold,\n color: colors.fg.neutral,\n }}\n >\n {title}\n </text>\n )}\n </view>\n <view\n className=\"bs-body\"\n style={{\n paddingBottom: safeAreaInsetBottom,\n }}\n >\n {children}\n </view>\n {footer && <view className=\"bs-footer\">{footer}</view>}\n </view>\n </view>\n </scroll-view>\n );\n}\n","import { useEffect, useState } from \"@lynx-js/react\";\nimport type { LogEntry } from \"../types\";\n\nexport const useConsole = () => {\n const [logs, setLogs] = useState<LogEntry[]>([]);\n\n useEffect(() => {\n if (typeof globalThis.__LYNX_CONSOLE__?.state?.logs === \"undefined\") {\n console.warn(\"[LynxConsole] Log monitoring not initialized\");\n return;\n }\n\n const state = globalThis.__LYNX_CONSOLE__.state;\n\n setLogs([...(state.logs ?? [])]);\n\n const updateLogs = (_entry: LogEntry) => {\n setLogs([...(state.logs ?? [])]);\n };\n\n const unsubscribe = state.logSubscribe?.(updateLogs);\n\n return unsubscribe;\n }, []);\n\n const clearLogs = () => {\n if (typeof globalThis.__LYNX_CONSOLE__?.state?.logs !== \"undefined\") {\n const state = globalThis.__LYNX_CONSOLE__.state;\n state.logs = [];\n setLogs([]);\n }\n };\n\n return { logs, clearLogs };\n};\n","import { useEffect, useState } from \"@lynx-js/react\";\nimport type { NetworkEntry } from \"../types\";\n\nexport const useNetwork = () => {\n const [networks, setNetworks] = useState<NetworkEntry[]>([]);\n\n useEffect(() => {\n if (typeof globalThis.__LYNX_CONSOLE__?.state?.networks === \"undefined\") {\n console.warn(\"[LynxConsole] Network monitoring not initialized\");\n return;\n }\n\n const state = globalThis.__LYNX_CONSOLE__.state;\n\n setNetworks([...(state.networks ?? [])]);\n\n const updateNetworks = (_entry: NetworkEntry) => {\n setNetworks([...(state.networks ?? [])]);\n };\n\n const unsubscribe = state.subscribeNetwork?.(updateNetworks);\n\n return unsubscribe;\n }, []);\n\n const clearNetworks = () => {\n if (typeof globalThis.__LYNX_CONSOLE__?.state?.networks !== \"undefined\") {\n const state = globalThis.__LYNX_CONSOLE__.state;\n state.networks = [];\n state.networksMap?.clear();\n setNetworks([]);\n }\n };\n\n return { networks, clearNetworks };\n};\n","import { useEffect, useState } from \"@lynx-js/react\";\nimport type { PerformanceEntryData } from \"../types\";\n\nexport const usePerformance = () => {\n const [performances, setPerformances] = useState<PerformanceEntryData[]>([]);\n\n useEffect(() => {\n if (\n typeof globalThis.__LYNX_CONSOLE__?.state?.performances === \"undefined\"\n ) {\n console.warn(\"[LynxConsole] Performance monitoring not initialized\");\n return;\n }\n\n const state = globalThis.__LYNX_CONSOLE__.state;\n\n setPerformances([...(state.performances ?? [])]);\n\n const updatePerformances = (_entry: PerformanceEntryData) => {\n setPerformances([...(state.performances ?? [])]);\n };\n\n const unsubscribe = state.subscribePerformance?.(updatePerformances);\n\n return unsubscribe;\n }, []);\n\n const clearPerformances = () => {\n if (\n typeof globalThis.__LYNX_CONSOLE__?.state?.performances !== \"undefined\"\n ) {\n const state = globalThis.__LYNX_CONSOLE__.state;\n state.performances = [];\n setPerformances([]);\n }\n };\n\n return { performances, clearPerformances };\n};\n","import { useRef } from \"@lynx-js/react\";\nimport type { NodesRef } from \"@lynx-js/types\";\n\ninterface FadeListProps {\n className?: string;\n listRef?: React.RefObject<NodesRef>;\n children: React.ReactNode;\n \"preload-buffer-count\"?: number;\n \"initial-scroll-index\"?: number;\n}\n\nexport const FadeList = ({\n className,\n listRef: externalListRef,\n children,\n ...listProps\n}: FadeListProps) => {\n const internalListRef = useRef<NodesRef>(null);\n const listRef = externalListRef ?? internalListRef;\n\n return (\n <list\n ref={listRef}\n scroll-orientation=\"vertical\"\n className={className}\n {...listProps}\n >\n {children}\n </list>\n );\n};\n","import { useEffect, useMemo, useRef, useState } from \"@lynx-js/react\";\nimport type { BaseEvent, InputInputEvent, NodesRef } from \"@lynx-js/types\";\nimport { stringify } from \"javascript-stringify\";\nimport { useThemeColors } from \"../styles/ThemeContext\";\nimport { type ThemeColors, fontWeight } from \"../styles/theme\";\nimport type { LogEntry, LogLevel } from \"../types\";\nimport \"./ConsolePanel.css\";\nimport { FadeList } from \"./FadeList\";\n\nconst LOG_LEVELS: LogLevel[] = [\"log\", \"info\", \"warn\", \"error\"];\n\nlet savedEnabledLevels: Set<LogLevel> | null = null;\nlet savedSearchQuery = \"\";\nlet closeFilterDropdown: (() => void) | null = null;\n\nexport const dismissFilterDropdown = () => closeFilterDropdown?.();\n\ninterface LogPanelProps {\n logs: LogEntry[];\n clearLogs: () => void;\n}\n\nconst runCode = (code: string) => {\n try {\n // biome-ignore lint: intentional REPL tool\n const result = eval(code);\n if (result instanceof Promise) {\n result.then((r) => console.log(r)).catch((e) => console.error(e));\n } else {\n console.log(result);\n }\n } catch (e) {\n console.error(e);\n }\n};\n\nfunction getLevelColor(colors: ThemeColors, level: LogLevel): string {\n switch (level) {\n case \"log\":\n return colors.palette.green600;\n case \"info\":\n return colors.palette.blue600;\n case \"warn\":\n return colors.palette.yellow600;\n case \"error\":\n return colors.palette.red600;\n }\n}\n\nfunction getLogItemBg(\n colors: ThemeColors,\n level: LogLevel,\n): string | undefined {\n switch (level) {\n case \"warn\":\n return colors.palette.yellow100;\n case \"error\":\n return colors.palette.red100;\n default:\n return undefined;\n }\n}\n\nfunction getStringColor(colors: ThemeColors, level: LogLevel): string {\n switch (level) {\n case \"warn\":\n return colors.palette.yellow900;\n case \"error\":\n return colors.palette.red900;\n default:\n return colors.fg.neutral;\n }\n}\n\nfunction getPrimitiveColor(colors: ThemeColors, level: LogLevel): string {\n switch (level) {\n case \"warn\":\n return colors.palette.yellow900;\n case \"error\":\n return colors.palette.red900;\n default:\n return colors.palette.blue600;\n }\n}\n\nexport const LogPanel = ({ logs, clearLogs }: LogPanelProps) => {\n const colors = useThemeColors();\n const [expandedArgs, setExpandedArgs] = useState(new Set());\n const [code, setCode] = useState(\"\");\n const [enabledLevels, setEnabledLevels] = useState<Set<LogLevel>>(\n () => savedEnabledLevels ?? new Set(LOG_LEVELS),\n );\n const [filterOpen, setFilterOpen] = useState(false);\n const [searchQuery, setSearchQuery] = useState(savedSearchQuery);\n const inputRef = useRef<NodesRef>(null);\n const searchInputRef = useRef<NodesRef>(null);\n const listRef = useRef<NodesRef>(null);\n\n useEffect(() => {\n savedEnabledLevels = enabledLevels;\n }, [enabledLevels]);\n\n useEffect(() => {\n savedSearchQuery = searchQuery;\n }, [searchQuery]);\n\n useEffect(() => {\n if (savedSearchQuery) {\n searchInputRef.current\n ?.invoke({ method: \"setValue\", params: { value: savedSearchQuery } })\n .exec();\n }\n }, []);\n\n useEffect(() => {\n closeFilterDropdown = () => setFilterOpen(false);\n return () => { closeFilterDropdown = null; };\n }, []);\n\n const filteredLogs = useMemo(\n () =>\n logs.filter((log) => {\n if (!enabledLevels.has(log.level)) return false;\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n return log.args.some((arg) => String(arg).toLowerCase().includes(query));\n }\n return true;\n }),\n [logs, enabledLevels, searchQuery],\n );\n const logsRef = useRef(filteredLogs);\n logsRef.current = filteredLogs;\n\n const toggleLevel = (level: LogLevel) => {\n setEnabledLevels((prev) => {\n const next = new Set(prev);\n if (next.has(level)) {\n next.delete(level);\n } else {\n next.add(level);\n }\n return next;\n });\n };\n\n const scrollToBottom = (smooth: boolean) => {\n if (logsRef.current.length === 0) return;\n listRef.current\n ?.invoke({\n method: \"scrollToPosition\",\n params: { position: logsRef.current.length - 1, smooth },\n })\n .exec();\n };\n\n useEffect(() => {\n scrollToBottom(true);\n }, [filteredLogs]);\n\n const toggleArg = (key: string) => {\n setExpandedArgs((prev) => {\n const next = new Set(prev);\n if (next.has(key)) {\n next.delete(key);\n } else {\n next.add(key);\n }\n return next;\n });\n };\n\n const handleRun = () => {\n const trimmed = code.trim();\n if (!trimmed) return;\n\n setCode(\"\");\n inputRef.current\n ?.invoke({ method: \"setValue\", params: { value: \"\" } })\n .exec();\n runCode(trimmed);\n setTimeout(() => scrollToBottom(false), 100);\n };\n\n const renderArg = (\n arg: unknown,\n parentKey: string,\n level: \"log\" | \"info\" | \"warn\" | \"error\",\n ): React.ReactNode => {\n const key = parentKey;\n const isExpanded = expandedArgs.has(key);\n\n if (arg === null) {\n return (\n <text style={{ color: colors.fg.neutralSubtle, fontWeight: fontWeight.regular }}>\n null\n </text>\n );\n }\n\n if (arg === undefined) {\n return (\n <text style={{ color: colors.fg.neutralSubtle, fontWeight: fontWeight.regular }}>\n undefined\n </text>\n );\n }\n\n if (typeof arg === \"string\") {\n const MAX_LENGTH = 80;\n const shouldTruncate = arg.length > MAX_LENGTH;\n const strColor = getStringColor(colors, level);\n\n if (!shouldTruncate) {\n return (\n <text\n className={\"cp-argString\"}\n style={{ color: strColor, fontWeight: fontWeight.regular }}\n >\n {arg}\n </text>\n );\n }\n\n return (\n <view className={\"cp-argObject\"}>\n <view className={\"cp-argObjectHeader\"} bindtap={() => toggleArg(key)}>\n <text\n className={\"cp-toggleIndicator\"}\n style={{ color: colors.fg.neutralSubtle, fontWeight: fontWeight.regular }}\n >\n {isExpanded ? \"▼\" : \"▶\"}\n </text>\n <text\n className={\"cp-argString\"}\n style={{ color: strColor, fontWeight: fontWeight.regular }}\n >\n {isExpanded ? arg : `${arg.slice(0, MAX_LENGTH)}...`}\n </text>\n </view>\n </view>\n );\n }\n\n if (typeof arg === \"number\" || typeof arg === \"boolean\") {\n return (\n <text\n className={\"cp-argPrimitive\"}\n style={{ color: getPrimitiveColor(colors, level), fontWeight: fontWeight.regular }}\n >\n {String(arg)}\n </text>\n );\n }\n\n if (typeof arg === \"object\") {\n let preview = \"Object\";\n if (Array.isArray(arg)) {\n preview = `Array(${arg.length})`;\n } else if (arg instanceof Map) {\n preview = `Map(${arg.size})`;\n } else if (arg instanceof Set) {\n preview = `Set(${arg.size})`;\n } else if (arg instanceof Date) {\n preview = `Date`;\n } else if (arg instanceof RegExp) {\n preview = `RegExp`;\n } else if (arg instanceof Error) {\n preview = `${arg.constructor.name}`;\n } else if (arg?.constructor?.name && arg.constructor.name !== \"Object\") {\n preview = arg.constructor.name;\n }\n\n let jsonString: string;\n if (arg instanceof Map) {\n const entries = Array.from(arg.entries()).map(\n ([k, v]) => ` [${stringify(k)}, ${stringify(v)}]`,\n );\n jsonString = `{\\n${entries.join(\",\\n\")}\\n}`;\n } else if (arg instanceof Set) {\n const values = Array.from(arg.values()).map((v) => stringify(v));\n jsonString = `{\\n${values.join(\", \")}\\n}`;\n } else {\n jsonString =\n stringify(arg, null, 2, { references: true }) ?? String(arg);\n }\n\n return (\n <view className={\"cp-argObject\"}>\n <view className={\"cp-argObjectHeader\"} bindtap={() => toggleArg(key)}>\n <text\n className={\"cp-toggleIndicator\"}\n style={{ color: colors.fg.neutralSubtle, fontWeight: fontWeight.regular }}\n >\n {isExpanded ? \"▼\" : \"▶\"}\n </text>\n <text\n className={\"cp-argObjectPreview\"}\n style={{ fontWeight: fontWeight.medium, color: colors.fg.neutral }}\n >\n {preview}\n </text>\n </view>\n {isExpanded && (\n <view className={\"cp-argObjectContent\"}>\n <text\n className={\"cp-argObjectJson\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutral }}\n >\n {jsonString}\n </text>\n </view>\n )}\n </view>\n );\n }\n\n return (\n <text\n className={\"cp-argPrimitive\"}\n style={{ color: getPrimitiveColor(colors, level), fontWeight: fontWeight.regular }}\n >\n {String(arg)}\n </text>\n );\n };\n\n return (\n <view\n className={\"cp-logContainer\"}\n bindtap={() => { if (filterOpen) setFilterOpen(false); }}\n >\n <view className={\"cp-logHeader\"}>\n <view className={\"cp-filterWrapper\"}>\n <view\n className={\"cp-filterButton\"}\n style={{ backgroundColor: colors.bg.neutralWeak }}\n catchtap={() => setFilterOpen((v) => !v)}\n >\n <text\n className={\"cp-filterButtonText\"}\n style={{ fontWeight: fontWeight.medium, color: colors.fg.neutralMuted }}\n >\n Filter ▼\n </text>\n </view>\n {filterOpen && (\n <view\n className={\"cp-filterDropdown\"}\n style={{\n backgroundColor: colors.bg.layerFloating,\n borderColor: colors.stroke.neutralSubtle,\n }}\n catchtap={() => {}}\n >\n {LOG_LEVELS.map((level) => (\n <view\n key={level}\n className={\"cp-filterOption\"}\n bindtap={() => toggleLevel(level)}\n >\n <text\n className={\"cp-filterCheckbox\"}\n style={{ fontWeight: fontWeight.medium, color: getLevelColor(colors, level) }}\n >\n {enabledLevels.has(level) ? \"✅\" : \"⬜\"}\n </text>\n <text\n className={\"cp-filterLabel\"}\n style={{ fontWeight: fontWeight.medium, color: getLevelColor(colors, level) }}\n >\n {level.toUpperCase()}\n </text>\n </view>\n ))}\n </view>\n )}\n </view>\n <view\n className={\"cp-searchWrapper\"}\n style={{ borderBottomColor: colors.stroke.neutralSubtle }}\n >\n <text\n className={\"cp-searchPrompt\"}\n style={{ fontWeight: fontWeight.medium, color: colors.fg.placeholder }}\n >\n {\"›\"}\n </text>\n <input\n ref={searchInputRef}\n className={\"cp-searchInput\"}\n style={{\n fontWeight: fontWeight.regular,\n color: colors.fg.neutral,\n caretColor: colors.palette.green600,\n }}\n placeholder=\"Search logs...\"\n bindinput={(e: BaseEvent<\"bindinput\", InputInputEvent>) =>\n setSearchQuery(e.detail.value)\n }\n />\n {searchQuery.length > 0 && (\n <view\n className={\"cp-searchClear\"}\n bindtap={() => {\n setSearchQuery(\"\");\n searchInputRef.current\n ?.invoke({ method: \"setValue\", params: { value: \"\" } })\n .exec();\n }}\n >\n <text\n className={\"cp-searchClearText\"}\n style={{ fontWeight: fontWeight.medium, color: colors.fg.placeholder }}\n >\n ✕\n </text>\n </view>\n )}\n </view>\n <view style={{ display: \"flex\", flexDirection: \"row\", gap: 8 }}>\n <view\n className={\"cp-clearButton\"}\n style={{ backgroundColor: colors.bg.neutralWeak }}\n bindtap={clearLogs}\n >\n <text\n className={\"cp-clearButtonText\"}\n style={{ fontWeight: fontWeight.medium, color: colors.fg.neutralMuted }}\n >\n 🗑\n </text>\n </view>\n </view>\n </view>\n <FadeList\n listRef={listRef}\n className={\"cp-logList\"}\n preload-buffer-count={10}\n initial-scroll-index={Math.max(0, filteredLogs.length - 1)}\n >\n {filteredLogs.length === 0 ? (\n <list-item item-key=\"empty-state\">\n <view className={\"cp-placeholder\"}>\n <text\n className={\"cp-placeholderText\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.disabled }}\n >\n No logs yet. Try console.log(\"Hello!\")\n </text>\n </view>\n </list-item>\n ) : (\n filteredLogs.map((log) => {\n return (\n <list-item key={log.id} item-key={log.id}>\n <view\n className={\"cp-logItem\"}\n style={{\n backgroundColor: getLogItemBg(colors, log.level),\n borderBottomColor: colors.stroke.neutralWeak,\n }}\n >\n <view className={\"cp-logItemHeader\"}>\n <text\n className={\"cp-logLevel\"}\n style={{\n fontWeight: fontWeight.bold,\n color: getLevelColor(colors, log.level),\n }}\n >\n {log.level.toUpperCase()}\n </text>\n <text\n className={\"cp-logTime\"}\n style={{\n fontWeight: fontWeight.regular,\n color: colors.fg.neutralSubtle,\n }}\n >\n {new Date(log.timestamp).toISOString()}\n </text>\n </view>\n <view className={\"cp-logArgsContainer\"}>\n {log.args.map((arg, index) => (\n <view\n key={`${log.id}-${index.toString()}`}\n className={\"cp-logArgItem\"}\n style={{ fontWeight: fontWeight.regular }}\n >\n {renderArg(\n arg,\n `${log.id}-${index.toString()}`,\n log.level,\n )}\n </view>\n ))}\n </view>\n </view>\n </list-item>\n );\n })\n )}\n </FadeList>\n <view className={\"cp-replInputRow\"}>\n <text\n className={\"cp-replPrompt\"}\n style={{ fontWeight: fontWeight.medium, color: colors.fg.placeholder }}\n >\n {\"›\"}\n </text>\n <input\n ref={inputRef}\n className={\"cp-replInput\"}\n style={{\n fontWeight: fontWeight.regular,\n color: colors.fg.neutral,\n caretColor: colors.palette.green600,\n }}\n placeholder=\"enter code...\"\n bindinput={(e: BaseEvent<\"bindinput\", InputInputEvent>) =>\n setCode(e.detail.value)\n }\n bindconfirm={handleRun}\n />\n <view\n className={\"cp-replRunButton\"}\n style={{ backgroundColor: colors.palette.green100 }}\n bindtap={handleRun}\n >\n <text\n className={\"cp-replRunButtonText\"}\n style={{ fontWeight: fontWeight.medium, color: colors.palette.green600 }}\n >\n Run\n </text>\n </view>\n </view>\n </view>\n );\n};\n","import { useThemeColors } from \"../styles/ThemeContext\";\nimport { fontWeight } from \"../styles/theme\";\nimport \"./NetworkPanel.css\";\n\ninterface NetworkDetailSectionProps {\n headers?: Record<string, string> | undefined;\n body?: string | undefined;\n error?: string | undefined;\n}\n\nexport const NetworkDetailSection = ({\n headers = {},\n body = \"\",\n error = \"\",\n}: NetworkDetailSectionProps) => {\n const colors = useThemeColors();\n\n return (\n <>\n {/* Headers */}\n <view className={\"np-detailSection\"}>\n <text\n className={\"np-detailSectionTitle\"}\n style={{ fontWeight: fontWeight.bold, color: colors.fg.neutral }}\n >\n Headers\n </text>\n {headers && Object.keys(headers).length > 0 ? (\n <view className={\"np-table\"}>\n {Object.entries(headers).map(([key, value]) => (\n <view\n key={key}\n className={\"np-tableRow\"}\n style={{ backgroundColor: colors.bg.neutralWeak }}\n >\n <text\n className={\"np-tableKey\"}\n style={{ fontWeight: fontWeight.bold, color: colors.fg.neutralSubtle }}\n >\n {key}\n </text>\n <text\n className={\"np-tableValue\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutral }}\n >\n {value}\n </text>\n </view>\n ))}\n </view>\n ) : (\n <text\n className={\"np-emptyText\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.disabled }}\n >\n No headers\n </text>\n )}\n </view>\n\n {/* Body */}\n <view className={\"np-detailSection\"}>\n <text\n className={\"np-detailSectionTitle\"}\n style={{ fontWeight: fontWeight.bold, color: colors.fg.neutral }}\n >\n Body\n </text>\n {error && (\n <text\n className={\"np-errorText\"}\n style={{\n fontWeight: fontWeight.regular,\n color: colors.palette.red600,\n backgroundColor: colors.palette.red100,\n }}\n >\n {error}\n </text>\n )}\n {body && (\n <text\n className={\"np-bodyText\"}\n style={{\n fontWeight: fontWeight.regular,\n color: colors.fg.neutral,\n backgroundColor: colors.bg.neutralWeak,\n }}\n >\n {body}\n </text>\n )}\n {!error && !body && (\n <text\n className={\"np-emptyText\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.disabled }}\n >\n No body\n </text>\n )}\n </view>\n </>\n );\n};\n","import { useState } from \"@lynx-js/react\";\nimport { useThemeColors } from \"../styles/ThemeContext\";\nimport { type ThemeColors, fontWeight } from \"../styles/theme\";\nimport type { NetworkEntry } from \"../types\";\nimport { FadeList } from \"./FadeList\";\nimport { NetworkDetailSection } from \"./NetworkDetailSection\";\nimport \"./NetworkPanel.css\";\n\ninterface NetworkPanelProps {\n networks: NetworkEntry[];\n clearNetworks: () => void;\n}\n\ntype TabType = \"general\" | \"request\" | \"response\";\n\nfunction getMethodColors(colors: ThemeColors, method: string) {\n switch (method) {\n case \"GET\":\n return { color: colors.palette.blue600, backgroundColor: colors.palette.blue100 };\n case \"POST\":\n return { color: colors.palette.green600, backgroundColor: colors.palette.green100 };\n case \"PUT\":\n return { color: colors.palette.yellow600, backgroundColor: colors.palette.yellow100 };\n case \"PATCH\":\n return { color: colors.palette.purple600, backgroundColor: colors.palette.purple100 };\n case \"DELETE\":\n return { color: colors.palette.red600, backgroundColor: colors.palette.red100 };\n default:\n return { color: colors.fg.neutral, backgroundColor: colors.bg.neutralWeak };\n }\n}\n\nfunction getStatusCodeColor(\n colors: ThemeColors,\n variant: \"success\" | \"error\" | \"pending\",\n): string {\n switch (variant) {\n case \"success\":\n return colors.palette.green600;\n case \"error\":\n return colors.palette.red600;\n case \"pending\":\n return colors.fg.neutralSubtle;\n }\n}\n\nfunction getItemBg(colors: ThemeColors, status: string): string | undefined {\n switch (status) {\n case \"pending\":\n return colors.palette.gray100;\n case \"error\":\n return colors.palette.red100;\n default:\n return undefined;\n }\n}\n\nexport const NetworkPanel = ({\n networks,\n clearNetworks,\n}: NetworkPanelProps) => {\n const colors = useThemeColors();\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [activeTab, setActiveTab] = useState<TabType>(\"general\");\n const formatDuration = (duration?: number): string => {\n if (!duration) return \"-\";\n if (duration < 1000) return `${duration}ms`;\n return `${(duration / 1000).toFixed(2)}s`;\n };\n\n const extractPath = (url: string): string => {\n const pathMatch = url.match(/^https?:\\/\\/[^/]+(.*)$/);\n if (pathMatch?.[1]) {\n return pathMatch[1].startsWith(\"/\")\n ? pathMatch[1].slice(1)\n : pathMatch[1];\n }\n return url;\n };\n\n const getGeneralInfo = (network: NetworkEntry) => {\n return [\n { key: \"URL\", value: network.url },\n { key: \"Method\", value: network.method },\n network.statusCode\n ? { key: \"Status\", value: String(network.statusCode) }\n : null,\n {\n key: \"Request Time\",\n value: new Date(network.startTime).toISOString(),\n },\n network.endTime\n ? {\n key: \"Response Time\",\n value: new Date(network.endTime).toISOString(),\n }\n : null,\n network.duration\n ? { key: \"Duration\", value: formatDuration(network.duration) }\n : null,\n ].filter((item) => item !== null);\n };\n\n const getStatusCodeVariant = (\n status: string,\n statusCode?: number,\n ): \"success\" | \"error\" | \"pending\" => {\n if (status === \"pending\") return \"pending\";\n if (status === \"error\") return \"error\";\n if (statusCode && statusCode >= 200 && statusCode < 300) return \"success\";\n return \"error\";\n };\n\n return (\n <view className={\"np-container\"}>\n <view className={\"np-header\"}>\n <text\n className={\"np-count\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutralSubtle }}\n >\n Total: {networks.length} requests\n </text>\n <view\n className={\"np-clearButton\"}\n style={{ backgroundColor: colors.bg.neutralWeak }}\n bindtap={clearNetworks}\n >\n <text\n className={\"np-clearButtonText\"}\n style={{ fontWeight: fontWeight.medium, color: colors.fg.neutralMuted }}\n >\n 🗑\n </text>\n </view>\n </view>\n\n {networks.length === 0 ? (\n <view className={\"np-placeholder\"}>\n <text\n className={\"np-placeholderText\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.disabled }}\n >\n No network requests yet\n </text>\n </view>\n ) : (\n <FadeList className={\"np-list\"}>\n {networks.map((network) => (\n <list-item key={network.id} item-key={network.id}>\n <view\n className={\"np-item\"}\n style={{\n backgroundColor: getItemBg(colors, network.status),\n borderBottomColor: colors.stroke.neutralWeak,\n }}\n >\n <view\n className={\"np-itemHeader\"}\n bindtap={() =>\n setSelectedId(selectedId === network.id ? null : network.id)\n }\n >\n <text\n className={\"np-method\"}\n style={{\n fontWeight: fontWeight.bold,\n ...getMethodColors(colors, network.method),\n }}\n >\n {network.method}\n </text>\n {network.statusCode && (\n <text\n className={\"np-statusCode\"}\n style={{\n fontWeight: fontWeight.bold,\n color: getStatusCodeColor(\n colors,\n getStatusCodeVariant(network.status, network.statusCode),\n ),\n }}\n >\n {network.statusCode}\n </text>\n )}\n {network.status === \"pending\" && (\n <text\n className={\"np-statusCode\"}\n style={{\n fontWeight: fontWeight.bold,\n color: colors.fg.neutralSubtle,\n }}\n >\n Pending...\n </text>\n )}\n <text\n className={\"np-time\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutralSubtle }}\n >\n {formatDuration(network.duration)}\n </text>\n <text\n className={\"np-time\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutralSubtle }}\n >\n {new Date(network.startTime).toISOString()}\n </text>\n </view>\n\n <text\n className={\"np-path\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutral }}\n bindtap={() =>\n setSelectedId(selectedId === network.id ? null : network.id)\n }\n >\n {extractPath(network.url)}\n </text>\n\n {selectedId === network.id && (\n <view\n className={\"np-detailsContainer\"}\n style={{ borderTopColor: colors.stroke.neutralSubtle }}\n >\n {/* Tabs */}\n <view className={\"np-tabs\"}>\n <view\n className={\"np-tab\"}\n style={{\n backgroundColor:\n activeTab === \"general\" ? colors.bg.neutralWeak : undefined,\n }}\n bindtap={() => setActiveTab(\"general\")}\n >\n <text\n className={\"np-tabText\"}\n style={{\n fontWeight: fontWeight.medium,\n color:\n activeTab === \"general\"\n ? colors.fg.neutral\n : colors.fg.neutralSubtle,\n }}\n >\n General\n </text>\n </view>\n <view\n className={\"np-tab\"}\n style={{\n backgroundColor:\n activeTab === \"request\" ? colors.bg.neutralWeak : undefined,\n }}\n bindtap={() => setActiveTab(\"request\")}\n >\n <text\n className={\"np-tabText\"}\n style={{\n fontWeight: fontWeight.medium,\n color:\n activeTab === \"request\"\n ? colors.fg.neutral\n : colors.fg.neutralSubtle,\n }}\n >\n Request\n </text>\n </view>\n <view\n className={\"np-tab\"}\n style={{\n backgroundColor:\n activeTab === \"response\" ? colors.bg.neutralWeak : undefined,\n }}\n bindtap={() => setActiveTab(\"response\")}\n >\n <text\n className={\"np-tabText\"}\n style={{\n fontWeight: fontWeight.medium,\n color:\n activeTab === \"response\"\n ? colors.fg.neutral\n : colors.fg.neutralSubtle,\n }}\n >\n Response\n </text>\n </view>\n </view>\n\n {/* Tab Content */}\n <view className={\"np-tabContent\"}>\n {activeTab === \"general\" && (\n <view className={\"np-table\"}>\n {getGeneralInfo(network).map((item) => (\n <view\n key={item.key}\n className={\"np-tableRow\"}\n style={{ backgroundColor: colors.bg.neutralWeak }}\n >\n <text\n className={\"np-tableKey\"}\n style={{\n fontWeight: fontWeight.bold,\n color: colors.fg.neutralSubtle,\n }}\n >\n {item.key}\n </text>\n <text\n className={\"np-tableValue\"}\n style={{\n fontWeight: fontWeight.regular,\n color: colors.fg.neutral,\n }}\n >\n {item.value}\n </text>\n </view>\n ))}\n </view>\n )}\n\n {activeTab === \"request\" && (\n <NetworkDetailSection\n headers={network.requestHeaders}\n body={network.requestBody}\n />\n )}\n\n {activeTab === \"response\" && (\n <NetworkDetailSection\n headers={network.responseHeaders}\n body={network.responseBody}\n error={network.error}\n />\n )}\n </view>\n </view>\n )}\n </view>\n </list-item>\n ))}\n </FadeList>\n )}\n </view>\n );\n};\n","import { useState } from \"@lynx-js/react\";\nimport { stringify } from \"javascript-stringify\";\nimport { useThemeColors } from \"../styles/ThemeContext\";\nimport { type ThemeColors, fontWeight } from \"../styles/theme\";\nimport type { PerformanceEntryData } from \"../types\";\nimport { FadeList } from \"./FadeList\";\nimport \"./PerformancePanel.css\";\n\ninterface PerformancePanelProps {\n performances: PerformanceEntryData[];\n clearPerformances: () => void;\n}\n\ninterface FcpMetric {\n name: string;\n duration: number;\n}\n\ninterface MetricFcpEntry {\n totalFcp?: FcpMetric;\n lynxFcp?: FcpMetric;\n fcp?: FcpMetric;\n}\n\nconst isMetricFcpEntry = (entry: PerformanceEntryData): boolean => {\n return entry.entryType === \"metric\" && entry.name === \"fcp\";\n};\n\nconst extractFcpMetrics = (entry: PerformanceEntryData) => {\n if (!isMetricFcpEntry(entry) || !entry.rawEntry) {\n return null;\n }\n\n const metricEntry = entry.rawEntry as MetricFcpEntry;\n\n return {\n totalFcp: metricEntry.totalFcp ?? undefined,\n lynxFcp: metricEntry.lynxFcp ?? undefined,\n fcp: metricEntry.fcp ?? undefined,\n };\n};\n\nconst formatDuration = (ms?: number): string => {\n if (ms === undefined) return \"-\";\n return `${ms.toFixed(2)}ms`;\n};\n\nconst getPrimaryFcpLabel = (entry: PerformanceEntryData): string => {\n const fcpMetrics = extractFcpMetrics(entry);\n if (!fcpMetrics) return \"\";\n\n const { totalFcp, lynxFcp, fcp } = fcpMetrics;\n\n if (totalFcp?.duration !== undefined) {\n return `totalFcp: ${formatDuration(totalFcp.duration)}`;\n }\n if (lynxFcp?.duration !== undefined) {\n return `lynxFcp: ${formatDuration(lynxFcp.duration)}`;\n }\n if (fcp?.duration !== undefined) {\n return `fcp: ${formatDuration(fcp.duration)}`;\n }\n return \"\";\n};\n\nfunction getEntryTypeColors(colors: ThemeColors, entryType: string) {\n switch (entryType) {\n case \"init\":\n return { color: colors.palette.blue600, backgroundColor: colors.palette.blue100 };\n case \"metric\":\n return { color: colors.palette.green600, backgroundColor: colors.palette.green100 };\n case \"pipeline\":\n return { color: colors.palette.purple600, backgroundColor: colors.palette.purple100 };\n case \"resource\":\n return { color: colors.palette.yellow600, backgroundColor: colors.palette.yellow100 };\n default:\n return { color: colors.fg.neutral, backgroundColor: colors.bg.neutralWeak };\n }\n}\n\nexport const PerformancePanel = ({\n performances,\n clearPerformances,\n}: PerformancePanelProps) => {\n const colors = useThemeColors();\n const [selectedId, setSelectedId] = useState<string | null>(null);\n if (performances.length === 0) {\n return (\n <view className={\"pp-container\"}>\n <view\n className={\"pp-header\"}\n style={{ borderBottomColor: colors.stroke.neutralSubtle }}\n >\n <text\n className={\"pp-count\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutralSubtle }}\n >\n 0 entries\n </text>\n <view\n bindtap={() => {\n console.log(\"[PerformancePanel] performances\", performances);\n }}\n style={{ padding: \"10px\", backgroundColor: \"red\" }}\n >\n <text>Log</text>\n </view>\n <view\n bindtap={clearPerformances}\n className={\"pp-clearButton\"}\n style={{ backgroundColor: colors.bg.neutralWeak }}\n >\n <text\n className={\"pp-clearButtonText\"}\n style={{ fontWeight: fontWeight.medium, color: colors.fg.neutralMuted }}\n >\n 🗑\n </text>\n </view>\n </view>\n <view className={\"pp-placeholder\"}>\n <text\n className={\"pp-placeholderText\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.disabled }}\n >\n No performance data yet...\n </text>\n </view>\n </view>\n );\n }\n\n return (\n <view className={\"pp-container\"}>\n <view\n className={\"pp-header\"}\n style={{ borderBottomColor: colors.stroke.neutralSubtle }}\n >\n <text\n className={\"pp-count\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutralSubtle }}\n >\n {performances.length} entries\n </text>\n <view\n bindtap={clearPerformances}\n className={\"pp-clearButton\"}\n style={{ backgroundColor: colors.bg.neutralWeak }}\n >\n <text\n className={\"pp-clearButtonText\"}\n style={{ fontWeight: fontWeight.medium, color: colors.fg.neutralMuted }}\n >\n 🗑\n </text>\n </view>\n </view>\n\n <FadeList className={\"pp-list\"}>\n {performances.map((perf) => {\n const isMetricFcp = isMetricFcpEntry(perf);\n const fcpMetrics = extractFcpMetrics(perf);\n const primaryFcp = getPrimaryFcpLabel(perf);\n const { totalFcp, lynxFcp, fcp } = fcpMetrics ?? {};\n\n return (\n <list-item key={perf.id} item-key={perf.id}>\n <view\n className={\"pp-item\"}\n style={{ borderBottomColor: colors.stroke.neutralWeak }}\n >\n <view\n className={\"pp-itemHeader\"}\n bindtap={() =>\n setSelectedId(selectedId === perf.id ? null : perf.id)\n }\n >\n <text\n className={\"pp-entryType\"}\n style={{\n fontWeight: fontWeight.bold,\n ...getEntryTypeColors(colors, perf.entryType),\n }}\n >\n {perf.entryType}\n </text>\n <text\n className={\"pp-entryName\"}\n style={{ fontWeight: fontWeight.medium, color: colors.fg.neutral }}\n >\n {perf.name}\n </text>\n <text\n className={\"pp-timestamp\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutralSubtle }}\n >\n {new Date(perf.timestamp).toISOString()}\n </text>\n </view>\n\n <view\n bindtap={() =>\n setSelectedId(selectedId === perf.id ? null : perf.id)\n }\n >\n {isMetricFcp && primaryFcp && (\n <text\n className={\"pp-fcpHighlight\"}\n style={{\n fontWeight: fontWeight.bold,\n color: colors.palette.blue600,\n backgroundColor: colors.palette.blue100,\n }}\n >\n {primaryFcp}\n </text>\n )}\n </view>\n\n {selectedId === perf.id && (\n <view className={\"pp-detailsContainer\"}>\n {isMetricFcp && fcpMetrics && (\n <view className={\"pp-fcpSection\"}>\n {totalFcp !== undefined && (\n <view\n className={\"pp-fcpMetric\"}\n style={{ backgroundColor: colors.bg.layerDefault }}\n >\n <view className={\"pp-fcpMetricHeader\"}>\n <text\n className={\"pp-fcpMetricName\"}\n style={{ fontWeight: fontWeight.bold, color: colors.fg.neutral }}\n >\n 전체 FCP\n </text>\n <text\n className={\"pp-fcpMetricValue\"}\n style={{ fontWeight: fontWeight.bold, color: colors.palette.blue600 }}\n >\n {formatDuration(totalFcp.duration)}\n </text>\n </view>\n <text\n className={\"pp-fcpMetricDescription\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutralSubtle }}\n >\n PrepareTemplate Start부터 Paint End 까지 걸리는\n 시간\n </text>\n </view>\n )}\n\n {lynxFcp !== undefined && (\n <view\n className={\"pp-fcpMetric\"}\n style={{ backgroundColor: colors.bg.layerDefault }}\n >\n <view className={\"pp-fcpMetricHeader\"}>\n <text\n className={\"pp-fcpMetricName\"}\n style={{ fontWeight: fontWeight.bold, color: colors.fg.neutral }}\n >\n LynxFCP\n </text>\n <text\n className={\"pp-fcpMetricValue\"}\n style={{ fontWeight: fontWeight.bold, color: colors.palette.blue600 }}\n >\n {formatDuration(lynxFcp.duration)}\n </text>\n </view>\n <text\n className={\"pp-fcpMetricDescription\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutralSubtle }}\n >\n Bundle Load 시작부터 Paint End 까지 걸리는 시간\n </text>\n </view>\n )}\n\n {fcp !== undefined && (\n <view\n className={\"pp-fcpMetric\"}\n style={{ backgroundColor: colors.bg.layerDefault }}\n >\n <view className={\"pp-fcpMetricHeader\"}>\n <text\n className={\"pp-fcpMetricName\"}\n style={{ fontWeight: fontWeight.bold, color: colors.fg.neutral }}\n >\n 렌더링 FCP\n </text>\n <text\n className={\"pp-fcpMetricValue\"}\n style={{ fontWeight: fontWeight.bold, color: colors.palette.blue600 }}\n >\n {formatDuration(fcp.duration)}\n </text>\n </view>\n <text\n className={\"pp-fcpMetricDescription\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutralSubtle }}\n >\n TemplateBundle 준비부터 Paint End 까지 걸리는 시간\n </text>\n </view>\n )}\n </view>\n )}\n\n {!!perf.rawEntry && (\n <view\n className={\"pp-rawEntrySection\"}\n style={{ backgroundColor: colors.bg.neutralWeak }}\n >\n <text\n className={\"pp-detailTitle\"}\n style={{ fontWeight: fontWeight.bold, color: colors.fg.neutral }}\n >\n Raw Entry\n </text>\n <text\n className={\"pp-rawEntry\"}\n style={{ fontWeight: fontWeight.regular, color: colors.fg.neutralSubtle }}\n >\n {String(stringify(perf.rawEntry, null, 2, { references: true }))}\n </text>\n </view>\n )}\n </view>\n )}\n </view>\n </list-item>\n );\n })}\n </FadeList>\n </view>\n );\n};\n","import { type ReactNode, useRef, useState } from \"@lynx-js/react\";\nimport type { ListSnapEvent, NodesRef } from \"@lynx-js/types\";\nimport { useThemeColors } from \"../styles/ThemeContext\";\nimport { fontWeight } from \"../styles/theme\";\nimport \"./Tabs.css\";\n\ntype TabsProps = {\n items: Array<{\n key: string;\n label: string;\n renderContent: () => ReactNode;\n }>;\n onTabChange?: () => void;\n};\n\nexport default function Tabs(props: TabsProps) {\n const colors = useThemeColors();\n const tabContentsRef = useRef<NodesRef>(null);\n const [activeIndex, setActiveIndex] = useState(0);\n const tabSize =\n props.items.length < 4\n ? undefined\n : (`t${Math.max(1, 5 - (props.items.length - 3))}`);\n\n return (\n <view className={\"tabs-root\"}>\n <view\n className={\"tabs-header\"}\n style={{\n boxShadow: `inset 0 -1px 0 0 ${colors.stroke.neutralSubtle}`,\n }}\n >\n {props.items.map((item, i) => (\n <view\n key={item.key}\n className={\"tabs-triggerButton\"}\n bindtap={() => {\n setActiveIndex(i);\n props.onTabChange?.();\n\n tabContentsRef.current\n ?.invoke({\n method: \"scrollToPosition\",\n params: {\n position: i,\n smooth: true,\n },\n })\n .exec();\n }}\n >\n <text\n className={`tabs-triggerButtonText${tabSize ? ` tabs-triggerButtonText--${tabSize}` : \"\"}`}\n style={{\n fontWeight: fontWeight.bold,\n color:\n i === activeIndex\n ? colors.fg.neutral\n : colors.fg.neutralSubtle,\n }}\n >\n {item.label}\n </text>\n {i === 0 && (\n <view\n className={\"tabs-triggerIndicator\"}\n style={{ transform: `translateX(${activeIndex * 100}%)` }}\n >\n <view\n className={\"tabs-triggerIndicatorLine\"}\n style={{ backgroundColor: colors.fg.neutral }}\n />\n </view>\n )}\n </view>\n ))}\n </view>\n\n <list\n ref={tabContentsRef}\n className={\"tabs-contents\"}\n scroll-orientation=\"horizontal\"\n item-snap={{ factor: 0, offset: 0 }}\n bindscroll={() => props.onTabChange?.()}\n bindsnap={(e: ListSnapEvent) => {\n setActiveIndex(e.detail.position);\n }}\n bounces={false}\n preload-buffer-count={props.items.length}\n >\n {props.items.map((item) => (\n <list-item\n key={item.key}\n item-key={item.key}\n recyclable={false}\n className={\"tabs-content\"}\n >\n {item.renderContent()}\n </list-item>\n ))}\n </list>\n </view>\n );\n}\n","import { useConsole, useNetwork, usePerformance } from \"../hooks\";\nimport type { CustomTab } from \"../types\";\nimport \"./ConsolePanel.css\";\nimport { LogPanel, dismissFilterDropdown } from \"./LogPanel\";\nimport { NetworkPanel } from \"./NetworkPanel\";\nimport { PerformancePanel } from \"./PerformancePanel\";\nimport Tabs from \"./Tabs\";\n\ninterface ConsolePanelProps {\n customTabs?: CustomTab[];\n}\n\nexport const ConsolePanel = ({ customTabs }: ConsolePanelProps) => {\n const { logs, clearLogs } = useConsole();\n const { networks, clearNetworks } = useNetwork();\n const { performances, clearPerformances } = usePerformance();\n\n const state = globalThis.__LYNX_CONSOLE__?.state;\n\n const items: Array<{\n key: string;\n label: string;\n renderContent: () => ReturnType<typeof LogPanel>;\n }> = [];\n\n if (state?.logs) {\n items.push({\n key: \"log\",\n label: \"Log\",\n renderContent: () => <LogPanel logs={logs} clearLogs={clearLogs} />,\n });\n }\n\n if (state?.networks) {\n items.push({\n key: \"network\",\n label: \"Network\",\n renderContent: () => (\n <NetworkPanel networks={networks} clearNetworks={clearNetworks} />\n ),\n });\n }\n\n if (state?.performances) {\n items.push({\n key: \"performance\",\n label: \"Perf\",\n renderContent: () => (\n <PerformancePanel\n performances={performances}\n clearPerformances={clearPerformances}\n />\n ),\n });\n }\n\n if (customTabs) {\n for (const tab of customTabs) {\n items.push({\n key: tab.key,\n label: tab.label,\n renderContent: tab.renderContent,\n });\n }\n }\n\n if (items.length === 0) {\n return null;\n }\n\n return (\n <view className=\"cp-container\">\n <Tabs onTabChange={dismissFilterDropdown} items={items} />\n </view>\n );\n};\n","import { useRef, useState } from \"@lynx-js/react\";\nimport type { BaseTouchEvent, Target } from \"@lynx-js/types\";\n\nconst LONG_PRESS_DURATION = 400;\nconst MOVE_THRESHOLD = 5;\n\nconst DEFAULT_RIGHT = 16;\nconst DEFAULT_BOTTOM = 84;\n\nlet savedRight = DEFAULT_RIGHT;\nlet savedBottom = DEFAULT_BOTTOM;\n\nexport function useLongPressDrag(onTap: () => void) {\n const [right, setRight] = useState(savedRight);\n const [bottom, setBottom] = useState(savedBottom);\n const [phase, setPhase] = useState<\"idle\" | \"dragging\" | \"releasing\">(\"idle\");\n const [tempRight, setTempRight] = useState(savedRight);\n const [tempBottom, setTempBottom] = useState(savedBottom);\n\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const draggingRef = useRef(false);\n const startRef = useRef({ x: 0, y: 0, r: 0, b: 0 });\n\n const clearTimer = () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n };\n\n const handleTouchStart = (e: BaseTouchEvent<Target>) => {\n startRef.current = {\n x: e.detail.x,\n y: e.detail.y,\n r: right,\n b: bottom,\n };\n draggingRef.current = false;\n\n timerRef.current = setTimeout(() => {\n draggingRef.current = true;\n setPhase(\"dragging\");\n setTempRight(right);\n setTempBottom(bottom);\n }, LONG_PRESS_DURATION);\n };\n\n const handleTouchMove = (e: BaseTouchEvent<Target>) => {\n const dx = e.detail.x - startRef.current.x;\n const dy = e.detail.y - startRef.current.y;\n\n if (\n !draggingRef.current &&\n (Math.abs(dx) > MOVE_THRESHOLD || Math.abs(dy) > MOVE_THRESHOLD)\n ) {\n clearTimer();\n }\n\n if (!draggingRef.current) return;\n\n // right/bottom 기준이므로 방향 반전\n setTempRight(startRef.current.r - dx);\n setTempBottom(startRef.current.b - dy);\n };\n\n const handleTouchEnd = () => {\n clearTimer();\n\n if (draggingRef.current) {\n setRight(tempRight);\n setBottom(tempBottom);\n savedRight = tempRight;\n savedBottom = tempBottom;\n setPhase(\"releasing\");\n draggingRef.current = false;\n setTimeout(() => setPhase(\"idle\"), 300);\n } else {\n onTap();\n }\n };\n\n const isDragging = phase === \"dragging\";\n\n return {\n phase,\n right: isDragging ? tempRight : right,\n bottom: isDragging ? tempBottom : bottom,\n clearTimer,\n handlers: {\n catchtouchstart: handleTouchStart,\n catchtouchmove: handleTouchMove,\n catchtouchend: handleTouchEnd,\n },\n };\n}\n","import type { ReactNode } from \"@lynx-js/react\";\nimport { useLongPressDrag } from \"../hooks/useLongPressDrag\";\nimport { useThemeColors } from \"../styles/ThemeContext\";\nimport { duration } from \"../styles/theme\";\nimport \"./FloatingButton.css\";\n\ninterface FloatingButtonProps {\n bindtap: () => void;\n children: ReactNode;\n}\n\nconst SHINE_STYLES = {\n idle: {\n transform: \"scale(0)\",\n opacity: 0,\n },\n dragging: {\n transform: \"scale(1)\",\n opacity: 1,\n transition: \"transform 300ms cubic-bezier(0.4, 0, 0.2, 1)\",\n },\n releasing: {\n transform: \"scale(1)\",\n opacity: 0,\n transition: \"opacity 300ms cubic-bezier(0.4, 0, 0.2, 1)\",\n },\n} as const;\n\nexport const FloatingButton = ({\n bindtap,\n children,\n}: FloatingButtonProps) => {\n const colors = useThemeColors();\n const { phase, right, bottom, clearTimer, handlers } =\n useLongPressDrag(bindtap);\n\n\n const handleReload = () => {\n try {\n lynx.reload({}, () => {\n console.log(\"reloaded!\");\n });\n } catch (e) {\n console.error(\"[LynxConsole] reload failed:\", e);\n }\n };\n\n const isDragging = phase === \"dragging\";\n\n return (\n <>\n <view\n className={\"fb-wrapper\"}\n consume-slide-event={[[-180, 180]]}\n style={{\n right: `${right}px`,\n bottom: `${bottom}px`,\n transform: isDragging ? \"scale(1.05)\" : \"scale(1)\",\n transition: `transform ${duration.d4} cubic-bezier(0.4, 0, 0.2, 1)`,\n }}\n {...handlers}\n >\n <view\n className={\"fb-button\"}\n style={{ backgroundColor: colors.palette.green600 }}\n >\n {children}\n <view className={\"fb-shineOverlay\"} style={SHINE_STYLES[phase]} />\n </view>\n <view\n className={\"fb-reloadButton\"}\n style={{ backgroundColor: colors.palette.green600 }}\n catchtouchstart={() => clearTimer()}\n bindtap={handleReload}\n >\n <text\n className={\"fb-reloadIcon\"}\n style={{ color: colors.palette.staticWhite }}\n >\n {\"\\u21BB\"}\n </text>\n </view>\n </view>\n </>\n );\n};\n","import {\n type ForwardedRef,\n forwardRef,\n useImperativeHandle,\n useMemo,\n useState,\n} from \"@lynx-js/react\";\nimport BottomSheet from \"./components/BottomSheet.jsx\";\nimport { ConsolePanel } from \"./components/ConsolePanel.jsx\";\nimport \"./components/FloatingButton.css\";\nimport { FloatingButton } from \"./components/FloatingButton.jsx\";\nimport { usePerformance } from \"./hooks/usePerformance\";\nimport { ThemeProvider } from \"./styles/ThemeContext\";\nimport { getColors } from \"./styles/theme\";\nimport type { CustomTab } from \"./types\";\n\nexport interface LynxConsoleHandle {\n open: () => void;\n close: () => void;\n isOpen: () => boolean;\n}\n\nexport interface LynxConsoleProps {\n theme?: \"light\" | \"dark\";\n safeAreaInsetBottom?: string;\n customTabs?: CustomTab[];\n}\n\ninterface FcpMetric {\n name: string;\n duration: number;\n}\n\ninterface MetricFcpEntry {\n totalFcp?: FcpMetric;\n lynxFcp?: FcpMetric;\n fcp?: FcpMetric;\n}\n\nconst LynxConsole = forwardRef<LynxConsoleHandle, LynxConsoleProps>(\n (\n { theme = \"light\", safeAreaInsetBottom = \"50px\", customTabs },\n ref: ForwardedRef<LynxConsoleHandle>,\n ) => {\n const [isOpen, setIsOpen] = useState(false);\n const [shouldClose, setShouldClose] = useState(false);\n const { performances } = usePerformance();\n const colors = useMemo(() => getColors(theme), [theme]);\n\n const latestFcp = useMemo(() => {\n for (let i = performances.length - 1; i >= 0; i--) {\n const perf = performances[i];\n if (perf && perf.entryType === \"metric\" && perf.name === \"fcp\") {\n const metricEntry = perf.rawEntry as MetricFcpEntry | undefined;\n // totalFcp를 먼저 시도하고, 없으면 lynxFcp 반환\n if (metricEntry?.totalFcp?.duration !== undefined) {\n return metricEntry.totalFcp;\n }\n if (metricEntry?.lynxFcp?.duration !== undefined) {\n return metricEntry.lynxFcp;\n }\n }\n }\n return undefined;\n }, [performances]);\n\n useImperativeHandle(ref, () => ({\n open: () => {\n setIsOpen(true);\n setShouldClose(false);\n },\n close: () => {\n setShouldClose(true);\n },\n isOpen: () => isOpen,\n }));\n\n const handleOpenBottomSheet = () => {\n setIsOpen(true);\n setShouldClose(false);\n };\n\n const handleCloseBottomSheet = () => {\n setIsOpen(false);\n setShouldClose(false);\n };\n\n return (\n <ThemeProvider value={colors}>\n <view\n style={{\n backgroundColor: colors.bg.layerDefault,\n color: colors.fg.neutral,\n }}\n >\n <FloatingButton bindtap={handleOpenBottomSheet}>\n <text className=\"fb-title\" style={{ fontWeight: \"400\", color: colors.palette.staticWhite }}>LynxConsole</text>\n <text className=\"fb-subtitle\" style={{ fontWeight: \"400\", color: colors.palette.staticWhite }}>\n {`${latestFcp?.name ?? \"FCP\"}: ${latestFcp?.duration ? latestFcp.duration.toFixed(2) : \"--\"}ms`}\n </text>\n </FloatingButton>\n {isOpen && (\n <BottomSheet\n isOpen={isOpen}\n shouldClose={shouldClose}\n onClose={handleCloseBottomSheet}\n title=\"Lynx Console\"\n safeAreaInsetBottom={safeAreaInsetBottom}\n >\n <ConsolePanel customTabs={customTabs} />\n </BottomSheet>\n )}\n </view>\n </ThemeProvider>\n );\n },\n);\n\nexport type { CustomTab } from \"./types\";\nexport default LynxConsole;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lynx-console",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "**/*.css",
@@ -17,8 +17,6 @@
17
17
  bottom: 0;
18
18
  left: 0;
19
19
  z-index: 9998;
20
- background: var(--lynx-console-color-bg-overlay);
21
- transition: opacity var(--lynx-console-duration-d6) cubic-bezier(0.4, 0, 0.2, 1);
22
20
  }
23
21
 
24
22
  .bs-content {
@@ -28,10 +26,8 @@
28
26
  flex-direction: column;
29
27
  box-sizing: border-box;
30
28
  word-break: break-all;
31
- background: var(--lynx-console-color-bg-layer-floating);
32
29
  border-top-left-radius: 24px;
33
30
  border-top-right-radius: 24px;
34
- transition: transform var(--lynx-console-duration-d6) cubic-bezier(0.4, 0, 0.2, 1);
35
31
  height: 500px;
36
32
  overflow: hidden;
37
33
  }
@@ -50,7 +46,6 @@
50
46
  .bs-handle {
51
47
  width: 36px;
52
48
  height: 4px;
53
- background-color: var(--lynx-console-color-palette-gray-400);
54
49
  border-radius: 9999px;
55
50
  margin-top: 12px;
56
51
  }
@@ -69,8 +64,6 @@
69
64
  .bs-title {
70
65
  font-size: 1.25rem;
71
66
  line-height: 1.6875rem;
72
- font-weight: var(--lynx-console-font-weight-bold);
73
- color: var(--lynx-console-color-fg-neutral);
74
67
  }
75
68
 
76
69
  .bs-body {
@@ -1,5 +1,7 @@
1
1
  import { type ReactNode, useEffect, useState } from "@lynx-js/react";
2
2
  import type { BaseTouchEvent, Target } from "@lynx-js/types";
3
+ import { useThemeColors } from "../styles/ThemeContext";
4
+ import { duration, fontWeight } from "../styles/theme";
3
5
  import "./BottomSheet.css";
4
6
 
5
7
  interface BottomSheetProps {
@@ -29,6 +31,7 @@ export default function BottomSheet({
29
31
  shouldClose = false,
30
32
  safeAreaInsetBottom = "25px",
31
33
  }: BottomSheetProps) {
34
+ const colors = useThemeColors();
32
35
  const [sheetHeight, setSheetHeight] = useState(savedHeight ?? DEFAULT_HEIGHT);
33
36
  const [tempHeight, setTempHeight] = useState(savedHeight ?? DEFAULT_HEIGHT);
34
37
  const [isDragging, setIsDragging] = useState(false);
@@ -100,7 +103,9 @@ export default function BottomSheet({
100
103
  <scroll-view
101
104
  className="bs-backdrop"
102
105
  style={{
106
+ background: colors.bg.overlay,
103
107
  opacity: isOpening || isClosing ? 0 : 1,
108
+ transition: `opacity ${duration.d6} cubic-bezier(0.4, 0, 0.2, 1)`,
104
109
  }}
105
110
  >
106
111
  <view className="bs-overlay" bindtap={handleClose}>
@@ -108,10 +113,13 @@ export default function BottomSheet({
108
113
  className="bs-content"
109
114
  catchtap={() => {}}
110
115
  style={{
116
+ background: colors.bg.layerFloating,
111
117
  height: `${isDragging ? tempHeight : sheetHeight}px`,
112
118
  transform:
113
119
  isOpening || isClosing ? "translateY(100%)" : "translateY(0)",
114
- transition: isDragging ? "none" : undefined,
120
+ transition: isDragging
121
+ ? "none"
122
+ : `transform ${duration.d6} cubic-bezier(0.4, 0, 0.2, 1)`,
115
123
  }}
116
124
  >
117
125
  {/* catchtap: 이벤트 버블링 차단 */}
@@ -121,10 +129,23 @@ export default function BottomSheet({
121
129
  bindtouchmove={handleTouchMove}
122
130
  bindtouchend={handleTouchEnd}
123
131
  >
124
- <view className="bs-handle" />
132
+ <view
133
+ className="bs-handle"
134
+ style={{ backgroundColor: colors.palette.gray400 }}
135
+ />
125
136
  </view>
126
137
  <view className="bs-header">
127
- {title && <text className="bs-title">{title}</text>}
138
+ {title && (
139
+ <text
140
+ className="bs-title"
141
+ style={{
142
+ fontWeight: fontWeight.bold,
143
+ color: colors.fg.neutral,
144
+ }}
145
+ >
146
+ {title}
147
+ </text>
148
+ )}
128
149
  </view>
129
150
  <view
130
151
  className="bs-body"