1- import React , { useState , useRef , useCallback , useEffect } from 'react' ;
1+ import React from 'react' ;
22import type { ScriptMetadata } from '../types' ;
33import type { ThemeColors } from './theme-colors' ;
44import { SectionHeader } from './section-header' ;
@@ -8,73 +8,7 @@ export interface MainFunctionSectionProps {
88 colors : ThemeColors ;
99}
1010
11- // ── Tooltip 定位:基于 fixed 坐标,避免被滚动容器裁剪 ──────────
12-
13- interface TooltipPos {
14- top : number ;
15- left : number ;
16- maxWidth : number ;
17- maxHeight : number ;
18- }
19-
20- const TOOLTIP_MARGIN = 6 ;
21- const TOOLTIP_MAX_WIDTH = 380 ;
22-
23- function calcTooltipPos (
24- anchorRect : DOMRect ,
25- tooltipEl : HTMLDivElement | null ,
26- ) : TooltipPos {
27- const vw = window . innerWidth ;
28- const vh = window . innerHeight ;
29-
30- // 优先显示在 anchor 下方,空间不足时翻到上方
31- const tooltipH = tooltipEl ?. scrollHeight ?? 200 ;
32- const spaceBelow = vh - anchorRect . bottom - TOOLTIP_MARGIN ;
33- const spaceAbove = anchorRect . top - TOOLTIP_MARGIN ;
34- const placeBelow = spaceBelow >= Math . min ( tooltipH , 260 ) || spaceBelow >= spaceAbove ;
35-
36- const top = placeBelow
37- ? anchorRect . bottom + TOOLTIP_MARGIN
38- : Math . max ( TOOLTIP_MARGIN , anchorRect . top - tooltipH - TOOLTIP_MARGIN ) ;
39-
40- // 水平方向:以 anchor 左边为起点,超出右边界则左移
41- let left = anchorRect . left ;
42- const maxRight = vw - TOOLTIP_MARGIN ;
43- if ( left + TOOLTIP_MAX_WIDTH > maxRight ) {
44- left = Math . max ( TOOLTIP_MARGIN , maxRight - TOOLTIP_MAX_WIDTH ) ;
45- }
46-
47- const maxWidth = Math . min ( TOOLTIP_MAX_WIDTH , maxRight - left ) ;
48- const maxHeight = placeBelow ? spaceBelow - TOOLTIP_MARGIN : spaceAbove - TOOLTIP_MARGIN ;
49-
50- return { top, left, maxWidth, maxHeight : Math . max ( maxHeight , 80 ) } ;
51- }
52-
53- // ── 组件 ──────────────────────────────────────────────────────
54-
5511export const MainFunctionSection : React . FC < MainFunctionSectionProps > = ( { metadata, colors } ) => {
56- const [ showTip , setShowTip ] = useState ( false ) ;
57- const [ pos , setPos ] = useState < TooltipPos | null > ( null ) ;
58- const anchorRef = useRef < HTMLSpanElement > ( null ) ;
59- const tooltipRef = useRef < HTMLDivElement > ( null ) ;
60-
61- const updatePos = useCallback ( ( ) => {
62- if ( ! anchorRef . current ) return ;
63- const rect = anchorRef . current . getBoundingClientRect ( ) ;
64- setPos ( calcTooltipPos ( rect , tooltipRef . current ) ) ;
65- } , [ ] ) ;
66-
67- useEffect ( ( ) => {
68- if ( ! showTip ) return ;
69- updatePos ( ) ;
70- window . addEventListener ( 'scroll' , updatePos , true ) ;
71- window . addEventListener ( 'resize' , updatePos ) ;
72- return ( ) => {
73- window . removeEventListener ( 'scroll' , updatePos , true ) ;
74- window . removeEventListener ( 'resize' , updatePos ) ;
75- } ;
76- } , [ showTip , updatePos ] ) ;
77-
7812 return (
7913 < div >
8014 < SectionHeader colors = { colors } label = "主函数" />
@@ -86,32 +20,6 @@ export const MainFunctionSection: React.FC<MainFunctionSectionProps> = ({ metada
8620 < span style = { { color : colors . text , fontWeight : 500 } } >
8721 { metadata . mainMethod }
8822 </ span >
89- { metadata . description && (
90- < span
91- ref = { anchorRef }
92- style = { { display : 'inline-flex' , cursor : 'help' , flexShrink : 0 } }
93- onMouseEnter = { ( ) => setShowTip ( true ) }
94- onMouseLeave = { ( ) => setShowTip ( false ) }
95- >
96- < span
97- style = { {
98- display : 'inline-flex' ,
99- alignItems : 'center' ,
100- justifyContent : 'center' ,
101- width : 14 ,
102- height : 14 ,
103- borderRadius : '50%' ,
104- border : `1px solid ${ colors . textSecondary } ` ,
105- color : colors . textSecondary ,
106- fontSize : 10 ,
107- lineHeight : 1 ,
108- fontWeight : 600 ,
109- } }
110- >
111- ?
112- </ span >
113- </ span >
114- ) }
11523 < span style = { { color : colors . textSecondary , fontSize : 11 } } >
11624 ({ metadata . requests . map ( ( r ) => `${ r . name } : ${ r . dataType } ` ) . join ( ', ' ) } )
11725 </ span >
@@ -122,37 +30,6 @@ export const MainFunctionSection: React.FC<MainFunctionSectionProps> = ({ metada
12230 ) }
12331 </ div >
12432 </ div >
125-
126- { /* Tooltip 渲染在 fixed 层,脱离滚动容器 */ }
127- { showTip && pos && metadata . description && (
128- < div
129- ref = { tooltipRef }
130- onMouseEnter = { ( ) => setShowTip ( true ) }
131- onMouseLeave = { ( ) => setShowTip ( false ) }
132- style = { {
133- position : 'fixed' ,
134- top : pos . top ,
135- left : pos . left ,
136- maxWidth : pos . maxWidth ,
137- maxHeight : pos . maxHeight ,
138- overflowY : 'auto' ,
139- padding : '8px 12px' ,
140- background : colors . headerBg ,
141- border : `1px solid ${ colors . border } ` ,
142- borderRadius : 6 ,
143- color : colors . text ,
144- fontSize : 12 ,
145- lineHeight : 1.65 ,
146- whiteSpace : 'pre-wrap' ,
147- wordBreak : 'break-word' ,
148- zIndex : 9999 ,
149- boxShadow : '0 4px 16px rgba(0,0,0,0.3)' ,
150- pointerEvents : 'auto' ,
151- } }
152- >
153- { metadata . description }
154- </ div >
155- ) }
15633 </ div >
15734 ) ;
15835} ;
0 commit comments